Bug3269 - Support for L3PrefixEndpoint and external endpoints in OfOverlay 19/21519/4
authorKeith Burns (alagalah) <alagalah@gmail.com>
Thu, 28 May 2015 02:51:59 +0000 (19:51 -0700)
committerKeith Burns (alagalah) <alagalah@gmail.com>
Mon, 1 Jun 2015 20:34:45 +0000 (13:34 -0700)
Change-Id: I1cc40a963eca9b2a3f2ac2f334f7443c9a90e3cc
Signed-off-by: Keith Burns (alagalah) <alagalah@gmail.com>
13 files changed:
groupbasedpolicy-ofoverlay-config/src/main/resources/initial/15-groupbasedpolicy-ofoverlay.xml
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAware.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/NeutronGbpMapperListener.java
neutron-ovsdb/src/main/java/org/opendaylight/groupbasedpolicy/neutron/ovsdb/util/NeutronOvsdbIidFactory.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/EndpointManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/OFOverlayRenderer.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/PolicyManager.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/DestinationMapper.java
renderers/ofoverlay/src/main/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/flow/PolicyEnforcer.java
renderers/ofoverlay/src/main/yang/ofoverlay-provider-impl.yang
renderers/ofoverlay/src/main/yang/ofoverlay.yang
renderers/ofoverlay/src/test/java/org/opendaylight/groupbasedpolicy/renderer/ofoverlay/MockPolicyManager.java

index d1817500b3879af810a7a89621a583317038f275..4876174711d2c27013fb43189da556e854b80d0e 100644 (file)
@@ -27,7 +27,7 @@
                       <name>binding-data-broker</name>
                     </data-broker>
                     <gbp-ofoverlay-table-offset>0</gbp-ofoverlay-table-offset>
-                    <external-router-mac>01:02:03:04:05:06</external-router-mac>
+                    <external-router-mac>88:f0:31:04:05:06</external-router-mac>
                 </module>
             </modules>
         </data>
