Bug 6831: Retain subnetroute with l3 directly-connected subnet 82/46982/3
authorVivekanandan Narasimhan <n.vivekanandan@ericsson.com>
Thu, 6 Oct 2016 13:12:39 +0000 (18:42 +0530)
committerSam Hague <shague@redhat.com>
Wed, 19 Oct 2016 16:06:56 +0000 (16:06 +0000)
The following review :

https://git.opendaylight.org/gerrit/#/c/46292/

was reverted via:
https://git.opendaylight.org/gerrit/#/c/46575/

The revert was done in order to maintain sanity of the
subnetroute feature which enables auto-discovery of
Non-Neutron IP addresses on an enterprise network by using
the datacenter as the proxy.

The revert however resulted in use-case breakage where rewrite of
MACAddresses held behind a directly connected subnet ceased
to happen.

With this fix, we bring back the use-case of rewrite of mac-addresses
for hosts behind a directly connected l3 subnet.  In addition to that
we attempt to maintain a working subnetroute functionality.

Change-Id: I89a61396d62e38cf9756cbd0bdb2b845b5e8e44f
Signed-off-by: Vivekanandan Narasimhan <n.vivekanandan@ericsson.com>
vpnservice/neutronvpn/neutronvpn-impl/src/main/java/org/opendaylight/netvirt/neutronvpn/NeutronvpnManager.java
vpnservice/vpnmanager/vpnmanager-api/src/main/yang/odl-l3vpn.yang
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/ArpNotificationHandler.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetRoutePacketInHandler.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java

index f58f8f9637c1b1c17e5cd7fa95571226b80d4ae8..0e90dee11098fe0de0dfbcef4c662135aba925ed 100644 (file)
@@ -621,7 +621,7 @@ public class NeutronvpnManager implements NeutronvpnService, AutoCloseable, Even
             StringBuilder IpPrefixBuild = new StringBuilder(ip.getIpAddress().getIpv4Address().getValue());
             String IpPrefix = IpPrefixBuild.append("/32").toString();
             Adjacency vmAdj = new AdjacencyBuilder().setKey(new AdjacencyKey(IpPrefix)).setIpAddress(IpPrefix)
-                    .setMacAddress(port.getMacAddress().getValue()).build();
+                    .setMacAddress(port.getMacAddress().getValue()).setPrimaryAdjacency(true).build();
             adjList.add(vmAdj);
             // create extra route adjacency
             if (rtr != null && rtr.getRoutes() != null) {
index f046595b7963dab4281f5d9e8144e562083f5224..926db0fc3863873c393ca0f60199573d4f399dd1 100644 (file)
@@ -16,6 +16,12 @@ module odl-l3vpn {
             key "ip_address";
             leaf-list next-hop-ip-list { type string; }
             leaf ip_address {type string;}
+            leaf primary-adjacency {
+                type boolean;
+                default false;
+                description 
+                    "Value of True indicates this is a primary adjacency";
+            }
             leaf label { type uint32; config "false"; } /* optional */
             leaf mac_address {type string;} /* optional */
         }
index 1d3bbf5cb9a91a6df748b2063aebba1b4c003d2e..6943ff58cb9c680afc6e57b2fd6401549464bfed 100644 (file)
@@ -143,7 +143,7 @@ public class ArpNotificationHandler implements OdlArputilListener {
                 } else {
                     synchronized ((vpnName + ipToQuery).intern()) {
                         VpnUtil.createVpnPortFixedIpToPort(dataBroker, vpnName, ipToQuery, srcInterface, srcMac.getValue(), false, false, true);
-                        addMipAdjacency(vpnName, srcInterface, srcIP);
+                        addMipAdjacency(vpnName, srcInterface, srcIP, null);
                     }
                 }
                 String targetIpToQuery = notification.getDstIpaddress().getIpv4Address().getValue();
@@ -261,7 +261,7 @@ public class ArpNotificationHandler implements OdlArputilListener {
                 } else {
                     synchronized ((vpnName + ipToQuery).intern()) {
                         VpnUtil.createVpnPortFixedIpToPort(dataBroker, vpnName, ipToQuery, srcInterface, srcMac.getValue(), false, false, true);
-                        addMipAdjacency(vpnName, srcInterface, srcIP);
+                        addMipAdjacency(vpnName, srcInterface, srcIP, srcMac.getValue());
                     }
                 }
             }
@@ -321,7 +321,7 @@ public class ArpNotificationHandler implements OdlArputilListener {
         });
     }
 
