Merge "Implemented unregister l3-prefix endpoint"
authorMartin Sunal <the.martin.sunal@gmail.com>
Mon, 27 Mar 2017 10:43:35 +0000 (10:43 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 27 Mar 2017 10:43:35 +0000 (10:43 +0000)
39 files changed:
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/DtoEquivalenceUtils.java
groupbasedpolicy/src/main/java/org/opendaylight/groupbasedpolicy/renderer/RendererConfigurationBuilder.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/NeutronMapper.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronFloatingIpAware.java
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-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSecurityGroupAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAware.java
neutron-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/rule/NeutronSecurityRuleAware.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronPortAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronRouterAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSecurityGroupAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/mapping/NeutronSubnetAwareDataStoreTest.java
neutron-mapper/src/test/java/org/opendaylight/groupbasedpolicy/neutron/mapper/test/NeutronMapperAssert.java
neutron-vpp-mapper/src/main/java/org/opendaylight/groupbasedpolicy/neutron/vpp/mapper/processors/PortHandler.java
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/GbpVppProviderInstance.java
renderers/vpp/src/main/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRenderer.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/AclManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppNodeManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/nat/NatUtil.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/acl/AccessListWrapper.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/routing/RoutingManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/sf/L4Classifier.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/GbpNetconfTransaction.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/util/VppIidFactory.java
renderers/vpp/src/main/resources/org.opendaylight.groupbasedpolicy.vpp.startup.cfg [new file with mode: 0644]
renderers/vpp/src/main/resources/org/opendaylight/blueprint/vpp-renderer.xml
renderers/vpp/src/main/yang/vpp-renderer.yang
renderers/vpp/src/test/java/org/opendaylight/controller/config/yang/config/vpp_provider/impl/VppRendererTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/VppRendererDataBrokerTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommandTest.java [new file with mode: 0644]
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/manager/VppManagerDataStoreTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/BridgeDomainManagerImplTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManagerTest.java
renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/VppRendererPolicyManagerTest.java

index b9e9c96205241042de59796ff2c11bdc98bf261e..bb2b6bf5134c9bf4fa74ceeef51b2388355a7f12 100644 (file)
@@ -16,6 +16,7 @@ import javax.annotation.Nullable;
 
 import com.google.common.annotations.VisibleForTesting;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.CommonEndpointFields;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.AddressEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoint.locations.ContainmentEndpointLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpoint;
@@ -61,6 +62,9 @@ class DtoEquivalenceUtils {
             if (!equalsCommonEndpointFields(a, b)) {
                 return false;
             }
+            if (!equalsAugmentations(a, b)) {
+                return false;
+            }
             return true;
         }
 
@@ -69,7 +73,6 @@ class DtoEquivalenceUtils {
             return t.hashCode();
         }
     };
-
     @VisibleForTesting
     static final Equivalence<ContainmentEndpoint> CONT_EP_EQ = new Equivalence<ContainmentEndpoint>() {
 
@@ -92,7 +95,6 @@ class DtoEquivalenceUtils {
             return t.hashCode();
         }
     };
-
     @VisibleForTesting
     static final Equivalence<AddressEndpointLocation> ADDR_EP_LOC_EQ =
             new Equivalence<AddressEndpointLocation>() {
@@ -116,7 +118,6 @@ class DtoEquivalenceUtils {
                     return t.hashCode();
                 }
             };
-
     @VisibleForTesting
     static final Equivalence<ContainmentEndpointLocation> CONT_EP_LOC_EQ =
             new Equivalence<ContainmentEndpointLocation>() {
@@ -137,7 +138,6 @@ class DtoEquivalenceUtils {
                     return t.hashCode();
                 }
             };
-
     @VisibleForTesting
     static final Equivalence<ForwardingByTenant> FWD_BY_TENANT_EQ = new Equivalence<ForwardingByTenant>() {
 
@@ -163,6 +163,19 @@ class DtoEquivalenceUtils {
 
     private DtoEquivalenceUtils() {}
 
+    private static boolean equalsAugmentations(AddressEndpoint a, AddressEndpoint b) {
+        if (a.getAugmentation(NatAddress.class) != null && b.getAugmentation(NatAddress.class) != null) {
+            if (!a.getAugmentation(NatAddress.class)
+                .getNatAddress()
+                .equals(b.getAugmentation(NatAddress.class).getNatAddress())) {
+                return false;
+            }
+        } else if (a.getAugmentation(NatAddress.class) != null || b.getAugmentation(NatAddress.class) != null) {
+            return false;
+        }
+        return true;
+    }
+
     static boolean equalsAddressEpByKey(@Nullable Map<AddressEndpointKey, AddressEndpoint> o1,
             @Nullable Map<AddressEndpointKey, AddressEndpoint> o2) {
         return equalsDtoMapsByEquivalence(o1, o2, ADDR_EP_EQ);
index 1401aab3bfe13ce2484b965f7f17bcbe2e857627..a7ce6b192b10afa23099c8231e182a02d9682daf 100644 (file)
@@ -340,11 +340,11 @@ public class RendererConfigurationBuilder {
             if (addrEpWithLocAug != null) {
                 addrEpWithLoc.addAugmentation(addrEpWithLocAug.getKey(), addrEpWithLocAug.getValue());
             }
-            if (ep.getAugmentation(NatAddress.class) != null) {
-                NatAddress natAddr = ep.getAugmentation(NatAddress.class);
-                    addrEpWithLoc.addAugmentation(NatAddressRenderer.class,
-                            new NatAddressRendererBuilder().setNatAddress(natAddr.getNatAddress()).build());
-            }
+        }
+        if (ep.getAugmentation(NatAddress.class) != null) {
+            NatAddress natAddr = ep.getAugmentation(NatAddress.class);
+            addrEpWithLoc.addAugmentation(NatAddressRenderer.class,
+                new NatAddressRendererBuilder().setNatAddress(natAddr.getNatAddress()).build());
         }
         return addrEpWithLoc.build();
     }
index f5f1939b3f1bdaa92e2506a03af862e938f421fb..f1cd873f3f6a60eae27c55c0f3b418c5c0287471 100644 (file)
@@ -108,8 +108,8 @@ public class NeutronMapper implements ClusteredDataTreeChangeListener<Neutron>,
             BaseEndpointService baseEpService) {
         EndpointRegistrator epRegistrator = new EndpointRegistrator(epService, baseEpService);
         networkAware = new NeutronNetworkAware(dataProvider);
-        securityGroupAware = new NeutronSecurityGroupAware(dataProvider);
         securityRuleAware = new NeutronSecurityRuleAware(dataProvider);
+        securityGroupAware = new NeutronSecurityGroupAware(dataProvider, securityRuleAware);
         subnetAware = new NeutronSubnetAware(dataProvider, epRegistrator);
         portAware = new NeutronPortAware(dataProvider, epRegistrator);
         routerAware = new NeutronRouterAware(dataProvider, epRegistrator);
index 8f8237cf1a5855682b2ebad69c71e5f510aee73f..95ff9197448b1693ef4d63f92c009f9b127658e5 100644 (file)
@@ -19,7 +19,10 @@ import org.opendaylight.groupbasedpolicy.neutron.mapper.util.Utils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.endpoints.address.endpoints.AddressEndpointKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.L3ContextId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.l3endpoint.rev151217.NatAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.floatingips.attributes.Floatingips;
@@ -44,7 +47,7 @@ public class NeutronFloatingIpAware implements NeutronAware<Floatingip> {
 
     @Override
     public void onCreated(Floatingip floatingIP, Neutron neutron) {
-        LOG.trace("created floatinIp - {}", floatingIP);
+        LOG.trace("created floatingIp - {}", floatingIP);
     }
 
     @Override
@@ -70,20 +73,32 @@ public class NeutronFloatingIpAware implements NeutronAware<Floatingip> {
     }
 
     @Deprecated
-    private void syncNatForEndpoint(ReadWriteTransaction rwTx, Floatingip newFloatingIp, Floatingip oldFloatingIp) {
+    private void syncNatForEndpoint(ReadWriteTransaction rwTx, Floatingip oldFloatingIp, Floatingip newFloatingIp) {
         IpAddress oldEpIp = oldFloatingIp.getFixedIpAddress();
         IpAddress newEpIp = newFloatingIp.getFixedIpAddress();
         IpAddress epNatIp = newFloatingIp.getFloatingIpAddress();
         L3ContextId routerL3ContextId = new L3ContextId(newFloatingIp.getRouterId().getValue());
+
+        if (oldEpIp != null) {
+            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
+                IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
+        }
+
         if (epNatIp != null && newEpIp != null) {
             NatAddress nat = new NatAddressBuilder().setNatAddress(epNatIp).build();
+            AddressEndpointKey aek =
+                new AddressEndpointKey(newEpIp.getIpv4Address().getValue() + "/32", IpPrefixType.class,
+                    routerL3ContextId, L3Context.class);
+            LOG.info("Adding NAT augmentation {} for base-endpoint {}", epNatIp, aek);
+            rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.addressEndpointIid(aek)
+                    .augmentation(
+                        org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddress.class),
+                new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.NatAddressBuilder()
+                    .setNatAddress(epNatIp)
+                    .build(), true);
             rwTx.put(LogicalDatastoreType.OPERATIONAL, IidFactory.l3EndpointIid(routerL3ContextId, newEpIp)
                 .augmentation(NatAddress.class), nat, true);
         }
-        if (oldEpIp != null) {
-            DataStoreHelper.removeIfExists(LogicalDatastoreType.OPERATIONAL,
-                    IidFactory.l3EndpointIid(routerL3ContextId, oldEpIp).augmentation(NatAddress.class), rwTx);
-        }
     }
 
     @Override
index c46cf2d3010fe39ea155fc6083b2f4b9da8b8598..c6bb87ddc0109be347f3137dd16cfc2b84fcbf06 100644 (file)
@@ -174,8 +174,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
                 .build();
             rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), l2Bd, true);
             // set virtual router IP for subnet
-            NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(
-                    routerPortSubnet, neutron);
+            NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(routerPortSubnet, neutron, null);
             rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
 
             // does the same for tenant forwarding domains
@@ -589,7 +588,7 @@ public class NeutronPortAware implements NeutronAware<Port> {
                 .build();
             rwTx.merge(LogicalDatastoreType.CONFIGURATION,
                     L2L3IidFactory.l2BridgeDomainIid(tenantId, fwdCtx.getContextId()), fwdCtx);
-            NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron);
+            NetworkDomain subnet = NeutronSubnetAware.createSubnet(routerPortSubnet, newNeutron, null);
             rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnet.getNetworkDomainId()),
                     subnet);
             unregisterEndpointAndRemoveMapping(createUnregisterEndpointInput(port, oldNeutron), port, rwTx);
index 5f634e55a0e89a7dc08f234c74e893ad08bd71a3..aaf1bd054c3f6f15ff21cc7599321b0aa55a7ca7 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Collections;
 import java.util.List;
 
 import javax.annotation.Nonnull;
@@ -22,6 +23,7 @@ import org.opendaylight.groupbasedpolicy.domain_extension.l2_l3.util.L2L3IidFact
 import org.opendaylight.groupbasedpolicy.neutron.gbp.util.NeutronGbpIidFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.EndpointRegistrator;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.util.NetworkUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.PortUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SubnetUtils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
@@ -50,7 +52,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentForwardingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.Subnet;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.Prefixes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContext;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.ForwardingContextBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
@@ -64,6 +70,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3ContextBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.Routers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
@@ -156,26 +163,42 @@ public class NeutronRouterAware implements NeutronAware<Router> {
 
             // router can have only one external network
             FixedIps ipWithSubnetFromGwPort = fixedIpsFromGwPort.get(0);
-            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet> potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
+            Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet>
+                potentialSubnet = SubnetUtils.findSubnet(ipWithSubnetFromGwPort.getSubnetId(), newNeutron.getSubnets());
             if (!potentialSubnet.isPresent()) {
                 LOG.warn("Illegal state - Subnet {} does not exist for router {}.",
                         ipWithSubnetFromGwPort.getSubnetId(), newRouter);
                 rwTx.cancel();
                 return;
             }
-            IpPrefix gatewayIp =  MappingUtils.ipAddressToIpPrefix(potentialSubnet.get().getGatewayIp());
-            boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp,
-                    routerL3CtxId, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue()));
+            tenantId = new TenantId(potentialSubnet.get().getTenantId().getValue());
+            IpAddress gwIp = potentialSubnet.get().getGatewayIp();
+            IpPrefix gatewayIp =  MappingUtils.ipAddressToIpPrefix(gwIp);
+            NetworkDomainId subnetId = new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId().getValue());
+            boolean registeredExternalGateway = registerExternalGateway(tenantId, gatewayIp, routerL3CtxId, subnetId);
             if (!registeredExternalGateway) {
                 LOG.warn("Could not add L3Prefix as gateway of default route. Gateway port {}", gwPort);
                 rwTx.cancel();
                 return;
             }
             addNeutronExtGwGbpMapping(routerL3CtxId, gatewayIp, rwTx);
-            NetworkDomain subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, new NetworkDomainId(ipWithSubnetFromGwPort.getSubnetId()
-                .getValue()));
-            rwTx.merge(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()),
-                    subnetDomain);
+            NetworkDomain subnetDomain;
+            List<Prefixes> defaultPrefixes =
+                Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build());
+            // if subnet is in external network then create subnet with IP from GW port as its virtual router IP
+            // else use subnet gateway as virtual router IP.
+            if (isSubnetInExternalNetwork(newNeutron.getNetworks().getNetwork(),
+                potentialSubnet.get().getNetworkId())) {
+                subnetDomain = createSubnetWithVirtualRouterIp(
+                        MappingUtils.ipAddressToIpPrefix(ipWithSubnetFromGwPort.getIpAddress()), subnetId,
+                        Collections.singletonList(
+                            new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
+            } else {
+                subnetDomain = createSubnetWithVirtualRouterIp(gatewayIp, subnetId, Collections.singletonList(
+                    new GatewaysBuilder().setGateway(gwIp).setPrefixes(defaultPrefixes).build()));
+            }
+            rwTx.merge(LogicalDatastoreType.CONFIGURATION,
+                L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain);
             ContextId l2BdId = new ContextId(potentialSubnet.get().getNetworkId().getValue());
             Optional<ForwardingContext> optBd = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
                     L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId), rwTx);
@@ -186,9 +209,10 @@ public class NeutronRouterAware implements NeutronAware<Router> {
                 rwTx.cancel();
                 return;
             }
-            ForwardingContext l2BdWithGw = new ForwardingContextBuilder(optBd.get())
-            .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
-            .build();
+            ForwardingContext forwardingContext = optBd.get();
+            ForwardingContext l2BdWithGw = new ForwardingContextBuilder(forwardingContext)
+                .setParent(MappingUtils.createParent(routerL3CtxId, MappingUtils.L3_CONTEXT))
+                .build();
             rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.l2BridgeDomainIid(tenantId, l2BdId),
                     l2BdWithGw);
         }
@@ -196,6 +220,10 @@ public class NeutronRouterAware implements NeutronAware<Router> {
         DataStoreHelper.submitToDs(rwTx);
     }
 
