Beispiel #1
0
// BuildGarpPkt builds a Gratuitous ARP packet
func BuildGarpPkt(ip net.IP, mac net.HardwareAddr, vlanID uint16) *openflow13.PacketOut {

	zMac, _ := net.ParseMAC("00:00:00:00:00:00")
	bMac, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")

	garpPkt, _ := protocol.NewARP(protocol.Type_Request)
	garpPkt.HWSrc = mac
	garpPkt.IPSrc = ip
	garpPkt.HWDst = zMac
	garpPkt.IPDst = ip

	// Build the ethernet packet
	ethPkt := protocol.NewEthernet()
	ethPkt.VLANID.VID = vlanID
	ethPkt.HWDst = bMac
	ethPkt.HWSrc = mac
	ethPkt.Ethertype = 0x0806
	ethPkt.Data = garpPkt

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

	return pktOut
}
Beispiel #2
0
func getIPPkt(ipSrc, ipDst string, portNo uint32) *ofctrl.PacketIn {
	p := new(ofctrl.PacketIn)
	p.Header = openflow13.NewOfp13Header()
	p.Header.Type = openflow13.Type_PacketIn
	p.BufferId = 0xffffffff
	p.Reason = 0
	p.TableId = 0
	p.Cookie = 0
	p.Match = *openflow13.NewMatch()
	inportField := openflow13.NewInPortField(portNo)
	m := &p.Match
	m.AddField(*inportField)
	ip := protocol.NewIPv4()
	ip.Version = 4
	ip.IHL = 5
	ip.DSCP = 0
	ip.ECN = 0
	ip.Length = 20
	ip.Protocol = ofctrl.IP_PROTO_TCP
	ip.NWSrc = net.ParseIP(ipSrc)
	ip.NWDst = net.ParseIP(ipDst)

	eth := protocol.NewEthernet()
	eth.Ethertype = protocol.IPv4_MSG
	eth.Data = ip

	p.TableId = SRV_PROXY_DNAT_TBL_ID
	p.Data = *eth
	return p
}
Beispiel #3
0
// injectArpReq injects an ARP request into ofnet
func injectArpReq(ofa *OfnetAgent, inPort, vlan int, macSrc, macDst, ipSrc, ipDst string) error {
	if macDst == "" {
		macDst = "ff:ff:ff:ff:ff:ff"
	}

	// inject an ARP request from ep1 for ep2
	arpReq := openflow13.NewPacketIn()
	arpReq.Match.Type = openflow13.MatchType_OXM
	arpReq.Match.AddField(*openflow13.NewInPortField(uint32(inPort)))
	arpReq.Data = *protocol.NewEthernet()
	arpReq.Data.Ethertype = protocol.ARP_MSG
	arpReq.Data.HWDst, _ = net.ParseMAC(macDst)
	arpReq.Data.HWSrc, _ = net.ParseMAC(macSrc)
	if vlan != 0 {
		arpReq.Data.VLANID.VID = uint16(vlan)
	}
	arpPkt, _ := protocol.NewARP(protocol.Type_Request)
	arpPkt.HWSrc, _ = net.ParseMAC(macSrc)
	arpPkt.IPSrc = net.ParseIP(ipSrc)
	arpPkt.HWDst, _ = net.ParseMAC("00:00:00:00:00:00")
	arpPkt.IPDst = net.ParseIP(ipDst)

	arpReq.Data.Data = arpPkt
	pkt := ofctrl.PacketIn(*arpReq)
	ofa.PacketRcvd(ofa.ofSwitch, &pkt)

	log.Debugf("Injected ARP request: %+v\n Packet: %+v", arpPkt, arpReq)
	return nil
}
Beispiel #4
0
// Process incoming ARP packets
func (self *Vrouter) processArp(pkt protocol.Ethernet, inPort uint32) {
	log.Debugf("processing ARP packet on port %d", inPort)
	switch t := pkt.Data.(type) {
	case *protocol.ARP:
		log.Debugf("ARP packet: %+v", *t)
		var arpHdr protocol.ARP = *t

		switch arpHdr.Operation {
		case protocol.Type_Request:
			// Lookup the Dest IP in the endpoint table
			vlan := self.agent.portVlanMap[inPort]
			if vlan == nil {
				return
			}
			endpointId := self.agent.getEndpointIdByIpVlan(arpHdr.IPDst, *vlan)
			endpoint := self.agent.endpointDb[endpointId]
			if endpoint == nil {
				// If we dont know the IP address, dont send an ARP response
				log.Infof("Received ARP request for unknown IP: %v", arpHdr.IPDst)
				return
			}

			// Form an ARP response
			arpResp, _ := protocol.NewARP(protocol.Type_Reply)
			arpResp.HWSrc = self.myRouterMac
			arpResp.IPSrc = arpHdr.IPDst
			arpResp.HWDst = arpHdr.HWSrc
			arpResp.IPDst = arpHdr.IPSrc

			log.Infof("Sending ARP response: %+v", arpResp)

			// build the ethernet packet
			ethPkt := protocol.NewEthernet()
			ethPkt.HWDst = arpResp.HWDst
			ethPkt.HWSrc = arpResp.HWSrc
			ethPkt.Ethertype = 0x0806
			ethPkt.Data = arpResp

			log.Infof("Sending ARP response Ethernet: %+v", ethPkt)

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

			log.Infof("Sending ARP response packet: %+v", pktOut)

			// Send it out
			self.ofSwitch.Send(pktOut)
		default:
			log.Infof("Dropping ARP response packet from port %d", inPort)
		}
	}
}
Beispiel #5
0
func (self *OfnetBgp) sendArp() {

	//Get the Mac of the vlan intf
	//Get the portno of the uplink
	//Build an arp packet and send on portno of uplink
	time.Sleep(5 * time.Second)
	for {
		if self.myBgpPeer == "" {
			return
		}

		intf, _ := net.InterfaceByName(self.vlanIntf)
		ofPortno, _ := self.agent.ovsDriver.GetOfpPortNo(self.vlanIntf)
		bMac, _ := net.ParseMAC("FF:FF:FF:FF:FF:FF")
		zeroMac, _ := net.ParseMAC("00:00:00:00:00:00")

		srcIP := net.ParseIP(self.routerIP)
		dstIP := net.ParseIP(self.myBgpPeer)
		arpReq, _ := protocol.NewARP(protocol.Type_Request)
		arpReq.HWSrc = intf.HardwareAddr
		arpReq.IPSrc = srcIP
		arpReq.HWDst = zeroMac
		arpReq.IPDst = dstIP

		log.Infof("Sending ARP Request: %+v", arpReq)

		// build the ethernet packet
		ethPkt := protocol.NewEthernet()
		ethPkt.HWDst = bMac
		ethPkt.HWSrc = arpReq.HWSrc
		ethPkt.Ethertype = 0x0806
		ethPkt.Data = arpReq

		log.Infof("Sending ARP Request Ethernet: %+v", ethPkt)

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

		log.Infof("Sending ARP Request packet: %+v", pktOut)

		// Send it out
		self.agent.ofSwitch.Send(pktOut)
		time.Sleep(1800 * time.Second)
	}
}
Beispiel #6
0
func getProxyARPResp(arpIn *protocol.ARP, tgtMac string, vid uint16, inPort uint32) *openflow13.PacketOut {
	arpPkt, _ := protocol.NewARP(protocol.Type_Reply)
	arpPkt.HWSrc, _ = net.ParseMAC(tgtMac)
	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 = 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))

	return pktOut
}
Beispiel #7
0
/*processArp does the following :
1)  Process incoming ARP packets
2)  Proxy with Router mac if arp request is from local internal endpoint
3)  Proxy with interface mac is arp request is from remote endpoint
4) Learn MAC,Port of the source if its not learnt and it is bgp peer endpoint
*/
func (self *Vlrouter) processArp(pkt protocol.Ethernet, inPort uint32) {
	log.Debugf("processing ARP packet on port %d", inPort)
	switch t := pkt.Data.(type) {
	case *protocol.ARP:
		log.Debugf("ARP packet: %+v", *t)
		var arpHdr protocol.ARP = *t
		var srcMac net.HardwareAddr
		var intf *net.Interface

		switch arpHdr.Operation {
		case protocol.Type_Request:
			// Lookup the Dest IP in the endpoint table
			endpoint := self.agent.getEndpointByIp(arpHdr.IPDst)
			if endpoint == nil {
				//If we dont know the IP address, dont send an ARP response
				log.Infof("Received ARP request for unknown IP: %v ", arpHdr.IPDst)
				return
			} else {
				if endpoint.EndpointType == "internal" || endpoint.EndpointType == "internal-bgp" {
					//srcMac, _ = net.ParseMAC(endpoint.MacAddrStr)
					intf, _ = net.InterfaceByName(self.agent.GetRouterInfo().VlanIntf)
					srcMac = intf.HardwareAddr
				} else if endpoint.EndpointType == "external" || endpoint.EndpointType == "external-bgp" {
					endpoint = self.agent.getEndpointByIp(arpHdr.IPSrc)
					if endpoint != nil {
						if endpoint.EndpointType == "internal" || endpoint.EndpointType == "internal-bgp" {
							srcMac = self.myRouterMac
						} else {
							return
						}

					} else {
						return
					}

				}
			}

			//Check if source endpoint is learnt.
			endpoint = self.agent.getEndpointByIp(arpHdr.IPSrc)
			if endpoint != nil && endpoint.EndpointType == "external-bgp" {
				//endpoint exists from where the arp is received.
				if endpoint.PortNo == 0 {
					log.Infof("Received ARP from BGP Peer on %s: Mac: %s", endpoint.PortNo, endpoint.MacAddrStr)
					//learn the mac address and portno for the endpoint
					self.RemoveEndpoint(endpoint)
					endpoint.PortNo = inPort
					endpoint.MacAddrStr = arpHdr.HWSrc.String()
					self.agent.endpointDb[endpoint.EndpointID] = endpoint
					self.AddEndpoint(endpoint)
					self.resolveUnresolvedEPs(endpoint.MacAddrStr, inPort)

				}
			}

			// Form an ARP response
			arpResp, _ := protocol.NewARP(protocol.Type_Reply)
			arpResp.HWSrc = srcMac
			arpResp.IPSrc = arpHdr.IPDst
			arpResp.HWDst = arpHdr.HWSrc
			arpResp.IPDst = arpHdr.IPSrc

			log.Infof("Sending ARP response: %+v", arpResp)

			// build the ethernet packet
			ethPkt := protocol.NewEthernet()
			ethPkt.HWDst = arpResp.HWDst
			ethPkt.HWSrc = arpResp.HWSrc
			ethPkt.Ethertype = 0x0806
			ethPkt.Data = arpResp

			log.Infof("Sending ARP response Ethernet: %+v", ethPkt)

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

			log.Infof("Sending ARP response packet: %+v", pktOut)

			// Send it out
			self.ofSwitch.Send(pktOut)
		case protocol.Type_Reply:
			endpoint := self.agent.getEndpointByIp(arpHdr.IPSrc)
			if endpoint != nil && endpoint.EndpointType == "external-bgp" {
				//endpoint exists from where the arp is received.
				if endpoint.PortNo == 0 {
					log.Infof("Received ARP from BGP Peer on %s: Mac: %s", endpoint.PortNo, endpoint.MacAddrStr)
					//learn the mac address and portno for the endpoint
					self.RemoveEndpoint(endpoint)
					endpoint.PortNo = inPort
					endpoint.MacAddrStr = arpHdr.HWSrc.String()
					self.agent.endpointDb[endpoint.EndpointID] = endpoint
					self.AddEndpoint(endpoint)
					self.resolveUnresolvedEPs(endpoint.MacAddrStr, inPort)

				}
			}

		default:
			log.Infof("Dropping ARP response packet from port %d", inPort)
		}
	}
}
Beispiel #8
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 uplinks
 * 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 (vl *VlanBridge) 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

		vl.agent.incrStats("ArpPktRcvd")

		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
			}

			vl.agent.incrStats("ArpReqRcvd")

			// Lookup the Source and Dest IP in the endpoint table
			//Vrf derivation logic :
			var vlan uint16
			_, fromUplink := vl.uplinkDb[inPort]
			if fromUplink {
				//arp packet came in from uplink hence tagged
				vlan = pkt.VLANID.VID
			} else {
				//arp packet came from local endpoints - derive vrf from inport
				if pVl := vl.agent.getPortVlanMap(inPort); pVl != nil {
					vlan = *(pVl)
				} else {
					log.Debugf("Invalid port vlan mapping. Ignoring arp packet")
					vl.agent.incrStats("ArpReqInvalidPortVlan")
					return
				}
			}
			srcEp := vl.agent.getEndpointByIpVlan(arpIn.IPSrc, vlan)
			dstEp := vl.agent.getEndpointByIpVlan(arpIn.IPDst, vlan)

			// No information about the src or dest EP. Drop the pkt.
			if srcEp == nil && dstEp == nil {
				log.Debugf("No information on source/destination. Ignoring ARP request.")
				vl.agent.incrStats("ArpRequestUnknownSrcDst")
				return
			}

			// if it came from uplink and the destination is not local, drop it
			if fromUplink {
				if dstEp == nil {
					vl.agent.incrStats("ArpReqUnknownDestFromUplink")
					return
				}

				if dstEp.OriginatorIp.String() != vl.agent.localIp.String() {
					vl.agent.incrStats("ArpReqNonLocalDestFromUplink")
					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() == vl.agent.localIp.String()) {
					// Send the packet out
					pktOut := getProxyARPResp(&arpIn, dstEp.MacAddrStr,
						pkt.VLANID.VID, inPort)
					vl.ofSwitch.Send(pktOut)

					vl.agent.incrStats("ArpReqRespSent")

					return
				}
			}

			proxyMac := vl.svcProxy.GetSvcProxyMAC(arpIn.IPDst)
			if proxyMac != "" {
				pktOut := getProxyARPResp(&arpIn, proxyMac,
					pkt.VLANID.VID, inPort)
				vl.ofSwitch.Send(pktOut)
				return
			}

			if srcEp != nil && dstEp == nil {
				// ARP request from local container to unknown IP
				// Reinject ARP to uplinks
				ethPkt := protocol.NewEthernet()
				ethPkt.VLANID.VID = srcEp.EndpointGroupVlan
				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 uplinks: %+v", arpIn.IPDst, ethPkt)

				// Packet out
				pktOut := openflow13.NewPacketOut()
				pktOut.InPort = inPort
				pktOut.Data = ethPkt
				for _, portNo := range vl.uplinkDb {
					log.Debugf("Sending to uplink: %+v", portNo)
					pktOut.AddAction(openflow13.NewActionOutput(portNo))
				}

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

				vl.agent.incrStats("ArpReqReinject")
			}

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

			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
			vl.ofSwitch.Send(pktOut)
		}
	}
}
Beispiel #9
0
// Process incoming ARP packets
func (self *Vrouter) processArp(pkt protocol.Ethernet, inPort uint32) {
	log.Debugf("processing ARP packet on port %d", inPort)
	switch t := pkt.Data.(type) {
	case *protocol.ARP:
		log.Debugf("ARP packet: %+v", *t)
		var arpHdr protocol.ARP = *t

		self.agent.incrStats("ArpPktRcvd")

		switch arpHdr.Operation {
		case protocol.Type_Request:
			self.agent.incrStats("ArpReqRcvd")

			var vlan *uint16
			if vlan = self.agent.getPortVlanMap(inPort); vlan == nil {
				self.agent.incrStats("ArpReqInvalidPortVlan")
				return
			}
			tgtMac := self.myRouterMac
			endpointId := self.agent.getEndpointIdByIpVlan(arpHdr.IPDst, *vlan)
			endpoint := self.agent.getEndpointByID(endpointId)
			if endpoint == nil {
				// Look for a service entry for the target IP
				proxyMac := self.svcProxy.GetSvcProxyMAC(arpHdr.IPDst)
				if proxyMac == "" {
					// If we dont know the IP address, dont send an ARP response
					log.Debugf("Received ARP request for unknown IP: %v", arpHdr.IPDst)
					self.agent.incrStats("ArpReqUnknownDest")
					return
				}

				tgtMac, _ = net.ParseMAC(proxyMac)
			}

			// Form an ARP response
			arpResp, _ := protocol.NewARP(protocol.Type_Reply)
			arpResp.HWSrc = tgtMac
			arpResp.IPSrc = arpHdr.IPDst
			arpResp.HWDst = arpHdr.HWSrc
			arpResp.IPDst = arpHdr.IPSrc

			log.Debugf("Sending ARP response: %+v", arpResp)

			// build the ethernet packet
			ethPkt := protocol.NewEthernet()
			ethPkt.HWDst = arpResp.HWDst
			ethPkt.HWSrc = arpResp.HWSrc
			ethPkt.Ethertype = 0x0806
			ethPkt.Data = arpResp

			log.Debugf("Sending ARP response Ethernet: %+v", ethPkt)

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

			log.Debugf("Sending ARP response packet: %+v", pktOut)

			// Send it out
			self.ofSwitch.Send(pktOut)
			self.agent.incrStats("ArpReqRespSent")

		default:
			log.Debugf("Dropping ARP response packet from port %d", inPort)
			self.agent.incrStats("ArpRespRcvd")
		}
	}
}
Beispiel #10
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 uplinks
 * 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 (vl *VlanBridge) 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
			}

			// Lookup the Source and Dest IP in the endpoint table
			//Vrf derivation logic :
			var vlan uint16
			if vl.uplinkDb[inPort] != 0 {
				//arp packet came in from uplink hence tagged
				vlan = pkt.VLANID.VID
			} else {
				//arp packet came from local endpoints - derive vrf from inport
				if vl.agent.portVlanMap[inPort] != nil {
					vlan = *(vl.agent.portVlanMap[inPort])
				} else {
					log.Debugf("Invalid port vlan mapping. Ignoring arp packet")
					return
				}
			}
			srcEp := vl.agent.getEndpointByIpVlan(arpIn.IPSrc, vlan)
			dstEp := vl.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() == vl.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
					vl.ofSwitch.Send(pktOut)

					return
				}
			}
			if srcEp != nil && dstEp == nil {
				// If the ARP request was received from uplink
				// Ignore processing the packet
				for _, portNo := range vl.uplinkDb {
					if portNo == inPort {
						log.Debugf("Ignore processing ARP packet from uplink")
						return
					}
				}

				// ARP request from local container to unknown IP
				// Reinject ARP to uplinks
				ethPkt := protocol.NewEthernet()
				ethPkt.VLANID.VID = srcEp.EndpointGroupVlan
				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 uplinks: %+v", arpIn.IPDst, ethPkt)

				// Packet out
				pktOut := openflow13.NewPacketOut()
				pktOut.InPort = inPort
				pktOut.Data = ethPkt
				for _, portNo := range vl.uplinkDb {
					log.Debugf("Sending to uplink: %+v", portNo)
					pktOut.AddAction(openflow13.NewActionOutput(portNo))
				}

				// Send the packet out
				vl.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
			vl.ofSwitch.Send(pktOut)
		}
	}
}
Beispiel #11
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)
		}
	}
}