index 04b5d49a2da8898ae74f8fe25beb0ff8ea618d11..d1197acff00155f5370c4d60c172061ca32865f6 100644 (file)
@@ -241,7 +241,7 @@ public class NeutronPortAware implements INeutronPortAware {
         List<EndpointGroupId> epgIds = new ArrayList<>();
         // each EP has to be in EPG ANY, except dhcp and router
         epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
-        epgIds.add(MappingUtils.EPG_ANY_ID);
+        epgIds.add(MappingUtils.EPG_ROUTER_ID);
         EndpointL3 epL3 = createL3Endpoint(tenantId, epL3Key, epgIds, networkContainment);
         InstanceIdentifier<EndpointL3> iid_l3 = IidFactory.endpointL3Iid(l3ContextId, ipAddress);
         rwTx.put(LogicalDatastoreType.OPERATIONAL, iid_l3, epL3, true);
@@ -712,7 +712,9 @@ public class NeutronPortAware implements INeutronPortAware {
 
         List<NeutronSecurityGroup> securityGroups = port.getSecurityGroups();
         if ((securityGroups == null || securityGroups.isEmpty())) {
-            if (!isDhcpPort(port)) {
+            if (isFloatingIpPort(port)) {
+                epgIds.add(MappingUtils.EPG_EXTERNAL_ID);
+            } else if (!isDhcpPort(port)) {
                 LOG.warn(
                         "Port {} does not contain any security group. The port should belong to 'default' security group at least.",
                         port.getPortUUID());
index 9b7946b118958b3b02e06fc02fdc1451fb977ddb..2dba955ec1a92259f452b237ed88486c7421383f 100644 (file)
@@ -415,23 +415,23 @@ public class NeutronRouterAware implements INeutronRouterAware {
 
     private static NeutronSecurityRule createRouterSecRule(String ruleUuid, TenantId tenantId, IpPrefix ipSubnet,
             EndpointGroupId consumerEpgId, boolean isEgress) {
-        NeutronSecurityRule dhcpSecRule = new NeutronSecurityRule();
-        dhcpSecRule.setSecurityRuleGroupID(MappingUtils.EPG_ROUTER_ID.getValue());
-        dhcpSecRule.setSecurityRuleTenantID(tenantId.getValue());
-        dhcpSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
+        NeutronSecurityRule routerSecRule = new NeutronSecurityRule();
+        routerSecRule.setSecurityRuleGroupID(MappingUtils.EPG_ROUTER_ID.getValue());
+        routerSecRule.setSecurityRuleTenantID(tenantId.getValue());
+        routerSecRule.setSecurityRuleRemoteIpPrefix(Utils.getStringIpPrefix(ipSubnet));
         if (isEgress) {
-            dhcpSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
-            dhcpSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
+            routerSecRule.setSecurityRuleUUID(NeutronUtils.EGRESS + "__" + ruleUuid);
+            routerSecRule.setSecurityRuleDirection(NeutronUtils.EGRESS);
         } else {
-            dhcpSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
-            dhcpSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
+            routerSecRule.setSecurityRuleUUID(NeutronUtils.INGRESS + "__" + ruleUuid);
+            routerSecRule.setSecurityRuleDirection(NeutronUtils.INGRESS);
         }
         if (ipSubnet.getIpv4Prefix() != null) {
-            dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
+            routerSecRule.setSecurityRuleEthertype(NeutronUtils.IPv4);
         } else {
-            dhcpSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
+            routerSecRule.setSecurityRuleEthertype(NeutronUtils.IPv6);
         }
-        return dhcpSecRule;
+        return routerSecRule;
     }
 
     @Override
index cb7b7d238619ede6c764cec13c17330bb7d020ea..36f4e0ca2e11c966c33d5ad8e520e54760d7dddc 100644 (file)
@@ -45,7 +45,7 @@ public class NeutronGbpMapperListener implements DataChangeListener, AutoCloseab
     public NeutronGbpMapperListener(DataBroker dataBroker) {
         this.dataBroker = checkNotNull(dataBroker);
         registration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
-                NeutronOvsdbIidFactory.neutronGbpExternalGatewaysIid(), this, DataChangeScope.SUBTREE);
+        NeutronOvsdbIidFactory.neutronGbpExternalGatewaysIid(), this, DataChangeScope.SUBTREE);
         LOG.trace("NeutronGbpMapperListener started");
     }
 
index 20a73b099b098017f0f453461c39d2f5128d03a3..995ebb1980229e02796308c743bd1adf9ba6755e 100644 (file)
@@ -33,4 +33,9 @@ public class NeutronOvsdbIidFactory {
                 .build();
     }
 
+    public static InstanceIdentifier<NeutronByGbpMappings> neutronGbpMappingsIid() {
+        return InstanceIdentifier.builder(Mappings.class)
+                .child(NeutronByGbpMappings.class)
+                .build();
+    }
 }
index 59ec983a0bac95447a67f037143dbc517dfd7122..1938fb238e288205d81320ac09177a87b02acc8e 100644 (file)
@@ -8,6 +8,9 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay;
 
+import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
+
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
@@ -24,6 +27,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataChangeEvent;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
@@ -33,25 +37,39 @@ import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
 import org.opendaylight.groupbasedpolicy.endpoint.EpRendererAugmentation;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
+import org.opendaylight.groupbasedpolicy.resolver.IndexedTenant;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.groupbasedpolicy.util.SetUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ConditionName;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L2BridgeDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterEndpointInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.RegisterL3PrefixEndpointInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3AddressKey;
 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.EndpointBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Builder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3Prefix;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoints.EndpointL3PrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.EndpointLocation.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig.LearningMode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayContextInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayL3ContextBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.Tenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L2BridgeDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
@@ -65,6 +83,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
 import com.google.common.collect.ImmutableList;
@@ -79,18 +98,16 @@ import com.google.common.collect.Sets;
  * In order to render the policy, we need to be able to efficiently enumerate
  * all endpoints on a particular switch and also all the switches containing
  * each particular endpoint group
-
  */
 public class EndpointManager implements AutoCloseable, DataChangeListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(EndpointManager.class);
     private final static InstanceIdentifier<Nodes> nodesIid = InstanceIdentifier.builder(Nodes.class).build();
-    private static final InstanceIdentifier<Endpoint> endpointsIid = InstanceIdentifier.builder(Endpoints.class)
-        .child(Endpoint.class)
-        .build();
+
     final ListenerRegistration<DataChangeListener> listenerReg;
 
     private final ConcurrentHashMap<EpKey, Endpoint> endpoints = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<EpKey, Endpoint> externalEndpointsWithoutLocation = new ConcurrentHashMap<>();
     private final ConcurrentHashMap<NodeId, ConcurrentMap<EgKey, Set<EpKey>>> endpointsByGroupByNode = new ConcurrentHashMap<>();
     private final ConcurrentHashMap<NodeId, Set<EpKey>> endpointsByNode = new ConcurrentHashMap<>();
 
@@ -110,8 +127,8 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         this.dataProvider = dataProvider;
         EndpointRpcRegistry.register(dataProvider, rpcRegistry, endpointRpcAug);
         if (dataProvider != null) {
-            listenerReg = dataProvider.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL, endpointsIid, this,
-                    DataChangeScope.ONE);
+            listenerReg = dataProvider.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
+                    IidFactory.endpointsIid(), this, DataChangeScope.SUBTREE);
         } else
             listenerReg = null;
 
@@ -202,9 +219,15 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         if (ebn == null)
             return Collections.emptyList();
         return ImmutableList.copyOf(Collections2.transform(ebn, indexTransform));
+    }
 
+    public synchronized Collection<Endpoint> getExternalEndpointsWithoutLoc() {
+        return ImmutableList.copyOf(externalEndpointsWithoutLocation.values());
     }
 
+    public synchronized Endpoint getExternalEndpointWithoutLoc(EpKey epKey) {
+        return externalEndpointsWithoutLocation.get(epKey);
+    }
     /**
      * Get the endpoint object for the given key
      *
@@ -237,14 +260,18 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
          * XXX: alagalah I wanted to avoid adding another Map. Due to not being able to
          * get to the granularity of the L3PrefixEndpoint List within the Endpoints container
          * in the datastore, we have to pull all the Endpoints. If this causes performance issues
-         * we may have to revisit a Map in updateEndpoint but note, this Endpoint doesn't have a location
+         * we may have to revisit a Map in updateEndpoint but note, this Endpoint doesn't have a
+         * location
          * and hence we would have to process it outside the null location check.
          */
 
         /*
-         * XXX: alagalah See how much nicer it would have been if we could have just called this L3PrefixEndpoint and
-         * refactored Endpoints to be L2Endpoint, L3Endpoint, L3PrefixEndpoint? Plurality reads sanely with
-         * that but not with this. Naming is important, and backwards compatibility sometimes isn't worth it.
+         * XXX: alagalah See how much nicer it would have been if we could have just called this
+         * L3PrefixEndpoint and
+         * refactored Endpoints to be L2Endpoint, L3Endpoint, L3PrefixEndpoint? Plurality reads
+         * sanely with
+         * that but not with this. Naming is important, and backwards compatibility sometimes isn't
+         * worth it.
          */
         if (dataProvider == null) {
             LOG.error("Null DataProvider in EndpointManager getEndpointsL3Prefix");
@@ -257,12 +284,13 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
             LOG.warn("No Endpoints present in datastore.");
             return null;
         }
