예제 #1
0
// sendGARP sends GARP for the specified IP, MAC
func (self *Vxlan) sendGARP(ip net.IP, mac net.HardwareAddr, vni uint64) error {

	// NOTE: Enable this when EVPN support is added.
	if !VXLAN_GARP_SUPPORTED {
		return nil
	}

	pktOut := BuildGarpPkt(ip, mac, 0)

	tunnelIdField := openflow13.NewTunnelIdField(vni)
	setTunnelAction := openflow13.NewActionSetField(*tunnelIdField)

	// Add set tunnel action to the instruction
	pktOut.AddAction(setTunnelAction)
	self.agent.vtepTableMutex.RLock()
	for _, vtepPort := range self.agent.vtepTable {
		log.Debugf("Sending to Vtep port: %+v", *vtepPort)
		pktOut.AddAction(openflow13.NewActionOutput(*vtepPort))
	}
	self.agent.vtepTableMutex.RUnlock()
	// Send it out
	self.ofSwitch.Send(pktOut)
	self.agent.incrStats("GarpPktSent")

	return nil
}
예제 #2
0
// Install a group entry in OF switch
func (self *Flood) install() error {
	groupMod := openflow13.NewGroupMod()
	groupMod.GroupId = self.GroupId

	// Change the OP to modify if it was already installed
	if self.isInstalled {
		groupMod.Command = openflow13.OFPGC_MODIFY
	}

	// OF type for flood list
	groupMod.Type = openflow13.OFPGT_ALL

	// Loop thru all output ports and add it to group bucket
	for _, output := range self.FloodList {
		// Get the output action from output entry
		act := output.outPort.GetOutAction()
		if act != nil {
			// Create a new bucket for each port
			bkt := openflow13.NewBucket()

			// Set tunnel Id if required
			if output.isTunnel {
				tunnelField := openflow13.NewTunnelIdField(output.tunnelId)
				setTunnel := openflow13.NewActionSetField(*tunnelField)
				bkt.AddAction(setTunnel)
			}

			// Always remove vlan tag
			popVlan := openflow13.NewActionPopVlan()
			bkt.AddAction(popVlan)

			// Add the output action to the bucket
			bkt.AddAction(act)

			// Add the bucket to group
			groupMod.AddBucket(*bkt)
		}
	}

	log.Infof("Installing Group entry: %+v", groupMod)

	// Send it to the switch
	self.Switch.Send(groupMod)

	// Mark it as installed
	self.isInstalled = true

	return nil
}
예제 #3
0
// Install all flow actions
func (self *Flow) installFlowActions(flowMod *openflow13.FlowMod,
	instr openflow13.Instruction) error {
	var actInstr openflow13.Instruction
	var addActn bool = false

	// Create a apply_action instruction to be used if its not already created
	switch instr.(type) {
	case *openflow13.InstrActions:
		actInstr = instr
	default:
		actInstr = openflow13.NewInstrApplyActions()
	}

	// Loop thru all actions
	for _, flowAction := range self.flowActions {
		switch flowAction.actionType {
		case "setVlan":
			// Push Vlan Tag action
			pushVlanAction := openflow13.NewActionPushVlan(0x8100)

			// Set Outer vlan tag field
			vlanField := openflow13.NewVlanIdField(flowAction.vlanId)
			setVlanAction := openflow13.NewActionSetField(*vlanField)

			// Prepend push vlan & setvlan actions to existing instruction
			actInstr.AddAction(setVlanAction, true)
			actInstr.AddAction(pushVlanAction, true)
			addActn = true

			log.Debugf("flow install. Added pushvlan action: %+v, setVlan actions: %+v",
				pushVlanAction, setVlanAction)

		case "popVlan":
			// Create pop vln action
			popVlan := openflow13.NewActionPopVlan()

			// Add it to instruction
			actInstr.AddAction(popVlan, true)
			addActn = true

			log.Debugf("flow install. Added popVlan action: %+v", popVlan)

		case "setMacDa":
			// Set Outer MacDA field
			macDaField := openflow13.NewEthDstField(flowAction.macAddr, nil)
			setMacDaAction := openflow13.NewActionSetField(*macDaField)

			// Add set macDa action to the instruction
			actInstr.AddAction(setMacDaAction, true)
			addActn = true

			log.Debugf("flow install. Added setMacDa action: %+v", setMacDaAction)

		case "setMacSa":
			// Set Outer MacSA field
			macSaField := openflow13.NewEthSrcField(flowAction.macAddr, nil)
			setMacSaAction := openflow13.NewActionSetField(*macSaField)

			// Add set macDa action to the instruction
			actInstr.AddAction(setMacSaAction, true)
			addActn = true

			log.Debugf("flow install. Added setMacSa Action: %+v", setMacSaAction)

		case "setTunnelId":
			// Set tunnelId field
			tunnelIdField := openflow13.NewTunnelIdField(flowAction.tunnelId)
			setTunnelAction := openflow13.NewActionSetField(*tunnelIdField)

			// Add set tunnel action to the instruction
			actInstr.AddAction(setTunnelAction, true)
			addActn = true

			log.Debugf("flow install. Added setTunnelId Action: %+v", setTunnelAction)

		case "setMetadata":
			// Set Metadata instruction
			metadataInstr := openflow13.NewInstrWriteMetadata(flowAction.metadata, flowAction.metadataMask)

			// Add the instruction to flowmod
			flowMod.AddInstruction(metadataInstr)

		default:
			log.Fatalf("Unknown action type %s", flowAction.actionType)
		}
	}

	// Add the instruction to flow if its not already added
	if (addActn) && (actInstr != instr) {
		// Add the instrction to flowmod
		flowMod.AddInstruction(actInstr)
	}

	return nil
}
예제 #4
0
/*
 * Process incoming ARP packets
 * ARP request handling in various scenarios:
 * Src and Dest EP known:
 *      - Proxy ARP if Dest EP is present locally on the host
 * Src EP known, Dest EP not known:
 *      - ARP Request to a router/VM scenario. Reinject ARP request to VTEPs
 * Src EP not known, Dest EP known:
 *      - Proxy ARP if Dest EP is present locally on the host
 * Src and Dest EP not known:
 *      - Ignore processing the request
 */
