Bug 5617: ExternalMapper refactoring 47/36047/15
authorMatej Perina <matej.perina@pantheon.sk>
Fri, 1 Apr 2016 13:53:09 +0000 (15:53 +0200)
committerMatej Perina <matej.perina@pantheon.sk>
Fri, 1 Apr 2016 13:53:09 +0000 (15:53 +0200)
Change-Id: I11869b14877599b6314c7bc5f93d8223a10d248d
Signed-off-by: Matej Perina <matej.perina@pantheon.sk>
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/external/ExternalMapper.java
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/mapper/external/ExternalMapperTest.java [moved from renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/ExternalMapperTest.java with 69% similarity]

index c31659350b3e27f33faec051d7b078a101e3862e..c07738f009673af41eff28143c6d9d19a80c0fb6 100755 (executable)
@@ -18,6 +18,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
 import org.opendaylight.groupbasedpolicy.dto.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
@@ -26,6 +28,7 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowTable;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.RegMatch;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.EndpointFwdCtxOrdinals;
 import org.opendaylight.yang.gen.v1.urn.cisco.params.xml.ns.yang.sfc.sff.ovs.rev140701.Node;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
@@ -38,7 +41,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.flow.M
 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.OfOverlayContext;
 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;
@@ -46,8 +48,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg5;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
-import org.apache.commons.net.util.SubnetUtils;
-import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -106,12 +106,16 @@ public class ExternalMapper extends FlowTable {
     @Override
     public void sync(Endpoint endpoint, OfWriter ofWriter) throws Exception {
 
-        // TODO: only temporary workaround, use src & dst endpoint in implementation
         NodeId nodeId = ctx.getEndpointManager().getEndpointNodeId(endpoint);
-
         // Default drop all
         ofWriter.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null, TABLE_ID));
 
+        /*
+         * Default Egress flow. Other methods may write to this table to augment egress
+         * functionality, such as bypassing/utilising the NAT table, or ServiceFunctionChaining
+         */
+        ofWriter.writeFlow(nodeId, TABLE_ID, defaultFlow());
+
         /*
          * When source address was translated to NAT address, it has to be figured out
          * whether or not the traffic should be tagged since external interfaces are
@@ -127,17 +131,17 @@ public class ExternalMapper extends FlowTable {
          * This is why subnet of NAT IP is resolved here.
          */
         Collection<EndpointL3> natL3Endpoints = ctx.getEndpointManager().getL3EndpointsWithNat();