-    private void addMipAdjacency(String vpnName, String vpnInterface, IpAddress prefix){
+    private void addMipAdjacency(String vpnName, String vpnInterface, IpAddress prefix, String mipMacAddress){
 
         LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
         InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
@@ -335,13 +335,13 @@ public class ArpNotificationHandler implements OdlArputilListener {
                 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
                 ip = VpnUtil.getIpPrefix(ip);
                 for (Adjacency adjacs : adjacencyList) {
-                    if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
+                    if (adjacs.isPrimaryAdjacency()) {
                         nextHopIpAddr = adjacs.getIpAddress();
                         nextHopMacAddress = adjacs.getMacAddress();
                         break;
                     }
                 }
-                if (nextHopMacAddress != null && ip != null) {
+                if (nextHopIpAddr != null) {
                     String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
                     long label =
                             VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
@@ -352,9 +352,12 @@ public class ArpNotificationHandler implements OdlArputilListener {
                         return;
                     }
                     String nextHopIp = nextHopIpAddr.split("/")[0];
-                    Adjacency newAdj = new AdjacencyBuilder().setIpAddress(ip).setKey
-                            (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp)).build();
-                    adjacencyList.add(newAdj);
+                    AdjacencyBuilder newAdjBuilder = new AdjacencyBuilder().setIpAddress(ip).setKey
+                            (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp));
+                    if (mipMacAddress != null) {
+                        newAdjBuilder.setMacAddress(mipMacAddress);
+                    }
+                    adjacencyList.add(newAdjBuilder.build());
                     Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
                     VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface)).
                             setName(vpnInterface).setVpnInstanceName(vpnName).addAugmentation(Adjacencies.class, aug)
index afe297006bed4a914f794421ae3c66a92a4aec87..4f5eed712580f1ca7c2d4bd715e3e92b067c031c 100644 (file)
@@ -126,108 +126,8 @@ public class SubnetRoutePacketInHandler implements PacketProcessingListener {
             }
             return;
         }
-        //All Arp responses learning for invisble IPs will now be handled by VpnManager
+        //All Arp responses learning for invisble IPs is handled by ArpNotificationHandler
 