func (self *Vxlan) processArp(pkt protocol.Ethernet, inPort uint32) {
	switch t := pkt.Data.(type) {
	case *protocol.ARP:
		log.Debugf("Processing ARP packet on port %d: %+v", inPort, *t)
		var arpIn protocol.ARP = *t

		switch arpIn.Operation {
		case protocol.Type_Request:
			// If it's a GARP packet, ignore processing
			if arpIn.IPSrc.String() == arpIn.IPDst.String() {
				log.Debugf("Ignoring GARP packet")
				return
			}

			if self.agent.portVlanMap[inPort] == nil {
				log.Debugf("Invalid port vlan mapping. Ignoring arp packet")
				return
			}
			vlan := self.agent.portVlanMap[inPort]

			// Lookup the Source and Dest IP in the endpoint table
			srcEp := self.agent.getEndpointByIpVlan(arpIn.IPSrc, *vlan)
			dstEp := self.agent.getEndpointByIpVlan(arpIn.IPDst, *vlan)

			// No information about the src or dest EP. Ignore processing.
			if srcEp == nil && dstEp == nil {
				log.Debugf("No information on source/destination. Ignoring ARP request.")
				return
			}
			// If we know the dstEp to be present locally, send the Proxy ARP response
			if dstEp != nil {
				// Container to Container communication. Send proxy ARP response.
				// Unknown node to Container communication
				//   -> Send proxy ARP response only if Endpoint is local.
				//   -> This is to avoid sending ARP responses from ofnet agent on multiple hosts
				if srcEp != nil ||
					(srcEp == nil && dstEp.OriginatorIp.String() == self.agent.localIp.String()) {
					// Form an ARP response
					arpPkt, _ := protocol.NewARP(protocol.Type_Reply)
					arpPkt.HWSrc, _ = net.ParseMAC(dstEp.MacAddrStr)
					arpPkt.IPSrc = arpIn.IPDst
					arpPkt.HWDst = arpIn.HWSrc
					arpPkt.IPDst = arpIn.IPSrc
					log.Debugf("Sending Proxy ARP response: %+v", arpPkt)

					// Build the ethernet packet
					ethPkt := protocol.NewEthernet()
					ethPkt.VLANID.VID = pkt.VLANID.VID
					ethPkt.HWDst = arpPkt.HWDst
					ethPkt.HWSrc = arpPkt.HWSrc
					ethPkt.Ethertype = 0x0806
					ethPkt.Data = arpPkt
					log.Debugf("Sending Proxy ARP response Ethernet: %+v", ethPkt)

					// Construct Packet out
					pktOut := openflow13.NewPacketOut()
					pktOut.Data = ethPkt
					pktOut.AddAction(openflow13.NewActionOutput(inPort))

					// Send the packet out
					self.ofSwitch.Send(pktOut)

					return
				}
			}
			if srcEp != nil && dstEp == nil {
				// If the ARP request was received from VTEP port
				// Ignore processing the packet
				for _, vtepPort := range self.agent.vtepTable {
					if *vtepPort == inPort {
						log.Debugf("Received packet from VTEP port. Ignore processing")
						return
					}
				}

				// ARP request from local container to unknown IP
				// Reinject ARP to VTEP ports
				ethPkt := protocol.NewEthernet()
				ethPkt.HWDst = pkt.HWDst
				ethPkt.HWSrc = pkt.HWSrc
				ethPkt.Ethertype = 0x0806
				ethPkt.Data = &arpIn

				log.Infof("Received ARP request for unknown IP: %v. "+
					"Reinjecting ARP request Ethernet to VTEP ports: %+v", arpIn.IPDst, ethPkt)

				// Packet out
				pktOut := openflow13.NewPacketOut()
				pktOut.InPort = inPort
				pktOut.Data = ethPkt

				tunnelIdField := openflow13.NewTunnelIdField(uint64(srcEp.Vni))
				setTunnelAction := openflow13.NewActionSetField(*tunnelIdField)

				// Add set tunnel action to the instruction
				pktOut.AddAction(setTunnelAction)

				for _, vtepPort := range self.agent.vtepTable {
					log.Debugf("Sending to VTEP port: %+v", *vtepPort)
					pktOut.AddAction(openflow13.NewActionOutput(*vtepPort))
				}

				// Send the packet out
				self.ofSwitch.Send(pktOut)
			}

		case protocol.Type_Reply:
			log.Debugf("Received ARP response packet: %+v from port %d", arpIn, inPort)

			ethPkt := protocol.NewEthernet()
			ethPkt.VLANID = pkt.VLANID
			ethPkt.HWDst = pkt.HWDst
			ethPkt.HWSrc = pkt.HWSrc
			ethPkt.Ethertype = 0x0806
			ethPkt.Data = &arpIn
			log.Debugf("Sending ARP response Ethernet: %+v", ethPkt)

			// Packet out
			pktOut := openflow13.NewPacketOut()
			pktOut.InPort = inPort
			pktOut.Data = ethPkt
			pktOut.AddAction(openflow13.NewActionOutput(openflow13.P_NORMAL))

			log.Debugf("Reinjecting ARP reply packet: %+v", pktOut)
			// Send it out
			self.ofSwitch.Send(pktOut)
		}
	}
}
예제 #5
0
// Install all flow actions
func (self *Flow) installFlowActions(flowMod *openflow13.FlowMod,
	instr openflow13.Instruction) error {
	var actInstr openflow13.Instruction
	var addActn bool = false

	// Create a apply_action instruction to be used if its not already created
	switch instr.(type) {
	case *openflow13.InstrActions:
		actInstr = instr
	default:
		actInstr = openflow13.NewInstrApplyActions()
	}

	// Loop thru all actions
	for _, flowAction := range self.flowActions {
		switch flowAction.actionType {
		case "pushMpls": //SRTE
			// Push mpls Tag action
			pushMplsAction := openflow13.NewActionPushMpls(0x8847)

			// Set Outer mpls label field
			mplsLabelField := openflow13.NewMplsLabelField(flowAction.mplsLabel)
			setMplsAction := openflow13.NewActionSetField(*mplsLabelField)

			// Prepend push mpls & setlabel actions to existing instruction
			actInstr.AddAction(setMplsAction, true)
			actInstr.AddAction(pushMplsAction, true)

			addActn = true

			log.Debugf("flow install. Added mpls action: %+v, setMpls actions: %+v",
				pushMplsAction, setMplsAction)
		case "popVlanPushMpls": //SRTE
			// Push mpls Tag action
			pushMplsAction := openflow13.NewActionPushMpls(0x8847)

			// Set Outer mpls label field
			mplsLabelField := openflow13.NewMplsLabelField(flowAction.mplsLabel)
			setMplsAction := openflow13.NewActionSetField(*mplsLabelField)

			// Prepend push mpls & setlabel actions to existing instruction
			actInstr.AddAction(setMplsAction, true)
			actInstr.AddAction(pushMplsAction, true)

			// Create pop vlan action
			popVlan := openflow13.NewActionPopVlan()

			// Add it to instruction
			actInstr.AddAction(popVlan, true)

			addActn = true

			log.Debugf("flow install. Added pop vlan action: %+v,  and Added mpls action: %+v, setMpls actions: %+v",
				popVlan, pushMplsAction, setMplsAction)
		case "popMplsPushVlan": //SRTE
			// Push Vlan Tag action
			pushVlanAction := openflow13.NewActionPushVlan(0x8100)

			// Set Outer vlan tag field
			vlanField := openflow13.NewVlanIdField(flowAction.vlanId, nil)
			setVlanAction := openflow13.NewActionSetField(*vlanField)

			// Prepend push vlan & setvlan actions to existing instruction
			actInstr.AddAction(setVlanAction, true)
			actInstr.AddAction(pushVlanAction, true)

			//popmpls action
			popMplsAction := openflow13.NewActionPopMpls(0x0800)

			actInstr.AddAction(popMplsAction, true)

			addActn = true
			log.Debugf("flow install. Added pop mpls action: %+v,  and Added push vlan action: %+v, setVlan actions: %+v",
				popMplsAction, setVlanAction, vlanField)
		case "swapMpls": //SRTE - Test this
			// Set Outer mpls label field
			mplsLabelField := openflow13.NewMplsLabelField(flowAction.mplsLabel)
			setMplsAction := openflow13.NewActionSetField(*mplsLabelField)

			// Prepend push mpls & setlabel actions to existing instruction
			actInstr.AddAction(setMplsAction, true)

			addActn = true

			log.Debugf("flow install. Added swap mpls - setMpls actions: %+v", setMplsAction)
		case "popMpls": //SRTE
			// Pop mpls Tag action
			popMplsAction := openflow13.NewActionPopMpls(0x0800)

			actInstr.AddAction(popMplsAction, true)

			addActn = true

			log.Debugf("flow install. Pop mpls action: %+v",
				popMplsAction)
		case "setVlan":
			// Push Vlan Tag action
			pushVlanAction := openflow13.NewActionPushVlan(0x8100)

			// Set Outer vlan tag field
			vlanField := openflow13.NewVlanIdField(flowAction.vlanId, nil)
			setVlanAction := openflow13.NewActionSetField(*vlanField)

			// Prepend push vlan & setvlan actions to existing instruction
			actInstr.AddAction(setVlanAction, true)
			actInstr.AddAction(pushVlanAction, true)
			addActn = true

			log.Debugf("flow install. Added pushvlan action: %+v, setVlan actions: %+v",
				pushVlanAction, setVlanAction)

		case "popVlan":
			// Create pop vln action
			popVlan := openflow13.NewActionPopVlan()

			// Add it to instruction
			actInstr.AddAction(popVlan, true)
			addActn = true

			log.Debugf("flow install. Added popVlan action: %+v", popVlan)

		case "setMacDa":
			// Set Outer MacDA field
			macDaField := openflow13.NewEthDstField(flowAction.macAddr, nil)
			setMacDaAction := openflow13.NewActionSetField(*macDaField)

			// Add set macDa action to the instruction
			actInstr.AddAction(setMacDaAction, true)
			addActn = true

			log.Debugf("flow install. Added setMacDa action: %+v", setMacDaAction)

		case "setMacSa":
			// Set Outer MacSA field
			macSaField := openflow13.NewEthSrcField(flowAction.macAddr, nil)
			setMacSaAction := openflow13.NewActionSetField(*macSaField)

			// Add set macDa action to the instruction
			actInstr.AddAction(setMacSaAction, true)
			addActn = true

			log.Debugf("flow install. Added setMacSa Action: %+v", setMacSaAction)

		case "setTunnelId":
			// Set tunnelId field
			tunnelIdField := openflow13.NewTunnelIdField(flowAction.tunnelId)
			setTunnelAction := openflow13.NewActionSetField(*tunnelIdField)

			// Add set tunnel action to the instruction
			actInstr.AddAction(setTunnelAction, true)
			addActn = true

			log.Debugf("flow install. Added setTunnelId Action: %+v", setTunnelAction)

		case "setMetadata":
			// Set Metadata instruction
			metadataInstr := openflow13.NewInstrWriteMetadata(flowAction.metadata, flowAction.metadataMask)

			// Add the instruction to flowmod
			flowMod.AddInstruction(metadataInstr)

		case "setIPSa":
			// Set IP src
			ipSaField := openflow13.NewIpv4SrcField(flowAction.ipAddr, nil)
			setIPSaAction := openflow13.NewActionSetField(*ipSaField)

			// Add set action to the instruction
			actInstr.AddAction(setIPSaAction, true)
			addActn = true

			log.Debugf("flow install. Added setIPSa Action: %+v", setIPSaAction)

		case "setIPDa":
			// Set IP dst
			ipDaField := openflow13.NewIpv4DstField(flowAction.ipAddr, nil)
			setIPDaAction := openflow13.NewActionSetField(*ipDaField)

			// Add set action to the instruction
			actInstr.AddAction(setIPDaAction, true)
			addActn = true

			log.Debugf("flow install. Added setIPDa Action: %+v", setIPDaAction)

		case "setTCPSrc":
			// Set TCP src
			tcpSrcField := openflow13.NewTcpSrcField(flowAction.l4Port)
			setTCPSrcAction := openflow13.NewActionSetField(*tcpSrcField)

			// Add set action to the instruction
			actInstr.AddAction(setTCPSrcAction, true)
			addActn = true

			log.Debugf("flow install. Added setTCPSrc Action: %+v", setTCPSrcAction)

		case "setTCPDst":
			// Set TCP dst
			tcpDstField := openflow13.NewTcpDstField(flowAction.l4Port)
			setTCPDstAction := openflow13.NewActionSetField(*tcpDstField)

			// Add set action to the instruction
			actInstr.AddAction(setTCPDstAction, true)
			addActn = true

			log.Debugf("flow install. Added setTCPDst Action: %+v", setTCPDstAction)

		case "setUDPSrc":
			// Set UDP src
			udpSrcField := openflow13.NewUdpSrcField(flowAction.l4Port)
			setUDPSrcAction := openflow13.NewActionSetField(*udpSrcField)

			// Add set action to the instruction
			actInstr.AddAction(setUDPSrcAction, true)
			addActn = true

			log.Debugf("flow install. Added setUDPSrc Action: %+v", setUDPSrcAction)

		case "setUDPDst":
			// Set UDP dst
			udpDstField := openflow13.NewUdpDstField(flowAction.l4Port)
			setUDPDstAction := openflow13.NewActionSetField(*udpDstField)

			// Add set action to the instruction
			actInstr.AddAction(setUDPDstAction, true)
			addActn = true

			log.Debugf("flow install. Added setUDPDst Action: %+v", setUDPDstAction)

		default:
			log.Fatalf("Unknown action type %s", flowAction.actionType)
		}
	}

	// Add the instruction to flow if its not already added
	if (addActn) && (actInstr != instr) {
		// Add the instrction to flowmod
		flowMod.AddInstruction(actInstr)
	}

	return nil
}