-        if (natL3Endpoints != null) {
-            for (EndpointL3 natL3Ep : natL3Endpoints) {
-                IpAddress natIpAddress = Preconditions.checkNotNull(natL3Ep.getAugmentation(NatAddress.class),
-                        "NAT address augmentation is missing for NAT endpoint: [{}].", natL3Ep.getKey())
-                    .getNatAddress();
+        for (EndpointL3 natL3Ep : natL3Endpoints) {
+            if (endpoint.getL2Context().equals(natL3Ep.getL2Context())
+                    && endpoint.getMacAddress().equals(natL3Ep.getMacAddress())) {
+                IpAddress natIpAddress = natL3Ep.getAugmentation(NatAddress.class).getNatAddress();
                 Subnet natIpSubnet = resolveSubnetForIpv4Address(ctx.getTenant(natL3Ep.getTenant()),
                         Preconditions.checkNotNull(natIpAddress.getIpv4Address(),
-                                "Endpoint {} does not have IPv4 address in NatAddress augmentation.", natL3Ep.getKey()));
+                                "Endpoint {} does not have IPv4 address in NatAddress augmentation.",
+                                natL3Ep.getKey()));
                 if (natIpSubnet != null && natIpSubnet.getParent() != null) {
-                    L2FloodDomain natEpl2Fd = ctx.getTenant(natL3Ep.getTenant()).resolveL2FloodDomain(
-                            natIpSubnet.getParent());
+                    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,
@@ -154,24 +158,20 @@ public class ExternalMapper extends FlowTable {
          * for applying VLAN tag is generated. The flow matches against REG5 holding
          * the L2FloodDomain and REG7 holding value of an external interface.
          */
-        for (Endpoint ep : ctx.getEndpointManager().getEndpointsForNode(nodeId)) {
-            L2FloodDomain l2Fd = ctx.getTenant(ep.getTenant()).resolveL2FloodDomain(ep.getNetworkContainment());
-            Segmentation segmentation = l2Fd.getAugmentation(Segmentation.class);
-            if (segmentation == null) {
-                continue;
-            }
-            Integer vlanId = segmentation.getSegmentationId();
-            for (Flow flow : buildPushVlanFlow(nodeId, OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, ep).getFdId(),
-                    vlanId, 220)) {
-                ofWriter.writeFlow(nodeId, TABLE_ID, flow);
-            }
+        L2FloodDomain l2Fd = ctx.getTenant(endpoint.getTenant()).resolveL2FloodDomain(endpoint.getNetworkContainment());
+        if (l2Fd == null) {
+            return;
+        }
+        Segmentation segmentation = l2Fd.getAugmentation(Segmentation.class);
+        EndpointFwdCtxOrdinals endpointOrdinals = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, endpoint);
+        if (segmentation == null || endpointOrdinals == null) {
+            return;
+        }
+        Integer vlanId = segmentation.getSegmentationId();
+        for (Flow flow : buildPushVlanFlow(nodeId, endpointOrdinals.getFdId(),
+                vlanId, 220)) {
+            ofWriter.writeFlow(nodeId, TABLE_ID, flow);
         }
-
-        /*
-         *  Default Egress flow. Other methods may write to this table to augment egress
-         *  functionality, such as bypassing/utilising the NAT table, or ServiceFunctionChaining
-         */
-        ofWriter.writeFlow(nodeId, TABLE_ID, defaultFlow());
     }
 
     /**
@@ -6,7 +6,7 @@
  * and is available at http://www.eclipse.org/legal/epl-v10.html
  */
 
-package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
+package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.external;
 
 import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.mock;
@@ -15,12 +15,15 @@ import static org.mockito.Mockito.verify;
 
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockOfContext;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.MockPolicyManager;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfWriter;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager;
-import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.external.ExternalMapper;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.endpoint.MockEndpointManager;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.mapper.MapperUtilsTest;
+import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.MockSwitchManager;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
@@ -35,22 +38,28 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-
-import com.google.common.collect.ImmutableSet;
 import org.powermock.api.mockito.PowerMockito;
 import org.powermock.core.classloader.annotations.PrepareForTest;
 import org.powermock.modules.junit4.PowerMockRunner;
 
+import com.google.common.collect.ImmutableSet;
+
 @RunWith(PowerMockRunner.class)
 @PrepareForTest({PolicyManager.class})
-public class ExternalMapperTest extends FlowTableTest {
+public class ExternalMapperTest extends MapperUtilsTest {
 
     private ExternalMapper mapper;
 
     private short tableId;
     private NodeId nodeId;
     private OfWriter ofWriter;
+    private MockEndpointManager endpointManagerMock;
+    private MockPolicyManager policyManagerMock;
+    private MockSwitchManager switchManagerMock;
+    private MockOfContext ctxMock;
 
+    private NodeConnectorId nodeConnectorId = new NodeConnectorId("openflow:1:1");
+    private MacAddress mac = new MacAddress("00:00:00:00:00:03");
     private NatAddress natAddr = new NatAddressBuilder()
         .setNatAddress(new IpAddress(new Ipv4Address("192.168.111.52")))
         .build();
@@ -58,13 +67,15 @@ public class ExternalMapperTest extends FlowTableTest {
     private EndpointL3 natL3Ep = new EndpointL3Builder()
         .setTenant(tid)
         .setL3Context(l3c)
+        .setMacAddress(mac)
+        .setL2Context(bd)
         .setIpAddress(new IpAddress(new Ipv4Address("10.0.0.3")))
         .addAugmentation(NatAddress.class, natAddr)
         .build();
 
     private Endpoint l2Ep = new EndpointBuilder()
         .setTenant(tid)
-        .setMacAddress(new MacAddress("00:00:00:00:00:03"))
+        .setMacAddress(mac)
         .setL2Context(bd)
         .setNetworkContainment(sub)
         .setEndpointGroup(eg)
@@ -74,11 +85,18 @@ public class ExternalMapperTest extends FlowTableTest {
     public void initialisation() {
         PowerMockito.stub(PowerMockito.method(PolicyManager.class, "setSfcTableOffset")).toReturn(true);
 
-        initCtx();
+        endpointManagerMock = new MockEndpointManager();
+        policyManagerMock = new MockPolicyManager(endpointManagerMock);
+        switchManagerMock = new MockSwitchManager();
+        ctxMock = new MockOfContext(null,
+                policyManagerMock,
+                switchManagerMock,
+                endpointManagerMock,
+                             null);
         tableId = 6;
         nodeId = mock(NodeId.class);
         ofWriter = mock(OfWriter.class);
-        mapper = new ExternalMapper(ctx, tableId);
+        mapper = new ExternalMapper(ctxMock, tableId);
     }
 
     @Test
@@ -86,27 +104,26 @@ public class ExternalMapperTest extends FlowTableTest {
         Assert.assertEquals(tableId, mapper.getTableId());
     }
 
-    @Ignore
     @Test
-    public void syncTest() throws Exception {
-        ctx.addTenant(baseTenant().build());
-        endpointManager.addL3Endpoint(natL3Ep);
+    public void testSync() throws Exception {
+        ctxMock.addTenant(baseTenant().build());
+        endpointManagerMock.addL3Endpoint(natL3Ep);
         l2Ep = new EndpointBuilder(l2Ep)
             .addAugmentation(OfOverlayContext.class,new OfOverlayContextBuilder()
                 .setNodeId(nodeId)
                 .build())
             .build();
-        endpointManager.addEndpoint(l2Ep);
-        switchManager.addSwitch(nodeId,null,ImmutableSet.of(new NodeConnectorId("openflow:1:1")), null);
-        //mapper.sync(nodeId, ofWriter);
+        endpointManagerMock.addEndpoint(l2Ep);
+        switchManagerMock.addSwitch(nodeId,null,ImmutableSet.of(nodeConnectorId), null);
+        mapper.sync(l2Ep, ofWriter);
         verify(ofWriter, times(4)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
     }
 
-    @Ignore
     @Test
-    public void syncTestNoExternalPorts() throws Exception {
+    public void testSync_NoExternalPorts() throws Exception {
         // we still need ExternalMapper flows (default output and default drop) to be generated
-        //mapper.sync(nodeId, ofWriter);
+        ctxMock.addTenant(baseTenant().build());
+        mapper.sync(l2Ep, ofWriter);
         verify(ofWriter, times(2)).writeFlow(any(NodeId.class), any(Short.class), any(Flow.class));
     }
 }