+    private boolean isSubnetInExternalNetwork(List<Network> networks, Uuid networkId) {
+        return networks.stream().anyMatch(net -> net.getUuid().equals(networkId) && NetworkUtils.isRouterExternal(net));
+    }
+
     private boolean registerExternalGateway(TenantId tenantId, IpPrefix ipPrefix, ContextId routerl3ContextId,
             NetworkDomainId networkDomainId) {
         AddressEndpointRegBuilder addrEpBuilder = new AddressEndpointRegBuilder();
@@ -220,8 +248,11 @@ public class NeutronRouterAware implements NeutronAware<Router> {
         return epRegistrator.unregisterEndpoint(addrEpBuilder.build());
     }
 
-    private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId) {
-        Subnet subnet = new SubnetBuilder().setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue())).build();
+private NetworkDomain createSubnetWithVirtualRouterIp(IpPrefix gatewayIp, NetworkDomainId subnetId, List<Gateways> gateways) {
+        Subnet subnet = new SubnetBuilder()
+            .setVirtualRouterIp(MappingUtils.ipPrefixToIpAddress(gatewayIp.getValue()))
+            .setGateways(gateways)
+            .build();
         return new NetworkDomainBuilder().setKey(new NetworkDomainKey(subnetId, MappingUtils.SUBNET))
             .addAugmentation(SubnetAugmentForwarding.class,
                     new SubnetAugmentForwardingBuilder().setSubnet(subnet).build())
@@ -233,15 +264,13 @@ public class NeutronRouterAware implements NeutronAware<Router> {
         InstanceIdentifier<L3Context> l3ContextIid =
                 IidFactory.l3ContextIid(tenantId, l3ContextId);
          Optional<L3Context> optL3Context = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, l3ContextIid, rwTx);
-         L3Context l3Context = null;
-         if (optL3Context.isPresent()) {
-             l3Context = optL3Context.get();
-         } else { // add L3 context if missing
-             l3Context = createL3CtxFromRouter(newRouter);
-             rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
-         }
+         L3Context l3Context;
+        if (!optL3Context.isPresent()) { // add L3 context if missing
+            l3Context = createL3CtxFromRouter(newRouter);
+            rwTx.put(LogicalDatastoreType.CONFIGURATION, l3ContextIid, l3Context, true);
+        }
 
-         if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
+        if (newRouter.getGatewayPortId() != null && oldRouter.getGatewayPortId() == null) {
              // external network is attached to router
              Uuid gatewayPortId = newRouter.getGatewayPortId();
              Optional<Port> potentialGwPort = PortUtils.findPort(gatewayPortId, newNeutron.getPorts());
@@ -372,7 +401,7 @@ public class NeutronRouterAware implements NeutronAware<Router> {
             org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet
                 subnet =
                 new org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.SubnetBuilder(
-                    subnetOptional.get()).setVirtualRouterIp(null).build();
+                    subnetOptional.get()).setVirtualRouterIp(null).setGateways(null).build();
             LOG.trace("Removing VirtualRouterIp from subnet {}.", subnetOptional.get());
             rwTx.put(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.subnetIid(tenantId, new SubnetId(ipWithSubnetFromGwPort.getSubnetId().getValue())), subnet);
@@ -496,7 +525,8 @@ public class NeutronRouterAware implements NeutronAware<Router> {
                 Subnet originalSubnet = domainOptional.get().getAugmentation(SubnetAugmentForwarding.class).getSubnet();
                 if (originalSubnet != null) {
                     LOG.trace("Deleting virtual router IP from Subnet {} in gateway {}", originalSubnet, gatewayPortId);
-                    SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null);
+                    SubnetBuilder subnetBuilder = new SubnetBuilder(originalSubnet).setVirtualRouterIp(null)
+                        .setGateways(null);
                     rwTx.put(LogicalDatastoreType.CONFIGURATION,
                         L2L3IidFactory.subnetIid(tenantId, domainId)
                             .augmentation(SubnetAugmentForwarding.class)
index 76b9edf6c6e05fd7f0ab029594fc6b5ccb0c9bdc..8478f59aee6b5194998c5473e527574afd727a95 100644 (file)
@@ -12,10 +12,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.groupbasedpolicy.util.IidFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Description;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.EndpointGroupId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.Name;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
@@ -40,9 +40,11 @@ public class NeutronSecurityGroupAware implements NeutronAware<SecurityGroup> {
     public static final InstanceIdentifier<SecurityGroup> SECURITY_GROUP_WILDCARD_IID =
             InstanceIdentifier.builder(Neutron.class).child(SecurityGroups.class).child(SecurityGroup.class).build();
     private final DataBroker dataProvider;
+    private final NeutronSecurityRuleAware ruleAware;
 
-    public NeutronSecurityGroupAware(DataBroker dataProvider) {
+    public NeutronSecurityGroupAware(DataBroker dataProvider, NeutronSecurityRuleAware ruleAware) {
         this.dataProvider = checkNotNull(dataProvider);
+        this.ruleAware = checkNotNull(ruleAware);
     }
 
     @Override
@@ -55,6 +57,7 @@ public class NeutronSecurityGroupAware implements NeutronAware<SecurityGroup> {
         } else {
             rwTx.cancel();
         }
+        ruleAware.flushPendingSecurityRulesFor(createdSecGroup.getKey(), neutron);
     }
 
     public boolean addNeutronSecurityGroup(SecurityGroup secGroup, ReadWriteTransaction rwTx) {
@@ -89,9 +92,24 @@ public class NeutronSecurityGroupAware implements NeutronAware<SecurityGroup> {
     @Override
     public void onDeleted(SecurityGroup deletedSecGroup, Neutron oldNeutron, Neutron newNeutron) {
         LOG.trace("deleted securityGroup - {}", deletedSecGroup);
-        ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
-        TenantId tenantId = new TenantId(deletedSecGroup.getTenantId().getValue());
-        EndpointGroupId epgId = new EndpointGroupId(deletedSecGroup.getUuid().getValue());
+        if (newNeutron != null && newNeutron.getSecurityRules() != null
+                && newNeutron.getSecurityRules().getSecurityRule() != null
+                && newNeutron.getSecurityRules()
+                    .getSecurityRule()
+                    .stream()
+                    .filter(sr -> sr.getSecurityGroupId().equals(deletedSecGroup.getUuid()))
+                    .findAny()
+                    .isPresent()) {
+            LOG.warn("Cannot remove security group {} before removing last security rule.", deletedSecGroup.getKey());
+            ruleAware.addPendingDeletedSecGroup(deletedSecGroup);
+            return;
+        }
+        deleteGbpEndpointGroup(dataProvider, new TenantId(deletedSecGroup.getTenantId().getValue()),
+                new EndpointGroupId(deletedSecGroup.getUuid().getValue()));
+    }
+
+    public static void deleteGbpEndpointGroup(DataBroker dataBroker, TenantId tenantId, EndpointGroupId epgId) {
+        ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
         Optional<EndpointGroup> potentialEpg = DataStoreHelper.removeIfExists(LogicalDatastoreType.CONFIGURATION,
                 IidFactory.endpointGroupIid(tenantId, epgId), rwTx);
         if (!potentialEpg.isPresent()) {
@@ -99,8 +117,6 @@ public class NeutronSecurityGroupAware implements NeutronAware<SecurityGroup> {
             rwTx.cancel();
             return;
         }
-
         DataStoreHelper.submitToDs(rwTx);
     }
-
 }
index 6d70dcd2fbb44ec514790384e7066cbfd73bd4c0..911aff6e3bd65042d9e5d65baafa861d3035af89 100644 (file)
@@ -9,7 +9,9 @@ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.Collections;
 import java.util.List;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -34,6 +36,8 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.SubnetBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.GatewaysBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.PrefixesBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomainBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.Subnet;
@@ -41,6 +45,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.provider.ext.rev150712.NetworkProviderExtension;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnet.attributes.AllocationPools;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.Subnets;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -85,31 +90,45 @@ public class NeutronSubnetAware implements
 
         Network networkOfSubnet = potentialNetwork.get();
 
-        NetworkDomain subnetDomain = null;
+        NetworkDomain subnetDomain;
+        IpAddress gatewayIp = neutronSubnet.getGatewayIp();
         if (NetworkUtils.isProviderPhysicalNetwork(networkOfSubnet)) {
-            subnetDomain = createSubnet(neutronSubnet, neutron);
-            IpAddress gatewayIp = neutronSubnet.getGatewayIp();
+            // add virtual router IP only in case it is provider physical network
+            subnetDomain = createSubnet(neutronSubnet, neutron, gatewayIp);
             boolean registeredDefaultRoute = epRegistrator.registerExternalL3PrefixEndpoint(MappingUtils.DEFAULT_ROUTE,
                     new L3ContextId(neutronSubnet.getNetworkId().getValue()), gatewayIp, tenantId);
             if (!registeredDefaultRoute) {
                 LOG.warn("Could not add EndpointL3Prefix as default route. Subnet within provider physical network {}",
-                        neutronSubnet);
+                    neutronSubnet);
                 rwTx.cancel();
                 return;
             }
         } else {
-            subnetDomain = createSubnet(neutronSubnet, neutron);
+            // virtual router IP is not set and it will be set when router gateway port is set
+            // or when a router port is attached to a network
+            if (NetworkUtils.isRouterExternal(networkOfSubnet)) {
+                subnetDomain = createSubnet(neutronSubnet, neutron, gatewayIp);
+            } else {
+                subnetDomain = createSubnet(neutronSubnet, neutron, null);
+            }
         }
         processTenantSubnet(neutronSubnet, networkOfSubnet, tenantId, rwTx);
-        rwTx.put(LogicalDatastoreType.CONFIGURATION, L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION,
+            L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId()), subnetDomain, true);
         DataStoreHelper.submitToDs(rwTx);
     }
 
     public static NetworkDomain createSubnet(
             org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet subnet,
-            Neutron neutron) {
+            Neutron neutron, IpAddress gwIpAddress) {
         SubnetBuilder sb = new SubnetBuilder();
         sb.setIpPrefix(subnet.getCidr());
+        if (gwIpAddress != null) {
+            sb.setGateways(Collections.singletonList(new GatewaysBuilder().setGateway(gwIpAddress)
+                .setPrefixes(
+                    Collections.singletonList(new PrefixesBuilder().setPrefix(MappingUtils.DEFAULT_ROUTE).build()))
+                .build()));
+        }
         if (neutron.getPorts() != null && neutron.getPorts().getPort() != null) {
             for (Port port : neutron.getPorts().getPort()) {
                 if (port.getFixedIps() == null || !port.getFixedIps()
@@ -147,12 +166,24 @@ public class NeutronSubnetAware implements
             sb.setIsTenant(NetworkUtils.isTenantNetwork(potentialNetwork.get()));
         }
         if (subnet.getAllocationPools() != null) {
-            List<AllocationPool> pools = subnet.getAllocationPools()
-                .stream()
-                .map(s -> new AllocationPoolBuilder().setFirst(s.getStart().getIpv4Address().getValue())
-                    .setLast(s.getEnd().getIpv4Address().getValue())
-                    .build())
-                .collect(Collectors.toList());
+            List<AllocationPool> pools =
+                    subnet.getAllocationPools().stream().map(new Function<AllocationPools, AllocationPool>() {
+
+                        @Override
+                        public AllocationPool apply(AllocationPools ap) {
+                            IpAddress start = ap.getStart();
+                            IpAddress end = ap.getEnd();
+                            AllocationPoolBuilder ab = new AllocationPoolBuilder();
+                            if (start.getIpv4Address() != null || end.getIpv4Address() != null) {
+                                ab.setFirst(start.getIpv4Address().getValue());
+                                ab.setLast(end.getIpv4Address().getValue());
+                            } else {
+                                ab.setFirst(start.getIpv6Address().getValue());
+                                ab.setLast(end.getIpv6Address().getValue());
+                            }
+                            return ab.build();
+                        }
+                    }).collect(Collectors.toList());
             sb.setAllocationPool(pools);
         }
         NetworkDomainBuilder ndb = new NetworkDomainBuilder();
index 096f0ad5a4049aabdaaddffd394676504cefa347..86e21b876a58761e99ae47af0953c47e5f554c2a 100644 (file)
@@ -10,7 +10,14 @@ package org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule;
 
 import static com.google.common.base.Preconditions.checkNotNull;
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
 
 import org.opendaylight.controller.config.yang.config.neutron_mapper.impl.NeutronMapperModule;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -20,6 +27,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.api.sf.ChainActionDefinition;
 import org.opendaylight.groupbasedpolicy.dto.EpgKeyDto;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronAware;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.NeutronSecurityGroupAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityGroupUtils;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.SecurityRuleUtils;
@@ -48,14 +56,17 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.policy.subject.feature.instances.ClassifierInstance;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroup;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.groups.attributes.security.groups.SecurityGroupKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.SecurityRules;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRule;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.secgroups.rev150712.security.rules.attributes.security.rules.SecurityRuleKey;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.HashMultiset;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Multiset;
@@ -70,6 +81,8 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
     private final DataBroker dataProvider;
     private final Multiset<InstanceIdentifier<ClassifierInstance>> createdClassifierInstances;
     private final Multiset<InstanceIdentifier<ActionInstance>> createdActionInstances;
+    private final Map<SecurityRuleKey, SecurityRule> pendingCreatedRules;
+    private final Map<SecurityGroupKey, SecurityGroup> pendingDeletedGroups;
     final static String PROVIDED_BY = "provided_by-";
     final static String POSSIBLE_CONSUMER = "possible_consumer-";
 
@@ -85,11 +98,25 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
         this.dataProvider = checkNotNull(dataProvider);
         this.createdClassifierInstances = checkNotNull(classifierInstanceNames);
         this.createdActionInstances = checkNotNull(createdActionInstances);
+        this.pendingCreatedRules = new HashMap<>();
+        this.pendingDeletedGroups = new HashMap<>();
     }
 
     @Override
     public void onCreated(SecurityRule secRule, Neutron neutron) {
         LOG.trace("created securityRule - {}", secRule);
+        if (neutron.getSecurityGroups() == null || neutron.getSecurityGroups().getSecurityGroup() == null
+                || !neutron.getSecurityGroups()
+                    .getSecurityGroup()
+                    .stream()
+                    .filter(sg -> sg.getKey().getUuid().equals(secRule.getSecurityGroupId()))
+                    .findFirst()
+                    .isPresent()) {
+            pendingCreatedRules.put(secRule.getKey(), secRule);
+            LOG.warn("Security group of security rule {} does not exist yet. The rule will be processed"
+                    + "when the missing security group is created.", secRule.getKey());
+            return;
+        }
         ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
         boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(secRule, neutron, rwTx);
         if (isNeutronSecurityRuleAdded) {
@@ -99,6 +126,24 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
         }
     }
 
+    public void flushPendingSecurityRulesFor(@Nonnull SecurityGroupKey secGroupKey, Neutron neutron) {
+        List<SecurityRule> rules = pendingCreatedRules.values()
+            .stream()
+            .filter(sr -> sr.getSecurityGroupId().equals(secGroupKey.getUuid()))
+            .collect(Collectors.toList());
+        rules.forEach(sr -> {
+            LOG.trace("Flushing pending security rule {}", sr);
+            ReadWriteTransaction rwTx = dataProvider.newReadWriteTransaction();
+            boolean isNeutronSecurityRuleAdded = addNeutronSecurityRule(sr, neutron, rwTx);
+            if (isNeutronSecurityRuleAdded) {
+                DataStoreHelper.submitToDs(rwTx);
+            } else {
+                rwTx.cancel();
+            }
+            pendingCreatedRules.remove(sr.getKey());
+        });
+    }
+
     public boolean addNeutronSecurityRule(SecurityRule secRule, Neutron neutron, ReadWriteTransaction rwTx) {
         return addNeutronSecurityRuleWithAction(secRule, neutron, MappingUtils.ALLOW_ACTION_CHOICE, rwTx);
     }
@@ -265,6 +310,11 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
                 newSecRule);
     }
 
+    public void addPendingDeletedSecGroup(SecurityGroup secGroup) {
+        LOG.trace("Caching pending deleted security group {}", secGroup.getKey());
+        pendingDeletedGroups.put(secGroup.getKey(), secGroup);
+    }
+
     @Override
     public void onDeleted(SecurityRule deletedSecRule, Neutron oldNeutron, Neutron newNeutron) {
         LOG.trace("deleted securityRule - {}", deletedSecRule);
@@ -272,6 +322,24 @@ public class NeutronSecurityRuleAware implements NeutronAware<SecurityRule> {
         boolean isNeutronSecurityRuleDeleted = deleteNeutronSecurityRule(deletedSecRule, oldNeutron, rwTx);
         if (isNeutronSecurityRuleDeleted) {
             DataStoreHelper.submitToDs(rwTx);
+            if (newNeutron == null || newNeutron.getSecurityRules() == null
+                || newNeutron.getSecurityRules().getSecurityRule() == null
+                || !newNeutron.getSecurityRules()
+                        .getSecurityRule()
+                        .stream()
+                        .filter(rule -> rule.getSecurityGroupId().equals(deletedSecRule.getSecurityGroupId()))
+                        .findAny()
+                        .isPresent()) {
+                SecurityGroupKey secGroupKey = new SecurityGroupKey(deletedSecRule.getSecurityGroupId());
+                SecurityGroup pendingSg = pendingDeletedGroups.get(secGroupKey);
+                if (pendingSg != null) {
+                    LOG.trace("Processing pending deleted security group {}", secGroupKey);
+                    NeutronSecurityGroupAware.deleteGbpEndpointGroup(dataProvider,
+                            new TenantId(deletedSecRule.getTenantId().getValue()),
+                            new EndpointGroupId(secGroupKey.getUuid().getValue()));
+                    pendingDeletedGroups.remove(secGroupKey);
+                }
+            }
         } else {
             rwTx.cancel();
         }
index cd5f3099eb9852ff043c581c8796b97d914af1dd..8d375b4b18bca161308b29a96561814c2a70d4ea 100644 (file)
@@ -189,23 +189,22 @@ public class NeutronPortAwareDataStoreTest extends NeutronMapperDataBrokerTest {
             .setFixedIps(ImmutableList.of(portIpWithSubnet))
             .build();
         portAware.onCreated(port, neutron);
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron, ipAddress);
 
         portAware.onDeleted(port, neutron, neutron);
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, port, subnet, neutron, ipAddress);
         NeutronMapperAssert.assertPortNotExists(dataBroker, port.getUuid());
     }
 
     @Test
     public void test_createRouterInterfacePort_noFixedIps() {
-        IpAddress ipAddress = new IpAddress(new Ipv4Address("10.0.0.2"));
         Subnets subnets = createSubnets();
         when(neutron.getSubnets()).thenReturn(subnets);
 
         Subnet subnet = subnets.getSubnet().get(0);
         Port port = newBasePort().setDeviceOwner(PortUtils.DEVICE_OWNER_ROUTER_IFACE).build();
         portAware.onCreated(port, neutron);
-        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, port, subnet, neutron, null);
     }
 
     @Test
index 2c72bb7761f1feabcf70a129f7682971c50cfa4d..683ff807f76bbdcc78da0059a0f847eca73de688 100644 (file)
@@ -21,7 +21,6 @@ import java.util.concurrent.Future;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -44,6 +43,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.policy.rev140421.tenants.tenant.forwarding.context.L3Context;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.Router;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.l3.rev150712.routers.attributes.routers.RouterBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.NetworksBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.NetworkBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
@@ -145,6 +145,7 @@ public class NeutronRouterAwareDataStoreTest extends NeutronMapperDataBrokerTest
     public void testOnUpdated() {
         Subnets subnets = createSubnets();
         when(neutron.getSubnets()).thenReturn(subnets);
+        when(neutron.getNetworks()).thenReturn(new NetworksBuilder().setNetwork(ImmutableList.of(network)).build());
 
         FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
         Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
@@ -279,6 +280,7 @@ public class NeutronRouterAwareDataStoreTest extends NeutronMapperDataBrokerTest
     public void testOnUpdated_noL2BridgeDomain() {
         Subnets subnets = createSubnets();
         when(neutron.getSubnets()).thenReturn(subnets);
+        when(neutron.getNetworks()).thenReturn(new NetworksBuilder().setNetwork(ImmutableList.of(network)).build());
 
         FixedIps fixedIps = new FixedIpsBuilder().setIpAddress(ipAddress).setSubnetId(subnetUuid).build();
         Port port = new PortBuilder().setUuid(gatewayPortUuid).setFixedIps(ImmutableList.of(fixedIps)).build();
index 9cc2f53d4ceb7fa9a889572d4e655d7ffba4fd77..bb2f9695c7b9bad10cab0a54f774c8bd5007a8dc 100644 (file)
@@ -15,6 +15,7 @@ import org.junit.Test;
 import org.junit.rules.ExpectedException;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronMapperDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.neutron.mapper.mapping.rule.NeutronSecurityRuleAware;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.NeutronEntityFactory;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.test.PolicyAssert;
 import org.opendaylight.groupbasedpolicy.neutron.mapper.util.MappingUtils;
@@ -37,7 +38,7 @@ public class NeutronSecurityGroupAwareDataStoreTest extends NeutronMapperDataBro
     @Before
     public void init() {
         dataBroker = getDataBroker();
-        groupAware = new NeutronSecurityGroupAware(dataBroker);
+        groupAware = new NeutronSecurityGroupAware(dataBroker, new NeutronSecurityRuleAware(dataBroker));
 
         secGroup1 = NeutronEntityFactory.securityGroup(secGroupId1, tenantId);
         secGroup2 = NeutronEntityFactory.securityGroup(secGroupId2, tenantId);
@@ -98,7 +99,7 @@ public class NeutronSecurityGroupAwareDataStoreTest extends NeutronMapperDataBro
     @Test
     public void testConstructor_invalidArgument() throws NullPointerException {
         thrown.expect(NullPointerException.class);
-        new NeutronSecurityGroupAware(null);
+        new NeutronSecurityGroupAware(null, null);
     }
 
     @Test
index e9b63dc74a41df07545c5e9aa3b6d536a6cb4113..f337fd83f13a00892e1e5f7cf62ca866f3213cee 100644 (file)
@@ -123,7 +123,7 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest
 
         subnetAware.onCreated(subnet, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
     }
 
     @Test
@@ -134,7 +134,7 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest
 
         subnetAware.onCreated(subnet, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron, null);
     }
 
     @Test
@@ -146,12 +146,12 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest
 
         subnetAware.onCreated(subnet, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
-        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
+        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet2, neutron, null);
 
         subnetAware.onUpdated(subnet, subnet2, neutron, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet2, neutron, null);
     }
 
     @Test
@@ -163,11 +163,11 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest
 
         subnetAware.onCreated(subnet, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
 
         subnetAware.onDeleted(subnet, neutron, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainNotExists(dataBroker, tenantUuid, subnet, neutron, null);
     }
     @Test
     public void testOnDeleted_wrongSubnet() {
@@ -178,11 +178,11 @@ public class NeutronSubnetAwareDataStoreTest extends NeutronMapperDataBrokerTest
 
         subnetAware.onCreated(subnet, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
 
         subnetAware.onDeleted(subnet2, neutron, neutron);
 
-        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron);
+        NeutronMapperAssert.assertNetworkDomainExists(dataBroker, tenantUuid, subnet, neutron, null);
     }
 
 }
index 5098cb3f3f50c6de45c84304409ca6d31924ba92..865837cfd6aa819b004809089543b5010823b9cc 100644 (file)
@@ -25,11 +25,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.UniqueId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.forwarding.by.tenant.NetworkDomain;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.neutron.gbp.mapper.rev150513.mappings.gbp.by.neutron.mappings.endpoints.by.ports.EndpointByPort;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.Subnet;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.subnets.rev150712.subnets.attributes.subnets.SubnetBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class NeutronMapperAssert {
@@ -56,35 +54,36 @@ public class NeutronMapperAssert {
         return portOptional;
     }
 
-    public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, Neutron neutron) {
+    public static void assertNetworkDomainExists(DataBroker dataBroker, Port port, Subnet subnet, Neutron neutron,
+        IpAddress ipAddress) {
         Optional<NetworkDomain> opt =
-                getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet);
+                getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, ipAddress, subnet);
         assertTrue(opt.isPresent());
     }
 
     public static void assertNetworkDomainNotExists(DataBroker dataBroker, Port port, Subnet subnet,
-            Neutron neutron) {
+            Neutron neutron, IpAddress ipAddress) {
         Optional<NetworkDomain> opt =
-                getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, subnet);
+                getNetworkDomainOptional(dataBroker, port.getTenantId(), neutron, ipAddress, subnet);
         assertFalse(opt.isPresent());
     }
 
     public static void assertNetworkDomainExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet,
-            Neutron neutron) {
-        Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet);
+            Neutron neutron, IpAddress ipAddress) {
+        Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, ipAddress, subnet);
         assertTrue(opt.isPresent());
     }
 
     public static void assertNetworkDomainNotExists(DataBroker dataBroker, Uuid tenantUuid, Subnet subnet,
-            Neutron neutron) {
-        Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, subnet);
+            Neutron neutron, IpAddress ipAddress) {
+        Optional<NetworkDomain> opt = getNetworkDomainOptional(dataBroker, tenantUuid, neutron, ipAddress, subnet);
         assertFalse(opt.isPresent());
     }
 
     private static Optional<NetworkDomain> getNetworkDomainOptional(DataBroker dataBroker, Uuid tenantUuid,
-            Neutron neutron, Subnet subnet) {
+            Neutron neutron, IpAddress ipAddress, Subnet subnet) {
         InstanceIdentifier<NetworkDomain> iid;
-        NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, neutron);
+        NetworkDomain subnetDomain = NeutronSubnetAware.createSubnet(subnet, neutron, ipAddress);
         TenantId tenantId = new TenantId(tenantUuid.getValue());
         iid = L2L3IidFactory.subnetIid(tenantId, subnetDomain.getNetworkDomainId());
         Optional<NetworkDomain> optional;