-        if (endpoints.get().getEndpointL3Prefix()==null) {
+        if (endpoints.get().getEndpointL3Prefix() == null) {
             LOG.warn("No L3 Prefix Endpoints present in datastore.");
             return null;
         }
         return endpoints.get().getEndpointL3Prefix();
     }
+
     /**
      * Set the learning mode to the specified value
      *
@@ -287,6 +315,28 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         return ImmutableList.copyOf(Collections2.transform(ebg, indexTransform));
     }
 
+    public synchronized Collection<Endpoint> getExtEpsNoLocForGroup(final EgKey eg) {
+
+        return ImmutableSet.copyOf(Collections2.filter(externalEndpointsWithoutLocation.values(), new Predicate<Endpoint>() {
+
+            @Override
+            public boolean apply(Endpoint input) {
+                Set<EndpointGroupId> epgIds = new HashSet<>();
+                if (input.getEndpointGroup() != null) {
+                    epgIds.add(input.getEndpointGroup());
+                }
+                if (input.getEndpointGroups() != null) {
+                    epgIds.addAll(input.getEndpointGroups());
+                }
+                if (epgIds.isEmpty()) {
+                    LOG.error("No EPGs for {}. This is not a valid Endpoint.",input.getKey());
+                    return false;
+                }
+                return (epgIds.contains(eg.getEgId()));
+            }
+
+        }));
+    }
     /**
      * Get the effective list of conditions that apply to a particular endpoint.
      * This could include additional conditions over the condition labels
@@ -422,9 +472,9 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
             if (dao instanceof Endpoint) {
                 updateEndpoint(null, (Endpoint) dao);
             } else if (dao instanceof EndpointL3) {
-                updateEndpointL3(null,(EndpointL3)dao);
+                updateEndpointL3(null, (EndpointL3) dao);
             } else if (dao instanceof EndpointL3Prefix) {
-
+                continue;
             }
         }
         for (InstanceIdentifier<?> iid : change.getRemovedPaths()) {
@@ -432,10 +482,10 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
             if (old == null) {
                 continue;
             }
-            if(old instanceof Endpoint) {
+            if (old instanceof Endpoint) {
                 updateEndpoint((Endpoint) old, null);
             } else if (old instanceof EndpointL3) {
-                continue;
+                updateEndpointL3((EndpointL3) old, null);
             } else if (old instanceof EndpointL3Prefix) {
                 continue;
             }
@@ -443,13 +493,11 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         Map<InstanceIdentifier<?>, DataObject> dao = change.getUpdatedData();
         for (Entry<InstanceIdentifier<?>, DataObject> entry : dao.entrySet()) {
             if (entry.getValue() instanceof Endpoint) {
-                DataObject old = change.getOriginalData().get(entry.getKey());
-                Endpoint oldEp = null;
-                if (old != null && old instanceof Endpoint)
-                    oldEp = (Endpoint) old;
+                Endpoint oldEp = (Endpoint) change.getOriginalData().get(entry.getKey());
                 updateEndpoint(oldEp, (Endpoint) entry.getValue());
             } else if (entry.getValue() instanceof EndpointL3) {
-                continue;
+                EndpointL3 oldEp3 = (EndpointL3)change.getOriginalData().get(entry.getKey());
+                updateEndpointL3(oldEp3, (EndpointL3) entry.getValue());
             } else if (entry.getValue() instanceof EndpointL3Prefix) {
                 continue;
             }
@@ -486,14 +534,20 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         }
     };
 
-    private boolean validEp(Endpoint endpoint) {
+    private boolean isValidEp(Endpoint endpoint) {
         return (endpoint != null && endpoint.getTenant() != null
                 && (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null)
                 && endpoint.getL2Context() != null && endpoint.getMacAddress() != null);
     }
 
+    private boolean isValidL3Ep(EndpointL3 endpoint) {
+        return (endpoint != null && endpoint.getTenant() != null
+                && (endpoint.getEndpointGroup() != null || endpoint.getEndpointGroups() != null)
+                && endpoint.getL3Context() != null && endpoint.getIpAddress() != null);
+    }
+
     private NodeId getLocation(Endpoint endpoint) {
-        if (!validEp(endpoint))
+        if (!isValidEp(endpoint))
             return null;
         OfOverlayContext context = endpoint.getAugmentation(OfOverlayContext.class);
         if (context != null)
@@ -503,13 +557,13 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
     }
 
     private EpKey getEpKey(Endpoint endpoint) {
-        if (!validEp(endpoint))
+        if (!isValidEp(endpoint))
             return null;
         return new EpKey(endpoint.getL2Context(), endpoint.getMacAddress());
     }
 
     public EgKey getEgKey(Endpoint endpoint) {
-        if (!validEp(endpoint))
+        if (!isValidEp(endpoint))
             return null;
         return new EgKey(endpoint.getTenant(), endpoint.getEndpointGroup());
     }
@@ -548,9 +602,155 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
     /**
      * Update the endpointL3 indexes. Set newEp to null to remove.
      */
