FIP PNF access from another node 47/76847/5
authorJosh <jhershbe@redhat.com>
Thu, 11 Oct 2018 08:07:36 +0000 (11:07 +0300)
committerSam Hague <shague@redhat.com>
Tue, 16 Oct 2018 12:53:35 +0000 (12:53 +0000)
A recent change [0] adds support for nodes that do
not have provider mappings. This patch fixes an issue
where if the traffic headed for the external network
is FIP'ed the controller can not send an ARP for the
destination address (and throws an excpetion) because
the code that looks for the router assumes the src
address is identical to the router's external IP.
See the comment in the code.

[0] https://git.opendaylight.org/gerrit/#/c/75570/

Change-Id: I02765b6309ab0ee55700394f5474ce8eb545b71d
Signed-off-by: Josh <jhershbe@redhat.com>
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/SubnetRoutePacketInHandler.java
vpnmanager/impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java

index 0047c96283dfa81e29b8c0d192a0dc5b81b69433..36d899f64bac28d004be0d33791da3f52f681d84 100644 (file)
@@ -333,6 +333,7 @@ public class SubnetRoutePacketInHandler implements PacketProcessingListener {
         String routerId = vpnUtil.getAssociatedExternalRouter(srcIpStr);
         if (null == routerId) {
             LOG.debug("This ip is not associated with any external router: {}", srcIpStr);
+            return;
         }
         handlePacketToExternalNetwork(new Uuid(vpnIdVpnInstanceName), routerId, dstIp, dstIpStr, elanTag);
     }
index a8f4cd6fc78982ef57e3cbb7503820771e3fc5f6..93f3cd11ced587b1f5c4e95b065ffc6b1c8aade9 100644 (file)
@@ -93,6 +93,7 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.vpn._interface.VpnInstanceNames;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
@@ -1103,17 +1104,50 @@ public final class VpnUtil {
         InstanceIdentifier<ExtRouters> extRouterInstanceIndentifier =
                 InstanceIdentifier.builder(ExtRouters.class).build();
         Optional<ExtRouters> extRouterData = read(LogicalDatastoreType.CONFIGURATION, extRouterInstanceIndentifier);
-        if (extRouterData.isPresent()) {
-            for (Routers routerData : extRouterData.get().getRouters()) {
-                List<ExternalIps> externalIps = routerData.getExternalIps();
-                for (ExternalIps externalIp : externalIps) {
-                    if (externalIp.getIpAddress().equals(extIp)) {
-                        return routerData.getRouterName();
-                    }
+        if (!extRouterData.isPresent()) {
+            return null;
+        }
+
+        // We need to find the router associated with the src ip of this packet.
+        // This case is either SNAT, in which case the src ip is the same as the
+        // router's external ip, or FIP in which case the src ip is in the router's
+        // external leg's subnet. We first check the SNAT case because it is much
+        // cheaper to do so because it does not require (potentially, there is a
+        // cache) an datastore read of the neutron subnet for each external IP.
+
+        String routerName = null;
+
+        for (Routers routerData : extRouterData.get().getRouters()) {
+            List<ExternalIps> externalIps = routerData.getExternalIps();
+            for (ExternalIps externalIp : externalIps) {
+                if (externalIp.getIpAddress().equals(extIp)) {
+                    routerName = routerData.getRouterName();
+                    break;
                 }
             }
         }
-        return null;
+
+        if (routerName != null) {
+            return routerName;
+        }
+
+        for (Routers routerData : extRouterData.get().getRouters()) {
+            List<ExternalIps> externalIps = routerData.getExternalIps();
+            for (ExternalIps externalIp : externalIps) {
+                Subnet neutronSubnet = neutronVpnService.getNeutronSubnet(externalIp.getSubnetId());
+                if (neutronSubnet == null) {
+                    LOG.warn("Failed to retrieve subnet {} referenced by router {}",
+                            externalIp.getSubnetId(), routerData);
+                    continue;
+                }
+                if (NWUtil.isIpAddressInRange(IpAddressBuilder.getDefaultInstance(extIp), neutronSubnet.getCidr())) {
+                    routerName = routerData.getRouterName();
+                    break;
+                }
+            }
+        }
+
+        return routerName;
     }
 
     static InstanceIdentifier<Routers> buildRouterIdentifier(String routerId) {