Add implementation for flat L3 overlay 96/56496/15
authorShakib Ahmed <sheikahm@cisco.com>
Fri, 12 May 2017 06:05:57 +0000 (23:05 -0700)
committerShakib Ahmed <sheikahm@cisco.com>
Thu, 15 Jun 2017 15:38:15 +0000 (08:38 -0700)
For flat L3 overlay, we need to put extra configs on top of regular
LISP configs. We need to enable proxy arp for interfaces, put proxy
arp ranges, put static routing, static arp. On top, we have to create
loopback interface, set unnumbered interfaces and add GPE action for
a route.

This patch implements:
 - Enable proxy arp for every port interface
 - Add proxy arp per subnet for a host
 - Add static routing for every port interface
 - Add static arp for every port interface
 - Add loopback interface per subnet for a host for unnumbered

Change-Id: I3779efe03855ac6602f397caaf5492c3c42d27f6
Signed-off-by: Shakib Ahmed <sheikahm@cisco.com>
33 files changed:
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/AbstractInterfaceCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/TapPortCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/VhostUserCommand.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/InterfaceManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/iface/VppPathMapper.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispState.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/LispStateManager.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java [deleted file]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java [deleted file]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/ConfigManagerHelper.java
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java [new file with mode: 0644]
renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/policy/ForwardingManager.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/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 6b50c3e5a72e4d0cd3950a393bca668a2c5985e6..80c8a9801a3170bb1f159c161d2e73d005e0f9a8 100644 (file)
@@ -24,7 +24,9 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.event.manager.GbpSubnetEventManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.GbpSubnetListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.RendererPolicyListener;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.listener.VppEndpointListener;
@@ -80,6 +82,7 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
     private VppEndpointListener vppEndpointListener;
     private RendererPolicyListener rendererPolicyListener;
     private GbpSubnetListener vppGbpSubnetListener;
+    private GbpSubnetEventManager subnetEventManager;
 
     VppRenderer(@Nonnull DataBroker dataBroker, @Nonnull BindingAwareBroker bindingAwareBroker,
                        @Nullable String publicInterfaces) {
@@ -143,14 +146,16 @@ public class VppRenderer implements AutoCloseable, BindingAwareProvider {
         AclManager aclManager = new AclManager(mountDataProvider);
         NatManager natManager = new NatManager(dataBroker, mountDataProvider);
         LispStateManager lispStateManager = new LispStateManager(mountDataProvider);
-        BviManager bviManager = new BviManager(mountDataProvider);
+        FlatOverlayManager flatOverlayManager = new FlatOverlayManager(mountDataProvider);
+        LoopbackManager loopbackManager = new LoopbackManager(mountDataProvider);
+        subnetEventManager = new GbpSubnetEventManager(loopbackManager);
         dtoEventBus.register(interfaceManager);
-        dtoEventBus.register(bviManager);
+        dtoEventBus.register(subnetEventManager);
         RoutingManager routingManager = new RoutingManager(dataBroker, mountDataProvider);
         bdManager = new BridgeDomainManagerImpl(dataBroker);
         ForwardingManager fwManager =
                 new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bdManager,
-                        lispStateManager, bviManager,dataBroker);
+                        lispStateManager, loopbackManager, flatOverlayManager, dataBroker);
         VppRendererPolicyManager vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
         dtoEventBus.register(vppRendererPolicyManager);
 
index 27d7bdeee54b5b21cb2c9c0dbb1fa2d0321badfe..8b921d64612968e64bc0353b4f7f9c82785ce25c 100644 (file)
@@ -16,6 +16,9 @@ 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.interfaces.rev140508.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyArpInterfaceAugmentationBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.interfaces._interface.ProxyArpBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -27,8 +30,10 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
     protected General.Operations operation;
     protected String name;
     protected String description;
-    String bridgeDomain;
-    Boolean enabled;
+    protected String bridgeDomain;
+    protected Boolean enabled;
+    protected Boolean enableProxyArp;
+    protected Long vrfId;
 
     public General.Operations getOperation() {
         return operation;
@@ -38,6 +43,10 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
         return name;
     }
 
+    public Long getVrfId() {
+        return vrfId;
+    }
+
     public String getDescription() {
         return description;
     }
@@ -47,7 +56,7 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
         return this;
     }
 
-    String getBridgeDomain() {
+    public String getBridgeDomain() {
         return bridgeDomain;
     }
 
@@ -98,4 +107,12 @@ public abstract class AbstractInterfaceCommand implements ConfigCommand, Interfa
         return VppIidFactory.getInterfaceIID(this.getInterfaceBuilder().getKey());
     }
 
+    protected void addEnableProxyArpAugmentation(InterfaceBuilder interfaceBuilder) {
+        if (enableProxyArp != null) {
+            ProxyArpInterfaceAugmentationBuilder augmentationBuilder = new ProxyArpInterfaceAugmentationBuilder();
+            augmentationBuilder.setProxyArp((new ProxyArpBuilder()).build());
+            interfaceBuilder.addAugmentation(ProxyArpInterfaceAugmentation.class, augmentationBuilder.build());
+        }
+    }
+
 }
index b9f5a679bb5360880676972ae11e80f294b60c78..97e4690bfa25b09bb4e5a988638b2997f8d05e71 100644 (file)
@@ -44,7 +44,6 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
     private boolean bvi;
     private IpAddress ipAddress;
     private IpPrefix ipPrefix;
-    private Long vrfId;
 
     private LoopbackCommand(LoopbackCommandBuilder builder) {
         this.name = builder.getInterfaceName();
@@ -57,6 +56,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
         this.ipAddress = builder.getIpAddress();
         this.ipPrefix = builder.getIpPrefix();
         this.vrfId = builder.getVrfId();
+        this.enableProxyArp = builder.getEnableProxyArp();
     }
 
     public static LoopbackCommandBuilder builder() {
@@ -79,10 +79,6 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
         return ipPrefix;
     }
 
-    Long getVrfId() {
-        return vrfId;
-    }
-
     @Override
     public InterfaceBuilder getInterfaceBuilder() {
         InterfaceBuilder interfaceBuilder = new InterfaceBuilder().setKey(new InterfaceKey(name))
@@ -115,6 +111,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
                                 .build())).build());
         interfaceBuilder.addAugmentation(Interface1.class, interface1Builder.build());
         interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build());
+        addEnableProxyArpAugmentation(interfaceBuilder);
         return interfaceBuilder;
     }
 