-    protected synchronized void updateEndpointL3(EndpointL3 oldEp, EndpointL3 newEp) {
+    protected synchronized void updateEndpointL3(EndpointL3 oldL3Ep, EndpointL3 newL3Ep) {
+
+        // if (oldEp == null && newEp != null ) {
+        if (newL3Ep != null) {
+            // new L3Endpoint
+            LOG.trace("Processing L3Endpoint");
+            if (isValidL3Ep(newL3Ep)) {
+                if (newL3Ep.getMacAddress() == null
+                        && getLocationType(newL3Ep) != null
+                        && getLocationType(newL3Ep).equals(LocationType.External)) {
+                    if (newL3Ep.getNetworkContainment() != null) {
+                        EndpointL3 l3Ep = updateEndpointL3MacAddress(newL3Ep);
+                        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+                        Endpoint newL2Ep = addEndpointFromL3Endpoint(l3Ep, rwTx);
+                        l3Ep=updateL3EndpointL2Context(l3Ep, newL2Ep.getL2Context());
+                        if (l3Ep == null) {
+                            return;
+                        }
+                        rwTx.put(LogicalDatastoreType.OPERATIONAL,
+                                IidFactory.endpointL3Iid(l3Ep.getL3Context(), l3Ep.getIpAddress()), l3Ep, true);
+                        DataStoreHelper.submitToDs(rwTx);
+                        return;
+                    } else {
+                        LOG.error("Cannot generate MacAddress for L3Endpoint {}. NetworkContainment is null.", newL3Ep);
+                        return;
+                    }
+                }
+            } else {
+                LOG.error("{} is not a valid L3 Endpoint", newL3Ep);
+                return;
+            }
+            return;
+        }
 
+        if (oldL3Ep != null && newL3Ep == null) {
+            // deleted L3Endpoint
+            return;
+        }
+
+        if (oldL3Ep != null && newL3Ep != null) {
+            LOG.trace("Updating L3 Endpoint {}");
+            // updated Endpoint
+            return;
+        }
+        if (newL3Ep.getAugmentation(OfOverlayL3Context.class) == null) {
+            LOG.info("L3Endpoint updatbut no augmentation information");
+            return;
+        }
     }
+
+    private EndpointL3 updateL3EndpointL2Context(EndpointL3 l3Ep, L2BridgeDomainId l2BdId) {
+
+        if(l3Ep == null || l2BdId == null) {
+            LOG.warn("L3Endpoint {} or L2BridgeDomain {} was null in updateEndpointL3L2Context.",l3Ep,l2BdId);
+            return null;
+        }
+        return new EndpointL3Builder(l3Ep)
+            .addAugmentation(OfOverlayL3Context.class, l3Ep.getAugmentation(OfOverlayL3Context.class))
+            .setL2Context(l2BdId)
+            .build();
+
+    }
+
+    private LocationType getLocationType(EndpointL3 epL3) {
+        if (epL3 == null
+                || epL3.getAugmentation(OfOverlayL3Context.class) == null
+                || epL3.getAugmentation(OfOverlayL3Context.class).getLocationType() == null ) {
+            return null;
+        }
+        return epL3.getAugmentation(OfOverlayL3Context.class).getLocationType();
+    }
+
+    private Endpoint addEndpointFromL3Endpoint(EndpointL3 l3Ep, ReadWriteTransaction rwTx) {
+        // Make an indexed tenant and resolveL2Bridgedomain from L3EP containment if not L3
+        // (instanceof)
+        OfOverlayL3Context ofL3Ctx = l3Ep.getAugmentation(OfOverlayL3Context.class);
+        OfOverlayContext ofCtx = getOfOverlayContextFromL3Endpoint(ofL3Ctx);
+        if (l3Ep.getNetworkContainment() instanceof L3Context) {
+            LOG.error("Cannot generate Endpoint from EndpointL3, network containment is L3Context.");
+            rwTx.cancel();
+            return null;
+        }
+
+        IndexedTenant indexedTenant;
+        Optional<Tenant> tenant = readFromDs(LogicalDatastoreType.CONFIGURATION, IidFactory.tenantIid(l3Ep.getTenant()),
+                rwTx);
+        if (tenant.isPresent()) {
+            indexedTenant = new IndexedTenant(tenant.get());
+        } else {
+            LOG.error("Could not find tenant {} for EndpointL3 {}", l3Ep.getTenant(), l3Ep);
+            rwTx.cancel();
+            return null;
+        }
+        List<L3Address> l3Address = new ArrayList<>();
+        l3Address.add(new L3AddressBuilder()
+                            .setIpAddress(l3Ep.getIpAddress())
+                            .setL3Context(l3Ep.getL3Context())
+                            .setKey(new L3AddressKey(l3Ep.getIpAddress(),l3Ep.getL3Context()))
+                            .build());
+        L2BridgeDomain l2Bd = indexedTenant.resolveL2BridgeDomain(l3Ep.getNetworkContainment());
+        Endpoint ep = new EndpointBuilder().setKey(new EndpointKey(l2Bd.getId(), l3Ep.getMacAddress()))
+            .setMacAddress(l3Ep.getMacAddress())
+            .setL2Context(l2Bd.getId())
+            .setEndpointGroups(l3Ep.getEndpointGroups())
+            .setTenant(l3Ep.getTenant())
+            .setL3Address(l3Address)
+            .setCondition(l3Ep.getCondition())
+            .setNetworkContainment(l3Ep.getNetworkContainment())
+            .addAugmentation(OfOverlayContext.class, ofCtx)
+            .build();
+        rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.endpointIid(ep.getL2Context(), ep.getMacAddress()), ep);
+        return ep;
+    }
+
+    private OfOverlayContext getOfOverlayContextFromL3Endpoint(OfOverlayL3Context ofL3Ctx) {
+        OfOverlayContextBuilder ofBuilder = new OfOverlayContextBuilder();
+        if (ofL3Ctx.getInterfaceId() != null) {
+            ofBuilder.setInterfaceId(ofL3Ctx.getInterfaceId());
+        }
+        if (ofL3Ctx.getLocationType() != null) {
+            ofBuilder.setLocationType(ofL3Ctx.getLocationType());
+        }
+        if (ofL3Ctx.getNodeConnectorId() != null) {
+            ofBuilder.setNodeConnectorId(ofL3Ctx.getNodeConnectorId());
+        }
+        if (ofL3Ctx.getNodeId() != null) {
+            ofBuilder.setNodeId(ofL3Ctx.getNodeId());
+        }
+        if (ofL3Ctx.getPortName() != null) {
+            ofBuilder.setPortName(ofL3Ctx.getPortName());
+        }
+
+        return ofBuilder.build();
+    }
+
+    private EndpointL3 updateEndpointL3MacAddress(EndpointL3 endpointL3) {
+
+        EndpointL3Builder epL3Builder = new EndpointL3Builder(endpointL3).addAugmentation(OfOverlayL3Context.class,
+                endpointL3.getAugmentation(OfOverlayL3Context.class))
+            .setMacAddress(getMacAddress(endpointL3))
+            .setTimestamp(System.currentTimeMillis());
+
+        return epL3Builder.build();
+    }
+
+    private MacAddress getMacAddress(EndpointL3 endpointL3) {
+        return PolicyManager.getExternaMacAddress();
+    }
+
     /**
      * Update the endpoint indexes. Set newEp to null to remove.
      */