index 11d7df4f8f67b7e462fb70248c68f768e5ebe848..3ca0883ea42a8b8699cacf92a545359e07c2d1b4 100644 (file)
@@ -365,10 +365,17 @@ public class PortHandler implements TransactionChainListener {
         if (Strings.isNullOrEmpty(port.getDeviceId())) {\r
             return Optional.absent();\r
         }\r
+        RouterKey routerKey = null;\r
+        try {\r
+            routerKey = new RouterKey(new Uuid(port.getDeviceId()));\r
+        } catch (IllegalArgumentException e) {\r
+            // port.getDeviceId() may not match Uuid.PATTERN_CONSTANTS\r
+            return Optional.absent();\r
+        }\r
         ReadOnlyTransaction rTx = transactionChain.newReadOnlyTransaction();\r
         InstanceIdentifier<Router> routerIid = InstanceIdentifier.builder(Neutron.class)\r
             .child(Routers.class)\r
-            .child(Router.class, new RouterKey(new Uuid(port.getDeviceId())))\r
+            .child(Router.class, routerKey)\r
             .build();\r
         Optional<Router> optRouter = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION, routerIid, rTx);\r
         rTx.close();\r
index 1124a1d9cf52a68202e0530c0f4bfdfa3a35cdba..2e42a1991b91f5485eb4a03dcec524d5b85451d3 100644 (file)
@@ -44,13 +44,16 @@ public class GbpVppProviderInstance implements ClusterSingletonService, VppAdapt
     private final ClusterSingletonServiceProvider clusterSingletonService;
     private ClusterSingletonServiceRegistration singletonServiceRegistration;
     private VppRenderer renderer;
+    private final String publicInterfaces;
 
     public GbpVppProviderInstance(final DataBroker dataBroker,
                                   final BindingAwareBroker bindingAwareBroker,
-                                  final ClusterSingletonServiceProvider clusterSingletonService) {
+                                  final ClusterSingletonServiceProvider clusterSingletonService,
+                                  final String publicInterfaces) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.bindingAwareBroker = Preconditions.checkNotNull(bindingAwareBroker);
         this.clusterSingletonService = Preconditions.checkNotNull(clusterSingletonService);
