X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Farphandler%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Farphandler%2Finternal%2FArpHandler.java;h=e5491824397c1678b26b819b4e2691d0295f95a6;hp=8c91c71533a19282c9f1c48e8697dd3f81d181ee;hb=721b580748cb93b3dac952ff1f111d0ab0da0c79;hpb=3979e330c9f95a898c54a9234f3a07e3b2ae4349 diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java index 8c91c71533..e549182439 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/internal/ArpHandler.java @@ -64,6 +64,31 @@ import org.opendaylight.controller.topologymanager.ITopologyManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * The ArpHandler offers services to react on ARP requests and replies + * sent by network hosts. Moreover it allows for creating ARP messages + * by the controller itself. + * + * The ARP Handler on ODL doesn't use the requester MAC address in + * order to avoid to have to build a spanning tree where to forward + * ARP Requests. The ARP requests are broadcast packets so in order to + * reach everywhere need to be flooded, when you flood in a network + * that is not a tree (all the networks has some level of redundancy) + * that would create forwarding loops without a spanning tree. Given + * the need is only to send out the ARP requests toward all the hosts + * we actually don't need to implement a flooding mechanism in software + * (which would be expensive) we just send out the ARP request toward + * all the ports that are suspected to be host ports on all the + * switches (from the controller). Now the condition for which a port + * is marked as host port could potentially be incorrect so when the + * controller sends out the ARP Request that could come back to the + * controller and could cause another request not needed. So changing + * the source MAC address of the request to be the one of the controller, + * controller can protect itself from honoring twice the same request. + * This enables an ARP handler resolution, without the need of spanning + * tree and limiting software flooding to the minimum required. + */ + public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateAware { private static final Logger log = LoggerFactory.getLogger(ArpHandler.class); static final String ARP_EVENT_CACHE_NAME = "arphandler.arpRequestReplyEvent"; @@ -113,16 +138,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } } - void setRouting(IRouting r) { - this.routing = r; - } - - void unsetRouting(IRouting r) { - if (this.routing == r) { - this.routing = null; - } - } - void setHostListener(IfHostListener s) { if (this.hostListeners != null) { this.hostListeners.add(s); @@ -172,6 +187,12 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA byte[] targetIP = tIP.getAddress(); ARP arp = createARP(ARP.REPLY, sMAC, senderIP, tMAC, targetIP); + if(log.isTraceEnabled()) { + log.trace("Sending Arp Reply with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}", + HexEncode.bytesToHexString(sMAC), + sIP, HexEncode.bytesToHexString(tMAC), tIP, p); + } + Ethernet ethernet = createEthernet(sMAC, tMAC, arp); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); @@ -180,8 +201,28 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA this.dataPacketService.transmitDataPacket(destPkt); } + private void logArpPacket(ARP pkt, NodeConnector p) { + try { + if (pkt.getOpCode() == ARP.REQUEST) { + log.trace("Received Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()), + InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()), + InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p); + } else if(pkt.getOpCode() == ARP.REPLY) { + log.trace("Received Arp Reply with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {}", HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()), + InetAddress.getByAddress(pkt.getSenderProtocolAddress()), HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()), + InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p); + } + } catch(UnknownHostException e) { + log.warn("Illegal Ip Address in the ARP packet", e); + } + } + protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p) { + if(log.isTraceEnabled()) { + logArpPacket(pkt, p); + } + byte[] sourceMAC = eHeader.getSourceMACAddress(); byte[] targetMAC = eHeader.getDestinationMACAddress(); /* @@ -357,6 +398,11 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA byte[] targetIPByte = targetIP.getAddress(); ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetHardwareAddress, targetIPByte); + if(log.isTraceEnabled()) { + log.trace("Sending Broadcast Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}", HexEncode.bytesToHexString(getControllerMAC()), + subnet.getNetworkAddress(), HexEncode.bytesToHexString(targetHardwareAddress), targetIP, p); + } + byte[] destMACAddress = NetUtils.getBroadcastMACAddr(); Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp); @@ -387,6 +433,13 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA byte[] targetMAC = host.getDataLayerAddressBytes(); ARP arp = createARP(ARP.REQUEST, getControllerMAC(), senderIP, targetMAC, targetIP); + if(log.isTraceEnabled()) { + log.trace("Sending Unicast Arp Request with srcMac {} - srcIp {} - dstMac {} - dstIp {} - outport {}", + HexEncode.bytesToHexString(getControllerMAC()), + subnet.getNetworkAddress(), HexEncode.bytesToHexString(targetMAC), host.getNetworkAddress(), + outPort); + } + Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); @@ -461,44 +514,26 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA log.debug("Can't find subnet matching {}, drop packet", dIP); return; } + // If packet is sent to the default gw (us), ignore it for now + if (subnet.getNetworkAddress().equals(dIP)) { + log.trace("Ignore IP packet destined to default gw"); + return; + } // see if we know about the host // Hosttracker hosts db key implementation - IHostId id = HostIdFactory.create(dIP, null); - HostNodeConnector host = hostTracker.hostFind(id); + HostNodeConnector host = hostTracker.hostFind(dIP); if (host == null) { - // if we don't, know about the host, try to find it + // if we don't know about the host, try to find it log.trace("Punted IP pkt to {}, sending bcast ARP event...", dIP); /* * unknown destination host, initiate bcast ARP request */ arpRequestReplyEvent.put(new ARPRequest(dIP, subnet), false); - } else if (routing == null || routing.getRoute(p.getNode(), host.getnodeconnectorNode()) != null) { - /* - * if IRouting is available, make sure that this packet can get it's - * destination normally before teleporting it there. If it's not - * available, then assume it's reachable. - * - * TODO: come up with a way to do this in the absence of IRouting - */ - - log.trace("forwarding punted IP pkt to {} received at {}", dIP, p); - - /* - * if we know where the host is and there's a path from where this - * packet was punted to where the host is, then deliver it to the - * host for now - */ - NodeConnector nc = host.getnodeConnector(); - - // re-encode the Ethernet packet (the parent of the IPv4 packet) - RawPacket rp = this.dataPacketService.encodeDataPacket(pkt.getParent()); - rp.setOutgoingNodeConnector(nc); - this.dataPacketService.transmitDataPacket(rp); } else { - log.trace("ignoring punted IP pkt to {} because there is no route from {}", dIP, p); + log.trace("Ignoring punted IP pkt to known host: {} (received on: {})", dIP, p); } }