Bug 5214 - ARP fix for external VLAN traffic 81/33781/7
authorTomas Cechvala <tcechval@cisco.com>
Thu, 21 Jan 2016 10:27:45 +0000 (11:27 +0100)
committerMartin Sunal <msunal@cisco.com>
Thu, 11 Feb 2016 22:05:44 +0000 (23:05 +0100)
External endpoints can receive tagged ARP response.

Change-Id: I0cd1b5d9a47aee8ded8d9a0c3f93598a159bf814
Signed-off-by: Tomas Cechvala <tcechval@cisco.com>
Signed-off-by: Martin Sunal <msunal@cisco.com>
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/FlowUtils.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/IngressNatMapper.java

index b8ea58f5da397478469b5baee0fcd81dae3f6920..40265483e1a097fac64ddd01eada1a23a0088693 100755 (executable)
@@ -93,12 +93,17 @@ public class ExternalMapper extends FlowTable {
                 IpAddress natIpAddress = Preconditions.checkNotNull(natL3Ep.getAugmentation(NatAddress.class),
                         "NAT address augmentation is missing for NAT endpoint: [{}].", natL3Ep.getKey())
                     .getNatAddress();
-                L2FloodDomain natEpl2Fd = resolveL2FloodDomainForIpv4Address(ctx.getTenant(natL3Ep.getTenant()),
+                Subnet natIpSubnet = resolveSubnetForIpv4Address(ctx.getTenant(natL3Ep.getTenant()),
                         Preconditions.checkNotNull(natIpAddress.getIpv4Address(),
                                 "Endpoint {} does not have IPv4 address in NatAddress augmentation.", natL3Ep.getKey()));
-                if (natEpl2Fd != null && natEpl2Fd.getAugmentation(Segmentation.class) != null) {
-                    Integer vlanId = natEpl2Fd.getAugmentation(Segmentation.class).getSegmentationId();
-                    ofWriter.writeFlow(nodeId, TABLE_ID, buildPushVlanFlow(natIpAddress.getIpv4Address(), vlanId, 222));
+                if (natIpSubnet != null && natIpSubnet.getParent() != null) {
+                    L2FloodDomain natEpl2Fd = ctx.getTenant(natL3Ep.getTenant()).resolveL2FloodDomain(
+                            natIpSubnet.getParent());
+                    if (natEpl2Fd.getAugmentation(Segmentation.class) != null) {
+                        Integer vlanId = natEpl2Fd.getAugmentation(Segmentation.class).getSegmentationId();
+                        ofWriter.writeFlow(nodeId, TABLE_ID,
+                                buildPushVlanFlow(natIpAddress.getIpv4Address(), vlanId, 222));
+                    }
                 }
             }
         }
@@ -130,31 +135,6 @@ public class ExternalMapper extends FlowTable {
         ofWriter.writeFlow(nodeId, TABLE_ID, defaultFlow());
     }
 
-    static L2FloodDomain resolveL2FloodDomainForIpv4Address(IndexedTenant t, Ipv4Address ipv4Addr) {
-        Preconditions.checkNotNull(ipv4Addr);
-        if (t == null || t.getTenant() == null || t.getTenant().getForwardingContext() == null) {
-            return null;
-        }
-        List<Subnet> subnets = t.getTenant().getForwardingContext().getSubnet();
-        if (subnets != null) {
-            for (Subnet subnet : subnets) {
-                if (belongsToSubnet(ipv4Addr, subnet.getIpPrefix().getIpv4Prefix())) {
-                    return t.resolveL2FloodDomain(subnet.getParent());
-                }
-            }
-        }
-        LOG.warn(
-                "No subnet for IPv4 address {} found in tenant {}!",
-                ipv4Addr.getValue(), t.getTenant().getId());
-        return null;
-    }
-
-    static boolean belongsToSubnet(Ipv4Address ipv4Address, Ipv4Prefix subnetPrefix) {
-        SubnetUtils su = new SubnetUtils(subnetPrefix.getValue());
-        SubnetInfo si = su.getInfo();
-        return si.isInRange(ipv4Address.getValue());
-    }
-
     /**
      * Generates a {@link Flow} for tagging VLAN traffic based on given arguments.
      *
@@ -183,6 +163,28 @@ public class ExternalMapper extends FlowTable {
             .build();
     }
 
+    public static Subnet resolveSubnetForIpv4Address(IndexedTenant t, Ipv4Address ipv4Addr) {
+        Preconditions.checkNotNull(ipv4Addr);
+        if (t == null || t.getTenant() == null || t.getTenant().getForwardingContext() == null) {
+            return null;
+        }
+        List<Subnet> subnets = t.getTenant().getForwardingContext().getSubnet();
+        if (subnets != null) {
+            for (Subnet subnet : subnets) {
+                if (belongsToSubnet(ipv4Addr, subnet.getIpPrefix().getIpv4Prefix())) {
+                    return subnet;
+                }
+            }
+        }
+        return null;
+    }
+
+    private static boolean belongsToSubnet(Ipv4Address ipv4Address, Ipv4Prefix subnetPrefix) {
+        SubnetUtils su = new SubnetUtils(subnetPrefix.getValue());
+        SubnetInfo si = su.getInfo();
+        return si.isInRange(ipv4Address.getValue());
+    }
+
     /**
      * Generates a {@link Flow} for tagging VLAN traffic based on given arguments.
      *
index 1aa784659fe26461151c11322328fb7d476724f9..6061c321b94f97e4b3de8e574bd8ba6c0e10540f 100755 (executable)
@@ -413,6 +413,16 @@ public final class FlowUtils {
         return actions;
     }
 
+    public static Action pushVlanAction() {
+        return new PushVlanActionCaseBuilder().setPushVlanAction(
+                new PushVlanActionBuilder().setEthernetType(VLAN).build()).build();
+    }
+
+    public static Action setVlanId(int vlanId) {
+        return new SetVlanIdActionCaseBuilder().setSetVlanIdAction(
+                new SetVlanIdActionBuilder().setVlanId(new VlanId(vlanId)).build()).build();
+    }
+
     public static org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction popVlanInstruction(
             int order) {
         List<ActionBuilder> actionBuilders = new ArrayList<>();
@@ -424,6 +434,10 @@ public final class FlowUtils {
             .build();
     }
 
+    public static Action popVlanAction() {
+        return new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build();
+    }
+
     public static Action setIpv4DstAction(Ipv4Address ipAddress) {
         Ipv4Builder ipDest = new Ipv4Builder();
         Ipv4Prefix prefixdst = new Ipv4Prefix(new Ipv4Prefix(ipAddress.getValue() + "/32"));
@@ -731,20 +745,6 @@ public final class FlowUtils {
         return emb.build();
     }
 
-    private static Action pushVlanAction() {
-        return new PushVlanActionCaseBuilder()
-            .setPushVlanAction(new PushVlanActionBuilder().setEthernetType(VLAN).build()).build();
-    }
-
-    private static Action popVlanAction() {
-        return new PopVlanActionCaseBuilder().setPopVlanAction(new PopVlanActionBuilder().build()).build();
-    }
-
-    private static Action setVlanId(int vlanId) {
-        return new SetVlanIdActionCaseBuilder()
-            .setSetVlanIdAction(new SetVlanIdActionBuilder().setVlanId(new VlanId(vlanId)).build()).build();
-    }
-
     private static List<ExtensionList> getExistingGeneralAugMatchNodesNodeTableFlow(MatchBuilder match) {
         ArrayList<ExtensionList> extensions = new ArrayList<>();
         if (match.getAugmentation(GeneralAugMatchNodesNodeTableFlow.class) != null) {
index f92198e074f22806778954a434a514d41baff2d0..5f2c11d45fba8cacb76dd424bfe09a39f7bfe46f 100755 (executable)
@@ -30,6 +30,7 @@ import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtil
 import java.math.BigInteger;
 import java.util.Collection;
 
+import org.apache.commons.lang3.ArrayUtils;
 import org.opendaylight.groupbasedpolicy.dto.EpKey;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
@@ -42,11 +43,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.acti
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.MatchBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.Endpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.Segmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
@@ -130,7 +135,7 @@ public class IngressNatMapper extends FlowTable {
         if (flow != null) {
             ofWriter.writeFlow(nodeId, TABLE_ID, flow);
         }
-        flow = createOutsideArpFlow(natAugL3Endpoint.getNatAddress(), l3Ep.getMacAddress(), nodeId);
+        flow = createOutsideArpFlow(l3Ep.getTenant(), natAugL3Endpoint.getNatAddress(), l3Ep.getMacAddress(), nodeId);
         if (flow != null) {
             ofWriter.writeFlow(nodeId, TABLE_ID, flow);
         }
@@ -191,25 +196,42 @@ public class IngressNatMapper extends FlowTable {
         return flowb.build();
     }
 
-    private Flow createOutsideArpFlow(IpAddress outsideDestAddress, MacAddress toMac, NodeId nodeId) {
-
+    private Flow createOutsideArpFlow(TenantId tenantId, IpAddress outsideDestAddress, MacAddress toMac, NodeId nodeId) {
         String ikey = outsideDestAddress.getIpv4Address().getValue();
         BigInteger intMac = new BigInteger(1, bytesFromHexString(toMac.getValue()));
-
-        FlowId flowId = new FlowId(new StringBuffer().append("outside-ip-arp|").append(ikey).toString());
         MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, ARP)).setLayer3Match(
                 new ArpMatchBuilder().setArpOp(Integer.valueOf(1))
                     .setArpTargetTransportAddress(new Ipv4Prefix(ikey + "/32"))
                     .build());
-
-        FlowBuilder flowb = base().setPriority(150)
-            .setId(flowId)
-            .setMatch(mb.build())
-            .setInstructions(
-                    instructions(applyActionIns(nxMoveEthSrcToEthDstAction(), setDlSrcAction(toMac),
-                            nxLoadArpOpAction(BigInteger.valueOf(2L)), nxMoveArpShaToArpThaAction(),
-                            nxLoadArpShaAction(intMac), nxMoveArpSpaToArpTpaAction(), nxLoadArpSpaAction(ikey),
-                            outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT")))));
+        Action[] outsideArpActions = {
+                nxMoveEthSrcToEthDstAction(),
+                setDlSrcAction(toMac),
+                nxLoadArpOpAction(BigInteger.valueOf(2L)),
+                nxMoveArpShaToArpThaAction(),
+                nxLoadArpShaAction(intMac),
+                nxMoveArpSpaToArpTpaAction(),
+                nxLoadArpSpaAction(ikey),
+                outputAction(new NodeConnectorId(nodeId.getValue() + ":INPORT"))
+        };
+        Subnet extSubnet = ExternalMapper.resolveSubnetForIpv4Address(ctx.getTenant(tenantId),
+                outsideDestAddress.getIpv4Address());
+        L2FloodDomain l2Fd = null;
+        if (extSubnet != null && extSubnet.getParent() != null) {
+            l2Fd = ctx.getTenant(tenantId).resolveL2FloodDomain(extSubnet.getParent());
+        }
+        FlowBuilder flowb = base().setPriority(150);
+        if (l2Fd != null && l2Fd.getAugmentation(Segmentation.class) != null) {
+            Integer vlanId = l2Fd.getAugmentation(Segmentation.class).getSegmentationId();
+            mb.setVlanMatch(FlowUtils.vlanMatch(0, false));
+            Action[] pushVlanpActions = {FlowUtils.pushVlanAction(), FlowUtils.setVlanId(vlanId)};
+            flowb.setInstructions(instructions(FlowUtils.applyActionIns(ArrayUtils.addAll(
+                    pushVlanpActions,
+                    outsideArpActions))));
+        } else {
+            flowb.setInstructions(instructions(FlowUtils.applyActionIns(outsideArpActions)));
+        }
+        flowb.setId(FlowIdUtils.newFlowId(TABLE_ID, "outside-ip-arp", mb.build()));
+        flowb.setMatch(mb.build());
         return flowb.build();
     }