From: Alessandro Boch Date: Fri, 27 Jun 2014 17:18:13 +0000 (-0700) Subject: ArpHandler to send ARP reply on proper vlan X-Git-Tag: release/helium~590^2 X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=commitdiff_plain;h=6f9fda057ddadd8d4eef643bca398cea65dd2007 ArpHandler to send ARP reply on proper vlan - Recently ARPHandler has been enhanced to process ARP request received on vlans. This further enhancement is for the respective controller generated ARP reply to be sent out on the proper vlan. Change-Id: Ib8e26901f625677ad59302dfd09add4719b7b02d Signed-off-by: Alessandro Boch --- diff --git a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java index a6ee60f65d..1a446b83db 100644 --- a/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java +++ b/opendaylight/arphandler/src/main/java/org/opendaylight/controller/arphandler/ARPReply.java @@ -23,14 +23,17 @@ public class ARPReply extends ARPEvent { private final byte[] tMac; private final byte[] sMac; private final InetAddress sIP; + private final short vlan; @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); + result = prime * result + ((port == null) ? 0 : port.hashCode()); result = prime * result + ((sIP == null) ? 0 : sIP.hashCode()); result = prime * result + Arrays.hashCode(sMac); result = prime * result + Arrays.hashCode(tMac); + result = prime * result + vlan; return result; } @@ -39,13 +42,20 @@ public class ARPReply extends ARPEvent { if (this == obj) { return true; } - if (obj == null) { + if (!super.equals(obj)) { return false; } if (!(obj instanceof ARPReply)) { return false; } ARPReply other = (ARPReply) obj; + if (port == null) { + if (other.port != null) { + return false; + } + } else if (!port.equals(other.port)) { + return false; + } if (sIP == null) { if (other.sIP != null) { return false; @@ -59,23 +69,28 @@ public class ARPReply extends ARPEvent { if (!Arrays.equals(tMac, other.tMac)) { return false; } + if (vlan != other.vlan) { + return false; + } return true; } - public ARPReply(NodeConnector port, InetAddress sIP, byte[] sMAC, InetAddress tIP, byte[] tMAC) { + public ARPReply(NodeConnector port, InetAddress sIP, byte[] sMAC, InetAddress tIP, byte[] tMAC, short vlan) { super(tIP); this.tMac = tMAC; this.sIP = sIP; this.sMac = sMAC; this.port = port; + this.vlan = vlan; } - public ARPReply(InetAddress tIP, byte[] tMAC) { + public ARPReply(InetAddress tIP, byte[] tMAC, short vlan) { super(tIP); this.tMac = tMAC; this.sIP = null; this.sMac = null; this.port = null; + this.vlan = vlan; } public byte[] getTargetMac() { @@ -94,6 +109,10 @@ public class ARPReply extends ARPEvent { return port; } + public short getVlan() { + return vlan; + } + /* * (non-Javadoc) * @@ -122,6 +141,10 @@ public class ARPReply extends ARPEvent { builder.append("sIP=") .append(sIP); } + if (vlan != 0) { + builder.append(", vlan=") + .append(vlan); + } builder.append("]"); return builder.toString(); } 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 db94a7c867..fe456f3f8e 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 @@ -49,13 +49,12 @@ import org.opendaylight.controller.sal.core.NodeConnector; import org.opendaylight.controller.sal.packet.ARP; import org.opendaylight.controller.sal.packet.Ethernet; import org.opendaylight.controller.sal.packet.IDataPacketService; +import org.opendaylight.controller.sal.packet.IEEE8021Q; import org.opendaylight.controller.sal.packet.IListenDataPacket; import org.opendaylight.controller.sal.packet.IPv4; -import org.opendaylight.controller.sal.packet.IEEE8021Q; import org.opendaylight.controller.sal.packet.Packet; import org.opendaylight.controller.sal.packet.PacketResult; import org.opendaylight.controller.sal.packet.RawPacket; -import org.opendaylight.controller.sal.routing.IRouting; import org.opendaylight.controller.sal.utils.EtherTypes; import org.opendaylight.controller.sal.utils.HexEncode; import org.opendaylight.controller.sal.utils.NetUtils; @@ -97,7 +96,6 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA private ISwitchManager switchManager; private ITopologyManager topologyManager; private IDataPacketService dataPacketService; - private IRouting routing; private IClusterContainerServices clusterContainerService; private IConnectionManager connectionManager; private Set hostListeners = new CopyOnWriteArraySet(); @@ -183,7 +181,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } } - protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP, byte[] tMAC, InetAddress tIP) { + protected void sendARPReply(NodeConnector p, byte[] sMAC, InetAddress sIP, byte[] tMAC, InetAddress tIP, short vlan) { byte[] senderIP = sIP.getAddress(); byte[] targetIP = tIP.getAddress(); ARP arp = createARP(ARP.REPLY, sMAC, senderIP, tMAC, targetIP); @@ -194,7 +192,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA sIP, HexEncode.bytesToHexString(tMAC), tIP, p); } - Ethernet ethernet = createEthernet(sMAC, tMAC, arp); + Ethernet ethernet = createEthernet(sMAC, tMAC, arp, vlan); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); destPkt.setOutgoingNodeConnector(p); @@ -202,26 +200,24 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA this.dataPacketService.transmitDataPacket(destPkt); } - private void logArpPacket(ARP pkt, NodeConnector p) { + private void logArpPacket(ARP pkt, NodeConnector p, short vlan) { 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.trace("Received Arp {} with srcMac {} - srcIp {} - dstMac {} - dstIp {} - inport {} {}", + ((pkt.getOpCode() == ARP.REQUEST) ? "Request" : "Reply"), + HexEncode.bytesToHexString(pkt.getSenderHardwareAddress()), + InetAddress.getByAddress(pkt.getSenderProtocolAddress()), + HexEncode.bytesToHexString(pkt.getTargetHardwareAddress()), + InetAddress.getByAddress(pkt.getTargetProtocolAddress()), p, (vlan != 0 ? "on vlan " + vlan : "")); + + } catch (UnknownHostException e) { log.warn("Illegal Ip Address in the ARP packet", e); } } - protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p) { + protected void handleARPPacket(Ethernet eHeader, ARP pkt, NodeConnector p, short vlan) { if(log.isTraceEnabled()) { - logArpPacket(pkt, p); + logArpPacket(pkt, p, vlan); } byte[] sourceMAC = eHeader.getSourceMACAddress(); @@ -265,7 +261,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA HostNodeConnector requestor = null; if (NetUtils.isUnicastMACAddr(sourceMAC) && p.getNode() != null) { try { - requestor = new HostNodeConnector(sourceMAC, sourceIP, p, subnet.getVlan()); + requestor = new HostNodeConnector(sourceMAC, sourceIP, p, vlan); } catch (ConstructionException e) { log.debug("Received ARP packet with invalid MAC: {}", HexEncode.bytesToHexString(sourceMAC)); return; @@ -295,7 +291,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA // the true value indicates we should generate replies to requestors // across the cluster log.trace("Received ARP reply packet from {}, reply to all requestors.", sourceIP); - arpRequestReplyEvent.put(new ARPReply(sourceIP, sourceMAC), true); + arpRequestReplyEvent.put(new ARPReply(sourceIP, sourceMAC, vlan), true); return; } @@ -316,11 +312,11 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA log.trace("Received local ARP req. for default gateway. Replying with controller MAC: {}", HexEncode.bytesToHexString(getControllerMAC())); } - sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP); + sendARPReply(p, getControllerMAC(), targetIP, pkt.getSenderHardwareAddress(), sourceIP, vlan); } else { log.trace("Received non-local ARP req. for default gateway. Raising reply event"); arpRequestReplyEvent.put( - new ARPReply(p, targetIP, getControllerMAC(), sourceIP, pkt.getSenderHardwareAddress()), false); + new ARPReply(p, targetIP, getControllerMAC(), sourceIP, pkt.getSenderHardwareAddress(), vlan), false); } return; } @@ -354,10 +350,10 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA log.trace("Received ARP req. for known host {}, sending reply...", targetIP); if (connectionManager.getLocalityStatus(p.getNode()) == ConnectionLocality.LOCAL) { sendARPReply(p, host.getDataLayerAddressBytes(), host.getNetworkAddress(), - pkt.getSenderHardwareAddress(), sourceIP); + pkt.getSenderHardwareAddress(), sourceIP, vlan); } else { arpRequestReplyEvent.put(new ARPReply(p, host.getNetworkAddress(), host.getDataLayerAddressBytes(), - sourceIP, pkt.getSenderHardwareAddress()), false); + sourceIP, pkt.getSenderHardwareAddress(), vlan), false); } } else { /* @@ -405,7 +401,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } byte[] destMACAddress = NetUtils.getBroadcastMACAddr(); - Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp); + Ethernet ethernet = createEthernet(getControllerMAC(), destMACAddress, arp, (short)0); // TODO For now send port-by-port, see how to optimize to // send to multiple ports at once @@ -417,9 +413,9 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } /** - * Send a unicast ARP Request to the known host on a specific switch/port as - * defined in the host. The sender IP is the networkAddress of the subnet - * The sender MAC is the controller's MAC + * Send a unicast ARP Request to the known host on specific (switch/port, + * vlan) as defined in the host. The sender IP is the networkAddress of the + * subnet The sender MAC is the controller's MAC */ protected void sendUcastARPRequest(HostNodeConnector host, Subnet subnet) { log.trace("sendUcastARPRequest host:{} subnet:{}", host, subnet); @@ -441,7 +437,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA outPort); } - Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp); + Ethernet ethernet = createEthernet(getControllerMAC(), targetMAC, arp, host.getVlan()); RawPacket destPkt = this.dataPacketService.encodeDataPacket(ethernet); destPkt.setOutgoingNodeConnector(outPort); @@ -499,7 +495,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA * @param pkt * @param p */ - protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p) { + protected void handlePuntedIPPacket(IPv4 pkt, NodeConnector p, short vlan) { InetAddress dIP = NetUtils.getInetAddress(pkt.getDestinationAddress()); if (dIP == null) { @@ -654,17 +650,19 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA log.trace("Received a frame of size: {}", inPkt.getPacketData().length); Packet formattedPak = this.dataPacketService.decodeDataPacket(inPkt); if (formattedPak instanceof Ethernet) { - Object nextPak = formattedPak.getPayload(); + Packet nextPak = formattedPak.getPayload(); + short vlan = 0; if (nextPak instanceof IEEE8021Q) { + vlan = ((IEEE8021Q) nextPak).getVid(); log.trace("Moved after the dot1Q header"); nextPak = ((IEEE8021Q) nextPak).getPayload(); } if (nextPak instanceof IPv4) { log.trace("Handle IP packet: {}", formattedPak); - handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector()); + handlePuntedIPPacket((IPv4) nextPak, inPkt.getIncomingNodeConnector(), vlan); } else if (nextPak instanceof ARP) { log.trace("Handle ARP packet: {}", formattedPak); - handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt.getIncomingNodeConnector()); + handleARPPacket((Ethernet) formattedPak, (ARP) nextPak, inPkt.getIncomingNodeConnector(), vlan); } } return PacketResult.IGNORED; @@ -685,12 +683,21 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA return arp; } - private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp) { + private Ethernet createEthernet(byte[] sourceMAC, byte[] targetMAC, ARP arp, short vlan) { Ethernet ethernet = new Ethernet(); ethernet.setSourceMACAddress(sourceMAC); ethernet.setDestinationMACAddress(targetMAC); - ethernet.setEtherType(EtherTypes.ARP.shortValue()); - ethernet.setPayload(arp); + if (vlan == 0) { + ethernet.setEtherType(EtherTypes.ARP.shortValue()); + ethernet.setPayload(arp); + } else { + IEEE8021Q dot1q = new IEEE8021Q(); + dot1q.setVid(vlan); + dot1q.setEtherType(EtherTypes.ARP.shortValue()); + dot1q.setPayload(arp); + ethernet.setEtherType(EtherTypes.VLANTAGGED.shortValue()); + ethernet.setPayload(dot1q); + } return ethernet; } @@ -736,7 +743,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA } } - private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC) { + private void generateAndSendReply(InetAddress sourceIP, byte[] sourceMAC, short vlan) { if (log.isTraceEnabled()) { log.trace("generateAndSendReply called with params sourceIP:{} sourceMAC:{}", sourceIP, HexEncode.bytesToHexString(sourceMAC)); @@ -750,13 +757,14 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA for (HostNodeConnector host : hosts) { if (log.isTraceEnabled()) { log.trace( - "Sending ARP Reply with src {}/{}, target {}/{}", + "Sending ARP Reply with src {}/{}, target {}/{} {}", new Object[] { HexEncode.bytesToHexString(sourceMAC), sourceIP, - HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host.getNetworkAddress() }); + HexEncode.bytesToHexString(host.getDataLayerAddressBytes()), host.getNetworkAddress(), + (vlan != 0 ? "on vlan " + vlan : "") }); } if (connectionManager.getLocalityStatus(host.getnodeconnectorNode()) == ConnectionLocality.LOCAL) { sendARPReply(host.getnodeConnector(), sourceMAC, sourceIP, host.getDataLayerAddressBytes(), - host.getNetworkAddress()); + host.getNetworkAddress(), vlan); } else { /* * In the remote event a requestor moved to another controller @@ -765,7 +773,7 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA */ arpRequestReplyEvent.put( new ARPReply(host.getnodeConnector(), sourceIP, sourceMAC, host.getNetworkAddress(), host - .getDataLayerAddressBytes()), false); + .getDataLayerAddressBytes(), vlan), false); } } } @@ -827,12 +835,12 @@ public class ArpHandler implements IHostFinder, IListenDataPacket, ICacheUpdateA // requestors across the cluster if (ev.isNewReply()) { log.trace("Trigger a generateAndSendReply in response to {}", rep); - generateAndSendReply(rep.getTargetIP(), rep.getTargetMac()); + generateAndSendReply(rep.getTargetIP(), rep.getTargetMac(), rep.getVlan()); // Otherwise, a specific reply. If local, send out. } else if (connectionManager.getLocalityStatus(rep.getPort().getNode()) == ConnectionLocality.LOCAL) { log.trace("ARPCacheEventHandler - sendUcatARPReply locally in response to {}", rep); sendARPReply(rep.getPort(), rep.getSourceMac(), rep.getSourceIP(), rep.getTargetMac(), - rep.getTargetIP()); + rep.getTargetIP(), rep.getVlan()); } } } catch (InterruptedException e) {