@@ -127,7 +124,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
     public String toString() {
         return "LoopPortUserCommand [physAddress=" + physAddress + ", IpAddress=" + ipAddress + ", IpPrefix=" + ipPrefix
                 + ", bridgeDomain=" + bridgeDomain + ", operations=" + operation + ", name=" + name + ", description="
-                + description + ", enabled=" + enabled + ", bvi=" + bvi + "]";
+                + description + ", enabled=" + enabled + ", bvi=" + bvi + ", enableProxyArp=" + enableProxyArp + "]";
     }
 
     private short getPrefixLength() {
@@ -146,6 +143,7 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
         private IpAddress ipAddress;
         private IpPrefix ipPrefix;
         private Long vrfId;
+        private Boolean enableProxyArp;
 
         public String getInterfaceName() {
             return interfaceName;
@@ -237,6 +235,14 @@ public class LoopbackCommand extends AbstractInterfaceCommand {
             return this;
         }
 
+        public Boolean getEnableProxyArp() {
+            return enableProxyArp;
+        }
+
+        public void setEnableProxyArp(Boolean enableProxyArp) {
+            this.enableProxyArp = enableProxyArp;
+        }
+
         /**
          * LoopPortCommand build method.
          *
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/LoopbackCommandWrapper.java
new file mode 100644 (file)
index 0000000..5a023a7
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017 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 org.opendaylight.groupbasedpolicy.renderer.vpp.util.General;
+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.IpPrefix;
+
+/**
+ * Created by Shakib Ahmed on 5/16/17.
+ */
+public class LoopbackCommandWrapper {
+
+    public static LoopbackCommand simpleLoopbackPutCommand(String interfaceName,
+                                                    long vrf,
+                                                    IpAddress ipAddress,
+                                                    IpPrefix cidr) {
+        LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder =
+                simpleLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr);
+        simpleLoopbackCommandBuilder.setOperation(General.Operations.PUT);
+        return simpleLoopbackCommandBuilder.build();
+    }
+
+    public static LoopbackCommand bviLoopbackPutCommand(String interfaceName,
+                                                 long vrf,
+                                                 IpAddress ipAddress,
+                                                 IpPrefix cidr,
+                                                 String bridgeDomainName) {
+        LoopbackCommand.LoopbackCommandBuilder bviLoopbackCommandBuilder =
+                bviLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr, bridgeDomainName);
+        bviLoopbackCommandBuilder.setOperation(General.Operations.PUT);
+        return bviLoopbackCommandBuilder.build();
+    }
+
+    private static LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder(String interfaceName,
+                                                                                       long vrf,
+                                                                                       IpAddress ipAddress,
+                                                                                       IpPrefix cidr) {
+        LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder = new LoopbackCommand.LoopbackCommandBuilder();
+        loopbackCommandBuilder.setInterfaceName(interfaceName);
+        loopbackCommandBuilder.setEnabled(true);
+        loopbackCommandBuilder.setVrfId(vrf);
+        loopbackCommandBuilder.setIpAddress(ipAddress);
+        loopbackCommandBuilder.setIpPrefix(cidr);
+        return loopbackCommandBuilder;
+    }
+
+    private static LoopbackCommand.LoopbackCommandBuilder bviLoopbackCommandBuilder(String interfaceName,
+                                                                                    long vrf,
+                                                                                    IpAddress ipAddress,
+                                                                                    IpPrefix cidr,
+                                                                                    String bridgeDomainName) {
+        LoopbackCommand.LoopbackCommandBuilder simpleLoopbackCommandBuilder =
+                simpleLoopbackCommandBuilder(interfaceName, vrf, ipAddress, cidr);
+        simpleLoopbackCommandBuilder.setBridgeDomain(bridgeDomainName);
+        simpleLoopbackCommandBuilder.setBvi(true);
+        return simpleLoopbackCommandBuilder;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/ProxyRangeCommand.java
new file mode 100644 (file)
index 0000000..1a65afe
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017 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.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 5/3/17.
+ */
+public class ProxyRangeCommand extends AbstractConfigCommand {
+    private static final Logger LOG = LoggerFactory.getLogger(ProxyRangeCommand.class);
+
+    private Long vrf;
+    private Ipv4Address startAddress;
+    private Ipv4Address endAddress;
+
+    public ProxyRangeCommand(ProxyRangeCommandBuilder builder) {
+        this.operation = builder.getOperation();
+        this.vrf = builder.getVrf();
+        this.startAddress = builder.getStartAddress();
+        this.endAddress = builder.getEndAddress();
+    }
+
+    public static ProxyRangeCommandBuilder builder() {
+        return new ProxyRangeCommandBuilder();
+    }
+
+    @Override
+    public InstanceIdentifier getIid() {
+        return VppIidFactory.getProxyRangeIid(vrf, startAddress, endAddress);
+    }
+
+    @Override
+    void put(ReadWriteTransaction rwTx) {
+        InstanceIdentifier<ProxyRange> proxyRangeInstanceIid = VppIidFactory.getProxyRangeIid(vrf, startAddress, endAddress);
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIid, getProxyRangeBuilder().build(), true);
+    }
+
+    @Override
+    void merge(ReadWriteTransaction rwTx) {
+        InstanceIdentifier<ProxyRange> proxyRangeInstanceIdentifier = VppIidFactory.
+                                                                        getProxyRangeIid(vrf, startAddress, endAddress);
+        rwTx.merge(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIdentifier, getProxyRangeBuilder().build(), true);
+    }
+
+    @Override
+    void delete(ReadWriteTransaction rwTx) {
+        try {
+            InstanceIdentifier<ProxyRange> proxyRangeInstanceIdentifier = VppIidFactory.
+                    getProxyRangeIid(vrf, startAddress, endAddress);
+            rwTx.delete(LogicalDatastoreType.CONFIGURATION, proxyRangeInstanceIdentifier);
+        } catch (IllegalStateException ex) {
+            LOG.debug("Proxy Range not deleted from DS {}", this, ex);
+        }
+    }
+
+    private ProxyRangeBuilder getProxyRangeBuilder() {
+        return new ProxyRangeBuilder()
+                .setKey(new ProxyRangeKey(this.endAddress, this.startAddress, this.vrf))
+                .setVrfId(this.vrf)
+                .setLowAddr(this.startAddress)
+                .setHighAddr(this.endAddress);
+    }
+
+
+    public static class ProxyRangeCommandBuilder {
+
+        private General.Operations operation;
+        private Long vrf;
+        private Ipv4Address startAddress;
+        private Ipv4Address endAddress;
+
+        public Long getVrf() {
+            return vrf;
+        }
+
+        public void setVrf(Long vrf) {
+            this.vrf = vrf;
+        }
+
+        public Ipv4Address getStartAddress() {
+            return startAddress;
+        }
+
+        public void setStartAddress(Ipv4Address startAddress) {
+            this.startAddress = startAddress;
+        }
+
+        public Ipv4Address getEndAddress() {
+            return endAddress;
+        }
+
+        public void setEndAddress(Ipv4Address endAddress) {
+            this.endAddress = endAddress;
+        }
+
+        public General.Operations getOperation() {
+            return operation;
+        }
+
+        public void setOperation(General.Operations operation) {
+            this.operation = operation;
+        }
+
+        /**
+         * ProxyRangeCommand build method.
+         *
+         * @return ProxyRangeCommand
+         * @throws IllegalArgumentException if vrf, operation, startAddress or endAddress is null.
+         */
+        public ProxyRangeCommand build() {
+            Preconditions.checkNotNull(operation, "Operation must not be null!");
+            Preconditions.checkNotNull(vrf, "vrf must not be null!");
+            Preconditions.checkNotNull(startAddress, "StartAddress must not be null!");
+            Preconditions.checkNotNull(endAddress, "EndAddress must not be null!");
+            return new ProxyRangeCommand(this);
+        }
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/commands/StaticArpCommand.java
new file mode 100644 (file)
index 0000000..64204f0
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2017 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.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Created by Shakib Ahmed on 5/3/17.
+ */
+public class StaticArpCommand extends AbstractConfigCommand{
+    private static final Logger LOG = LoggerFactory.getLogger(StaticArpCommand.class);
+
+    private Ipv4AddressNoZone ip;
+    private PhysAddress linkLayerAddress;
+    private InterfaceKey interfaceKey;
+
+    public StaticArpCommand(NeighborCommandBuilder builder) {
+        this.operation = builder.getOperation();
+        this.ip = builder.getIp();
+        this.linkLayerAddress = builder.getLinkLayerAddress();
+        this.interfaceKey = builder.getInterfaceKey();
+    }
+
+    public static NeighborCommandBuilder builder() {
+        return new NeighborCommandBuilder();
+    }
+
+    @Override
+    public InstanceIdentifier getIid() {
+        return VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip));
+    }
+
+    @Override
+    void put(ReadWriteTransaction rwTx) {
+        InstanceIdentifier<Neighbor> iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip));
+        rwTx.put(LogicalDatastoreType.CONFIGURATION, iid, getNeighborBuilder().build());
+    }
+
+    @Override
+    void merge(ReadWriteTransaction rwTx) {
+        InstanceIdentifier<Neighbor> iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip));
+        rwTx.merge(LogicalDatastoreType.CONFIGURATION, iid, getNeighborBuilder().build());
+    }
+
+    @Override
+    void delete(ReadWriteTransaction rwTx) {
+        try {
+            InstanceIdentifier<Neighbor> iid = VppIidFactory.getNeighborIid(interfaceKey, new NeighborKey(ip));
+            rwTx.delete(LogicalDatastoreType.CONFIGURATION, iid);
+        } catch (IllegalStateException ex) {
+            LOG.debug("Proxy Range not deleted from DS {}", this, ex);
+        }
+    }
+
+    private NeighborBuilder getNeighborBuilder() {
+        return new NeighborBuilder()
+                    .setKey(new NeighborKey(this.ip))
+                    .setIp(this.ip)
+                    .setLinkLayerAddress(this.linkLayerAddress);
+    }
+
+    public static class NeighborCommandBuilder {
+        private General.Operations operation;
+        private Ipv4AddressNoZone ip;
+        private PhysAddress linkLayerAddress;
+        private InterfaceKey interfaceKey;
+
+        public General.Operations getOperation() {
+            return operation;
+        }
+
+        public void setOperation(General.Operations operation) {
+            this.operation = operation;
+        }
+
+        public Ipv4AddressNoZone getIp() {
+            return ip;
+        }
+
+        public void setIp(Ipv4AddressNoZone ip) {
+            this.ip = ip;
+        }
+
+        public PhysAddress getLinkLayerAddress() {
+            return linkLayerAddress;
+        }
+
+        public void setLinkLayerAddress(PhysAddress linkLayerAddress) {
+            this.linkLayerAddress = linkLayerAddress;
+        }
+
+        public InterfaceKey getInterfaceKey() {
+            return interfaceKey;
+        }
+
+        public void setInterfaceKey(InterfaceKey interfaceKey) {
+            this.interfaceKey = interfaceKey;
+        }
+
+        /**
+         * StaticArpCommand build method.
+         *
+         * @return StaticArpCommand
+         * @throws IllegalArgumentException if ip or operation is null.
+         */
+        public StaticArpCommand build() {
+            Preconditions.checkNotNull(operation, "Operation must not be null!");
+            Preconditions.checkNotNull(ip, "ip must not be null!");
+
+            return new StaticArpCommand(this);
+        }
+    }
+}
index 7f277799a1715b792080a4ed449bfa68923255e9..5a3612815f1f574c948c17c9f6b0d0153c8acca4 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.TapBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.interconnection.BridgeBasedBuilder;
 
@@ -38,6 +39,7 @@ public class TapPortCommand extends AbstractInterfaceCommand {
         this.description = builder.getDescription();
         this.bridgeDomain = builder.getBridgeDomain();
         this.deviceInstance = builder.getDeviceInstance();
+        this.enableProxyArp = builder.getEnableProxyArp();
     }
 
     public static TapPortCommandBuilder builder() {
@@ -73,12 +75,17 @@ public class TapPortCommand extends AbstractInterfaceCommand {
                         .setDeviceInstance(this.deviceInstance)
                         .build());
 
+        if (getVrfId() != null) {
+            vppAugmentationBuilder.setRouting(new RoutingBuilder().setIpv4VrfId(getVrfId()).build());
+        }
+
         if (!Strings.isNullOrEmpty(bridgeDomain)) {
             vppAugmentationBuilder.setL2(new L2Builder()
                     .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build());
         }
 
         interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build());
+        addEnableProxyArpAugmentation(interfaceBuilder);
         return interfaceBuilder;
     }
 