@@ -572,9 +772,22 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         boolean notifyOldEg = false;
         boolean notifyNewEg = false;
 
-        // When newLoc and oldLoc are null there is nothing to do
+        /*
+         *  When newLoc and oldLoc are null for Internal ports there is nothing to do
+         */
         if (newLoc == null && oldLoc == null) {
-            return;
+            if ((oldEp != null && isInternal(oldEp))
+                    || (newEp !=null && isInternal(newEp))) {
+                return;
+            } else {
+                // Maintain "external endpoints" map
+                if (newEp != null) {
+                    externalEndpointsWithoutLocation.put(newEpKey, newEp);
+                } else {
+                    externalEndpointsWithoutLocation.remove(oldEpKey);
+                }
+                return; // No more processing for Externals.
+            }
         }
 
         Set<EndpointGroupId> newEpgIds = new HashSet<EndpointGroupId>();
@@ -617,7 +830,7 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
         /*
          * New endpoint with location information
          */
-        if (oldEp == null && newEp != null && newLoc != null) {
+        if (oldEp == null && newEp != null && newLoc != null ) {
             // Update endpointsByNode
             if (endpointsByNode.get(newLoc) == null) {
                 // TODO: alagalah cleaner way with checking epsNode
@@ -803,6 +1016,18 @@ public class EndpointManager implements AutoCloseable, DataChangeListener {
             }
     }
 
+    private boolean isExternal(Endpoint ep) {
+        return !isInternal(ep);
+    }
+
+    public static boolean isInternal(Endpoint ep) {
+        Preconditions.checkNotNull(ep);
+        OfOverlayContext ofc = ep.getAugmentation(OfOverlayContext.class);
+        if (ofc == null) return true; // Default is internal
+        if (ofc.getLocationType() == null || ofc.getLocationType().equals(LocationType.Internal)) return true; // Default is internal
+        return false;
+    }
+
     // A wrapper class around node, nodeConnector info so we can pass a final
     // object inside OnSuccess anonymous inner class
     private static class NodeInfo {
index db005e46e51aacbfc14af976e3b295b15924c28d..d0d87ee45086f3fd4a8fd730607f835267e19b52 100644 (file)
@@ -19,8 +19,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.node.SwitchManager;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.ofoverlay.rev140528.OfOverlayConfig;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
index d4f00b25eefcff3085cca5fcd72cac1cb3e9e496..b45073205eef74237959368f54fb528dfcb96f89 100755 (executable)
@@ -45,7 +45,7 @@ import org.opendaylight.groupbasedpolicy.resolver.PolicyListener;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyScope;
 import org.opendaylight.groupbasedpolicy.util.SingletonTask;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
@@ -90,6 +90,7 @@ public class PolicyManager
     private final short TABLEID_EGRESS_NAT = (short) (tableOffset+5);
     private final short TABLEID_EXTERNAL_MAPPER = (short) (tableOffset+6);
 
+    private static MacAddress externaMacAddress;
 
     private final SwitchManager switchManager;
     private final PolicyResolver policyResolver;
@@ -118,13 +119,14 @@ public class PolicyManager
                          RpcProviderRegistry rpcRegistry,
                          ScheduledExecutorService executor,
                          short tableOffset,
-                         MacAddress exernalRouterMac) {
+                         MacAddress externalRouterMac) {
         super();
         this.switchManager = switchManager;
         this.executor = executor;
         this.policyResolver = policyResolver;
         this.dataBroker = dataBroker;
         this.tableOffset=tableOffset;
+        this.externaMacAddress=externalRouterMac;
 
 
         if (dataBroker != null) {
@@ -262,7 +264,9 @@ public class PolicyManager
         // No-op for now
     }
 
-
+    public static MacAddress getExternaMacAddress() {
+        return externaMacAddress;
+    }
 
     // **************
     // Implementation
index 0b132d3897498d4b4ff77450ba63551e9d841e24..ef433579405456f03799026bd76beb213633df58 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow;
 
+import static com.google.common.base.Preconditions.checkNotNull;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.ARP;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.IPv4;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.IPv6;
@@ -32,6 +33,7 @@ import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtil
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.outputAction;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlDstAction;
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.setDlSrcAction;
+import static org.opendaylight.groupbasedpolicy.util.DataStoreHelper.readFromDs;
 
 import java.math.BigInteger;
 import java.util.ArrayList;
@@ -46,9 +48,7 @@ import java.util.Objects;
 import java.util.Set;
 
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
-import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.groupbasedpolicy.endpoint.EpKey;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.OfContext;
 import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.PolicyManager.FlowMap;
@@ -57,6 +57,7 @@ import org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.OrdinalFactory.
 import org.opendaylight.groupbasedpolicy.resolver.EgKey;
 import org.opendaylight.groupbasedpolicy.resolver.PolicyInfo;
 import org.opendaylight.groupbasedpolicy.resolver.TenantUtils;
+import org.opendaylight.groupbasedpolicy.util.IidFactory;
 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.Ipv4Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Prefix;
@@ -76,6 +77,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.Endpoints;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.fields.L3Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.rev140421.endpoint.l3.prefix.fields.EndpointL3Gateways;
 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.endpoint.rev140421.endpoints.EndpointL3Key;
@@ -101,16 +103,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev14
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg6;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflowjava.nx.match.rev140421.NxmNxReg7;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.overlay.rev150105.TunnelTypeVxlan;
-import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Strings;
 import com.google.common.collect.HashMultimap;
 import com.google.common.collect.SetMultimap;
 import com.google.common.collect.Sets;
-import com.google.common.util.concurrent.CheckedFuture;
 
 /**
  * Manage the table that maps the destination address to the next hop for the
@@ -131,10 +132,11 @@ public class DestinationMapper extends FlowTable {
      */
     public static final MacAddress ROUTER_MAC = new MacAddress("88:f0:31:b5:12:b5");
     public static final MacAddress MULTICAST_MAC = new MacAddress("01:00:00:00:00:00");
+    public static final Integer BASE_L3_PRIORITY = 100;
 
     public DestinationMapper(OfContext ctx, short tableId) {
         super(ctx);
-        this.TABLE_ID=tableId;
+        this.TABLE_ID = tableId;
     }
 
     Map<TenantId, HashSet<Subnet>> subnetsByTenant = new HashMap<TenantId, HashSet<Subnet>>();
@@ -147,7 +149,7 @@ public class DestinationMapper extends FlowTable {
     @Override
     public void sync(NodeId nodeId, PolicyInfo policyInfo, FlowMap flowMap) throws Exception {
 
-        TenantId currentTenant=null;
+        TenantId currentTenant = null;
 
         flowMap.writeFlow(nodeId, TABLE_ID, dropFlow(Integer.valueOf(1), null));
 
@@ -217,6 +219,13 @@ public class DestinationMapper extends FlowTable {
         Collection<EndpointL3Prefix> prefixEps = ctx.getEndpointManager().getEndpointsL3PrefixForTenant(currentTenant);
         if (prefixEps != null) {
             LOG.trace("DestinationMapper - Processing L3PrefixEndpoints");
+            for (EndpointL3Prefix prefixEp : prefixEps) {
+                Flow prefixFlow = createL3PrefixFlow(prefixEp, policyInfo, nodeId);
+                if (prefixFlow != null) {
+                    flowMap.writeFlow(nodeId, TABLE_ID, prefixFlow);
+                    LOG.trace("Wrote L3Prefix flow");
+                }
+            }
         }
 
     }
@@ -224,14 +233,172 @@ public class DestinationMapper extends FlowTable {
     // set up next-hop destinations for all the endpoints in the endpoint
     // group on the node
 
+    private Flow createL3PrefixFlow(EndpointL3Prefix prefixEp, PolicyInfo policyInfo, NodeId nodeId) throws Exception {
+        /*
+         * Priority: 100+lengthprefix
+         * Match: prefix, l3c, "mac address of router" ?
+         * Action:
+         * - set Reg2, Reg3 for L3Ep by L2Ep ?
+         * - if external,
+         * - Reg7: use switch location external port else punt for now
+         * - if internal
+         * - Reg7: grab L2Ep from L3Ep and use its location info
+         * - goto_table: POLENF (will check there for external on EP)
+         */
+
+        ReadOnlyTransaction rTx = ctx.getDataBroker().newReadOnlyTransaction();
+        // TODO Bug #3440 Target: Be - should support for more than first gateway.
+        EndpointL3Gateways l3Gateway = prefixEp.getEndpointL3Gateways().get(0);
+        Optional<EndpointL3> optL3Ep = readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.endpointL3Iid(l3Gateway.getL3Context(), l3Gateway.getIpAddress()), rTx);
+        if (!optL3Ep.isPresent()) {
+            LOG.error("createL3PrefixFlow - L3Endpoint gateway {} for L3Prefix {} not found.", l3Gateway, prefixEp);
+            return null;
+        }
+        EndpointL3 l3Ep = optL3Ep.get();
+        Optional<Endpoint> optL2Ep = readFromDs(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.endpointIid(l3Ep.getL2Context(), l3Ep.getMacAddress()), rTx);
+        if (!optL2Ep.isPresent()) {
+            LOG.error("createL3PrefixFlow - L2Endpoint for L3Gateway {} not found.", l3Ep);
+            return null;
+        }
+        Endpoint l2Ep = optL2Ep.get();
+        EndpointFwdCtxOrdinals epFwdCtxOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx, policyInfo, l2Ep);
+
+        NetworkDomainId epNetworkContainment = getEPNetworkContainment(l2Ep);
+
+        MacAddress epDestMac = l2Ep.getMacAddress();
+        MacAddress destSubnetGatewayMac = l2Ep.getMacAddress();
+
+        ArrayList<Instruction> l3instructions = new ArrayList<>();
+        List<Action> applyActions = new ArrayList<>();
+        List<Action> l3ApplyActions = new ArrayList<>();
+
+        int order = 0;
+
+        Action setdEPG = nxLoadRegAction(NxmNxReg2.class, BigInteger.valueOf(epFwdCtxOrds.getEpgId()));
+        Action setdCG = nxLoadRegAction(NxmNxReg3.class, BigInteger.valueOf(epFwdCtxOrds.getCgId()));
+        Action setNextHop;
+        String nextHop=null;
+
+        OfOverlayContext ofc = l2Ep.getAugmentation(OfOverlayContext.class);
+        LocationType location;
+
+        if (ofc != null && ofc.getLocationType() != null) {
+            location = ofc.getLocationType();
+        } else if (ofc != null) {
+            // Augmentation, but using default location
+            location = LocationType.Internal;
+        } else {
+            LOG.info("createL3PrefixFlow - Endpoint {} had no augmentation.", l2Ep);
+            return null;
+        }
+
+        long portNum = -1;
+
+        if (location.equals(LocationType.Internal)) {
+            checkNotNull(ofc.getNodeConnectorId());
+            nextHop = ofc.getNodeConnectorId().getValue();
+            try {
+                portNum = getOfPortNum(ofc.getNodeConnectorId());
+            } catch (NumberFormatException ex) {
+                LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
+                return null;
+            }
+
+        } else {
+            // External
+            Set<NodeConnectorId> externalPorts = ctx.getSwitchManager().getExternalPorts(nodeId);
+            checkNotNull(externalPorts);
+            for (NodeConnectorId externalPort : externalPorts) {
+                // TODO Bug #3440 Target: Be - should support for more than first external port.
+                nextHop = externalPort.getValue();
+                try {
+                    portNum = getOfPortNum(externalPort);
+                } catch (NumberFormatException ex) {
+                    LOG.warn("Could not parse port number {}", ofc.getNodeConnectorId(), ex);
+                    return null;
+                }
+                continue;
+            }
+        }
+
+        if (Strings.isNullOrEmpty(nextHop)
+                || portNum == -1) {
+            LOG.error("createL3Prefix - Cannot find nodeConnectorId for {} for Prefix: ", l2Ep, prefixEp);
+            return null;
+        }
+        setNextHop = nxLoadRegAction(NxmNxReg7.class, BigInteger.valueOf(portNum));
+
+        Action setDlDst = setDlDstAction(epDestMac);
+        l3ApplyActions.add(setDlDst);
+
+        Action decTtl = decNwTtlAction();
+        l3ApplyActions.add(decTtl);
+
+        order += 1;
+        applyActions.add(setdEPG);
+        applyActions.add(setdCG);
+        applyActions.add(setNextHop);
+
+        applyActions.addAll(l3ApplyActions);
+        Instruction applyActionsIns = new InstructionBuilder().setOrder(order++)
+            .setInstruction(applyActionIns(applyActions.toArray(new Action[applyActions.size()])))
+            .build();
+
+        l3instructions.add(applyActionsIns);
+        Instruction gotoTable = new InstructionBuilder().setOrder(order++)
+            .setInstruction(gotoTableIns(ctx.getPolicyManager().getTABLEID_POLICY_ENFORCER()))
+            .build();
+        l3instructions.add(gotoTable);
+
+        Layer3Match m = null;
+        Long etherType = null;
+        String ikey = null;
+        Integer prefixLength=0;
+        if (prefixEp.getIpPrefix().getIpv4Prefix() != null) {
+            ikey = prefixEp.getIpPrefix().getIpv4Prefix().getValue();
+            etherType = IPv4;
+            prefixLength=Integer.valueOf(prefixEp.getIpPrefix().getIpv4Prefix().getValue().split("/")[1]);
+            m = new Ipv4MatchBuilder().setIpv4Destination(new Ipv4Prefix(ikey)).build();
+        } else if (prefixEp.getIpPrefix().getIpv6Prefix() != null) {
+            ikey = prefixEp.getIpPrefix().getIpv6Prefix().getValue();
+            etherType = IPv6;
+            /*
+             *  This will result in flows with priority between 100-228, but since its matching on IPv6 prefix as well
+             *  this shouldn't pose and issue, as the priority is more important within the address space of the matcher,
+             *  even though technically flows are processed in priority order.
+             */
+
+            prefixLength=Integer.valueOf(prefixEp.getIpPrefix().getIpv6Prefix().getValue().split("/")[1]);
+            m = new Ipv6MatchBuilder().setIpv6Destination(new Ipv6Prefix(ikey)).build();
+        } else {
+            LOG.error("Endpoint has IPAddress that is not recognised as either IPv4 or IPv6.", prefixEp);
+            return null;
+        }
+
+        FlowId flowid = new FlowId(new StringBuilder().append(Integer.toString(epFwdCtxOrds.getL3Id()))
+            .append("|l3prefix|")
+            .append(ikey)
+            .append("|")
+            .append(destSubnetGatewayMac)
+            .append("|")
+            .append(nextHop)
+            .toString());
+        MatchBuilder mb = new MatchBuilder().setEthernetMatch(ethernetMatch(null, null, etherType));
+//        MatchBuilder mb = new MatchBuilder();//.setLayer3Match(m);
+        addNxRegMatch(mb, RegMatch.of(NxmNxReg6.class, Long.valueOf(epFwdCtxOrds.getL3Id())));
+        FlowBuilder flowb = base().setId(flowid)
+            .setPriority(Integer.valueOf(BASE_L3_PRIORITY+prefixLength))
+            .setMatch(mb.build())
+            .setInstructions(new InstructionsBuilder().setInstruction(l3instructions).build());
+        return flowb.build();
+    }
+
     private Flow createBroadcastFlow(EndpointFwdCtxOrdinals epOrd) {
         FlowId flowId = new FlowId("broadcast|" + epOrd.getFdId());
-        MatchBuilder mb = new MatchBuilder()
-                            .setEthernetMatch(new EthernetMatchBuilder()
-                            .setEthernetDestination(new EthernetDestinationBuilder().
-                                                        setAddress(MULTICAST_MAC)
-                                                        .setMask(MULTICAST_MAC).build())
-                            .build());
+        MatchBuilder mb = new MatchBuilder().setEthernetMatch(new EthernetMatchBuilder().setEthernetDestination(
+                new EthernetDestinationBuilder().setAddress(MULTICAST_MAC).setMask(MULTICAST_MAC).build()).build());
         addNxRegMatch(mb, RegMatch.of(NxmNxReg5.class, Long.valueOf(epOrd.getFdId())));
 
         FlowBuilder flowb = base().setPriority(Integer.valueOf(140))
@@ -543,7 +710,7 @@ public class DestinationMapper extends FlowTable {
         Subnet destSubnet = null;
         HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
         if (subnets == null) {
-            LOG.trace("No subnets in tenant {}", destL3Address.getIpAddress());
+            LOG.trace("No subnets in tenant {}", destEp.getTenant());
             return null;
         }
         NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
@@ -792,7 +959,7 @@ public class DestinationMapper extends FlowTable {
         Subnet destSubnet = null;
         HashSet<Subnet> subnets = getSubnets(destEp.getTenant());
         if (subnets == null) {
-            LOG.trace("No subnets in tenant {}", destL3Address.getIpAddress());
+            LOG.trace("No subnets in tenant {}", destEp.getTenant());
             return null;
         }
         NetworkDomainId epNetworkContainment = getEPNetworkContainment(destEp);
@@ -1024,24 +1191,6 @@ public class DestinationMapper extends FlowTable {
         return localSubnets;
     }
 
-    /**
-     * Reads data from datastore as synchronous call.
-     *
-     * @return {@link Optional#isPresent()} is {@code true} if reading was
-     *         successful and data exists in datastore; {@link Optional#isPresent()} is
-     *         {@code false} otherwise
-     */
-    public static <T extends DataObject> Optional<T> readFromDs(LogicalDatastoreType store, InstanceIdentifier<T> path,
-            ReadTransaction rTx) {
-        CheckedFuture<Optional<T>, ReadFailedException> resultFuture = rTx.read(store, path);
-        try {
-            return resultFuture.checkedGet();
-        } catch (ReadFailedException e) {
-            LOG.warn("Read failed from DS.", e);
-            return Optional.absent();
-        }
-    }
-
     static byte[] bytesFromHexString(String values) {
         String target = "";
         if (values != null) {
index 72a8a9f003f7c7310d9c8cbf39e84762cc511845..6fcfdcb35f0de54c072d175fb80f3bf91d1e12fe 100644 (file)
@@ -14,6 +14,7 @@ import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtil
 import static org.opendaylight.groupbasedpolicy.renderer.ofoverlay.flow.FlowUtils.nxOutputRegAction;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -120,7 +121,10 @@ public class PolicyEnforcer extends FlowTable {
             for (EgKey srcEpgKey : ctx.getEndpointManager().getEgKeysForEndpoint(srcEp)) {
                 Set<EgKey> peers = policyInfo.getPeers(srcEpgKey);
                 for (EgKey dstEpgKey : peers) {
-                    for (Endpoint dstEp : ctx.getEndpointManager().getEndpointsForGroup(dstEpgKey)) {
+                    Set<Endpoint> dstEndpoints = new HashSet<>();
+                    dstEndpoints.addAll(ctx.getEndpointManager().getEndpointsForGroup(dstEpgKey));
+                    dstEndpoints.addAll(ctx.getEndpointManager().getExtEpsNoLocForGroup(dstEpgKey));
+                    for (Endpoint dstEp : dstEndpoints) {
                         // mEPG ordinals
                         EndpointFwdCtxOrdinals srcEpFwdCxtOrds = OrdinalFactory.getEndpointFwdCtxOrdinals(ctx,
                                 policyInfo, srcEp);
index 829f78e628df2641b37ea2ba1871b5a18a126b6b..447e8a827bb1bf557a3b4dafdb7046d073dfbc90 100644 (file)
@@ -13,7 +13,7 @@ module ofoverlay-provider-impl {
 
     import config { prefix config; revision-date 2013-04-05; }
     import opendaylight-md-sal-binding { prefix mdsal; revision-date 2013-10-28; }
-    import ietf-yang-types { prefix "yang"; revision-date 2013-07-15; }
+    import ietf-yang-types { prefix "yang"; revision-date 2010-09-24; }
 
     description
         "This module contains the base YANG definitions for 
index 6edfca3327c12a424640ec42cc4d9deaa52a834e..60dd6080f87c247821de936e7b9a9dd5f12024df 100644 (file)
@@ -105,6 +105,26 @@ module ofoverlay {
             description
                 "Unique identifier for interface";
         }
+
+        container napt-translations {
+            description "List of NAPT translations";
+            list napt-translation {
+                key "ip-address";
+                uses napt-fields;
+            }
+        }
+    }
+
+    grouping napt-fields {
+        description "Support for IP NAPT";
+        leaf ip-address {
+            description "Ip address the L3Endpoint translates to.";
+            type inet:ip-address;
+        }
+        leaf port {
+            description "Port that L3Endpoint translates to.";
+            type inet:port-number;
+        }
     }
 
     augment "/endpoint:endpoints/endpoint:endpoint" {
index d92820a350a1f505e639a09439f15f91b266873e..650ecae90b344bdc646daa0ada0eaa932b752a6f 100644 (file)
@@ -9,7 +9,7 @@
 package org.opendaylight.groupbasedpolicy.renderer.ofoverlay;
 
 import org.opendaylight.groupbasedpolicy.resolver.PolicyResolver;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 
 public class MockPolicyManager extends PolicyManager {