-        /*if (tableId == NwConstants.L3_INTERFACE_TABLE) {
-            LOG.trace("SubnetRoutePacketInHandler: Packet from Table {} received as {}",
-                    NwConstants.L3_INTERFACE_TABLE, notification);
-            try {
-                res.deserialize(data, 0, data.length * NetUtils.NumBitsInAByte);
-            } catch (Exception e) {
-                LOG.warn("SubnetRoutePacketInHandler: Failed to decode Table " + NwConstants.L3_INTERFACE_TABLE + " Packet ", e);
-                return;
-            }
-            try {
-                Packet pkt = res.getPayload();
-                if (pkt instanceof ARP) {
-                    LOG.debug("SubnetRoutePacketInHandler: ARP packet received");
-                    ARP arpPacket = (ARP) pkt;
-                    boolean arpReply = (arpPacket.getOpCode() == 2) ? true : false;
-                    if (arpReply) {
-                        //Handle subnet routes arp responses
-                        LOG.debug("SubnetRoutePacketInHandler: ARP reply received");
-                        byte[] respSrc = arpPacket.getSenderProtocolAddress();
-                        byte[] respDst = arpPacket.getTargetProtocolAddress();
-                        String respIp = toStringIpAddress(respSrc);
-                        String check = toStringIpAddress(respDst) + respIp;
-                        if (VpnUtil.getNeutronPortNamefromPortFixedIp(dataBroker, respIp) != null) {
-                            LOG.debug("SubnetRoutePacketInHandler: ARP reply Packet received with "
-                                    + "Source IP {} which is a valid Neutron port, ignoring subnet route processing", respIp);
-                            return;
-                        }
-                        String destination = VpnUtil.getIpPrefix(respIp);
-                        String srcIp = toStringIpAddress(respSrc);
-                        String destIp = toStringIpAddress(respDst);
-                        long vpnId = MetaDataUtil.getVpnIdFromMetadata(metadata);
-                        LOG.info("SubnetRoutePacketInHandler: Processing ARP response Packet received with Source IP {} "
-                                + "and Target IP {} and vpnId {}", srcIp, destIp, vpnId);
-                        InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnIdsInstanceIdentifier = getVpnIdToVpnInstanceIdentifier(vpnId);
-                        Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnIdsOptional = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
-                        if(!vpnIdsOptional.isPresent()) {
-                            // Donot trigger subnetroute logic for packets from unknown VPNs
-                            LOG.info("Ignoring ARP response packet with destination Ip {} and source Ip {} as it came on with VPN ID {}", destIp, srcIp, vpnId);
-                            return;
-                        }
-                        // It is an ARP request on a configured VPN.  So we must attempt to respond.
-                        org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds vpnIds = vpnIdsOptional.get();
-                        if (VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker, vpnIds.getVpnInstanceName(), srcIp) != null) {
-                            LOG.debug("SubnetRoutePacketInHandler: ARP response Packet received with "
-                                    + "Target IP {} is a valid Neutron port, ignoring subnet route processing", destIp);
-                            return;
-                        }
-                        String destination = VpnUtil.getIpPrefix(srcIp);
-                        long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
-                        LOG.info("SubnetRoutePacketInHandler: ARP reply received for target IP {} from LPort {}" + srcIp, portTag);
-                        IfIndexInterface interfaceInfo = VpnUtil.getInterfaceInfoByInterfaceTag(dataBroker, portTag);
-                        String ifName = interfaceInfo.getInterfaceName();
-                        InstanceIdentifier<VpnInterface> vpnIfIdentifier = VpnUtil.getVpnInterfaceIdentifier(ifName);
-                        VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, ifName);
-
-                        //Get VPN interface adjacencies
-                        if (vpnInterface != null) {
-                            InstanceIdentifier<Adjacencies> path = vpnIfIdentifier.augmentation(Adjacencies.class);
-                            Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
-                            String nextHopIpAddr = null;
-                            String nextHopMacAddress = null;
-                            if (adjacencies.isPresent()) {
-                                List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
-                                for (Adjacency adjacs : adjacencyList) {
-                                    if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
-                                        nextHopIpAddr = adjacs.getIpAddress();
-                                        nextHopMacAddress = adjacs.getMacAddress();
-                                        break;
-                                    }
-                                }
-                                if (nextHopMacAddress != null && destination != null) {
-                                    String rd = VpnUtil.getVpnRd(dataBroker, vpnInterface.getVpnInstanceName());
-                                    long label =
-                                            VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
-                                                    VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnInterface.getVpnInstanceName(), destination));
-                                    String nextHopIp = nextHopIpAddr.split("/")[0];
-                                    // FIXME 9: To be fixed with VPNManager patch
-                                    // Adjacency newAdj = new AdjacencyBuilder().setIpAddress(destination).setKey
-                                            (new AdjacencyKey(destination)).setNextHopIp(nextHopIp).build();
-                                    adjacencyList.add(newAdj);
-                                    Adjacency newAdj = new AdjacencyBuilder().setIpAddress(destination).setKey
-                                            (new AdjacencyKey(destination)).setNextHopIpList(Arrays.asList(nextHopIp)).build();
-                                    adjacencyList.add(newAdj);
-                                    Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
-                                    VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface.getName())).
-                                            setName(vpnInterface.getName()).setVpnInstanceName(vpnInterface.getVpnInstanceName()).
-                                            addAugmentation(Adjacencies.class, aug).build();
-                                    VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfIdentifier, newVpnIntf);
-                                    LOG.debug("SubnetRoutePacketInHandler: Successfully stored subnetroute Adjacency into VpnInterface {}", newVpnIntf);
-                                }
-                            }
-                        }
-                    }
-                }
-            } catch (Exception ex) {
-                //Failed to decode packet
-                LOG.error("SubnetRoutePacketInHandler: Failed to handle subnetroute Table " + NwConstants.L3_INTERFACE_TABLE +
-                        " packets ", ex);
-            }
-        }*/
     }
 
     private static BigInteger getTargetDpnForPacketOut(DataBroker broker, long elanTag, int ipAddress) {
index 0efecd35e5a6260ac1112c9187a1f89c0c3dd50d..717c11bb0d9a07a21f2801e8eae17abcf394e89a 100644 (file)
@@ -296,7 +296,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         return;
                     }
                     for (Adjacency adj : adjs) {
-                        if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
+                        if (adj.isPrimaryAdjacency()) {
                             primaryInterfaceIp = adj.getIpAddress();
                             break;
                         }
@@ -635,7 +635,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                         (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
                         .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
 
-                if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
+                if (nextHop.isPrimaryAdjacency()) {
                     LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
                     writeOperTxn.merge(
                             LogicalDatastoreType.OPERATIONAL,
@@ -1177,7 +1177,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                 LOG.trace("NextHops are " + nextHops);
                 for (Adjacency nextHop : nextHops) {
                     List<String> nhList = new ArrayList<String>();
-                    if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
+                    if (nextHop.isPrimaryAdjacency()) {
                         // This is either an extra-route (or) a learned IP via subnet-route
                         String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
                         if (nextHopIp == null || nextHopIp.isEmpty()) {
@@ -1464,6 +1464,7 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             VpnInterface currVpnIntf = optVpnInterface.get();
             String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
             String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
+
             rd = (rd != null) ? rd : currVpnIntf.getVpnInstanceName();
             InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
             Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath);
@@ -1489,9 +1490,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
             VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
 
             VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
-            for (String nh : adj.getNextHopIpList()) {
-                addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
-                        currVpnIntf.getName());
+            if (adj.getNextHopIpList() != null) {
+                for (String nh : adj.getNextHopIpList()) {
+                    addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
+                            currVpnIntf.getName());
+                }
             }
         }
     }
@@ -1523,10 +1526,11 @@ public class VpnInterfaceManager extends AsyncDataTreeChangeListenerBase<VpnInte
                                     aug, dpnId, currVpnIntf.isScheduledForRemove());
 
                             VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
-
-                            for (String nh : adj.getNextHopIpList()) {
-                                delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
-                                        currVpnIntf.getName());
+                            if (adj.getNextHopIpList() != null) {
+                                for (String nh : adj.getNextHopIpList()) {
+                                    delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
+                                            currVpnIntf.getName());
+                                }
                             }
                             break;
                         }