@@ -99,6 +106,8 @@ public class TapPortCommand extends AbstractInterfaceCommand {
         private String description;
         private Long deviceInstance = null;
         private boolean enabled = true;
+        private Boolean enableProxyArp;
+        private Long vrfId;
 
         String getInterfaceName() {
             return interfaceName;
@@ -172,6 +181,22 @@ public class TapPortCommand extends AbstractInterfaceCommand {
             return this;
         }
 
+        public Boolean getEnableProxyArp() {
+            return enableProxyArp;
+        }
+
+        public void setEnableProxyArp(Boolean enableProxyArp) {
+            this.enableProxyArp = enableProxyArp;
+        }
+
+        public Long getVrfId() {
+            return vrfId;
+        }
+
+        public void setVrfId(Long vrfId) {
+            this.vrfId = vrfId;
+        }
+
         /**
          * TapPortCommand build method.
          *
index d9ad9d89d6df03e822cf20e58d7e1491aa789638..2a60ddf33175a32fdba656cf02757236e164d76c 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.VppInterfaceAugmentationBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.VhostUserBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.l2.base.attributes.interconnection.BridgeBasedBuilder;
 
@@ -35,6 +36,7 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
         this.enabled = builder.isEnabled();
         this.description = builder.getDescription();
         this.bridgeDomain = builder.getBridgeDomain();
+        this.enableProxyArp = builder.getEnableProxyArp();
 
     }
 
@@ -64,12 +66,18 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
         // Create the vhost augmentation
         VppInterfaceAugmentationBuilder vppAugmentationBuilder = new VppInterfaceAugmentationBuilder()
                 .setVhostUser(new VhostUserBuilder().setRole(role).setSocket(socket).build());
+
+        if (getVrfId() != null) {
+            vppAugmentationBuilder.setRouting(new RoutingBuilder().setIpv4VrfId(getVrfId()).build());
+        }
+
         if (!Strings.isNullOrEmpty(bridgeDomain)) {
             vppAugmentationBuilder.setL2(new L2Builder()
                     .setInterconnection(new BridgeBasedBuilder().setBridgeDomain(bridgeDomain).build()).build());
         }
 
         interfaceBuilder.addAugmentation(VppInterfaceAugmentation.class, vppAugmentationBuilder.build());
+        addEnableProxyArpAugmentation(interfaceBuilder);
         return interfaceBuilder;
     }
 
@@ -89,6 +97,8 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
         private boolean enabled = true;
         private String description;
         private String bridgeDomain;
+        private Boolean enableProxyArp;
+        private Long vrfId;
 
         public String getName() {
             return name;
@@ -153,6 +163,22 @@ public class VhostUserCommand extends AbstractInterfaceCommand {
             return this;
         }
 
+        public Boolean getEnableProxyArp() {
+            return enableProxyArp;
+        }
+
+        public void setEnableProxyArp(Boolean enableProxyArp) {
+            this.enableProxyArp = enableProxyArp;
+        }
+
+        public Long getVrfId() {
+            return vrfId;
+        }
+
+        public void setVrfId(Long vrfId) {
+            this.vrfId = vrfId;
+        }
+
         /**
          * VhostUserCommand build method.
          *
index d8da5666930fad1cb5ad951e432f2838b773bea0..22f7851add36ad91b6fe1252af5723a96911bd7f 100644 (file)
@@ -174,7 +174,7 @@ public class InterfaceManager implements AutoCloseable {
         LOG.trace("Creating VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice);
         Optional<AbstractInterfaceCommand> potentialIfaceCommand = Optional.absent();
         if (interfaceTypeChoice instanceof VhostUserCase) {
-            potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
+            potentialIfaceCommand = createVhostInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
         } else if (interfaceTypeChoice instanceof TapCase) {
             potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.PUT);
         } else if (interfaceTypeChoice instanceof LoopbackCase){
@@ -249,7 +249,7 @@ public class InterfaceManager implements AutoCloseable {
         LOG.trace("Deleting VPP endpoint {}, type of {}", vppEndpoint, interfaceTypeChoice.toString());
         Optional<AbstractInterfaceCommand> potentialIfaceCommand = Optional.absent();
         if (interfaceTypeChoice instanceof VhostUserCase) {
-            potentialIfaceCommand = createInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
+            potentialIfaceCommand = createVhostInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
         } else if (interfaceTypeChoice instanceof TapCase) {
             potentialIfaceCommand = createTapInterfaceWithoutBdCommand(vppEndpoint, Operations.DELETE);
         } else if (interfaceTypeChoice instanceof LoopbackCase){
@@ -315,8 +315,8 @@ public class InterfaceManager implements AutoCloseable {
         }
     }
 
-    private Optional<AbstractInterfaceCommand> createInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
-            @Nonnull Operations operations) {
+    private Optional<AbstractInterfaceCommand> createVhostInterfaceWithoutBdCommand(@Nonnull VppEndpoint vppEp,
+                                                                                    @Nonnull Operations operations) {
         if (!hasNodeAndInterface(vppEp)) {
             LOG.debug("Interface command is not created for {}", vppEp);
             return Optional.absent();
@@ -334,6 +334,11 @@ public class InterfaceManager implements AutoCloseable {
             builder.setSocket(socket);
             builder.setRole(VhostUserRole.Client);
         }
+
+        if (ConfigUtil.getInstance().isL3FlatEnabled()) {
+            builder.setEnableProxyArp(true);
+        }
+
         VhostUserCommand vhostUserCommand =
                 builder.setOperation(operations).setDescription(vppEp.getDescription()).build();
         return Optional.of(vhostUserCommand);
@@ -355,8 +360,12 @@ public class InterfaceManager implements AutoCloseable {
                 return Optional.absent();
             }
             builder.setTapName(name);
-            builder.setPhysAddress(tapIface.getPhysicalAddress());
         }
+
+        if (ConfigUtil.getInstance().isL3FlatEnabled()) {
+            builder.setEnableProxyArp(true);
+        }
+
         TapPortCommand tapPortCommand = builder
                 .setOperation(operation)
                 .setDescription(vppEp.getDescription())
index 6cebc3f8561b491505bb3deb36a6579188d81a48..a802c1bdceb9a0c0f84fb9bf6fc1ee667a29ec1f 100644 (file)
@@ -53,6 +53,24 @@ public class VppPathMapper {
         return Optional.of(VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)));
     }
 
+    public static Optional<String> interfacePathToInterfaceName(@Nullable String restPath) {
+        if (Strings.isNullOrEmpty(restPath)) {
+            return Optional.absent();
+        }
+        if (restPath.length() < INTERFACE_PATH_MIN_LENGTH) {
+            return Optional.absent();
+        }
+        if (!restPath.startsWith(INTERFACE_PATH_BEFORE_KEY)) {
+            return Optional.absent();
+        }
+        if (!restPath.endsWith(INTERFACE_PATH_AFTER_KEY)) {
+            return Optional.absent();
+        }
+        int endIndexInterfaceName = restPath.length() - INTERFACE_PATH_AFTER_KEY.length();
+        String interfaceName = restPath.substring(INTERFACE_PATH_BEFORE_KEY.length(), endIndexInterfaceName);
+        return Optional.of(interfaceName);
+    }
+
     public static String bridgeDomainToRestPath(String bridgeDomainName) {
         return BD_PATH_BEFORE_KEY + bridgeDomainName + BD_PATH_AFTER_KEY;
     }
index 9b46a7565c8c87e41bd1ddff0aff349d32b2ad2c..418fc56e89db564fb352f2feade7391d516e27d8 100644 (file)
@@ -28,6 +28,7 @@ public class LispState {
     private Set<Long> vniSet;
     private boolean mapRegisteredEnabled;
     private HashMap<Eid, String> eidToMappingIdMapper;
+    private int interfaceCount;
 
     public LispState(String hostName) {
         this.hostName = hostName;
@@ -38,6 +39,7 @@ public class LispState {
         mapRegisteredEnabled = false;
         vniSet = new HashSet<>();
         eidToMappingIdMapper = new HashMap<>();
+        interfaceCount = 1;
     }
 
     public String getHostName() {
@@ -105,6 +107,7 @@ public class LispState {
     }
 
     public void addInEidSet(Eid eid, String mappingId) {
+        interfaceCount++;
         eidToMappingIdMapper.put(eid, mappingId);
     }
 
@@ -119,4 +122,8 @@ public class LispState {
     public String getEidMapping(Eid eid) {
         return eidToMappingIdMapper.get(eid);
     }
+
+    public int getInterfaceId() {
+        return interfaceCount;
+    }
 }
index 95e11c3097a0f6c802b2d91e27aa3999d9ec1c24..c8684b4d8dd04453acf0138836be3ae4c19456c4 100644 (file)
@@ -218,7 +218,7 @@ public class LispStateManager {
     private void addEidInEidTable(DataBroker vppDataBroker,
                                   LispState lispState,
                                   Eid eid) throws LispConfigCommandFailedException {
-        String mappingId = lispStateHelper.constructMappingName(lispState.eidCount());
+        String mappingId = lispStateHelper.constructMappingName(lispState.getInterfaceId());
         AbstractLispCommand<LocalMapping> addLocalMappingInEidTableCommand = LispCommandWrapper
                 .addLocalMappingInEidTable(mappingId,
                         eid,
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviHostSpecificInfo.java
deleted file mode 100644 (file)
index b8315a2..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2017 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.lisp.bvi;
-
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.Multimap;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.stream.Collectors;
-
-/**
- * Created by Shakib Ahmed on 4/26/17.
- */
-public class BviHostSpecificInfo {
-    private HashMap<String, HashMap<String, String>> hostIdToSubnetMapper;
-    private Multimap<String, String> subnetUuidToHostIdList;
-
-    public BviHostSpecificInfo() {
-        hostIdToSubnetMapper = new HashMap<>();
-        subnetUuidToHostIdList = ArrayListMultimap.create();
-    }
-
-    private HashMap<String, String> getSubnetsOfHost(String hostName) {
-        return hostIdToSubnetMapper.get(hostName);
-    }
-
-    private void putSubnetInfoOfAHost(String hostId, String subnetUuid, String interfaceName) {
-        HashMap<String, String> subnetsOfAHost = getSubnetsOfHost(hostId);
-
-        if (subnetsOfAHost == null) {
-            subnetsOfAHost = new HashMap<>();
-            hostIdToSubnetMapper.put(hostId, subnetsOfAHost);
-        }
-        subnetsOfAHost.put(subnetUuid, interfaceName);
-    }
-
-    public boolean bviAlreadyExists(String hostName, String subnetUuid) {
-        return hostIdToSubnetMapper.containsKey(hostName) &&
-                hostIdToSubnetMapper.get(hostName).containsKey(subnetUuid);
-    }
-
-    public void addBviForHost(String hostName, String subnetUuid, String interfaceName) {
-        putSubnetInfoOfAHost(hostName, subnetUuid, interfaceName);
-        subnetUuidToHostIdList.put(subnetUuid, hostName);
-    }
-
-    public int getBviCount(String hostName) {
-        if (hostIdToSubnetMapper.get(hostName) == null) {
-            return 0;
-        }
-        return hostIdToSubnetMapper.get(hostName).size();
-    }
-
-    public void clearSubnet(String subnetUuid) {
-        subnetUuidToHostIdList.get(subnetUuid).forEach(hostId -> {
-            deleteParticularSubnetFromHost(hostId, subnetUuid);
-        });
-        subnetUuidToHostIdList.get(subnetUuid).clear();
-    }
-
-    private void deleteParticularSubnetFromHost(String hostId, String subnetUuid) {
-        hostIdToSubnetMapper.get(hostId).remove(subnetUuid);
-    }
-
-    public List<String> getHostsWithSubnet(String subnetUuid) {
-        return subnetUuidToHostIdList.get(subnetUuid).stream().collect(Collectors.toList());
-    }
-
-    public String getInterfaceNameForBviInHost(String hostId, String subnetUuid) {
-        if (hostIdToSubnetMapper.get(hostId) != null) {
-            return hostIdToSubnetMapper.get(hostId).get(subnetUuid);
-        } else {
-            return null;
-        }
-    }
-}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/bvi/BviManager.java
deleted file mode 100644 (file)
index 078a3fd..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright (c) 2017 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.lisp.bvi;
-
-import com.google.common.base.Preconditions;
-import com.google.common.eventbus.Subscribe;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
-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.renderer.vpp.util.VppIidFactory;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.annotation.Nonnull;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-
-/**
- * Created by Shakib Ahmed on 4/26/17.
- */
-public class BviManager {
-    private static final Logger LOG = LoggerFactory.getLogger(BviManager.class);
-
-    private ConfigManagerHelper managerHelper;
-
-    private HashMap<String, GbpSubnet> subnetInformation;
-
-    private BviHostSpecificInfo bviHostSpecificInfo;
-    private NeutronTenantToVniMapper neutronTenantToVniMapper;
-
-    public BviManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
-        managerHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
-        subnetInformation = new HashMap<>();
-        bviHostSpecificInfo = new BviHostSpecificInfo();
-        neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
-    }
-
-    @Subscribe
-    public synchronized void gbpSubnetChanged(GbpSubnetEvent event) {
-        final GbpSubnet oldGbpSubnet = event.getBefore().orNull();
-        final GbpSubnet newGbpSubnet = event.getAfter().orNull();
-        switch (event.getDtoModificationType()) {
-            case CREATED:
-                Preconditions.checkNotNull(newGbpSubnet);
-                processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
-                break;
-            case UPDATED:
-                Preconditions.checkNotNull(oldGbpSubnet);
-                Preconditions.checkNotNull(newGbpSubnet);
-                processSubnetDeleted(oldGbpSubnet.getId());
-                processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
-                break;
-            case DELETED:
-                Preconditions.checkNotNull(oldGbpSubnet);
-                processSubnetDeleted(oldGbpSubnet.getId());
-                break;
-        }
-    }
-
-    private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) {
-        subnetInformation.put(subnetUuid, subnetInfo);
-    }
-
-    private void processSubnetDeleted(String subnetUuid) {
-        subnetInformation.remove(subnetUuid);
-
-        deleteBviIfExists(subnetUuid);
-    }
-
-    public GbpSubnet getSubnetInfo(String subnetUuid) {
-        return subnetInformation.get(subnetUuid);
-    }
-
-    public void createBviIfNecessary(AddressEndpointWithLocation addressEp,
-                                     String bridgeDomainName) {
-        try {
-            DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(addressEp).get();
-            String hostName = managerHelper.getHostName(addressEp).get();
-            String subnetUuid = managerHelper.getSubnet(addressEp);
-
-            if (bviHostSpecificInfo.bviAlreadyExists(hostName, subnetUuid)) {
-                return;
-            }
-
-            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
-                    "Subnet UUID {} hasn't been created yet!", subnetUuid);
-
-            LoopbackCommand.LoopbackCommandBuilder loopbackCommandBuilder =
-                    new LoopbackCommand.LoopbackCommandBuilder();
-            loopbackCommandBuilder.setInterfaceName("loop"
-                    + bviHostSpecificInfo.getBviCount(hostName));
-            loopbackCommandBuilder.setBridgeDomain(bridgeDomainName);
-            loopbackCommandBuilder.setBvi(true);
-            loopbackCommandBuilder.setEnabled(true);
-            loopbackCommandBuilder.setVrfId(getVni(addressEp.getTenant().getValue()));
-            loopbackCommandBuilder.setIpAddress(gbpSubnetInfo.getGatewayIp());
-            loopbackCommandBuilder.setIpPrefix(gbpSubnetInfo.getCidr());
-            loopbackCommandBuilder.setOperation(General.Operations.PUT);
-            createBviInterface(hostName, vppDataBroker, loopbackCommandBuilder);
-        } catch (LispConfigCommandFailedException e) {
-            LOG.debug("LISP loopback command failed for {}", e.getMessage());
-        }
-    }
-
-    public void createBviInterface(String hostName, DataBroker vppDataBroker,
-                                   LoopbackCommand.LoopbackCommandBuilder commandBuilder) throws LispConfigCommandFailedException {
-
-        if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
-                                                     commandBuilder.build(),
-                                                     GbpNetconfTransaction.RETRY_COUNT)) {
-            bviHostSpecificInfo.addBviForHost(hostName,
-                                              commandBuilder.getBridgeDomain(),
-                                              commandBuilder.getInterfaceName());
-        } else {
-            throw new LispConfigCommandFailedException("BVI could not be created for "
-                    + hostName + " and bridge domain " + commandBuilder.getBridgeDomain());
-        }
-    }
-
-    public void deleteBviIfExists(String subnetUuid) {
-
-        List<String> hostsWithSubnet = bviHostSpecificInfo.getHostsWithSubnet(subnetUuid);
-
-        hostsWithSubnet.forEach(host -> {
-            DataBroker vppDataBroker = managerHelper.getPotentialExternalDataBroker(host).get();
-            String bviInterfaceName = bviHostSpecificInfo.getInterfaceNameForBviInHost(host, subnetUuid);
-            GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker,
-                    VppIidFactory.getInterfaceIID(new InterfaceKey(bviInterfaceName)), GbpNetconfTransaction.RETRY_COUNT);
-        });
-    }
-
-    private long getVni(String tenantUuid) {
-        return neutronTenantToVniMapper.getVni(tenantUuid);
-    }
-}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/event/manager/GbpSubnetEventManager.java
new file mode 100644 (file)
index 0000000..a4c438e
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017 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.lisp.event.manager;
+
+import com.google.common.base.Preconditions;
+import com.google.common.eventbus.Subscribe;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.event.GbpSubnetEvent;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.MountedDataBrokerProvider;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Created by Shakib Ahmed on 5/3/17.
+ */
+public class GbpSubnetEventManager {
+    private static final Logger LOG = LoggerFactory.getLogger(GbpSubnetEventManager.class);
+
+    private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetInfoMapper;
+    private LoopbackManager loopbackManager;
+
+    public GbpSubnetEventManager(@Nonnull LoopbackManager loopbackManager) {
+        this.loopbackManager = loopbackManager;
+        this.subnetUuidToGbpSubnetInfoMapper = SubnetUuidToGbpSubnetMapper.getInstance();
+    }
+
+    @Subscribe
+    public synchronized void gbpSubnetChanged(GbpSubnetEvent event) {
+        final GbpSubnet oldGbpSubnet = event.getBefore().orNull();
+        final GbpSubnet newGbpSubnet = event.getAfter().orNull();
+
+        LOG.debug("GbpSubnet information updated.\nPrevious: {}\nPresent: {}\n", oldGbpSubnet, newGbpSubnet);
+
+        switch (event.getDtoModificationType()) {
+            case CREATED:
+                Preconditions.checkNotNull(newGbpSubnet);
+                processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
+                break;
+            case UPDATED:
+                Preconditions.checkNotNull(oldGbpSubnet);
+                Preconditions.checkNotNull(newGbpSubnet);
+                processSubnetDeleted(oldGbpSubnet.getId());
+                processSubnetCreated(newGbpSubnet.getId(), newGbpSubnet);
+                break;
+            case DELETED:
+                Preconditions.checkNotNull(oldGbpSubnet);
+                processSubnetDeleted(oldGbpSubnet.getId());
+                break;
+        }
+    }
+
+    private void processSubnetCreated(String subnetUuid, GbpSubnet subnetInfo) {
+        subnetUuidToGbpSubnetInfoMapper.addSubnetInfo(subnetUuid, subnetInfo);
+    }
+
+    private void processSubnetDeleted(String subnetUuid) {
+        subnetUuidToGbpSubnetInfoMapper.removeSubnetInfo(subnetUuid);
+        loopbackManager.deleteLoopbackIfExists(subnetUuid);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/FlatOverlayManager.java
new file mode 100644 (file)
index 0000000..a671a1e
--- /dev/null
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2017 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.lisp.flat.overlay;
+
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.StaticArpCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostVrfRoutingInformationMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
+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.renderer.vpp.util.VppIidFactory;
+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.Ipv4AddressNoZone;
+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.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Created by Shakib Ahmed on 5/2/17.
+ */
+public class FlatOverlayManager {
+    private static final Logger LOG = LoggerFactory.getLogger(FlatOverlayManager.class);
+
+    private ConfigManagerHelper overlayHelper;
+
+    private NeutronTenantToVniMapper neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
+    private HostVrfRoutingInformationMapper hostVrfInfo = HostVrfRoutingInformationMapper.getInstance();
+
+    private StaticRoutingHelper staticRoutingHelper;
+
+    public FlatOverlayManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
+        this.overlayHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
+        staticRoutingHelper = new StaticRoutingHelper();
+    }
+
+    public void configureEndpointForFlatOverlay(AddressEndpointWithLocation addressEp) {
+        configureInterfaceForFlatOverlay(addressEp);
+        addStaticArp(addressEp);
+        addStaticRoute(addressEp);
+    }
+
+    public void handleEndpointDeleteForFlatOverlay(AddressEndpointWithLocation addressEp) {
+        deleteStaticRoute(addressEp);
+    }
+
+    private void configureInterfaceForFlatOverlay(AddressEndpointWithLocation addressEp) {
+        addInterfaceInVrf(addressEp);
+    }
+
+    private void addInterfaceInVrf(AddressEndpointWithLocation addressEp) {
+        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
+        long vni = getVni(addressEp.getTenant().getValue());
+        long vrf = vni;
+        Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
+
+        Preconditions.checkArgument(interfaceNameOptional.isPresent());
+
+        if (!putVrfInInterface(vppDataBroker, interfaceNameOptional.get(), vrf)) {
+            LOG.warn("Failed to put interface {} to vrf {}", interfaceNameOptional.get(), vrf);
+        } else {
+            LOG.debug("Added interface {} to vrf {}", interfaceNameOptional.get(), vrf);
+        }
+    }
+
+    private boolean putVrfInInterface(DataBroker vppDataBroker,
+                                  String interfaceName,
+                                  Long vrf) {
+        InstanceIdentifier<Routing> iid = VppIidFactory.getRoutingIid(new InterfaceKey(interfaceName));
+        RoutingBuilder builder = new RoutingBuilder();
+        builder.setIpv4VrfId(vrf);
+        return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker, iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT);
+    }
+
+    private void addStaticArp(AddressEndpointWithLocation addressEp) {
+        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
+        String hostName = overlayHelper.getHostName(addressEp).get();
+        String physicalAddress = overlayHelper.getPhysicalAddress(addressEp);
+        Optional<String> interfaceNameOptional = overlayHelper.getInterfaceName(addressEp);
+
+        Preconditions.checkArgument(interfaceNameOptional.isPresent());
+
+        String interfaceName = interfaceNameOptional.get();
+        InterfaceKey interfaceKey = new InterfaceKey(interfaceName);
+
+        Ipv4AddressNoZone ip = new Ipv4AddressNoZone(overlayHelper.getInterfaceIp(addressEp));
+
+        if (!putIpv4Neighbor(vppDataBroker, interfaceKey, new PhysAddress(physicalAddress), ip)) {
+            LOG.warn("Failed to put static arp with interface {} for ip={} and physical-address={}", interfaceName,
+                    ip, physicalAddress);
+        } else {
+            LOG.debug("Added Static arp ({} {}) in host {} for interface {}", ip, physicalAddress, hostName,
+                    interfaceName);
+        }
+    }
+
+    private boolean putIpv4Neighbor(DataBroker vppDataBroker,
+                                 InterfaceKey interfaceKey,
+                                 PhysAddress physAddress,
+                                 Ipv4AddressNoZone ip) {
+        StaticArpCommand.NeighborCommandBuilder neighborCommandBuilder = new StaticArpCommand.NeighborCommandBuilder();
+
+        neighborCommandBuilder.setOperation(General.Operations.PUT);
+        neighborCommandBuilder.setInterfaceKey(interfaceKey);
+        neighborCommandBuilder.setIp(ip);
+        neighborCommandBuilder.setLinkLayerAddress(physAddress);
+
+        return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
+                neighborCommandBuilder.build(), GbpNetconfTransaction.RETRY_COUNT);
+    }
+
+    private void addStaticRoute(AddressEndpointWithLocation addressEp) {
+        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
+        String hostName = overlayHelper.getHostName(addressEp).get();
+
+        long vni = getVni(addressEp.getTenant().getValue());
+        long vrf = vni;
+
+        if (!hostVrfInfo.vrfExists(hostName, vrf)) {
+            if (!staticRoutingHelper.addRoutingProtocolForVrf(vppDataBroker, hostName, vrf)) {
+                LOG.warn("Failed to add Routing protocol for host {} and vrf {}!", hostName, vrf);
+            }
+        }
+
+        String outgoingInterfaceName = overlayHelper.getInterfaceName(addressEp).get();
+        Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
+
+        if (staticRoutingHelper.endPointRoutingExists(outgoingInterfaceName, ipWithoutPrefix)) {
+            return;
+        }
+
+        Ipv4Prefix ipv4Prefix = overlayHelper.getInterfaceIpAsPrefix(addressEp);
+
+        if (!staticRoutingHelper.addSingleStaticRouteInRoutingProtocol(vppDataBroker,
+                                                                  hostName,
+                                                                  vrf,
+                                                                  ipWithoutPrefix,
+                                                                  ipv4Prefix,
+                                                                  outgoingInterfaceName)) {
+            LOG.warn("Failed to add routing ({} via {}) in vrf {} in compute host {}!",
+                    ipv4Prefix, outgoingInterfaceName, vrf, hostName);
+        } else {
+            LOG.debug("Added route ({} via {}) in vrf {} in compute host {}",
+                    ipv4Prefix, outgoingInterfaceName, vrf, hostName);
+        }
+    }
+
+    private void deleteStaticRoute(AddressEndpointWithLocation addressEp) {
+        DataBroker vppDataBroker = overlayHelper.getPotentialExternalDataBroker(addressEp).get();
+        String hostName = overlayHelper.getHostName(addressEp).get();
+        String interfaceName = overlayHelper.getInterfaceName(addressEp).get();
+
+        long vni = getVni(addressEp.getTenant().getValue());
+        long vrf = vni;
+
+        Ipv4Address ipWithoutPrefix = overlayHelper.getInterfaceIp(addressEp);
+
+        if (!staticRoutingHelper.deleteSingleStaticRouteFromRoutingProtocol(vppDataBroker,
+                                                                       hostName,
+                                                                       vrf,
+                                                                       interfaceName)) {
+            LOG.warn("Failed to delete route ({} via {}) from vrf {} from host{}",
+                    ipWithoutPrefix, interfaceName, vrf, hostName);
+
+        } else {
+            LOG.debug("Delete Static Route ({} via {}) from vrf {} from host {}",
+                    ipWithoutPrefix, interfaceName, vrf, hostName);
+        }
+    }
+
+    private long getVni(String tenantUuid) {
+        return neutronTenantToVniMapper.getVni(tenantUuid);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/RoutingInfo.java
new file mode 100644 (file)
index 0000000..18853a9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2017 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.lisp.flat.overlay;
+
+/**
+ * Created by Shakib Ahmed on 5/4/17.
+ */
+public class RoutingInfo {
+    private String ProtocolName;
+    private int count = 0;
+
+    public String getProtocolName() {
+        return ProtocolName;
+    }
+
+    public void setProtocolName(String protocolName) {
+        ProtocolName = protocolName;
+    }
+
+    public int getCount() {
+        return count;
+    }
+
+    public void incrementCount() {
+        count++;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/flat/overlay/StaticRoutingHelper.java
new file mode 100644 (file)
index 0000000..b438a91
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017 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.lisp.flat.overlay;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.HostVrfRoutingInformationMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.InterfaceNameToRouteInfoMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.GbpNetconfTransaction;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.util.VppIidFactory;
+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.routing.routing.instance.routing.protocols.routing.protocol._static.routes.Ipv4;
+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.RouteKey;
+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.StaticRoutes;
+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.Arrays;
+import java.util.List;
+
+/**
+ * Created by Shakib Ahmed on 5/4/17.
+ */
+public class StaticRoutingHelper {
+    private static final Logger LOG = LoggerFactory.getLogger(StaticRoutingHelper.class);
+
+    private static final String ROUTING_PROTOCOL_NAME_PREFIX = "static-routing-";
+    private static final String DEFAULT_DESCRIPTION = "Static route added from GBP for flat L3 overlay";
+
+    private HostVrfRoutingInformationMapper hostVrfInfo = HostVrfRoutingInformationMapper.getInstance();
+
+    private InterfaceNameToRouteInfoMapper interfaceNameToRouteInfoMapper;
+
+    public StaticRoutingHelper() {
+        interfaceNameToRouteInfoMapper = new InterfaceNameToRouteInfoMapper();
+    }
+
+    public synchronized boolean addRoutingProtocolForVrf(DataBroker vppDataBroker,
+                                         String hostId,
+                                         long vrf) {
+        String routingProtocolName = getRoutingProtocolName(vrf);
+        RoutingProtocolBuilder builder = new RoutingProtocolBuilder();
+        builder.setKey(new RoutingProtocolKey(routingProtocolName));
+        builder.setName(routingProtocolName);
+        builder.setType(Static.class);
+        builder.setDescription(DEFAULT_DESCRIPTION);
+        RoutingProtocolVppAttrBuilder vppAugmentationBuilder = new RoutingProtocolVppAttrBuilder();
+
+        vppAugmentationBuilder.
+                setVppProtocolAttributes(new VppProtocolAttributesBuilder()
+                                                .setPrimaryVrf(new VniReference(vrf)).build());
+
+        builder.addAugmentation(RoutingProtocolVppAttr.class, vppAugmentationBuilder.build());
+
+        InstanceIdentifier<RoutingProtocol> iid = VppIidFactory
+                .getRoutingInstanceIid(builder.getKey());
+        if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
+                iid, builder.build(), GbpNetconfTransaction.RETRY_COUNT)) {
+            RoutingInfo info = new RoutingInfo();
+            info.setProtocolName(routingProtocolName);
+            hostVrfInfo.addRoutingVrfToHost(hostId, vrf, info);
+            return true;
+        }
+
+        return false;
+    }
+
+    public boolean endPointRoutingExists(String interfaceName, Ipv4Address ip) {
+        return interfaceNameToRouteInfoMapper.routeAlreadyExists(interfaceName, ip);
+    }
+
+    public synchronized boolean addSingleStaticRouteInRoutingProtocol(DataBroker vppDataBroker,
+                                                      String hostId,
+                                                      long vrf,
+                                                      Ipv4Address nextHopAddress,
+                                                      Ipv4Prefix ipPrefix,
+                                                      String outgoingInterface) {
+        RouteBuilder builder = new RouteBuilder();
+
+        Long routingId = hostVrfInfo.getEndPointCountInVrf(hostId, vrf);
+
+        builder.setId(routingId);
+        builder.setDestinationPrefix(ipPrefix);
+        builder.setKey(new RouteKey(builder.getId()));
+        builder.setNextHopOptions(new SimpleNextHopBuilder()
+                                        .setNextHop(nextHopAddress)
+                                        .setOutgoingInterface(outgoingInterface)
+                                        .build());
+
+        List<Route> routes = Arrays.asList(builder.build());
+
+        Ipv4 ipv4Route = new Ipv4Builder().setRoute(routes).build();
+
+        InstanceIdentifier<Ipv4> iid = VppIidFactory.
+                getRoutingInstanceIid(new RoutingProtocolKey(hostVrfInfo.getProtocolName(hostId, vrf)))
+                .child(StaticRoutes.class)
+                .augmentation(StaticRoutes1.class)
+                .child(Ipv4.class);
+
+        if (GbpNetconfTransaction.netconfSyncedMerge(vppDataBroker, iid, ipv4Route, GbpNetconfTransaction.RETRY_COUNT)) {
+            interfaceNameToRouteInfoMapper.addRouteForInterface(outgoingInterface, nextHopAddress, routingId);
+            hostVrfInfo.addStaticRoute(hostId, vrf);
+            return true;
+        }
+
+        return false;
+    }
+
+    public synchronized boolean deleteSingleStaticRouteFromRoutingProtocol(DataBroker vppDataBroker,
+                                                                        String hostId,
+                                                                        long vrf,
+                                                                        String outgoingInterface) {
+        List<Long> allRoutingIdsForPort = interfaceNameToRouteInfoMapper.getRoutingIdsAssociatedWithInterface(outgoingInterface);
+
+        boolean allOk = true;
+
+        for (Long routingId : allRoutingIdsForPort) {
+            InstanceIdentifier<Route> iid = VppIidFactory.
+                    getRoutingInstanceIid(new RoutingProtocolKey(hostVrfInfo.getProtocolName(hostId, vrf)))
+                    .child(StaticRoutes.class)
+                    .augmentation(StaticRoutes1.class)
+                    .child(Ipv4.class)
+                    .child(Route.class, new RouteKey(routingId));
+            if (!GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker, iid, GbpNetconfTransaction.RETRY_COUNT)) {
+                LOG.warn("Route delete failed for interface {} from {}", outgoingInterface, hostId);
+                allOk = false;
+            }
+        }
+
+        interfaceNameToRouteInfoMapper.clearStaticRoutesForInterface(outgoingInterface);
+        return allOk;
+    }
+
+    public static String getRoutingProtocolName(long vrf) {
+        return ROUTING_PROTOCOL_NAME_PREFIX + vrf;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/LoopbackManager.java
new file mode 100644 (file)
index 0000000..fd26f16
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * Copyright (c) 2017 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.lisp.loopback;
+
+import com.google.common.base.Preconditions;
+import org.apache.commons.lang3.tuple.Pair;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.LoopbackCommandWrapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.ProxyRangeCommand;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.exception.LispConfigCommandFailedException;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.LoopbackHostSpecificInfoMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.NeutronTenantToVniMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.mappers.SubnetUuidToGbpSubnetMapper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.ConfigManagerHelper;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.util.IpAddressUtil;
+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.renderer.vpp.util.VppIidFactory;
+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.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import java.util.List;
+
+/**
+ * Created by Shakib Ahmed on 4/26/17.
+ */
+public class LoopbackManager {
+    private static final Logger LOG = LoggerFactory.getLogger(LoopbackManager.class);
+
+    private ConfigManagerHelper loopbackManagerHelper;
+
+    private LoopbackHostSpecificInfoMapper subnetHostSpecificInfo;
+    private NeutronTenantToVniMapper neutronTenantToVniMapper;
+    private SubnetUuidToGbpSubnetMapper subnetUuidToGbpSubnetMapper;
+
+    private static final String LOOP_NAME_PREFIX = "loop-";
+
+    public LoopbackManager(@Nonnull MountedDataBrokerProvider mountedDataBrokerProvider) {
+        this.loopbackManagerHelper = new ConfigManagerHelper(mountedDataBrokerProvider);
+        this.subnetHostSpecificInfo = new LoopbackHostSpecificInfoMapper();
+        this.neutronTenantToVniMapper = NeutronTenantToVniMapper.getInstance();
+        this.subnetUuidToGbpSubnetMapper = SubnetUuidToGbpSubnetMapper.getInstance();
+    }
+
+    public void createBviLoopbackIfNeeded(AddressEndpointWithLocation addressEp,
+                                          String bridgeDomainName) {
+        try {
+            DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get();
+            String hostName = loopbackManagerHelper.getHostName(addressEp).get();
+            String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
+
+            if (subnetHostSpecificInfo.loopbackAlreadyExists(hostName, subnetUuid)) {
+                subnetHostSpecificInfo.addNewPortInHostSubnet(hostName, subnetUuid);
+                return;
+            }
+
+            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
+                    "Subnet UUID {} hasn't been created yet!", subnetUuid);
+
+            String interfaceName = LOOP_NAME_PREFIX + subnetHostSpecificInfo.getLoopbackCount(hostName);
+            long vni = getVni(addressEp.getTenant().getValue());
+
+            LoopbackCommand bviLoopbackCommand = LoopbackCommandWrapper
+                    .bviLoopbackPutCommand(interfaceName, vni, gbpSubnetInfo.getGatewayIp(), gbpSubnetInfo.getCidr(),
+                            bridgeDomainName);
+            createLoopbackInterface(hostName, subnetUuid, vppDataBroker, bviLoopbackCommand);
+        } catch (LispConfigCommandFailedException e) {
+            LOG.warn("LISP couldn't be configured: {}", e.getMessage());
+        }
+    }
+
+    public void createSimpleLoopbackIfNeeded(AddressEndpointWithLocation addressEp) {
+        try {
+            DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get();
+            String hostName = loopbackManagerHelper.getHostName(addressEp).get();
+            String subnetUuid = loopbackManagerHelper.getSubnet(addressEp);
+
+            if (subnetHostSpecificInfo.loopbackAlreadyExists(hostName, subnetUuid)) {
+                return;
+            }
+
+            String interfaceName = LOOP_NAME_PREFIX + subnetHostSpecificInfo.getLoopbackCount(hostName);
+            long vni = getVni(addressEp.getTenant().getValue());
+            long vrf = vni;
+
+            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(getSubnetInfo(subnetUuid),
+                    "Subnet UUID {} hasn't been created yet!", subnetUuid);
+
+            LoopbackCommand simpleLoopbackCommand = LoopbackCommandWrapper
+                    .simpleLoopbackPutCommand(interfaceName, vrf, gbpSubnetInfo.getGatewayIp(),
+                            gbpSubnetInfo.getCidr());
+
+            createLoopbackInterface(hostName, subnetUuid, vppDataBroker, simpleLoopbackCommand);
+            addProxyArpRange(vppDataBroker, vrf, gbpSubnetInfo, hostName);
+        } catch (LispConfigCommandFailedException e) {
+            LOG.warn("LISP couldn't be configured: {}", e.getMessage());
+        }
+    }
+
+    private void createLoopbackInterface(String hostName, String subnetUuid, DataBroker vppDataBroker,
+                                        LoopbackCommand loopbackCommand) throws LispConfigCommandFailedException {
+
+        if (GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
+                                                     loopbackCommand,
+                                                     GbpNetconfTransaction.RETRY_COUNT)) {
+            subnetHostSpecificInfo.addLoopbackForHost(hostName, subnetUuid, loopbackCommand.getName(),
+                    loopbackCommand.getVrfId());
+            subnetHostSpecificInfo.addNewPortInHostSubnet(hostName, subnetUuid);
+        } else {
+            throw new LispConfigCommandFailedException("BVI could not be created for "
+                    + hostName + " and bridge domain " + loopbackCommand.getBridgeDomain());
+        }
+    }
+
+    public void deleteLoopbackIfExists(String subnetUuid) {
+
+        List<String> hostsWithSubnet = subnetHostSpecificInfo.getHostsWithSubnet(subnetUuid);
+
+        hostsWithSubnet.forEach(host -> {
+            DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(host).get();
+            String interfaceName = subnetHostSpecificInfo.getInterfaceNameForLoopbackInHost(host, subnetUuid);
+
+            try {
+                deleteSpecificLoopback(vppDataBroker, interfaceName);
+            } catch (LispConfigCommandFailedException e) {
+                e.printStackTrace();
+            }
+        });
+
+        subnetHostSpecificInfo.clearSubnet(subnetUuid);
+    }
+
+    public void handleEndpointDelete(AddressEndpointWithLocation addressEp) {
+        DataBroker vppDataBroker = loopbackManagerHelper.getPotentialExternalDataBroker(addressEp).get();
+        String hostId = loopbackManagerHelper.getHostName(addressEp).get();
+        String portSubnetUuid = loopbackManagerHelper.getSubnet(addressEp);
+        String interfaceName = subnetHostSpecificInfo.getInterfaceNameForLoopbackInHost(hostId, portSubnetUuid);
+        if (subnetHostSpecificInfo.deletePortFromHostSubnetAndTriggerLoopbackDelete(hostId, portSubnetUuid)) {
+            GbpSubnet gbpSubnetInfo = Preconditions.checkNotNull(subnetUuidToGbpSubnetMapper.getSubnetInfo(portSubnetUuid),
+                    "Invalid port!");
+            long vni = getVni(addressEp.getTenant().getValue());
+            try {
+                deleteSpecificLoopback(vppDataBroker, interfaceName);
+                deleteProxyArpRange(vppDataBroker, vni, gbpSubnetInfo, hostId);
+            } catch (LispConfigCommandFailedException e) {
+                LOG.warn("Loopback not deleted properly: {}", e.getMessage());
+            }
+        }
+    }
+
+    private void deleteSpecificLoopback(DataBroker vppDataBroker, String interfaceName) throws LispConfigCommandFailedException {
+        if (!GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker,
+                VppIidFactory.getInterfaceIID(new InterfaceKey(interfaceName)), GbpNetconfTransaction.RETRY_COUNT)) {
+            throw new LispConfigCommandFailedException("Failed to delete Loopback interface!");
+        } else {
+            LOG.debug("Deleted loopback interface!");
+        }
+    }
+
+    private void addProxyArpRange(DataBroker vppDataBroker,
+                                  long vrf,
+                                  GbpSubnet gbpSubnetInfo,
+                                  String hostName) throws LispConfigCommandFailedException {
+        Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix();
+
+        Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for "
+        + "subnet uuid =" +  gbpSubnetInfo.getId() + "!");
+
+        Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
+
+        if (!putArpRangesCommand(vppDataBroker,
+                                 vrf,
+                                 startAndEndAddress.getLeft(),
+                                 startAndEndAddress.getRight())) {
+            throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
+            gbpSubnetInfo.getId() + "!");
+        } else {
+            LOG.debug("Configured proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(),
+                    startAndEndAddress.getRight(), hostName);
+        }
+    }
+
+    private void deleteProxyArpRange(DataBroker vppDataBroker,
+                                long vrf,
+                                GbpSubnet gbpSubnetInfo,
+                                String hostName) throws LispConfigCommandFailedException {
+        Ipv4Prefix subnetPrefix = gbpSubnetInfo.getCidr().getIpv4Prefix();
+
+        Preconditions.checkNotNull(subnetPrefix, "Subnet CIDR found to be null for "
+                + "subnet uuid =" +  gbpSubnetInfo.getId() + "!");
+
+        Pair<Ipv4Address, Ipv4Address> startAndEndAddress = IpAddressUtil.getStartAndEndIp(subnetPrefix);
+
+        if (!deleteArpRangesCommand(vppDataBroker,
+                                    vrf,
+                                    startAndEndAddress.getLeft(),
+                                    startAndEndAddress.getRight())) {
+            throw new LispConfigCommandFailedException("Proxy arp configuration failed for subnet uuid: " +
+                    gbpSubnetInfo.getId() + "!");
+        } else {
+            LOG.debug("Removed proxy arp for range {} to {} on node : {}!", startAndEndAddress.getLeft(),
+                    startAndEndAddress.getRight(), hostName);
+        }
+    }
+
+    private boolean putArpRangesCommand(DataBroker vppDataBroker, long vrf, Ipv4Address start, Ipv4Address end) {
+        ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder();
+        builder.setOperation(General.Operations.PUT);
+        builder.setVrf(vrf);
+        builder.setStartAddress(start);
+        builder.setEndAddress(end);
+
+        return GbpNetconfTransaction.netconfSyncedWrite(vppDataBroker,
+                                                        builder.build(),
+                                                        GbpNetconfTransaction.RETRY_COUNT);
+    }
+
+    private boolean deleteArpRangesCommand(DataBroker vppDataBroker,
+                                           long vrf,
+                                           Ipv4Address start,
+                                           Ipv4Address end) {
+        ProxyRangeCommand.ProxyRangeCommandBuilder builder = new ProxyRangeCommand.ProxyRangeCommandBuilder();
+        builder.setOperation(General.Operations.DELETE);
+        builder.setVrf(vrf);
+        builder.setStartAddress(start);
+        builder.setEndAddress(end);
+
+        return GbpNetconfTransaction.netconfSyncedDelete(vppDataBroker,
+                                                         builder.build(),
+                                                         GbpNetconfTransaction.RETRY_COUNT);
+    }
+
+    private long getVni(String tenantUuid) {
+        return neutronTenantToVniMapper.getVni(tenantUuid);
+    }
+
+    private GbpSubnet getSubnetInfo(String subnetUuid) {
+        return subnetUuidToGbpSubnetMapper.getSubnetInfo(subnetUuid);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/loopback/SubnetHostInfo.java
new file mode 100644 (file)
index 0000000..62986f3
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others. 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.lisp.loopback;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Created by Shakib Ahmed on 5/16/17.
+ */
+public class SubnetHostInfo {
+    private String interfaceName;
+    private int portCount;
+
+    public SubnetHostInfo(String interfaceName) {
+        this.interfaceName = interfaceName;
+        this.portCount = 0;
+    }
+
+    public String getInterfaceName() {
+        return interfaceName;
+    }
+
+    public void setInterfaceName(String interfaceName) {
+        this.interfaceName = interfaceName;
+    }
+
+    public void incrementPortCount() {
+        portCount++;
+    }
+
+    public void decrementPortCount() {
+        Preconditions.checkArgument(portCount > 0, "No port to decrement");
+        portCount--;
+    }
+
+    public int incrementAndGetPortCount() {
+        incrementPortCount();
+        return portCount;
+    }
+
+    public int decrementAndGetPortCount() {
+        decrementPortCount();
+        return portCount;
+    }
+
+    public int getPortCount() {
+        return portCount;
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/HostVrfRoutingInformationMapper.java
new file mode 100644 (file)
index 0000000..97d8834
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017 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.lisp.mappers;
+
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.RoutingInfo;
+
+import java.util.HashMap;
+
+/**
+ * Created by Shakib Ahmed on 5/4/17.
+ */
+public class HostVrfRoutingInformationMapper {
+    HashMap<String, HashMap<Long, RoutingInfo> > mapper;
+
+    private static final HostVrfRoutingInformationMapper INSTANCE = new HostVrfRoutingInformationMapper();
+
+    private HostVrfRoutingInformationMapper() {
+        mapper = new HashMap<>();
+    }
+
+    public static HostVrfRoutingInformationMapper getInstance() {
+        return INSTANCE;
+    }
+
+    public void addRoutingVrfToHost(String hostId, long vrf, RoutingInfo routingInfo) {
+        HashMap<Long, RoutingInfo> routingInfoMapper = mapper.get(hostId);
+
+        if (routingInfoMapper == null) {
+            routingInfoMapper = new HashMap<>();
+            mapper.put(hostId, routingInfoMapper);
+        }
+
+        routingInfoMapper.put(vrf, routingInfo);
+    }
+
+    public boolean vrfExists(String hostId, long vrf) {
+        return mapper.containsKey(hostId) && mapper.get(hostId).containsKey(vrf);
+    }
+
+    public String getProtocolName(String hostId, long vrf) {
+        Preconditions.checkArgument(vrfExists(hostId, vrf));
+
+        return mapper.get(hostId).get(vrf).getProtocolName();
+    }
+
+    public void addStaticRoute(String hostId, long vrf) {
+        HashMap<Long, RoutingInfo> routingInfoMapper = mapper.get(hostId);
+
+        Preconditions.checkNotNull(routingInfoMapper, "Routing protocol not created, can't add route entry");
+
+        RoutingInfo routingInfo = routingInfoMapper.get(vrf);
+
+        Preconditions.checkNotNull(routingInfoMapper, "VRF was not created for this host");
+
+        routingInfo.incrementCount();
+    }
+
+    public Long getEndPointCountInVrf(String hostId, long vrf) {
+        int count = 0;
+
+        if (vrfExists(hostId, vrf)) {
+            count = mapper.get(hostId).get(vrf).getCount();
+        }
+        return (long) (count + 1);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/InterfaceNameToRouteInfoMapper.java
new file mode 100644 (file)
index 0000000..f227684
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 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.lisp.mappers;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Created by Shakib Ahmed on 5/26/17.
+ */
+public class InterfaceNameToRouteInfoMapper {
+    HashMap<String, StaticRouteInfoMapper> interfaceNameToStaticRouteMapper;
+
+    public InterfaceNameToRouteInfoMapper() {
+        interfaceNameToStaticRouteMapper = new HashMap<>();
+    }
+
+    public boolean routeAlreadyExists(String interfaceName, Ipv4Address ip) {
+        StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName);
+
+        if (staticRouteInfoMapper == null) {
+            return false;
+        }
+
+        return staticRouteInfoMapper.routeWithIpExists(ip);
+    }
+
+    public void addRouteForInterface(String interfaceName, Ipv4Address ip, Long routeId) {
+        StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName);
+
+        if (staticRouteInfoMapper == null) {
+            staticRouteInfoMapper = new StaticRouteInfoMapper();
+            interfaceNameToStaticRouteMapper.put(interfaceName, staticRouteInfoMapper);
+        }
+
+        staticRouteInfoMapper.addIpRouteForInterface(ip, routeId);
+    }
+
+    public List<Long> getRoutingIdsAssociatedWithInterface(String interfaceName) {
+        StaticRouteInfoMapper staticRouteInfoMapper = interfaceNameToStaticRouteMapper.get(interfaceName);
+
+        return staticRouteInfoMapper == null ? new ArrayList<>() : staticRouteInfoMapper.getAllRoutingIds();
+    }
+
+    public void clearStaticRoutesForInterface(String interfaceName) {
+        interfaceNameToStaticRouteMapper.remove(interfaceName);
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/LoopbackHostSpecificInfoMapper.java
new file mode 100644 (file)
index 0000000..3d6302c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2017 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.lisp.mappers;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.apache.commons.lang3.mutable.MutableInt;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.SubnetHostInfo;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Created by Shakib Ahmed on 4/26/17.
+ */
+public class LoopbackHostSpecificInfoMapper {
+    private HashMap<String, HashMap<String, SubnetHostInfo>> hostIdToSubnetMapper;
+    private Multimap<String, String> subnetUuidToHostIdListMapper;
+    private HashMap<String, MutableInt> hostIdToLoopbackCountMapper;
+
+    public LoopbackHostSpecificInfoMapper() {
+        hostIdToSubnetMapper = new HashMap<>();
+        subnetUuidToHostIdListMapper = ArrayListMultimap.create();
+        hostIdToLoopbackCountMapper = new HashMap<>();
+    }
+
+    private HashMap<String, SubnetHostInfo> getSubnetsOfHost(String hostName) {
+        return hostIdToSubnetMapper.get(hostName);
+    }
+
+    public boolean loopbackAlreadyExists(String hostName, String subnetUuid) {
+        return hostIdToSubnetMapper.containsKey(hostName) &&
+                hostIdToSubnetMapper.get(hostName).containsKey(subnetUuid);
+    }
+
+    public void addLoopbackForHost(String hostName, String subnetUuid, String interfaceName, long vrf) {
+        putSubnetInfoOfAHost(hostName, subnetUuid, interfaceName, vrf);
+        subnetUuidToHostIdListMapper.put(subnetUuid, hostName);
+    }
+
+    private void putSubnetInfoOfAHost(String hostId, String subnetUuid, String interfaceName, long vrf) {
+        HashMap<String, SubnetHostInfo> subnetsOfAHost = getSubnetsOfHost(hostId);
+        MutableInt loopbackCount = getMutableIntAfterInitIfNecessary(hostId);
+
+        loopbackCount.add(1);
+
+        if (subnetsOfAHost == null) {
+            subnetsOfAHost = new HashMap<>();
+            hostIdToSubnetMapper.put(hostId, subnetsOfAHost);
+        }
+
+        SubnetHostInfo subnetHostInfo = new SubnetHostInfo(interfaceName);
+        subnetsOfAHost.put(subnetUuid, subnetHostInfo);
+    }
+
+    private MutableInt getMutableIntAfterInitIfNecessary(String hostId) {
+        MutableInt loopbackCount = hostIdToLoopbackCountMapper.get(hostId);
+
+        if (loopbackCount == null) {
+            loopbackCount = new MutableInt();
+            loopbackCount.setValue(0);
+            hostIdToLoopbackCountMapper.put(hostId, loopbackCount);
+        }
+        return loopbackCount;
+    }
+
+    public int getLoopbackCount(String hostName) {
+        MutableInt loopbackCount = getMutableIntAfterInitIfNecessary(hostName);
+        return loopbackCount.getValue();
+    }
+
+    public void clearSubnet(String subnetUuid) {
+        subnetUuidToHostIdListMapper.get(subnetUuid).forEach(hostId -> {
+            deleteParticularSubnetFromHost(hostId, subnetUuid);
+        });
+        subnetUuidToHostIdListMapper.get(subnetUuid).clear();
+    }
+
+    private void deleteParticularSubnetFromHost(String hostId, String subnetUuid) {
+        hostIdToSubnetMapper.get(hostId).remove(subnetUuid);
+    }
+
+    private void deleteHostFromSubnetMap(String subnetUuid, String hostId) {
+        subnetUuidToHostIdListMapper.get(subnetUuid).remove(hostId);
+    }
+
+    public List<String> getHostsWithSubnet(String subnetUuid) {
+        return subnetUuidToHostIdListMapper.get(subnetUuid).stream().collect(Collectors.toList());
+    }
+
+    public String getInterfaceNameForLoopbackInHost(String hostId, String subnetUuid) {
+        if (hostIdToSubnetMapper.get(hostId) != null) {
+            return hostIdToSubnetMapper.get(hostId).get(subnetUuid).getInterfaceName();
+        } else {
+            return null;
+        }
+    }
+
+    public int getPortCount(String hostId, String subnetUuid) {
+        if (hostIdToSubnetMapper.containsKey(hostId)) {
+            if (hostIdToSubnetMapper.get(hostId).containsKey(subnetUuid)) {
+                return hostIdToSubnetMapper.get(hostId).get(subnetUuid).getPortCount();
+            } else {
+                return 0;
+            }
+        } else {
+            return 0;
+        }
+    }
+
+    public void addNewPortInHostSubnet(String hostId, String subnetUuid) {
+        getSubnetsOfHost(hostId).get(subnetUuid).incrementPortCount();
+    }
+
+    public boolean deletePortFromHostSubnetAndTriggerLoopbackDelete(String hostId, String subnetUuid) {
+        if (getSubnetsOfHost(hostId).containsKey(subnetUuid)) {
+            int count = getSubnetsOfHost(hostId).get(subnetUuid).decrementAndGetPortCount();
+
+            if (count == 0) {
+                deleteParticularSubnetFromHost(hostId, subnetUuid);
+            }
+
+            return count == 0;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/StaticRouteInfoMapper.java
new file mode 100644 (file)
index 0000000..a05060e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2017 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.lisp.mappers;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Created by Shakib Ahmed on 5/26/17.
+ */
+public class StaticRouteInfoMapper {
+    HashMap<Ipv4Address, Long> interfaceIpToRouteIdMapper;
+
+    public StaticRouteInfoMapper() {
+        interfaceIpToRouteIdMapper = new HashMap<>();
+    }
+
+    public void addIpRouteForInterface(Ipv4Address ip, Long routingId) {
+        interfaceIpToRouteIdMapper.put(ip, routingId);
+    }
+
+    public boolean routeWithIpExists(Ipv4Address ip) {
+        return interfaceIpToRouteIdMapper.containsKey(ip);
+    }
+
+    public Long getRouteIdForIp(Ipv4Address ip) {
+        return interfaceIpToRouteIdMapper.get(ip);
+    }
+
+    public List<Long> getAllRoutingIds() {
+        return interfaceIpToRouteIdMapper.entrySet()
+                .stream()
+                .map(ipv4AddressLongEntry -> ipv4AddressLongEntry.getValue())
+                .collect(Collectors.toList());
+    }
+}
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/mappers/SubnetUuidToGbpSubnetMapper.java
new file mode 100644 (file)
index 0000000..68b3146
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 Cisco Systems, Inc.  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.lisp.mappers;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.GbpSubnet;
+
+import java.util.HashMap;
+
+/**
+ * Created by Shakib Ahmed on 5/3/17.
+ */
+public class SubnetUuidToGbpSubnetMapper {
+
+    private HashMap<String, GbpSubnet> subnetInformation;
+
+    private static SubnetUuidToGbpSubnetMapper INSTANCE = new SubnetUuidToGbpSubnetMapper();
+
+    private SubnetUuidToGbpSubnetMapper() {
+        subnetInformation = new HashMap<>();
+    }
+
+    public static SubnetUuidToGbpSubnetMapper getInstance() {
+        return INSTANCE;
+    }
+
+    public void addSubnetInfo(String subnetUuid, GbpSubnet subnetInfo) {
+        subnetInformation.put(subnetUuid, subnetInfo);
+    }
+
+    public GbpSubnet getSubnetInfo(String subnetUuid) {
+        return subnetInformation.get(subnetUuid);
+    }
+
+    public void removeSubnetInfo(String subnetUuid) {
+        subnetInformation.remove(subnetUuid);
+    }
+}
index 91185b7af556ac7d322427a0a798994d9caf219f..8b6240e4782994b89cf42666e9135c73269810ac 100644 (file)
@@ -38,7 +38,9 @@ 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.has.child.endpoints.ChildEndpoint;
 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.MacAddressType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.renderer.rev151103.renderers.renderer.renderer.policy.configuration.endpoints.AddressEndpointWithLocation;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.groupbasedpolicy.vpp_renderer.rev160425.config.VppEndpoint;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lisp.rev170315.HmacKeyType;
@@ -276,10 +278,31 @@ public class ConfigManagerHelper {
         return locatorSet.iterator().next().getValue();
     }
 
+    public Optional<String> getInterfaceName(AddressEndpointWithLocation addedEp) {
+        ExternalLocationCase epLoc = resolveAndValidateLocation(addedEp);
+        String interfacePath = epLoc.getExternalNodeConnector();
+
+        return VppPathMapper.interfacePathToInterfaceName(interfacePath);
+    }
+
     public HmacKey getDefaultHmacKey() {
         return LispUtil.toHmacKey(HmacKeyType.Sha196Key, LispStateManager.DEFAULT_XTR_KEY);
     }
 
+    public String getPhysicalAddress(AddressEndpointWithLocation addressEp) {
+        String physicalAddress = null;
+
+        List<ChildEndpoint> childEndpoints = addressEp.getChildEndpoint();
+        for (ChildEndpoint childEndpoint : childEndpoints) {
+            if (childEndpoint.getAddressType().equals(MacAddressType.class)) {
+                physicalAddress = childEndpoint.getAddress();
+                break;
+            }
+        }
+        return Preconditions.checkNotNull(physicalAddress, "Physical address not found " +
+                "in address endpoint: " + addressEp);
+    }
+
     public Routing getRouting(long vrf) {
         return new RoutingBuilder().setIpv4VrfId(vrf).build();
     }
diff --git a/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java b/renderers/vpp/src/main/java/org/opendaylight/groupbasedpolicy/renderer/vpp/lisp/util/IpAddressUtil.java
new file mode 100644 (file)
index 0000000..7d135cf
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2017 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.lisp.util;
+
+import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.commons.net.util.SubnetUtils;
+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;
+
+/**
+ * Created by Shakib Ahmed on 5/3/17.
+ */
+public class IpAddressUtil {
+
+    public static Pair<Ipv4Address, Ipv4Address> getStartAndEndIp(Ipv4Prefix ipv4Prefix) {
+        SubnetUtils subnetUtils = new SubnetUtils(ipv4Prefix.getValue());
+        SubnetUtils.SubnetInfo prefixSubnetInfo = subnetUtils.getInfo();
+        Ipv4Address lowIp = new Ipv4Address(prefixSubnetInfo.getLowAddress());
+        Ipv4Address highIp = new Ipv4Address(prefixSubnetInfo.getHighAddress());
+        return new ImmutablePair<>(lowIp, highIp);
+    }
+}
\ No newline at end of file
index f3d9331a32912b9d904d5fe1a2986d829b79d35f..a42835acda5c0ef7c7cd6ff08cc831ff0c0baf02 100644 (file)
@@ -28,7 +28,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.commands.RoutingCommand;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.config.ConfigUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatUtil;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
@@ -102,19 +103,21 @@ public final class ForwardingManager {
     private final NatManager natManager;
     private final RoutingManager routingManager;
     private final LispStateManager lispStateManager;
-    private final BviManager bviManager;
+    private final LoopbackManager loopbackManager;
+    private final FlatOverlayManager flatOverlayManager;
     private final DataBroker dataBroker;
 
     public ForwardingManager(@Nonnull InterfaceManager ifaceManager, @Nonnull AclManager aclManager,
-        @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager,
-        @Nonnull LispStateManager lispStateManager, @Nonnull BviManager bviManager,
-        @Nonnull DataBroker dataBroker) {
+                             @Nonnull NatManager natManager, @Nonnull RoutingManager routingManager, @Nonnull BridgeDomainManager bdManager,
+                             @Nonnull LispStateManager lispStateManager, @Nonnull LoopbackManager loopbackManager, @Nonnull FlatOverlayManager flatOverlayManager,
+                             @Nonnull DataBroker dataBroker) {
         this.ifaceManager = Preconditions.checkNotNull(ifaceManager);
         this.bdManager = Preconditions.checkNotNull(bdManager);
         this.natManager = Preconditions.checkNotNull(natManager);
         this.routingManager = Preconditions.checkNotNull(routingManager);
         this.lispStateManager = Preconditions.checkNotNull(lispStateManager);
-        this.bviManager = Preconditions.checkNotNull(bviManager);
+        this.loopbackManager = Preconditions.checkNotNull(loopbackManager);
+        this.flatOverlayManager = Preconditions.checkNotNull(flatOverlayManager);
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.aclManager = Preconditions.checkNotNull(aclManager);
     }
@@ -205,6 +208,10 @@ public final class ForwardingManager {
 
         if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
             lispStateManager.configureEndPoint(rEp);
+            if (ConfigUtil.getInstance().isL3FlatEnabled()) {
+                flatOverlayManager.configureEndpointForFlatOverlay(rEp);
+                loopbackManager.createSimpleLoopbackIfNeeded(rEp);
+            }
         }
 
         ExternalLocationCase rEpLoc = resolveAndValidateLocation(rEp);
@@ -229,7 +236,7 @@ public final class ForwardingManager {
                     LOG.debug("Interface added to bridge-domain {} for endpoint {}", l2FloodDomain, rEp);
 
                     if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
-                        bviManager.createBviIfNecessary(rEp, l2FloodDomain);
+                        loopbackManager.createBviLoopbackIfNeeded(rEp, l2FloodDomain);
                     }
 
                 } catch (InterruptedException | ExecutionException e) {
@@ -275,6 +282,12 @@ public final class ForwardingManager {
             try {
                 if (ConfigUtil.getInstance().isLispOverlayEnabled()) {
                     lispStateManager.deleteLispConfigurationForEndpoint(rEp);
+                    loopbackManager.handleEndpointDelete(rEp);
+
+                    if (ConfigUtil.getInstance().isL3FlatEnabled()) {
+                        flatOverlayManager.handleEndpointDeleteForFlatOverlay(rEp);
+                    }
+
                 }
                 ifaceManager.deleteBridgeDomainFromInterface(rEp).get();
                 LOG.debug("bridge-domain was deleted from interface for endpoint {}", rEp);
index b054a000dd29dce5d5e0782379083fa73d477725..ca2922d681e6b8527c5ba79599842f8f1b8d480d 100644 (file)
@@ -53,6 +53,23 @@ public class GbpNetconfTransaction {
         return result;
     }
 
+    /***
+     * Netconf wrapper for merge operation on a Netconf Device
+     * @param mountpoint    netconf device
+     * @param iid           path for Data to be merged to
+     * @param data          data to be merged
+     * @param retryCounter  retry counter, will repeat the operation for specified amount of times if transaction fails
+     * @param <T>           data type
+     * @return true if transaction is successful, false otherwise
+     */
+    public static <T extends DataObject> boolean netconfSyncedMerge(@Nonnull final DataBroker mountpoint,
+                                                                    @Nonnull final InstanceIdentifier<T> iid, @Nonnull final T data, byte retryCounter) {
+        VbdNetconfTransaction.REENTRANT_LOCK.lock();
+        boolean result = merge(mountpoint, iid, data, retryCounter);
+        VbdNetconfTransaction.REENTRANT_LOCK.unlock();
+        return result;
+    }
+
     /***
      * Netconf wrapper method for synced requests for write operation on a Netconf Device
      * @param mountpoint    netconf device
@@ -193,6 +210,39 @@ public class GbpNetconfTransaction {
         }
     }
 
+    /**
+     * Merge data to remote device. Transaction is restarted if failed
+     *
+     * @param mountpoint   to access remote device
+     * @param iid          data identifier
+     * @param data         to merge
+     * @param retryCounter number of attempts
+     * @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 merge(final DataBroker mountpoint, final InstanceIdentifier<T> iid,
+                                                        final T data, byte retryCounter) {
+        LOG.trace("Netconf MERGE transaction started. RetryCounter: {}", retryCounter);
+        Preconditions.checkNotNull(mountpoint);
+        final ReadWriteTransaction rwTx = mountpoint.newReadWriteTransaction();
+        try {
+            rwTx.merge(LogicalDatastoreType.CONFIGURATION, iid, data, true);
+            final CheckedFuture<Void, TransactionCommitFailedException> futureTask = rwTx.submit();
+            futureTask.get();
+            LOG.trace("Netconf MERGE transaction done for {}", iid);
+            return true;
+        } catch (Exception e) {
+            // Retry
+            if (retryCounter > 0) {
+                LOG.warn("Netconf MERGE transaction failed to {}. Restarting transaction ... ", e.getMessage());
+                return write(mountpoint, iid, data, --retryCounter);
+            } else {
+                LOG.warn("Netconf MERGE transaction unsuccessful. Maximal number of attempts reached. Trace: {}", e);
+                return false;
+            }
+        }
+    }
+
     /**
      * Use {@link AbstractLispCommand} to put data into netconf transaction and submit. Transaction is restarted if failed
      *
index 95e0bc39fd277461404ef7f37a65ac217e22855b..a20f03cb52b9aece1877d6423cfd3751d44f3e77 100644 (file)
@@ -13,9 +13,14 @@ 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;
+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.interfaces.rev140508.Interfaces;
 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.interfaces.rev140508.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.Neighbor;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.NeighborKey;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.nat.rev150908.NatConfig;
 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;
@@ -58,6 +63,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.bridge.domains.state.BridgeDomainKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315.interfaces._interface.L2;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.acl.rev161214.VppAcl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.ProxyRanges;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRange;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.vpp.proxy.arp.rev170315.proxy.ranges.ProxyRangeKey;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
@@ -199,4 +207,26 @@ public class VppIidFactory {
         return InstanceIdentifier.builder(Lisp.class)
                 .child(LispFeatureData.class).build();
     }
+
+    public static InstanceIdentifier<ProxyRange> getProxyRangeIid(Long vrf,
+                                                                  Ipv4Address startAddress,
+                                                                  Ipv4Address endAddress) {
+        return InstanceIdentifier.builder(ProxyRanges.class)
+                .child(ProxyRange.class, new ProxyRangeKey(endAddress, startAddress, vrf)).build();
+    }
+
+    public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315
+            .interfaces._interface.Routing> getRoutingIid(InterfaceKey interfaceKey) {
+        return getInterfaceIID(interfaceKey)
+                .augmentation(VppInterfaceAugmentation.class)
+                .child(org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.v3po.rev170315
+                        .interfaces._interface.Routing.class);
+    }
+
+    public static InstanceIdentifier<Neighbor> getNeighborIid(InterfaceKey interfaceKey, NeighborKey neighborKey) {
+        return getInterfaceIID(interfaceKey)
+                .augmentation(Interface1.class)
+                .child(Ipv4.class)
+                .child(Neighbor.class, neighborKey);
+    }
 }
index 541f2acddde214e1f9ab253729a58bfeaa7f0451..f6d6fdffd48ad149ad2dfe8defa23b97c422be14 100644 (file)
@@ -24,7 +24,8 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
@@ -109,10 +110,11 @@ public class BridgeDomainManagerImplTest extends CustomDataBrokerTest {
         final NatManager natManager = Mockito.mock(NatManager.class);
         final RoutingManager routingManager = Mockito.mock(RoutingManager.class);
         final LispStateManager lispStateManager = Mockito.mock(LispStateManager.class);
-        final BviManager bviManager = Mockito.mock(BviManager.class);
+        final FlatOverlayManager flatOverlayManager = Mockito.mock(FlatOverlayManager.class);
+        final LoopbackManager loopbackManager = Mockito.mock(LoopbackManager.class);
         final ForwardingManager fwManager =
             new ForwardingManager(interfaceManager, aclManager, natManager, routingManager, bridgeDomainManager,
-                lispStateManager, bviManager, dataBroker);
+                lispStateManager, loopbackManager, flatOverlayManager, dataBroker);
         fwManager.setTimer((byte) 1);
     }
 
index 1ae6f5f09bd7519a26c3ab5c924ea5e2bcfef26d..53416e2eddcb408a520ae64d01e6d2eecb6496ca 100644 (file)
@@ -24,7 +24,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.DtoFactory;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.api.BridgeDomainManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AccessListWrapper;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
@@ -72,7 +73,9 @@ public class ForwardingManagerTest extends CustomDataBrokerTest {
     @Mock
     private LispStateManager lispStateManager;
     @Mock
-    private BviManager bviManager;
+    private FlatOverlayManager flatOverlayManager;
+    @Mock
+    private LoopbackManager loopbackManager;
 
     private ForwardingManager fwdManager;
 
@@ -80,7 +83,7 @@ public class ForwardingManagerTest extends CustomDataBrokerTest {
     public void init() {
         fwdManager =
             new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager, lispStateManager,
-                    bviManager, getDataBroker());
+                    loopbackManager, flatOverlayManager, getDataBroker());
     }
 
     @Override
index b1201c90734f69c6e79cd72e8dac9cc51f83d612..1f28549ff47833a4c4ba11c930d5226c3836d68e 100644 (file)
@@ -29,7 +29,8 @@ import org.opendaylight.groupbasedpolicy.renderer.vpp.event.VppEndpointConfEvent
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.InterfaceManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.iface.VppEndpointLocationProvider;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.LispStateManager;
-import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.bvi.BviManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.loopback.LoopbackManager;
+import org.opendaylight.groupbasedpolicy.renderer.vpp.lisp.flat.overlay.FlatOverlayManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.nat.NatManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.policy.acl.AclManager;
 import org.opendaylight.groupbasedpolicy.renderer.vpp.routing.RoutingManager;
@@ -89,7 +90,8 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
     private NatManager natManager;
     private RoutingManager routingManager;
     private LispStateManager lispStateManager;
-    private BviManager bviManager;
+    private LoopbackManager loopbackManager;
+    private FlatOverlayManager flatOverlayManager;
     private VppRendererPolicyManager vppRendererPolicyManager;
 
     @Override
@@ -113,9 +115,10 @@ public class VppRendererPolicyManagerTest extends CustomDataBrokerTest {
         routingManager = new RoutingManager(dataBroker, mountedDataProviderMock);
         bdManager = new BridgeDomainManagerImpl(mountPointDataBroker);
         lispStateManager = new LispStateManager(mountedDataProviderMock);
-        bviManager = new BviManager(mountedDataProviderMock);
+        loopbackManager = new LoopbackManager(mountedDataProviderMock);
+        flatOverlayManager = new FlatOverlayManager(mountedDataProviderMock);
         fwManager = new ForwardingManager(ifaceManager, aclManager, natManager, routingManager, bdManager,
-                lispStateManager, bviManager, dataBroker);
+                lispStateManager, loopbackManager, flatOverlayManager, dataBroker);
         vppRendererPolicyManager = new VppRendererPolicyManager(fwManager, aclManager, dataBroker);
         fwManager.setTimer((byte) 1);
     }