// 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 }
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 }
// 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 }
// 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) } } }
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) } }
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 }
/*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) } } }
/* * 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) } } }
// 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") } } }
/* * 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) } } }
/* * 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) } } }