+        this.publicInterfaces = publicInterfaces;
     }
 
     public void initialize() {
@@ -61,7 +64,7 @@ public class GbpVppProviderInstance implements ClusterSingletonService, VppAdapt
     @Override
     public void instantiateServiceInstance() {
         LOG.info("Instantiating {}", this.getClass().getSimpleName());
-        renderer = new VppRenderer(dataBroker, bindingAwareBroker);
+        renderer = new VppRenderer(dataBroker, bindingAwareBroker, publicInterfaces);
     }
 
     @Override
index 635d5038d1ff2d21ecfb6ee417317ba6fb4e4b7d..242bd2f0a059c78e2e606be51cafc23e992aa0df 100644 (file)
@@ -11,6 +11,9 @@ package org.opendaylight.controller.config.yang.config.vpp_provider.impl;
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.MountPointService;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
@@ -18,8 +21,8 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.adapter.VppRpcServiceImpl;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener;
@@ -30,6 +33,7 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.BridgeDomainManagerImpl;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.ForwardingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.VppRendererPolicyManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.AllowAction;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.Classifier;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.sf.EtherTypeClassifier;
@@ -80,9 +84,12 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
     private VppEndpointListener vppEndpointListener;
     private RendererPolicyListener rendererPolicyListener;
     private VppRpcServiceImpl vppRpcServiceImpl;
+    private final String publicInterfaces;
 
-    public VppRenderer(DataBroker dataBroker, BindingAwareBroker bindingAwareBroker) {
+    public VppRenderer(@Nonnull DataBroker dataBroker, @Nonnull BindingAwareBroker bindingAwareBroker,
+            @Nullable String publicInterfaces) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
+        this.publicInterfaces = publicInterfaces;
         bindingAwareBroker.registerProvider(this);
         EtherTypeClassifier etherTypeClassifier = new EtherTypeClassifier(null);
         IpProtoClassifier ipProtoClassifier = new IpProtoClassifier(etherTypeClassifier);
@@ -129,7 +136,7 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
         MountPointService mountService =
                 Preconditions.checkNotNull(providerContext.getSALService(MountPointService.class));
         MountedDataBrokerProvider mountDataProvider = new MountedDataBrokerProvider(mountService, dataBroker);
-        vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+        vppNodeManager = new VppNodeManager(dataBroker, providerContext, publicInterfaces);
 
         EventBus dtoEventBus = new EventBus((exception, context) -> LOG.error("Could not dispatch event: {} to {}",
                 context.getSubscriber(), context.getSubscriberMethod(), exception));
@@ -137,8 +144,10 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
         aclManager = new AclManager(mountDataProvider);
         NatManager natManager = new NatManager(dataBroker, mountDataProvider);
         dtoEventBus.register(interfaceManager);
+        RoutingManager routingManager = new RoutingManager(dataBroker, mountDataProvider);
         BridgeDomainManager bdManager = new BridgeDomainManagerImpl(dataBroker);
-        ForwardingManager fwManager = new ForwardingManager(interfaceManager, aclManager, natManager, bdManager, dataBroker);
+        ForwardingManager fwManager =
+            new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
         dtoEventBus.register(vppRendererPolicyManager);
 
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommand.java
new file mode 100644 (file)
index 0000000..cc08914
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributesBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+public class RoutingCommand {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractInterfaceCommand.class);
+    public static String ROUTER_INSTANCE_NAME = "vpp-routing-instance";
+    private General.Operations operation;
+    private String routerProtocol;
+    private Long vrfId;
+    private List<Route> routes;
+
+    public String getRouterProtocol() {
+        return routerProtocol;
+    }
+
+    public Long getVrfId() {
+        return vrfId;
+    }
+
+    public List<Route> getRoutes() {
+        return routes;
+    }
+
+    private RoutingCommand(RoutingCommandBuilder builder) {
+        operation = builder.getOperation();
+        routerProtocol = builder.getRouterProtocol();
+        vrfId = builder.getVrfId();
+        routes = builder.getRoutes();
+    }
+
+    public static RoutingCommandBuilder builder() {
+        return new RoutingCommandBuilder();
+    }
+
+    public General.Operations getOperation() {
+        return operation;
+    }
+
+    public RoutingProtocolBuilder getRoutingProtocolBuilder() {
+        return new RoutingProtocolBuilder()
+            .setEnabled(true)
+            .setType(Static.class)
+            .setName(routerProtocol)
+            .addAugmentation(RoutingProtocolVppAttr.class, new RoutingProtocolVppAttrBuilder().setVppProtocolAttributes(
+                new VppProtocolAttributesBuilder().setPrimaryVrf(new VniReference(vrfId)).build()).build())
+            .setStaticRoutes(new StaticRoutesBuilder().addAugmentation(StaticRoutes1.class,
+                new StaticRoutes1Builder().setIpv4(new Ipv4Builder().setRoute(routes).build()).build()).build());
+    }
+
+    public void execute(ReadWriteTransaction rwTx) {
+        switch (getOperation()) {
+            case PUT:
+                LOG.debug("Executing Add operations for routing command: {}", this);
+                put(rwTx);
+                break;
+            case DELETE:
+                LOG.debug("Executing Delete operations for routing command: {}", this);
+                delete(rwTx);
+                break;
+            case MERGE:
+                LOG.debug("Executing Merge operations for routing command: {}", this);
+                merge(rwTx);
+                break;
+            default:
+                LOG.error("Execution failed for routing command: {}", this);
+                break;
+        }
+    }
+
+    private void merge(ReadWriteTransaction rwTx) {
+        rwTx.merge(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol)),
+            getRoutingProtocolBuilder().build(), true);
+    }
+
+    private void delete(ReadWriteTransaction rwTx) {
+        try {
+            rwTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(
+                routerProtocol)));
+        } catch (IllegalStateException ex) {
+            LOG.debug("Routing protocol not deleted from DS {}", this, ex);
+        }
+    }
+
+    private void put(ReadWriteTransaction rwTx) {
+        InstanceIdentifier<RoutingProtocol> routingInstanceIid =
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, routingInstanceIid, getRoutingProtocolBuilder().build(), true);
+    }
+
+    @Override public String toString() {
+        return "RoutingCommand [routerProtocol=" + routerProtocol + ", routes=" + routes + ", operations="
+            + operation + "]";
+    }
+
+    public static class RoutingCommandBuilder {
+
+        private General.Operations operation;
+        private String routerProtocol;
+        private Long vrfId;
+        private List<Route> routes;
+
+        public General.Operations getOperation() {
+            return operation;
+        }
+
+        public RoutingCommandBuilder setOperation(General.Operations operation) {
+            this.operation = operation;
+            return this;
+        }
+
+        public String getRouterProtocol() {
+            return routerProtocol;
+        }
+
+        public RoutingCommandBuilder setRouterProtocol(String routerProtocol) {
+            this.routerProtocol = routerProtocol;
+            return this;
+        }
+
+        public Long getVrfId() {
+            return vrfId;
+        }
+
+        public RoutingCommandBuilder setVrfId(Long vrfId) {
+            this.vrfId = vrfId;
+            return this;
+        }
+
+        public List<Route> getRoutes() {
+            return routes;
+        }
+
+        public RoutingCommandBuilder setRoutes(List<Route> routes) {
+            this.routes = routes;
+            return this;
+        }
+
+        /**
+         * RoutingCommand build method.
+         *
+         * @return RoutingCommand
+         * @throws IllegalArgumentException if routerProtocol, operation or vrfId is null.
+         */
+        public RoutingCommand build() {
+            Preconditions.checkArgument(this.operation != null);
+            Preconditions.checkArgument(this.routerProtocol != null);
+            Preconditions.checkArgument(this.vrfId != null);
+            return new RoutingCommand(this);
+        }
+    }
+}
index 29f55835a68a358836e562e053ccd9b1911ed06c..502abd7c33934138a5fde982fda87c039241f9a0 100644 (file)
@@ -55,7 +55,14 @@ public class AclManager {
     public void updateAclsForRendEp(RendererEndpointKey rEpKey, PolicyContext policyCtx) {
         LOG.info("Updating policy for endpoint {}", rEpKey);
         AddressEndpointWithLocation peerAddrEp = policyCtx.getAddrEpByKey().get(KeyFactory.addressEndpointKey(rEpKey));
-        ExternalLocationCase epLoc = InterfaceManager.resolveAndValidateLocation(peerAddrEp);
+        ExternalLocationCase epLoc;
+        try {
+            epLoc = InterfaceManager.resolveAndValidateLocation(peerAddrEp);
+        } catch (NullPointerException | IllegalArgumentException e) {
+            //TODO investigate, don't just move on.
+            LOG.warn("Peer {} has no location. Moving on...", peerAddrEp, e.getMessage());
+            return;
+        }
         InstanceIdentifier<?> vppNodeIid = epLoc.getExternalNodeMountPoint();
         Optional<InstanceIdentifier<Interface>> optInterfaceIid =
                 VppPathMapper.interfaceToInstanceIdentifier(epLoc.getExternalNodeConnector());
index adeed842a9ed56012229a66cd0cef0986347aee1..84736ff4596fa786b1dbac5a19e120d61713c006 100644 (file)
@@ -11,14 +11,23 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.manager;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connected;
 import static org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus.ConnectionStatus.Connecting;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.List;
-import java.util.concurrent.*;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 import java.util.stream.Collectors;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
 import com.google.common.util.concurrent.CheckedFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.MountPoint;
@@ -43,6 +52,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_render
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNodeConnectionStatus;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.status.available.capabilities.AvailableCapability;
@@ -58,6 +68,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 public class VppNodeManager {
 
     private static final short DURATION = 3000;
@@ -66,14 +77,37 @@ public class VppNodeManager {
     private static final String V3PO_CAPABILITY = "(urn:opendaylight:params:xml:ns:yang:v3po?revision=2016-12-14)v3po";
     private static final String INTERFACES_CAPABILITY = "(urn:ietf:params:xml:ns:yang:ietf-interfaces?revision=2014-05-08)ietf-interfaces";
     private static final NodeId CONTROLLER_CONFIG_NODE = new NodeId("controller-config");
+    private static final String NO_PUBLIC_INT_SPECIFIED = "unspecified";
+    private final Map<NodeId, PhysicalInterfaceKey> extInterfaces = new HashMap<>();
     private final DataBroker dataBroker;
     private final List<String> requiredCapabilities;
     private final MountPointService mountService;
 
-    public VppNodeManager(final DataBroker dataBroker, final BindingAwareBroker.ProviderContext session) {
+    public VppNodeManager(@Nonnull final DataBroker dataBroker,
+            @Nonnull final BindingAwareBroker.ProviderContext session, @Nullable String physicalInterfaces) {
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.mountService = Preconditions.checkNotNull(session.getSALService(MountPointService.class));
         requiredCapabilities = initializeRequiredCapabilities();
+        if (!Strings.isNullOrEmpty(physicalInterfaces) && physicalInterfaces != NO_PUBLIC_INT_SPECIFIED) {
+            loadPhysicalInterfaces(physicalInterfaces);
+        }
+    }
+
+    /**
+     * Caches list of physical interfaces.
+     */
+    public void loadPhysicalInterfaces(@Nonnull String physicalInterfaces) {
+        for (String intfOnNode : Sets.newConcurrentHashSet(Splitter.on(",").split(physicalInterfaces))) {
+            List<String> entries = Lists.newArrayList(Splitter.on(":").split(intfOnNode));
+            if (entries.size() != 2) {
+                LOG.warn("Cannot resolve {} initial configuration for physical interfaces.", intfOnNode);
+                continue;
+            }
+            NodeId nodeId = new NodeId(entries.get(0));
+            PhysicalInterfaceKey infaceKey = new PhysicalInterfaceKey(entries.get(1));
+            LOG.info("Interface " + infaceKey + " on node " + nodeId + "will be considered as external");
+            extInterfaces.put(nodeId, infaceKey);
+        }
     }
 
     /**
@@ -296,7 +330,6 @@ public class VppNodeManager {
 
     private void syncPhysicalInterfacesInLocalDs(DataBroker mountPointDataBroker, InstanceIdentifier<Node> nodeIid) {
         ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
-        InstanceIdentifier.create(Interfaces.class);
         ReadOnlyTransaction rTx = mountPointDataBroker.newReadOnlyTransaction();
         Optional<Interfaces> readIfaces = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
                 InstanceIdentifier.create(Interfaces.class), rTx);
@@ -307,8 +340,10 @@ public class VppNodeManager {
                 .build();
             Optional<RendererNode> optRendNode = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,
                     rendererNodeIid, rwTx);
-            RendererNode rendNode = new RendererNodeBuilder(optRendNode.get()).addAugmentation(
-                    VppInterfaceAugmentation.class, resolveTerminationPoints(readIfaces.get())).build();
+            NodeId nodeId = nodeIid.firstKeyOf(Node.class).getNodeId();
+            RendererNode rendNode = new RendererNodeBuilder(optRendNode.get())
+                .addAugmentation(VppInterfaceAugmentation.class, resolveTerminationPoints(nodeId, readIfaces.get()))
+                .build();
             rwTx.put(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodeIid(optRendNode.get()), rendNode,
                     true);
         }
@@ -316,18 +351,26 @@ public class VppNodeManager {
         DataStoreHelper.submitToDs(rwTx);
     }
 
-    private VppInterfaceAugmentation resolveTerminationPoints(Interfaces interfaces) {
+    private VppInterfaceAugmentation resolveTerminationPoints(NodeId nodeId, Interfaces interfaces) {
         List<PhysicalInterface> phIfaces = new ArrayList<>();
-        PhysicalInterfaceBuilder phIface = new PhysicalInterfaceBuilder();
         if (interfaces != null && interfaces.getInterface() != null) {
             interfaces.getInterface()
                 .stream()
                 .filter(iface -> iface.getType().equals(EthernetCsmacd.class))
                 .filter(iface -> iface.getAugmentation(Interface1.class) != null)
                 .forEach(iface -> {
+                    PhysicalInterfaceBuilder phIface = new PhysicalInterfaceBuilder();
                     phIface.setInterfaceName(iface.getName());
                     phIface.setType(iface.getType());
                     phIface.setAddress(resolveIpAddress(iface.getAugmentation(Interface1.class)));
+
+                    if (extInterfaces.get(nodeId) != null && extInterfaces.get(nodeId)
+                        .getInterfaceName()
+                        .equals(phIface.getInterfaceName())) {
+                        phIface.setExternal(true);
+                        LOG.trace("Assigning external Interface, interface name: {}, extInterface name: {}",
+                            phIface.getInterfaceName(), extInterfaces.get(nodeId).getInterfaceName());
+                    }
                     phIfaces.add(phIface.build());
                 });
         }
index a5821228beda73aa7e1e89f1410cad4f5ebaaeeb..0b046e2c4a323656ef6700e91661e5a42b411591 100644 (file)
@@ -12,24 +12,20 @@ import java.net.Inet4Address;
 import java.net.Inet6Address;\r
 import java.net.InetAddress;\r
 import java.net.UnknownHostException;\r
-import java.util.ArrayList;\r
 import java.util.List;\r
-import java.util.concurrent.ExecutionException;\r
 import java.util.concurrent.atomic.AtomicInteger;\r
 import java.util.stream.Collectors;\r
 \r
+import org.apache.commons.net.util.SubnetUtils;\r
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
-import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
-import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
-import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;\r
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;\r
@@ -40,20 +36,13 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntry;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
 import com.google.common.base.Optional;\r
-import com.google.common.util.concurrent.AsyncFunction;\r
-import com.google.common.util.concurrent.Futures;\r
-import com.google.common.util.concurrent.ListenableFuture;\r
-\r
 public class NatManager {\r
 \r
     private static final Logger LOG = LoggerFactory.getLogger(NatManager.class);\r
@@ -68,42 +57,9 @@ public class NatManager {
         this.mountDataProvider = mountDataProvider;\r
     }\r
 \r
-    public Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix) {\r
-        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();\r
-        Optional<RendererNodes> readFromDs = DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL,\r
-                VppIidFactory.getRendererNodesIid(), rTx);\r
-        rTx.close();\r
-        if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
-            return Optional.absent();\r
-        }\r
-        RendererNodes rendererNodes = readFromDs.get();\r
-        List<RendererNode> vppNodes = rendererNodes.getRendererNode()\r
-            .stream()\r
-            .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
-            .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
-            .collect(Collectors.toList());\r
-        for (RendererNode rn : vppNodes) {\r
-            java.util.Optional<PhysicalInterface> optResolvedIface = rn.getAugmentation(VppInterfaceAugmentation.class)\r
-                .getPhysicalInterface()\r
-                .stream()\r
-                .filter(phIface -> phIface.getAddress() != null)\r
-                .filter(phIface -> phIface.getAddress()\r
-                    .stream()\r
-                    .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
-                .findFirst();\r
-            if (optResolvedIface.isPresent()) {\r
-                return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
-                    .builder()\r
-                    .augmentation(VppInterfaceAugmentation.class)\r
-                    .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
-                    .build());\r
-            }\r
-        }\r
-        return Optional.absent();\r
-    }\r
-\r
     public Optional<MappingEntryBuilder> resolveSnatEntry(String internal, Ipv4Address external) {\r
         IpAddress internalIp = null;\r
+        LOG.trace("Resolving SNAT entry for internal: {}, external: {}", internal, external);\r
         try {\r
             InetAddress inetAddr = InetAddress.getByName(internal);\r
             if (inetAddr instanceof Inet4Address) {\r
@@ -115,12 +71,21 @@ public class NatManager {
             LOG.error("Cannot resolve host IP {}. {}", internal, e.getMessage());\r
             return Optional.absent();\r
         }\r
-        return Optional.of(new MappingEntryBuilder().setInternalSrcAddress(internalIp).setExternalSrcAddress(external));\r
+        SubnetUtils subnet = new SubnetUtils(internal + "/32" );\r
+        Long index = Integer.toUnsignedLong(subnet.getInfo().asInteger(internal));\r
+        MappingEntryBuilder mappingEntryBuilder =\r
+            new MappingEntryBuilder().setType(\r
+                org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.MappingEntry.Type.Static)\r
+                .setIndex(index)\r
+                .setInternalSrcAddress(internalIp)\r
+                .setExternalSrcAddress(external);\r
+        LOG.trace("Resolved SNAT mapping: {}", mappingEntryBuilder.build().toString());\r
+        return Optional.of(mappingEntryBuilder);\r
     }\r
 \r
-    public ListenableFuture<Void> submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
+    public void submitNatChanges(List<InstanceIdentifier<PhysicalInterface>> physIfacesIid,\r
             List<MappingEntryBuilder> natEntries, PolicyContext policyCtx, boolean add) {\r
-        List<ListenableFuture<Void>> submitedFutures = new ArrayList<>();\r
+        LOG.trace("Preparing to submit NAT changes {} on physical interfaces", natEntries.toArray(), physIfacesIid);\r
         for (InstanceIdentifier<PhysicalInterface> iidPhysIface : physIfacesIid) {\r
             InstanceIdentifier<?> nodeIid = iidPhysIface.firstKeyOf(RendererNode.class).getNodePath();\r
             Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);\r
@@ -128,45 +93,39 @@ public class NatManager {
                 throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);\r
             }\r
             String phInterfaceName = iidPhysIface.firstKeyOf(PhysicalInterface.class).getInterfaceName();\r
-            ReadWriteTransaction rwTx = mountPointDataBroker.get().newReadWriteTransaction();\r
-            InstanceIdentifier<Interface> interfaceIID = VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
-            submitedFutures.add(Futures.transform(rwTx.read(LogicalDatastoreType.CONFIGURATION, interfaceIID),\r
-                    new AsyncFunction<Optional<Interface>, Void>() {\r
+            InstanceIdentifier<Interface> interfaceIID =\r
+                VppIidFactory.getInterfaceIID(new InterfaceKey(phInterfaceName));\r
 \r
-                        @Override\r
-                        public ListenableFuture<Void> apply(Optional<Interface> readIface) throws Exception {\r
-                            if (!readIface.isPresent()) {\r
-                                LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
-                                return Futures.immediateFuture(null);\r
-                            }\r
-                            if (add) {\r
-                                LOG.trace("Setting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
-                                NatUtil.setOutboundInterface(readIface.get(), rwTx); \r
-                                rwTx.put(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id),\r
-                                        buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx)));\r
-                            } else {\r
-                                LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
-                                NatUtil.unsetOutboundInterface(readIface.get(), rwTx);\r
-                                if (rwTx.read(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id))\r
-                                    .get()\r
-                                    .isPresent()) {\r
-                                    rwTx.delete(LogicalDatastoreType.CONFIGURATION, VppIidFactory.getNatInstanceIid(id));\r
-                                }\r
-                            }\r
-                            return rwTx.submit();\r
-                        }\r
-                    }));\r
-        }\r
-        try {\r
-            Futures.allAsList(submitedFutures).get();\r
-        } catch (InterruptedException | ExecutionException e) {\r
-            LOG.error("Failed to sync NAT. {}", e.getMessage());\r
-            e.printStackTrace();\r
+            Optional<Interface> readIface =\r
+                GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION, interfaceIID,\r
+                    GbpNetconfTransaction.RETRY_COUNT);\r
+\r
+            if (!readIface.isPresent()) {\r
+                LOG.error("Interface {} not found on mount point {}", phInterfaceName, nodeIid);\r
+                return;\r
+            }\r
+            if (add) {\r
+                LOG.trace("Setting outbound NAT on interface {} on node: {}", iidPhysIface.getPathArguments(), nodeIid);\r
+                NatUtil.setOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+                NatInstance natInstance =\r
+                    buildNatInstance(natEntries, NatUtil.resolveDynamicNat(policyCtx, natEntries));\r
+                GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(),\r
+                    VppIidFactory.getNatInstanceIid(id), natInstance, GbpNetconfTransaction.RETRY_COUNT);\r
+            } else {\r
+                LOG.trace("UNsetting outbound NAT on interface {}.", iidPhysIface.getPathArguments());\r
+                NatUtil.unsetOutboundInterface(readIface.get(), mountPointDataBroker.get());\r
+                if (GbpNetconfTransaction.read(mountPointDataBroker.get(), LogicalDatastoreType.CONFIGURATION,\r
+                    VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT).isPresent()) {\r
+                    GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(),\r
+                        VppIidFactory.getNatInstanceIid(id), GbpNetconfTransaction.RETRY_COUNT);\r
+                }\r
+            }\r
+            return;\r
         }\r
-        return Futures.immediateFuture(null);\r
     }\r
 \r
-    private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries, List<ExternalIpAddressPool> poolEntries) {\r
+    private NatInstance buildNatInstance(List<MappingEntryBuilder> natEntries,\r
+        List<ExternalIpAddressPool> poolEntries) {\r
         AtomicInteger ai = new AtomicInteger();\r
          List<MappingEntry> mappingEntries = natEntries.stream().map(me -> {\r
             int value = ai.get();\r
@@ -174,6 +133,10 @@ public class NatManager {
             return me.setIndex((long) value).build();\r
         }).collect(Collectors.toList());\r
         MappingTable mappingTable = new MappingTableBuilder().setMappingEntry(mappingEntries).build();\r
-        return new NatInstanceBuilder().setId(id).setExternalIpAddressPool(poolEntries).setMappingTable(mappingTable).build();\r
+        return new NatInstanceBuilder()\r
+            .setId(id)\r
+            .setExternalIpAddressPool(poolEntries)\r
+            .setMappingTable(mappingTable)\r
+            .build();\r
     }\r
 }\r
index c2fff1cae300230be05e7ede89c29e5e59f0dd68..6887d6f79ed40195b6701bbf083860b31f987c3b 100644 (file)
@@ -1,6 +1,6 @@
 /*\r
  * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.\r
- * \r
+ *\r
  * This program and the accompanying materials are made available under the\r
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
@@ -10,6 +10,12 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp.nat;
 \r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
+\r
+import com.google.common.annotations.VisibleForTesting;\r
+import com.google.common.base.Optional;\r
+\r
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;\r
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;\r
 import java.util.List;\r
 import java.util.Map;\r
 import java.util.Map.Entry;\r
@@ -21,14 +27,26 @@ import org.apache.commons.net.util.SubnetUtils;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;\r
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.PolicyContext;\r
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;\r
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;\r
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;\r
+import org.opendaylight.groupbasedpolicy.util.NetUtils;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.nat.instance.mapping.table.MappingEntryBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPool;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.parameters.ExternalIpAddressPoolBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.AllocationPool;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.RendererNodes;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.VppInterfaceAugmentation;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;\r
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterfaceKey;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214.NatInterfaceAugmentation;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.Nat;\r
@@ -36,8 +54,13 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interfa
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.InboundBuilder;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang._interface.nat.rev161214._interface.nat.attributes.nat.OutboundBuilder;\r
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import java.util.stream.Collectors;\r
 \r
 public class NatUtil {\r
+    private static final Logger LOG = LoggerFactory.getLogger(NatUtil.class);\r
 \r
     public void setInboundInterface(Interface iface, WriteTransaction wTx) {\r
         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
@@ -45,22 +68,62 @@ public class NatUtil {
         wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
     }\r
 \r
-    public static void setOutboundInterface(Interface iface, WriteTransaction wTx) {\r
+    public static void setOutboundInterface(Interface iface, DataBroker dataBroker) {\r
         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
         Nat nat = new NatBuilder().setOutbound(new OutboundBuilder().build()).build();\r
-        wTx.put(LogicalDatastoreType.CONFIGURATION, natIid, nat);\r
+        GbpNetconfTransaction.netconfSyncedWrite(dataBroker, natIid, nat, GbpNetconfTransaction.RETRY_COUNT);\r
+\r
     }\r
 \r
-    public static void unsetOutboundInterface(Interface iface, WriteTransaction wTx) {\r
+    public static void unsetOutboundInterface(Interface iface, DataBroker dataBroker) {\r
         InstanceIdentifier<Nat> natIid = buildNatIid(VppIidFactory.getInterfaceIID(iface.getKey()));\r
-        wTx.delete(LogicalDatastoreType.CONFIGURATION, natIid);\r
+        GbpNetconfTransaction.netconfSyncedDelete(dataBroker, natIid, GbpNetconfTransaction.RETRY_COUNT);\r
     }\r
 \r
     public static InstanceIdentifier<Nat> buildNatIid(InstanceIdentifier<Interface> ifaceIid) {\r
         return ifaceIid.builder().augmentation(NatInterfaceAugmentation.class).child(Nat.class).build();\r
     }\r
 \r
-    public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx) {\r
+    public static Optional<InstanceIdentifier<PhysicalInterface>> resolvePhysicalInterface(IpPrefix extSubnetPrefix,\r
+        ReadOnlyTransaction rTx) {\r
+        Optional<RendererNodes> readFromDs =\r
+            DataStoreHelper.readFromDs(LogicalDatastoreType.OPERATIONAL, VppIidFactory.getRendererNodesIid(), rTx);\r
+        rTx.close();\r
+        if (!readFromDs.isPresent() || readFromDs.get().getRendererNode() == null) {\r
+            return Optional.absent();\r
+        }\r
+        RendererNodes rendererNodes = readFromDs.get();\r
+        List<RendererNode>\r
+            vppNodes =\r
+            rendererNodes.getRendererNode()\r
+                .stream()\r
+                .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class) != null)\r
+                .filter(rn -> rn.getAugmentation(VppInterfaceAugmentation.class).getPhysicalInterface() != null)\r
+                .collect(Collectors.toList());\r
+        for (RendererNode rn : vppNodes) {\r
+            java.util.Optional<PhysicalInterface>\r
+                optResolvedIface =\r
+                rn.getAugmentation(VppInterfaceAugmentation.class)\r
+                    .getPhysicalInterface()\r
+                    .stream()\r
+                    .filter(phIface -> phIface.getAddress() != null)\r
+                    .filter(phIface -> phIface.getAddress()\r
+                        .stream()\r
+                        .anyMatch(ipAddr -> NetUtils.isInRange(extSubnetPrefix, String.valueOf(ipAddr.getValue()))))\r
+                    .findFirst();\r
+            if (optResolvedIface.isPresent()) {\r
+                return Optional.of(VppIidFactory.getRendererNodeIid(rn)\r
+                    .builder()\r
+                    .augmentation(VppInterfaceAugmentation.class)\r
+                    .child(PhysicalInterface.class, new PhysicalInterfaceKey(optResolvedIface.get().getKey()))\r
+                    .build());\r
+            }\r
+        }\r
+        return Optional.absent();\r
+    }\r
+\r
+    public static List<ExternalIpAddressPool> resolveDynamicNat(@Nonnull PolicyContext policyCtx,\r
+        List<MappingEntryBuilder> natEntries) {\r
         List<RendererForwardingByTenant> rendererForwardingByTenant =\r
                 policyCtx.getPolicy().getConfiguration().getRendererForwarding().getRendererForwardingByTenant();\r
         Map<Long, Ipv4Prefix> hm = new HashMap<>();\r
@@ -72,7 +135,7 @@ public class NatUtil {
                     for (AllocationPool pool : subnet.getSubnet().getAllocationPool()) {\r
                         if (subnet.getSubnet().getIpPrefix().getIpv4Prefix() != null) {\r
                             hm.putAll(resolveIpv4Prefix(subnet.getSubnet().getIpPrefix().getIpv4Prefix(),\r
-                                    pool.getFirst(), pool.getLast()));\r
+                                    pool.getFirst(), pool.getLast(), natEntries));\r
                         }\r
                     }\r
                 }\r
@@ -80,13 +143,17 @@ public class NatUtil {
         }\r
         List<ExternalIpAddressPool> extIps = new ArrayList<>();\r
         for (Entry<Long, Ipv4Prefix> entry : hm.entrySet()) {\r
-            new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey()).setExternalIpPool(entry.getValue()).build();\r
+            extIps.add(new ExternalIpAddressPoolBuilder().setPoolId(entry.getKey())\r
+                .setExternalIpPool(entry.getValue())\r
+                .build());\r
         }\r
         return extIps;\r
     }\r
 \r
+    @VisibleForTesting\r
     private static Map<Long,Ipv4Prefix> resolveIpv4Prefix(@Nonnull Ipv4Prefix prefix, @Nonnull String first,\r
-            @Nullable String last) {\r
+            @Nullable String last, @Nullable List<MappingEntryBuilder> natEntries) {\r
+        LOG.trace("Resolving Ipv4Prefix. prefix: {}, first: {}, last: {}", prefix.getValue(), first, last);\r
         SubnetUtils subnet = new SubnetUtils(prefix.getValue());\r
         Map<Long,Ipv4Prefix> ext = new HashMap<>();\r
         int min = subnet.getInfo().asInteger(first);\r
@@ -95,11 +162,20 @@ public class NatUtil {
             if (asInt < min) {\r
                 continue;\r
             }\r
-            ext.put(Long.valueOf(asInt), new Ipv4Prefix(addr + "/32"));\r
-            if (last == null || subnet.getInfo().asInteger(addr) > subnet.getInfo().asInteger(last)) {\r
+            ext.put(Integer.toUnsignedLong(asInt), new Ipv4Prefix(addr + "/32"));\r
+            if (last == null || subnet.getInfo().asInteger(addr) >= subnet.getInfo().asInteger(last)) {\r
                 break;\r
             }\r
         }\r
+        if (natEntries != null) {\r
+            for (MappingEntryBuilder natEntry : natEntries) {\r
+                Ipv4Address externalSrcAddress = natEntry.getExternalSrcAddress();\r
+                long id = Integer.toUnsignedLong(subnet.getInfo().asInteger(externalSrcAddress.getValue()));\r
+                if (ext.get(id) != null) {\r
+                    ext.remove(id);\r
+                }\r
+            }\r
+        }\r
         return ext;\r
     }\r
 }\r
index 2120b5c0da79824ffb29f35f65382c5823de3b20..c6daeead5e9ffeee4356a1c463d6976cd2c4e190 100644 (file)
@@ -24,10 +24,14 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListUtil;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
@@ -38,13 +42,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpo
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.common.endpoint.fields.network.containment.containment.NetworkDomainContainment;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.LocationType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.absolute.location.location.type.ExternalLocationCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.ParentEndpointChoice;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.ParentEndpointCase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.parent.child.endpoints.parent.endpoint.choice.parent.endpoint._case.ParentEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.ContextId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.NetworkDomainId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.common.rev140421.TenantId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.IpPrefixType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.L2FloodDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.MacAddressType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.NetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.rev160427.forwarding.fields.Parent;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.NatAddressRenderer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.Configuration;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.Endpoints;
@@ -89,13 +98,16 @@ public final class ForwardingManager {
     private final AclManager aclManager;
     private final BridgeDomainManager bdManager;
     private final NatManager natManager;
+    private final RoutingManager routingManager;
     private final DataBroker dataBroker;
 
     public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull AclManager aclManager,
-        @Nonnull NatManager natManager, @Nonnull BridgeDomainManager bdManager, @Nonnull DataBroker dataBroker) {
+        @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager,
+        @Nonnull DataBroker dataBroker) {
         this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
         this.bdManager = Preconditions.checkNotNull(bdManager);
         this.natManager = Preconditions.checkNotNull(natManager);
+        this.routingManager = Preconditions.checkNotNull(routingManager);
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.aclManager = Preconditions.checkNotNull(aclManager);
     }
@@ -364,7 +376,8 @@ public final class ForwardingManager {
         for (RendererNetworkDomain rendDomain : rendNetDomains) {
             Optional<IpPrefix> resolvedIpPrefix = resolveIpPrefix(rendDomain);
             if (resolvedIpPrefix.isPresent()) {
-                Optional<InstanceIdentifier<PhysicalInterface>> resPhIface = natManager.resolvePhysicalInterface(resolvedIpPrefix.get());
+                Optional<InstanceIdentifier<PhysicalInterface>> resPhIface =
+                    NatUtil.resolvePhysicalInterface(resolvedIpPrefix.get(), dataBroker.newReadOnlyTransaction());
                 if (resPhIface.isPresent()) {
                     physIfaces.add(resPhIface.get());
                 }
@@ -387,13 +400,19 @@ public final class ForwardingManager {
             if (addrEp.getAugmentation(NatAddressRenderer.class) == null) {
                 continue;
             }
+            String enpointIP = resolveEpIpAddressForSnat(addrEp);
+
+            if (enpointIP == null) {
+                LOG.warn("Endpoints {} IP cannot be null, skipping processing of SNAT", addrEp);
+            }
+
             NatAddressRenderer natAddr = addrEp.getAugmentation(NatAddressRenderer.class);
             if (natAddr.getNatAddress() == null && natAddr.getNatAddress().getIpv4Address() == null) {
-                LOG.warn("Only Ipv4 SNAT is currently supported. Cannot apply SNAT for [{},{}]", addrEp.getAddress(),
+                LOG.warn("Only Ipv4 SNAT is currently supported. Cannot apply SNAT for [{},{}]", enpointIP,
                         natAddr.getNatAddress());
                 continue;
             }
-            Optional<MappingEntryBuilder> entry = natManager.resolveSnatEntry(addrEp.getAddress(), natAddr.getNatAddress()
+            Optional<MappingEntryBuilder> entry = natManager.resolveSnatEntry(enpointIP, natAddr.getNatAddress()
                 .getIpv4Address());
             if (entry.isPresent()) {
                 sNatEntries.add(entry.get());
@@ -402,8 +421,76 @@ public final class ForwardingManager {
         return sNatEntries;
     }
 
+    private String resolveEpIpAddressForSnat(AddressEndpointWithLocation addrEp) {
+        if (addrEp.getAddressType().equals(MacAddressType.class)) {
+            ParentEndpointChoice parentEndpointChoice = addrEp.getParentEndpointChoice();
+            if (parentEndpointChoice instanceof ParentEndpointCase
+                && !((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().isEmpty()) {
+                ParentEndpoint parentEndpoint = ((ParentEndpointCase) parentEndpointChoice).getParentEndpoint().get(0);
+                if (parentEndpoint.getAddressType().equals(IpPrefixType.class)) {
+                    String[] ipWithPrefix = parentEndpoint.getAddress().split("/");
+                    return ipWithPrefix[0];
+                } else {
+                    LOG.warn("Endpoint {} Does not have a Parent Ep with IP for SNAT. skipping processing of SNAT",
+                        addrEp);
+                    return null;
+                }
+
+            } else {
+                LOG.warn("Endpoint {} Does not contain IP address for SNAT. skipping processing of SNAT", addrEp);
+                return null;
+            }
+        } else if (addrEp.getAddressType().equals(IpPrefixType.class)) {
+            return addrEp.getAddress();
+        }
+        return null;
+    }
+
     @VisibleForTesting
     void setTimer(byte time) {
         WAIT_FOR_BD_PROCESSING = time;
     }
+
+    public void syncRouting(PolicyContext policyCtx) {
+        Configuration cfg = policyCtx.getPolicy().getConfiguration();
+        if (cfg != null && cfg.getRendererForwarding() != null) {
+            for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
+                if (fwd == null) {
+                    continue;
+                }
+
+                List<InstanceIdentifier<PhysicalInterface>>
+                    physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
+                Map<InstanceIdentifier<?>, RoutingCommand> routingCommandMap =
+                    routingManager.createRouting(fwd, physIfacesIid, General.Operations.PUT);
+
+                routingCommandMap.forEach((node, command) -> {
+                    if (command != null && routingManager.submitRouting(command, node)) {
+                        LOG.debug("Routing was successfully applied: {}.", command);
+                    }
+                });
+            }
+        }
+    }
+
+    public void deleteRouting(PolicyContext policyCtx) {
+        Configuration cfg = policyCtx.getPolicy().getConfiguration();
+        if (cfg != null && cfg.getRendererForwarding() != null) {
+            for (RendererForwardingByTenant fwd : cfg.getRendererForwarding().getRendererForwardingByTenant()) {
+                if (fwd == null) {
+                    continue;
+                }
+
+                List<InstanceIdentifier<PhysicalInterface>>
+                    physIfacesIid = resolvePhysicalInterfacesForNat(fwd.getRendererNetworkDomain());
+                Map<InstanceIdentifier<?>, RoutingCommand> routingCommandMap =
+                    routingManager.createRouting(fwd, physIfacesIid, General.Operations.DELETE);
+                routingCommandMap.forEach((node, command) -> {
+                    if (command != null && routingManager.submitRouting(command, node)) {
+                        LOG.debug("Routing was successfully removed: {}.", command);
+                    }
+                });
+            }
+        }
+    }
 }
index 2ef3cae9f6b430fe672260325c76402d4972360c..3b7ae60461820784397e571691a738c6f102d796 100644 (file)
@@ -55,6 +55,7 @@ import com.google.common.eventbus.Subscribe;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 
+
 public class VppRendererPolicyManager {
 
     private static final Logger LOG = LoggerFactory.getLogger(VppRendererPolicyManager.class);
@@ -116,6 +117,7 @@ public class VppRendererPolicyManager {
     }
 
     private void rendererPolicyUpdated(RendererPolicy rPolicyBefore, RendererPolicy rPolicyAfter) {
+        LOG.trace("VPP renderer policy updated");
         PolicyContext policyCtxBefore = new PolicyContext(rPolicyBefore);
         PolicyContext policyCtxAfter = new PolicyContext(rPolicyAfter);
         MapDifference<String, Collection<NodeId>> vppNodesByL2FlDiff =
@@ -169,6 +171,9 @@ public class VppRendererPolicyManager {
 
         fwManager.syncNatEntries(policyCtxAfter);
 
+        fwManager.deleteRouting(policyCtxBefore);
+        fwManager.syncRouting(policyCtxAfter);
+
         SetView<RendererEndpointKey> createdRendEps = Sets.difference(rendEpsAfter, rendEpsBefore);
         LOG.debug("Created renderer endpoints {}", createdRendEps);
         createdRendEps.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtxAfter));
@@ -257,16 +262,19 @@ public class VppRendererPolicyManager {
     }
 
     private void rendererPolicyCreated(RendererPolicy rPolicy) {
+        LOG.trace("VPP renderer policy version {} created", rPolicy.getVersion());
         PolicyContext policyCtx = new PolicyContext(rPolicy);
         ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
 
         SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
         fwManager.createBridgeDomainOnNodes(vppNodesByL2Fd);
         fwManager.syncNatEntries(policyCtx);
+        fwManager.syncRouting(policyCtx);
         rEpKeys.forEach(rEpKey -> fwManager.createForwardingForEndpoint(rEpKey, policyCtx));
     }
 
     private void rendererPolicyDeleted(RendererPolicy rendererPolicy) {
+        LOG.trace("VPP renderer policy version {} deleted", rendererPolicy.getVersion());
         PolicyContext policyCtx = new PolicyContext(rendererPolicy);
         ImmutableSet<RendererEndpointKey> rEpKeys = policyCtx.getPolicyTable().rowKeySet();
 
@@ -274,6 +282,7 @@ public class VppRendererPolicyManager {
 
         SetMultimap<String, NodeId> vppNodesByL2Fd = resolveVppNodesByL2Fd(rEpKeys, policyCtx);
         fwManager.deleteNatEntries(policyCtx);
+        fwManager.deleteRouting(policyCtx);
         fwManager.removeBridgeDomainOnNodes(vppNodesByL2Fd);
     }
 
index cffb525aec6e24d14bf333a7ff7dee1ce27552e6..0a22d95c7fb62215b361e13a7cb5eb5f445e352f 100644 (file)
@@ -77,7 +77,7 @@ public abstract class AccessListWrapper {
 
     public void writeAcl(@Nonnull DataBroker mountPoint, @Nonnull InterfaceKey ifaceKey) {
         Acl builtAcl = this.buildVppAcl(ifaceKey);
-        LOG.info("Writing access-list {}", builtAcl.getAclName());
+        LOG.trace("Writing access-list {}", builtAcl.getAclName());
         boolean write = GbpNetconfTransaction.netconfSyncedWrite(mountPoint,
                 VppIidFactory.getVppAcl(resolveAclName(ifaceKey)), builtAcl, GbpNetconfTransaction.RETRY_COUNT);
         if (!write) {
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/routing/RoutingManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/routing/RoutingManager.java
new file mode 100644 (file)
index 0000000..0483a43
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.routing;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+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.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.SubnetAugmentRenderer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.Gateways;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.forwarding.l2_l3.rev160427.has.subnet.subnet.gateways.Prefixes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.nodes.RendererNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.RendererForwardingByTenant;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.renderer.forwarding.renderer.forwarding.by.tenant.RendererNetworkDomain;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.renderers.renderer.renderer.nodes.renderer.node.PhysicalInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RoutingManager {
+    private static final Logger LOG = LoggerFactory.getLogger(RoutingManager.class);
+
+    private static final long DEFAULT_TABLE = 0L;
+
+    private final DataBroker dataBroker;
+    private final MountedDataBrokerProvider mountDataProvider;
+
+    public RoutingManager(DataBroker dataBroker, MountedDataBrokerProvider mountDataProvider) {
+        this.dataBroker = dataBroker;
+        this.mountDataProvider = mountDataProvider;
+    }
+
+    public Map<InstanceIdentifier<?>, RoutingCommand> createRouting(
+        @Nonnull RendererForwardingByTenant forwardingByTenant, List<InstanceIdentifier<PhysicalInterface>> physIntIids,
+        General.Operations operation) {
+
+        Map<InstanceIdentifier<?>, RoutingCommand> routingCommands = new HashMap<>();
+
+        getExternalGateways(forwardingByTenant.getRendererNetworkDomain()).forEach((gateways, virtualRouterIp) -> {
+            LOG.trace("Creating routing for Tenant {}, gateway {}, virtualRouterIp {}.",
+                forwardingByTenant.getTenantId(), gateways, virtualRouterIp);
+            List<Route> ipv4Routes = new ArrayList<>();
+            PhysicalInterface outboundInterface = resolveOutboundInterface(virtualRouterIp, physIntIids);
+            InstanceIdentifier<?> node = resolveOutboundNode(virtualRouterIp, physIntIids);
+
+            String outboundIntName = outboundInterface != null ? outboundInterface.getInterfaceName() : null;
+
+            if (Strings.isNullOrEmpty(outboundIntName)) {
+                LOG.trace("Route skipped, no physical interface for gateway found {} in interfaces {}", gateways,
+                    physIntIids);
+            } else {
+                Long routeIndex = 0L;
+                IpAddress externalGwIp = gateways.getGateway();
+                for (Prefixes prefixes : gateways.getPrefixes()) {
+                    routeIndex++;
+                    Route ipv4Route = buildIpv4Route(outboundIntName, routeIndex, externalGwIp, prefixes);
+                    //todo add support for ipv6
+                    LOG.trace("Adding new route {}.", ipv4Route);
+                    ipv4Routes.add(ipv4Route);
+                }
+            }
+
+            if (!ipv4Routes.isEmpty()) {
+                RoutingCommand command = routingCommands.put(node, new RoutingCommand.RoutingCommandBuilder()
+                        .setOperation(operation)
+                        .setRouterProtocol("learned-protocol-0")
+                        .setRoutes(ipv4Routes)
+                        //todo in multi-tenant environment we need to use different vrfID for each tenant
+                        .setVrfId(DEFAULT_TABLE)
+                        .build());
+                LOG.trace("Creating of routing successful, routing command: {}.", command);
+            }
+        });
+
+        return routingCommands;
+    }
+
+    private Route buildIpv4Route(String outboundIntName, Long routeIndex, IpAddress externalGwIp, Prefixes prefixes) {
+        return new RouteBuilder().setId(routeIndex)
+            .setDestinationPrefix(new Ipv4Prefix(prefixes.getPrefix().getIpv4Prefix()))
+            .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(externalGwIp.getIpv4Address()))
+                .setOutgoingInterface(outboundIntName)
+                .build())
+            .build();
+    }
+
+    /**
+     * Used to extract external gateways from network domains if they contain any gateways
+     * @param rendererNetworkDomain list of network domains from which we extract external gateways
+     * @return map of extracted gateways by virtual router IP from network domain list.
+     */
+    private Map<Gateways, IpAddress> getExternalGateways(List<RendererNetworkDomain> rendererNetworkDomain){
+        Map<Gateways, IpAddress> gateways = new HashMap<>();
+        for (RendererNetworkDomain domain : rendererNetworkDomain) {
+            SubnetAugmentRenderer subnet = domain.getAugmentation(SubnetAugmentRenderer.class);
+            IpAddress virtualRouterIp = subnet.getSubnet().getVirtualRouterIp();
+            if (virtualRouterIp == null){
+                continue;
+            }
+            List<Gateways> gatewaysList = subnet.getSubnet().getGateways();
+            if (gatewaysList != null) {
+                for (Gateways gateway : gatewaysList) {
+                    gateways.put(gateway, virtualRouterIp);
+                    LOG.trace("Found external Gateway {}", gateway);
+                }
+            }
+        }
+        return gateways;
+    }
+
+    private PhysicalInterface resolveOutboundInterface(@Nonnull IpAddress extIfaceIp,
+        List<InstanceIdentifier<PhysicalInterface>> physIntIids) {
+        LOG.trace("Resolving External interface {} from interfaces {}.", extIfaceIp, physIntIids);
+        for (InstanceIdentifier<PhysicalInterface> identifier : physIntIids) {
+            Optional<PhysicalInterface> physicalInterfaceOptional = DataStoreHelper.readFromDs(
+                LogicalDatastoreType.OPERATIONAL, identifier, dataBroker.newReadOnlyTransaction());
+            if (!physicalInterfaceOptional.isPresent()) {
+                continue;
+            }
+            if (physicalInterfaceOptional.get().isExternal()) {
+                return physicalInterfaceOptional.get();
+            }
+            if (physicalInterfaceOptional.get().getAddress().contains(extIfaceIp)){
+                return physicalInterfaceOptional.get();
+            }
+        }
+        return null;
+    }
+
+    private InstanceIdentifier<?> resolveOutboundNode(@Nonnull IpAddress extIfaceIp,
+        List<InstanceIdentifier<PhysicalInterface>> physIntIids) {
+        for (InstanceIdentifier<PhysicalInterface> identifier : physIntIids) {
+            Optional<PhysicalInterface> physicalInterfaceOptional = DataStoreHelper.readFromDs(
+                LogicalDatastoreType.OPERATIONAL, identifier, dataBroker.newReadOnlyTransaction());
+            if (!physicalInterfaceOptional.isPresent()){
+                continue;
+            }
+            if (physicalInterfaceOptional.get().isExternal()) {
+                return identifier.firstKeyOf(RendererNode.class).getNodePath();
+            }
+            if (physicalInterfaceOptional.get().getAddress().contains(extIfaceIp)){
+                return identifier.firstKeyOf(RendererNode.class).getNodePath();
+            }
+        }
+        return null;
+    }
+
+    public boolean submitRouting(@Nonnull RoutingCommand routing, InstanceIdentifier<?> nodeIid) {
+        if (nodeIid == null) {
+            LOG.info("NodeId is null Cannot create routing. RoutingCommand: {}", routing);
+            return false;
+        }
+        LOG.trace("Submitting routing for routing command: {}, nodeId: {}", routing, nodeIid);
+
+        Optional<DataBroker> mountPointDataBroker = mountDataProvider.getDataBrokerForMountPoint(nodeIid);
+        if (!mountPointDataBroker.isPresent()) {
+            throw new IllegalStateException("Cannot find data broker for mount point " + nodeIid);
+        }
+        LOG.info("Routing was created for forwarding. Routing: {}, for node: {}", routing, nodeIid);
+        if (routing.getOperation() == General.Operations.PUT){
+            return GbpNetconfTransaction.netconfSyncedWrite(mountPointDataBroker.get(), routing,
+                GbpNetconfTransaction.RETRY_COUNT);
+        } else if (routing.getOperation() == General.Operations.DELETE){
+            return GbpNetconfTransaction.netconfSyncedDelete(mountPointDataBroker.get(), routing,
+                GbpNetconfTransaction.RETRY_COUNT);
+        }
+        return false;
+    }
+}
index 26fd5e67e87e80c87481e26ff016382d8106d07f..f0d93dbe7e59c25d892037bf72b30844322daf26 100644 (file)
@@ -130,8 +130,8 @@ public class L4Classifier extends Classifier {
         return ruleBuilder;
     }
 
-    private SourcePortRangeBuilder resolveSourcePortRange(Map<String, ParameterValue> params, String portParam, String portRangeParam) {
-        LOG.info("Updating dest port params:{}", params);
+    private SourcePortRangeBuilder resolveSourcePortRange(Map<String, ParameterValue> params, String portParam,
+        String portRangeParam) {
         SourcePortRangeBuilder srcRange = new SourcePortRangeBuilder();
         if (params.get(portParam) != null) {
             PortNumber portNumber = new PortNumber(params.get(portParam).getIntValue().intValue());
@@ -144,8 +144,8 @@ public class L4Classifier extends Classifier {
         return srcRange;
     }
 
-    private DestinationPortRangeBuilder resolveDestinationPortRange(Map<String, ParameterValue> params, String portParam, String portRangeParam) {
-        LOG.info("Updating source port params:{}", params);
+    private DestinationPortRangeBuilder resolveDestinationPortRange(Map<String, ParameterValue> params,
+        String portParam, String portRangeParam) {
         DestinationPortRangeBuilder dstRange = new DestinationPortRangeBuilder();
         if (params.get(portParam) != null) {
             PortNumber portNumber = new PortNumber(params.get(portParam).getIntValue().intValue());
index 12f5b6acf3d7322e1563e4ad03015dbd53a13617..9c5d01a9004841d366f6dbf95b0df0498e7c9e62 100644 (file)
@@ -17,8 +17,11 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ConfigCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
 import org.opendaylight.vbd.impl.transaction.VbdNetconfTransaction;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
@@ -26,6 +29,7 @@ import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
 import com.google.common.util.concurrent.CheckedFuture;
 
 public class GbpNetconfTransaction {
@@ -65,6 +69,21 @@ public class GbpNetconfTransaction {
         return result;
     }
 
+    /***
+     * Netconf wrapper method for synced requests for write operation on a Netconf Device
+     * @param mountpoint    netconf device
+     * @param command       routing command that needs to be executed
+     * @param retryCounter  retry counter, will repeat the operation for specified amount of times if transaction fails
+     * @return true if transaction is successful, false otherwise
+     */
+    public static boolean netconfSyncedWrite(@Nonnull final DataBroker mountpoint, @Nonnull final RoutingCommand command,
+        byte retryCounter) {
+        VbdNetconfTransaction.REENTRANT_LOCK.lock();
+        boolean result = write(mountpoint, command, retryCounter);
+        VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+        return result;
+    }
+
     /***
      * Netconf wrapper method for synced requests for delete operation on a Netconf Device
      * @param mountpoint    netconf device
@@ -96,6 +115,20 @@ public class GbpNetconfTransaction {
         return result;
     }
 
+    /***
+     * Netconf wrapper method for synced requests for delete operation on a Netconf Device
+     * @param mountpoint    netconf device
+     * @param command       routing command that needs to be executed
+     * @param retryCounter  retry counter, will repeat the operation for specified amount of times if transaction fails
+     * @return true if transaction is successful, false otherwise
+     */
+    public static boolean netconfSyncedDelete(@Nonnull final DataBroker mountpoint,
+        @Nonnull final RoutingCommand command, byte retryCounter) {
+        VbdNetconfTransaction.REENTRANT_LOCK.lock();
+        boolean result = deleteIfExists(mountpoint, command, retryCounter);
+        VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+        return result;
+    }
 
     /**
      * Use {@link ConfigCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
@@ -127,6 +160,36 @@ public class GbpNetconfTransaction {
         }
     }
 
+    /**
+     * Use {@link RoutingCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
+     *
+     * @param mountpoint   to access remote device
+     * @param command      routing command with data, datastore type and iid
+     * @param retryCounter number of attempts
+     * @return true if transaction is successful, false otherwise
+     */
+    private static boolean write(final DataBroker mountpoint, final RoutingCommand command, byte retryCounter) {
+        LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
+        Preconditions.checkNotNull(mountpoint);
+        final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
+        try {
+            command.execute(rwTx);
+            final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
+            futureTask.get();
+            LOG.trace("Netconf WRITE transaction done for command {}", command);
+            return true;
+        } catch (Exception e) {
+            // Retry
+            if (retryCounter > 0) {
+                LOG.warn("Netconf WRITE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+                return write(mountpoint, command, --retryCounter);
+            } else {
+                LOG.warn("Netconf WRITE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
+                return false;
+            }
+        }
+    }
+
     /**
      * Write data to remote device. Transaction is restarted if failed
      *
@@ -137,10 +200,8 @@ public class GbpNetconfTransaction {
      * @param <T>          generic data type. Has to be child of {@link DataObject}
      * @return true if transaction is successful, false otherwise
      */
-    private static <T extends DataObject> boolean write(final DataBroker mountpoint,
-                                                                    final InstanceIdentifier<T> iid,
-                                                                    final T data,
-                                                                    byte retryCounter) {
+    private static <T extends DataObject> boolean write(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
+        final T data, byte retryCounter) {
         LOG.trace("Netconf WRITE transaction started. RetryCounter: {}", retryCounter);
         Preconditions.checkNotNull(mountpoint);
         final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
@@ -173,16 +234,14 @@ public class GbpNetconfTransaction {
      * @return optional data object if successful, {@link Optional#absent()} if failed
      */
     public static synchronized <T extends DataObject> Optional<T> read(final DataBroker mountpoint,
-                                                                       final LogicalDatastoreType datastoreType,
-                                                                       final InstanceIdentifier<T> iid,
-                                                                       byte retryCounter) {
+        final LogicalDatastoreType datastoreType, final InstanceIdentifier<T> iid, byte retryCounter) {
         LOG.trace("Netconf READ transaction started. RetryCounter: {}", retryCounter);
         Preconditions.checkNotNull(mountpoint);
         final ReadOnlyTransaction rTx = mountpoint.newReadOnlyTransaction();
         Optional<T> data;
         try {
             final CheckedFuture<Optional<T>, ReadFailedException> futureData =
-                    rTx.read(datastoreType, iid);
+                rTx.read(datastoreType, iid);
             data = futureData.get();
             LOG.trace("Netconf READ transaction done. Data present: {}", data.isPresent());
             return data;
@@ -207,13 +266,32 @@ public class GbpNetconfTransaction {
      * @param retryCounter number of attempts
      * @return true if transaction is successful, false otherwise
      */
-    private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command,
-                                              byte retryCounter) {
+    private static boolean deleteIfExists(final DataBroker mountpoint, final ConfigCommand command, byte retryCounter) {
         Preconditions.checkNotNull(mountpoint);
         InstanceIdentifier<Interface> iid = VppIidFactory.getInterfaceIID(command.getInterfaceBuilder().getKey());
         return deleteIfExists(mountpoint, iid, retryCounter);
     }
 
+    /**
+     * Remove data from remote device using {@link ConfigCommand}
+     *
+     * @param mountpoint   to access remote device
+     * @param command      config command with data, datastore type and iid
+     * @param retryCounter number of attempts
+     * @return true if transaction is successful, false otherwise
+     */
+    private static boolean deleteIfExists(final DataBroker mountpoint, final RoutingCommand command,
+        byte retryCounter) {
+        Preconditions.checkNotNull(mountpoint);
+        String routerProtocol = command.getRouterProtocol();
+        if (Strings.isNullOrEmpty(routerProtocol)) {
+            routerProtocol = "learned-protocol-0";
+        }
+        InstanceIdentifier<RoutingProtocol> iid =
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routerProtocol));
+        return deleteIfExists(mountpoint, iid, retryCounter);
+    }
+
     /**
      * Remove data from remote device. Data presence is verified before removal. Transaction is restarted if failed.
      *
@@ -224,14 +302,13 @@ public class GbpNetconfTransaction {
      * @return true if transaction is successful, false otherwise
      */
     private static <T extends DataObject> boolean deleteIfExists(final DataBroker mountpoint,
-                                                                     final InstanceIdentifier<T> iid,
-                                                                     byte retryCounter) {
+        final InstanceIdentifier<T> iid, byte retryCounter) {
         LOG.trace("Netconf DELETE transaction started. Data will be read at first. RetryCounter: {}", retryCounter);
         Preconditions.checkNotNull(mountpoint);
         final Optional<T> optionalObject = read(mountpoint, LogicalDatastoreType.CONFIGURATION, iid, RETRY_COUNT);
         if (!optionalObject.isPresent()) {
             LOG.warn("Netconf DELETE transaction aborted. Data to remove are not present or cannot be read. Iid: {}",
-                    iid);
+                iid);
             // Return true, this state is not considered as an error
             return true;
         }
index d6861e798fa32880bbb9d33e3ee3b97f27098d8b..402aa2d371a401907347cc9aa0b27b38ac1a542b 100644 (file)
@@ -9,6 +9,7 @@
 package org.opendaylight.groupbasedpolicy.renderer.vpp.util;
 
 import org.opendaylight.controller.config.yang.config.vpp_provider.impl.VppRenderer;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.AccessLists;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.Acl;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.access.control.list.rev160708.access.lists.AclKey;
@@ -19,6 +20,12 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev1509
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.NatInstances;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstance;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.nat.config.nat.instances.NatInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstance;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.RoutingInstanceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.RoutingProtocols;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.Renderers;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.RendererKey;
@@ -119,4 +126,13 @@ public class VppIidFactory {
                 .child(NatInstance.class, new NatInstanceKey(natInstance))
                 .build();
     }
+
+    public static InstanceIdentifier<RoutingProtocol> getRoutingInstanceIid(
+        final RoutingProtocolKey routingProtocolKey) {
+        return InstanceIdentifier.builder(Routing.class)
+            .child(RoutingInstance.class, new RoutingInstanceKey(RoutingCommand.ROUTER_INSTANCE_NAME))
+            .child(RoutingProtocols.class)
+            .child(RoutingProtocol.class, routingProtocolKey)
+            .build();
+    }
 }
diff --git a/renderers/vpp/src/main/resources/org.opendaylight.groupbasedpolicy.vpp.startup.cfg b/renderers/vpp/src/main/resources/org.opendaylight.groupbasedpolicy.vpp.startup.cfg
new file mode 100644 (file)
index 0000000..362951a
--- /dev/null
@@ -0,0 +1,12 @@
+# INITIAL VPP HOSTCONFIG CONFIGURATION
+#
+# Uncomment lines on the bottom of this file to change
+# default values of vpp-renderer bundle config.
+# The file should be placed to karaf_root_dir/etc
+#
+# To explicitly specify which physical interface of a
+# node should be used public interface, uncomment and modify the
+# line on the bottom of this document. Specifying one physical
+# interface per node is currently supported.
+#
+#public-interfaces = compute1:TenGigabitEthernet8/0/0,compute2:TenGigabitEthernet8/0/0
\ No newline at end of file
index 62a8dbfbd4fd1eec8f7ffb9e6b3343da7ef6814c..cfde3ccea53e29b183c9ecc484f2f3c8db391be6 100644 (file)
@@ -1,19 +1,27 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
            xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
            odl:use-default-for-reference-types="true">
 
     <reference id="dataBroker" interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"/>
     <reference id="broker" interface="org.opendaylight.controller.sal.binding.api.BindingAwareBroker"/>
     <reference id="clusterSingletonService" interface="org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider"/>
 
+    <cm:property-placeholder persistent-id="org.opendaylight.groupbasedpolicy.vpp.startup" update-strategy="none">
+        <cm:default-properties>
+            <cm:property name="public-interfaces" value="unspecified"/>
+        </cm:default-properties>
+    </cm:property-placeholder>
+
     <bean id="vppRenderer" class="org.opendaylight.controller.config.yang.config.vpp_provider.impl.GbpVppProviderInstance"
         init-method="initialize" destroy-method="close">
         <argument ref="dataBroker"/>
         <argument ref="broker"/>
         <argument ref="clusterSingletonService" />
+        <argument value="${public-interfaces}"/>
     </bean>
 
     <odl:rpc-implementation ref="vppRenderer"/>
 
-</blueprint>
\ No newline at end of file
+</blueprint>
index 8c95cdb938f06ed707c3df92aba87ce54eeaee8c..9c80c6b357d8afbc68d818c56a8529df431cf936 100644 (file)
@@ -178,6 +178,10 @@ module vpp-renderer {
             leaf-list address {
                 type inet-types:ip-address;
             }
+            leaf external {
+                type boolean;
+                default  "false";
+            }
         }
     }
 
index 5ff71e0adc42b55b10f706e3a1d75f767f1e080b..e8932d96a82acb986246755a402165b649396d53 100644 (file)
@@ -74,7 +74,7 @@ public class VppRendererTest  extends VppRendererDataBrokerTest {
 
     @Test
     public void testCreateVppRenderer() throws Exception {
-        VppRenderer vppRenderer = new VppRenderer(dataBroker, bindingAwareBroker);
+        VppRenderer vppRenderer = new VppRenderer(dataBroker, bindingAwareBroker, null);
 
         vppRenderer.onSessionInitiated(providerContext);
 
index 97793caa27ac96a58be83538aa1fc2aa3d3a47c3..96f9693a883511b8071f9ad899d86e67e5fb4841 100644 (file)
@@ -11,6 +11,8 @@ package org.opendaylight.groupbasedpolicy.renderer.vpp;
 import com.google.common.collect.ImmutableList;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;\r
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;\r
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Routing;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.endpoint_location_provider.rev160419.LocationProviders;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.Renderer;\r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;\r
@@ -30,7 +32,7 @@ public class VppRendererDataBrokerTest extends CustomDataBrokerTest {
     @Override\r
     public Collection<Class<?>> getClassesFromModules() {\r
         return ImmutableList.of(Interfaces.class, Interface.class, VhostUser.class, NetworkTopology.class,\r
-                Topology.class, Node.class, NetconfNode.class, Renderer.class, LocationProviders.class, Config.class,\r
-            NatInterfaceAugmentation.class);\r
+            Topology.class, Node.class, NetconfNode.class, Renderer.class, LocationProviders.class, Config.class,\r
+            NatInterfaceAugmentation.class, Routing.class, StaticRoutes1.class);\r
     }\r
 }\r
diff --git a/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommandTest.java b/renderers/vpp/src/test/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/RoutingCommandTest.java
new file mode 100644 (file)
index 0000000..73554c9
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2016 Cisco Systems. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.groupbasedpolicy.renderer.vpp.commands;
+
+import com.google.common.base.Optional;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+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.LogicalDatastoreType;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.VppRendererDataBrokerTest;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.StaticRoutes1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.Route;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.VppIpv4RouteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ipv4.unicast.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol._static.routes.ipv4.route.next.hop.options.SimpleNextHopBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.Static;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocol;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.RoutingProtocolKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.routing.rev140524.routing.routing.instance.routing.protocols.routing.protocol.StaticRoutesBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttr;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.RoutingProtocolVppAttrBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.vpp.routing.rev161214.routing.routing.instance.routing.protocols.routing.protocol.VppProtocolAttributesBuilder;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+
+public class RoutingCommandTest extends VppRendererDataBrokerTest {
+
+    private final static String NEXT_HOP = "10.0.0.1";
+    private final static String OUT_INTERFACE = "GigabitEthernet0/a/0";
+    private final static String PREFIX = "10.0.0.0/24";
+    private final static String PREFIX_2 = "0.0.0.0/0";
+    private final static String ROUTER_PROTOCOL = "vpp-routing-protocol_0";
+    private final static String ROUTE1_DESCRIPTION = "route 1";
+    private final static String ROUTE2_DESCRIPTION = "route 2";
+    private final static VniReference VNI_REFERENCE = new VniReference(0L);
+    private final static Route
+        ROUTE_1 =
+        new RouteBuilder().setId(1L)
+            .setDescription(ROUTE1_DESCRIPTION)
+            .setDestinationPrefix(new Ipv4Prefix(PREFIX))
+            .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(NEXT_HOP))
+                .setOutgoingInterface(OUT_INTERFACE)
+                .build())
+            .setVppIpv4Route(new VppIpv4RouteBuilder().setClassifyTable("0").setSecondaryVrf(VNI_REFERENCE).build())
+            .build();
+    private final static Route
+        ROUTE_2 =
+        new RouteBuilder().setId(2L)
+            .setDescription(ROUTE2_DESCRIPTION)
+            .setDestinationPrefix(new Ipv4Prefix(PREFIX_2))
+            .setNextHopOptions(new SimpleNextHopBuilder().setNextHop(new Ipv4Address(NEXT_HOP))
+                .setOutgoingInterface(OUT_INTERFACE)
+                .build())
+            .setVppIpv4Route(new VppIpv4RouteBuilder().setClassifyTable("0").setSecondaryVrf(VNI_REFERENCE).build())
+            .build();
+    private final static List<Route> ROUTES = Collections.singletonList(ROUTE_1);
+    private final static List<Route> ROUTES2 = Collections.singletonList(ROUTE_2);
+
+    private final static RoutingProtocol ROUTING_PROTOCOL = new RoutingProtocolBuilder()
+        .setEnabled(true)
+        .setType(Static.class)
+        .setName(ROUTER_PROTOCOL)
+        .addAugmentation(RoutingProtocolVppAttr.class, new RoutingProtocolVppAttrBuilder().setVppProtocolAttributes(
+            new VppProtocolAttributesBuilder().setPrimaryVrf(VNI_REFERENCE).build()).build())
+        .setStaticRoutes(new StaticRoutesBuilder().addAugmentation(StaticRoutes1.class,
+            new StaticRoutes1Builder().setIpv4(new Ipv4Builder().setRoute(ROUTES).build()).build()).build())
+        .build();
+
+    private DataBroker dataBroker;
+
+    @Before
+    public void init() {
+        dataBroker = getDataBroker();
+    }
+
+    @Test
+    public void addRoutingCommandTest() throws ExecutionException, InterruptedException {
+        ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+
+        RoutingCommand
+            routingCommand =
+            RoutingCommand.builder()
+                .setOperation(General.Operations.PUT)
+                .setRouterProtocol(ROUTER_PROTOCOL)
+                .setRoutes(ROUTES)
+                .setVrfId(VNI_REFERENCE.getValue())
+                .build();
+
+        Assert.assertEquals(General.Operations.PUT, routingCommand.getOperation());
+        Assert.assertEquals(ROUTER_PROTOCOL, routingCommand.getRouterProtocol());
+        Assert.assertEquals(VNI_REFERENCE.getValue(), routingCommand.getVrfId());
+        Assert.assertEquals(ROUTES, routingCommand.getRoutes());
+
+        Optional<RoutingProtocol> routingProtocolOptional = executeCommand(rwTx, routingCommand);
+
+        Assert.assertTrue(routingProtocolOptional.isPresent());
+        Assert.assertEquals(ROUTING_PROTOCOL, routingProtocolOptional.get());
+    }
+
+    @Test
+    public void removeRoutingCommandTest() throws ExecutionException, InterruptedException {
+        Optional<RoutingProtocol> optional = writeBasicRoutingProtocol();
+        ReadWriteTransaction rwTx;
+
+        Assert.assertTrue(optional.isPresent());
+
+        rwTx = dataBroker.newReadWriteTransaction();
+        RoutingCommand routingCommand =
+            RoutingCommand.builder()
+                .setOperation(General.Operations.DELETE)
+                .setRouterProtocol(ROUTER_PROTOCOL)
+                .setVrfId(VNI_REFERENCE.getValue())
+                .build();
+        routingCommand.execute(rwTx);
+        rwTx.submit();
+
+        optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())),
+            dataBroker.newReadOnlyTransaction());
+
+        Assert.assertFalse(optional.isPresent());
+    }
+
+    @Test
+    public void mergeRoutingCommandTest() throws ExecutionException, InterruptedException {
+        Optional<RoutingProtocol> optional = writeBasicRoutingProtocol();
+        ReadWriteTransaction rwTx;
+
+        Assert.assertTrue(optional.isPresent());
+
+        rwTx = dataBroker.newReadWriteTransaction();
+
+        RoutingCommand
+            routingCommand =
+            RoutingCommand.builder()
+                .setOperation(General.Operations.MERGE)
+                .setRouterProtocol(ROUTER_PROTOCOL)
+                .setRoutes(ROUTES2)
+                .setVrfId(VNI_REFERENCE.getValue())
+                .build();
+
+        routingCommand.execute(rwTx);
+        rwTx.submit();
+
+        optional = DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())),
+            dataBroker.newReadOnlyTransaction());
+
+        Assert.assertTrue(optional.isPresent());
+        RoutingProtocol routingProtocol = optional.get();
+        StaticRoutes1 staticRoutes1 = routingProtocol.getStaticRoutes().getAugmentation(StaticRoutes1.class);
+        Assert.assertTrue(staticRoutes1.getIpv4().getRoute().contains(ROUTE_1));
+        Assert.assertTrue(staticRoutes1.getIpv4().getRoute().contains(ROUTE_2));
+    }
+
+    private Optional<RoutingProtocol> writeBasicRoutingProtocol() throws InterruptedException, ExecutionException {
+        ReadWriteTransaction rwTx = dataBroker.newReadWriteTransaction();
+        rwTx.put(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(ROUTER_PROTOCOL)), ROUTING_PROTOCOL, true);
+        rwTx.submit().get();
+
+        return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(ROUTER_PROTOCOL)),
+            dataBroker.newReadOnlyTransaction());
+    }
+
+    private Optional<RoutingProtocol> executeCommand(ReadWriteTransaction rwTx, RoutingCommand routingCommand)
+        throws ExecutionException, InterruptedException {
+        routingCommand.execute(rwTx);
+
+        rwTx.submit().get();
+
+        ReadOnlyTransaction rTx = dataBroker.newReadOnlyTransaction();
+
+        return DataStoreHelper.readFromDs(LogicalDatastoreType.CONFIGURATION,
+            VppIidFactory.getRoutingInstanceIid(new RoutingProtocolKey(routingCommand.getRouterProtocol())), rTx);
+    }
+}
index 48eb9e810d5d34299de6b04c9a8bea8c1be700bd..7b8622fdbe34bf29c79c9eb4bafa61b291356586 100644 (file)
@@ -90,7 +90,7 @@ public class VppManagerDataStoreTest extends VppRendererDataBrokerTest {
             .thenReturn(Optional.of(mountPoint));
         Mockito.when(mountPoint.getService(Matchers.<Class<DataBroker>>any())).thenReturn(Optional.of(dataBroker2));
         dataBroker = getDataBroker();
-        vppNodeManager = new VppNodeManager(dataBroker, providerContext);
+        vppNodeManager = new VppNodeManager(dataBroker, providerContext, null);
         vppNodeListener = new VppNodeListener(dataBroker, vppNodeManager, new EventBus());
     }
 
index 3e618a87931c5078d8d6d040669785d6622be78d..461cb2dde0e62ad1bfc6abaf1d463e2776558e72 100644 (file)
@@ -8,13 +8,13 @@
 
 package org.opendaylight.groupbasedpolicy.renderer.vpp.policy;
 
-import javax.annotation.Nonnull;
-
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.concurrent.ExecutionException;
 
+import javax.annotation.Nonnull;
+
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
@@ -25,6 +25,7 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
 import org.opendaylight.groupbasedpolicy.util.DataStoreHelper;
@@ -67,7 +68,8 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
     private final static NodeId VPP_NODE_ID = new NodeId("vppNode");
     private final static Topology BASE_TOPOLOGY = new TopologyBuilder().setTopologyId(BASE_TOPOLOGY_ID)
         .setNode(Collections.singletonList(new NodeBuilder().setNodeId(VPP_NODE_ID)
-                .setSupportingNode(Collections.singletonList(new SupportingNodeBuilder().setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF)
+                .setSupportingNode(Collections.singletonList(new SupportingNodeBuilder()
+                        .setTopologyRef(SUPPORTING_TOPOLOGY_NETCONF)
                         .setNodeRef(VPP_NODE_ID)
                         .build()))
                 .build()))
@@ -103,8 +105,10 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
         final InterfaceManager interfaceManager = Mockito.mock(InterfaceManager.class);
         final AclManager aclManager = Mockito.mock(AclManager.class);
         final NatManager natManager = Mockito.mock(NatManager.class);
+        final RoutingManager routingManager = Mockito.mock(RoutingManager.class);
         final ForwardingManager fwManager =
-            new ForwardingManager(interfaceManager, aclManager, natManager, bridgeDomainManager, dataBroker);
+            new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bridgeDomainManager,
+                dataBroker);
         fwManager.setTimer((byte) 1);
     }
 
index 0b118631adb386da8fad9451088c171ab18d790b..6fe134fd10278b2e4964f33c92be9578e090a991 100644 (file)
@@ -24,8 +24,9 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.base_endpoint.rev160427.has.absolute.location.AbsoluteLocation;
@@ -64,12 +65,15 @@ public class ForwardingManagerTest extends CustomDataBrokerTest {
     private BridgeDomainManager bdManager;
     @Mock
     private NatManager natManager;
+    @Mock
+    private RoutingManager routingManager;
 
     private ForwardingManager fwdManager;
 
     @Before
     public void init() {
-        fwdManager = new ForwardingManager(ifaceManager, aclManager,natManager, bdManager, getDataBroker());
+        fwdManager =
+            new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, getDataBroker());
     }
 
     @Override
@@ -111,7 +115,8 @@ public class ForwardingManagerTest extends CustomDataBrokerTest {
         Mockito.when(bdManager.createVlanBridgeDomainOnVppNode(Mockito.eq(BD_1), Mockito.any(VlanId.class),
                 Mockito.eq(NODE_1)))
             .thenReturn(Futures.immediateFuture(null));
-        GbpBridgeDomain bd = new GbpBridgeDomainBuilder().setId(BD_1).setType(VlanNetwork.class).setVlan(VLAN_1).build();
+        GbpBridgeDomain bd =
+            new GbpBridgeDomainBuilder().setId(BD_1).setType(VlanNetwork.class).setVlan(VLAN_1).build();
         InstanceIdentifier<GbpBridgeDomain> bdIid =
                 InstanceIdentifier.builder(Config.class).child(GbpBridgeDomain.class, bd.getKey()).build();
         WriteTransaction wTx = getDataBroker().newWriteOnlyTransaction();
@@ -164,12 +169,14 @@ public class ForwardingManagerTest extends CustomDataBrokerTest {
         String clientIp = "1.1.1.1";
         String clientIfaceName = "client1";
         String bdNameOnVpp = "bdRed";
-        AbsoluteLocation clientLocation = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, clientIfaceName);
+        AbsoluteLocation clientLocation =
+            DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, clientIfaceName);
         AddressEndpointWithLocation clientEp =
                 DtoFactory.createEndpoint(clientIp, DtoFactory.L2FD_CTX.getValue(), clientLocation);
         String webIp = "2.2.2.2";
         String webIfaceName = "web1";
-        AbsoluteLocation webLocation = DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, webIfaceName);
+        AbsoluteLocation webLocation =
+            DtoFactory.absoluteLocation(DtoFactory.VPP_NODE_1_IID, bdNameOnVpp, webIfaceName);
         AddressEndpointWithLocation webEp =
                 DtoFactory.createEndpoint(webIp, DtoFactory.L2FD_CTX.getValue(), webLocation);
         Configuration configuration = DtoFactory.createConfiguration(Arrays.asList(clientEp), Arrays.asList(webEp));
index d6bd6ee962cf5e469d1e00958804e47cf91ab6d6..061255831d9780171d7e6cbf8b98649b284c35ed 100644 (file)
@@ -30,6 +30,7 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.KeyFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
 import org.opendaylight.groupbasedpolicy.test.CustomDataBrokerTest;
@@ -49,11 +50,11 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.r
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocationKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.Config;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpointKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.bridge.domain.base.attributes.PhysicalLocationRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425._interface.attributes._interface.type.choice.VhostUserCaseBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.VxlanVni;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev161214.interfaces._interface.L2;
@@ -84,6 +85,7 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
     private AclManager aclManager;
     private ForwardingManager fwManager;
     private NatManager natManager;
+    private RoutingManager routingManager;
     private VppRendererPolicyManager vppRendererPolicyManager;
 
     @Override
@@ -104,8 +106,9 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         ifaceManager = new InterfaceManager(mountedDataProviderMock, dataBroker);
         aclManager = new AclManager(mountedDataProviderMock);
         natManager = new NatManager(dataBroker, mountedDataProviderMock);
+        routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
         bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
-        fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, bdManager, dataBroker);
+        fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, dataBroker);
         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
         fwManager.setTimer((byte) 1);
     }