BUG 6489: Routes to InterVpnLink not advertised on BGP 60/44460/2
authorSuraj Ranjan <suraj.ranjan@ericsson.com>
Mon, 22 Aug 2016 09:00:39 +0000 (14:30 +0530)
committerSuraj Ranjan <suraj.ranjan@ericsson.com>
Mon, 22 Aug 2016 15:11:05 +0000 (20:41 +0530)
 + Missing functionality: when a route pointing to an interVpnLink
   endpoint is added/removed to a Neutron Router, CSC must advertise
   the prefix. The nexthop(s) for the BGP are the DPNs where the
   endpoint of the InterVpnLink was instantiated

 + Moves some InterVpnLink utility methods from VpnUtil.java to
   InterVpnLinkUtil.java

 + Changes some return values to Optional.

Change-Id: I9e671b34400151099e501d26a8a7839c7730d0b7
Signed-off-by: Suraj Ranjan <suraj.ranjan@ericsson.com>
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnInterfaceManager.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnRpcServiceImpl.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/VpnUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkNodeAddTask.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkNodeListener.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/netvirt/vpnmanager/intervpnlink/InterVpnLinkUtil.java
vpnservice/vpnmanager/vpnmanager-impl/src/main/resources/org/opendaylight/blueprint/vpnmanager.xml

index 738e07782429ae3ed1cb8a6235752a27784b242e..601b373a69e7b713033f817f1a5de8f7e01e1e8f 100644 (file)
@@ -55,6 +55,7 @@ import org.opendaylight.genius.utils.ServiceIndex;
 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkUtil;
 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
@@ -1585,8 +1586,9 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
         // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
         // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
         // first place.
-        InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
-        if ( interVpnLink != null ) {
+        Optional<InterVpnLink> optInterVpnLink = InterVpnLinkUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
+        if ( optInterVpnLink.isPresent() ) {
+            InterVpnLink interVpnLink = optInterVpnLink.get();
             // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
             // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
             // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
@@ -1599,7 +1601,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             String dstVpnRd = VpnUtil.getVpnRd(dataBroker, dstVpnUuid);
             long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
                     VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
-            VpnUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
+            InterVpnLinkUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
         } else {
             if (rd != null) {
                 addPrefixToBGP(rd, destination, nextHop, label, null);
index 44cb63717b577cdbe3349601659308414f79530d..3df342e910e7b2652bfe2dcf61edbe39f47bc3cb 100644 (file)
@@ -7,10 +7,14 @@
  */
 package org.opendaylight.netvirt.vpnmanager;
 
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.SettableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
+import org.opendaylight.netvirt.vpnmanager.intervpnlink.InterVpnLinkUtil;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
@@ -21,9 +25,11 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 import java.util.concurrent.Future;
 
 public class VpnRpcServiceImpl implements VpnRpcService {
@@ -32,13 +38,15 @@ public class VpnRpcServiceImpl implements VpnRpcService {
     private final IdManagerService idManager;
     private final VpnInterfaceManager vpnInterfaceMgr;
     private IFibManager fibManager;
+    private IBgpManager bgpManager;
 
     public VpnRpcServiceImpl(final DataBroker dataBroker, final IdManagerService idManager,
-                             final VpnInterfaceManager vpnIfaceMgr, final IFibManager fibManager) {
+                             final VpnInterfaceManager vpnIfaceMgr, final IFibManager fibManager, IBgpManager bgpManager) {
         this.dataBroker = dataBroker;
         this.idManager = idManager;
         this.vpnInterfaceMgr = vpnIfaceMgr;
         this.fibManager = fibManager;
+        this.bgpManager = bgpManager;
     }
 
     public void setFibManager(IFibManager fibMgr) {
@@ -142,10 +150,33 @@ public class VpnRpcServiceImpl implements VpnRpcService {
             return result;
         }
 
-        InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
-        if ( interVpnLink != null ) {
-            // A static route pointing to an InterVpnLink endpoint: just write the VrfEntry
-            fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, destination, Arrays.asList(nexthop), label.intValue(), RouteOrigin.STATIC, null);
+        Optional<InterVpnLink> interVpnLink = InterVpnLinkUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
+        if ( interVpnLink.isPresent() ) {
+            // A static route pointing to an InterVpnLink endpoint: write the VrfEntry and inform DC-GW
+            LOG.debug("addStaticRoute: Writing FibEntry to DS:  vpnRd={}, prefix={}, label={}, nexthop={} (interVpnLink)",
+                    vpnRd, destination, label, nexthop);
+            fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, destination, Arrays.asList(nexthop), label.intValue(),
+                    RouteOrigin.STATIC, null);
+
+            // The nexthop list to advertise to BGP contains the list of IPs of those DPNs where the
+            // endpoint has been instantiated
+            List<String> nexthopList = new ArrayList<String>();
+            List<BigInteger> dpns = InterVpnLinkUtil.getVpnLinkEndpointDPNsByIp(dataBroker, nexthop);
+            for ( BigInteger dpnId : dpns ) {
+                nexthopList.add(InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId));
+            }
+            try {
+                LOG.debug("addStaticRoute:advertise IVpnLink route to BGP:  vpnRd={}, prefix={}, label={}, nexthops={}",
+                        vpnRd, destination, label, nexthopList);
+                bgpManager.advertisePrefix(vpnRd, destination, nexthopList, label.intValue());
+            } catch (Exception e) {
+                String errMsg = "Could not advertise route [vpn=" + vpnRd + ", prefix=" + destination + ", label="
+                        + label + ", nexthops=" + nexthopList + ", ] to BGP. Reason: " + e;
+                LOG.warn("Could not advertise route [vpn={}, prefix={}, label={}, nexthops={}] to BGP. Reason: ",
+                        vpnRd, destination, label, nexthopList, e);
+                result.set(RpcResultBuilder.<AddStaticRouteOutput>failed().withError(ErrorType.APPLICATION, errMsg)
+                        .build());
+            }
         } else {
             vpnInterfaceMgr.addExtraRoute(destination, nexthop, vpnRd, null /*routerId */, label.intValue(),
                                           null /* intfName */);
@@ -199,10 +230,14 @@ public class VpnRpcServiceImpl implements VpnRpcService {
             return result;
         }
 
-        InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
-        if ( interVpnLink != null ) {
-            // A static route pointing to an InterVpnLink endpoint: just remove the VrfEntry from DS
+        Optional<InterVpnLink> optVpnLink = InterVpnLinkUtil.getInterVpnLinkByEndpointIp(dataBroker, nexthop);
+        if ( optVpnLink.isPresent() ) {
             fibManager.removeOrUpdateFibEntry(dataBroker,  vpnRd, destination, nexthop, null);
+            try {
+                bgpManager.withdrawPrefix(vpnRd, destination);
+            } catch (Exception e) {
+                LOG.warn("Could not withdraw route [vpn={}  prefix={}] to BGP. Reason:", vpnRd, destination, e);
+            }
         } else {
             vpnInterfaceMgr.delExtraRoute(destination, nexthop, vpnRd, null /*routerId*/, null /*intfName*/);
         }
index 324e89ce643bb6f6e7caac3a092c058fdbc3f24b..8004bbf7cbd1c49c00f8259724020762746b9730 100644 (file)
@@ -180,34 +180,6 @@ public class VpnUtil {
         return new VpnBuilder().setKey(new VpnKey(vrfId)).setVrfId(vrfId).build();
     }
 
-    /**
-     * Retrieves the Instance Identifier that points to an InterVpnLink object
-     * in MDSL
-     *
-     * @param vpnLinkName The name of the InterVpnLink
-     * @return The requested InstanceIdentifier
-     */
-    public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
-        return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
-    }
-
-    /**
-     * Get inter-VPN link state
-     *
-     * @param broker dataBroker service reference
-     * @param vpnLinkName The name of the InterVpnLink
-     * @return the object that contains the State of the specified InterVpnLink
-     */
-    public static InterVpnLinkState getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
-        InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(vpnLinkName);
-        Optional<InterVpnLinkState> vpnLinkState = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
-                vpnLinkStateIid);
-        if (vpnLinkState.isPresent()) {
-            return vpnLinkState.get();
-        }
-        return null;
-    }
-
     /**
      * Get VRF table given a Route Distinguisher
      *
@@ -1019,161 +991,6 @@ public class VpnUtil {
         }
     }
 
-    /**
-     * Retrieves all configured InterVpnLinks
-     *
-     * @param broker dataBroker service reference
-     * @return the list of InterVpnLinks
-     */
-    public static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
-        InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
-
-        Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
-                interVpnLinksIid);
-
-        return (interVpnLinksOpData.isPresent()) ? interVpnLinksOpData.get().getInterVpnLink()
-                : new ArrayList<InterVpnLink>();
-    }
-
-    /**
-     * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated
-     *
-     * @param broker dataBroker service reference
-     * @param vpnLinkName the name of the InterVpnLink
-     * @param vpnUuid UUID of the VPN whose endpoint to be checked
-     * @return the list of DPN Ids
-     */
-    public static List<BigInteger> getVpnLinkEndpointDPNs(DataBroker broker, String vpnLinkName, String vpnUuid) {
-        InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
-        if (interVpnLinkState.getFirstEndpointState().getVpnUuid().getValue().equals(vpnUuid)) {
-            return interVpnLinkState.getFirstEndpointState().getDpId();
-        } else {
-            return interVpnLinkState.getSecondEndpointState().getDpId();
-        }
-    }
-
-    /**
-     * Retrieves an InterVpnLink by searching by one of its endpoint's IP.
-     *
-     * @param broker dataBroker service reference
-     * @param endpointIp IP to serch for.
-     * @return the InterVpnLink or null if no InterVpnLink can be found
-     */
-    public static InterVpnLink getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
-        List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
-        for (InterVpnLink interVpnLink : allInterVpnLinks) {
-            if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
-                    || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
-                return interVpnLink;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Retrieves the InterVpnLink that has one of its 2 endpoints installed in
-     * the specified DpnId
-     *
-     * @param broker dataBroker service reference
-     * @param dpnId Id of the DPN
-     * @return The InterVpnLink object if found, Optional.absent() otherwise
-     */
-    public static Optional<InterVpnLink> getInterVpnLinkByDpnId(DataBroker broker, BigInteger dpnId) {
-        List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
-        for (InterVpnLink interVpnLink : allInterVpnLinks) {
-            InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
-            if ( ( interVpnLinkState != null )
-                 && ( interVpnLinkState.getFirstEndpointState().getDpId().contains(dpnId)
-                      || interVpnLinkState.getSecondEndpointState().getDpId().contains(dpnId) ) ) {
-                return Optional.fromNullable(interVpnLink);
-            }
-        }
-        return Optional.absent();
-    }
-
-    /**
-     * Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN
-     *
-     * @param broker           dataBroker service reference
-     * @param bgpManager       Used to advertise routes to the BGP Router
-     * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
-     * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
-     * @param dstVpnUuid       UUID of the VPN that is going to receive the route
-     * @param prefix           Prefix of the route
-     * @param label            Label of the route in the original VPN
-     */
-    public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
-                                 String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
-        leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, prefix, label, RouteOrigin.INTERVPN);
-    }
-
-    /**
-     * Leaks a route from one VPN to another.
-     *
-     * @param broker           dataBroker service reference
-     * @param bgpManager       Used to advertise routes to the BGP Router
-     * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
-     * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
-     * @param dstVpnUuid       UUID of the VPN that is going to receive the route
-     * @param prefix           Prefix of the route
-     * @param label            Label of the route in the original VPN
-     * @param forcedOrigin     By default, origin for leaked routes should be INTERVPN, however it is possible to
-     *                         provide a different origin if desired.
-     */
-    public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
-                                 String srcVpnUuid, String dstVpnUuid, String prefix, Long label,
-                                 RouteOrigin forcedOrigin) {
-        Preconditions.checkNotNull(interVpnLink);
-
-        // The source VPN must participate in the InterVpnLink
-        Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid)
-                        || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid),
-                "The source VPN {} does not participate in the interVpnLink {}",
-                srcVpnUuid, interVpnLink.getName());
-        // The destination VPN must participate in the InterVpnLink
-        Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid)
-                        || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid),
-                "The destination VPN {} does not participate in the interVpnLink {}",
-                dstVpnUuid, interVpnLink.getName());
-
-        boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
-
-        String endpointIp = (destinationIs1stEndpoint) ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
-                : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
-
-        VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
-                .setLabel(label).setNextHopAddressList(Arrays.asList(endpointIp))
-                .setOrigin(RouteOrigin.INTERVPN.getValue())
-                .build();
-
-        String dstVpnRd = getVpnRd(broker, dstVpnUuid);
-        InstanceIdentifier<VrfEntry> newVrfEntryIid =
-                InstanceIdentifier.builder(FibEntries.class)
-                        .child(VrfTables.class, new VrfTablesKey(dstVpnRd))
-                        .child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix()))
-                        .build();
-        asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
-
-        // Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
-        // endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
-        // VPN has been instantiated
-        List<String> ecmpNexthops = new ArrayList<String>();
-        InterVpnLinkState vpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
-        List<BigInteger> dpnIdList = (destinationIs1stEndpoint) ? vpnLinkState.getFirstEndpointState().getDpId()
-                : vpnLinkState.getSecondEndpointState().getDpId();
-        List<String> nexthops = new ArrayList<String>();
-        for (BigInteger dpnId : dpnIdList) {
-            nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
-        }
-        try {
-            bgpManager.advertisePrefix(dstVpnRd, newVrfEntry.getDestPrefix(), nexthops, label.intValue());
-        } catch (Exception exc) {
-            LOG.error("Could not advertise prefix {} with label {} to VPN rd={}",
-                    newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd);
-        }
-    }
-
-
     /**
      * Retrieves the ids of the currently operative DPNs
      *
index 60f17bf2cfdf58fa4f643f78b6172532bbbcc614..6ac8d8427017584851585ab8331e3082d542cc6e 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
@@ -116,7 +117,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
 
         int numberOfDpns = Integer.getInteger(NBR_OF_DPNS_PROPERTY_NAME, 1);
         // Create VpnLink state
-        InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(add.getName());
+        InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = InterVpnLinkUtil.getInterVpnLinkStateIid(add.getName());
         InterVpnLinkState vpnLinkState = new InterVpnLinkStateBuilder().setInterVpnLinkName(add.getName()).build();
         MDSALUtil.syncWrite(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnLinkStateIid, vpnLinkState);
 
@@ -249,8 +250,8 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
             long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
                                              VpnUtil.getNextHopLabelKey(dstVpnRd, vrfEntry.getDestPrefix()));
 
-            VpnUtil.leakRoute(dataBroker, bgpManager, vpnLink, srcVpnUuid, dstVpnUuid,
-                              vrfEntry.getDestPrefix(), label);
+            InterVpnLinkUtil.leakRoute(dataBroker, bgpManager, vpnLink, srcVpnUuid, dstVpnUuid, vrfEntry.getDestPrefix(),
+                                       label);
         }
     }
 
@@ -274,7 +275,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
                 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
                                                   VpnUtil.getNextHopLabelKey(vpn1Rd, vrfEntry.getDestPrefix()));
 
-                VpnUtil.leakRoute(dataBroker, bgpManager, vpnLink, vpn2Uuid, vpn1Uuid, vrfEntry.getDestPrefix(),
+                InterVpnLinkUtil.leakRoute(dataBroker, bgpManager, vpnLink, vpn2Uuid, vpn1Uuid, vrfEntry.getDestPrefix(),
                                   label, RouteOrigin.value(vrfEntry.getOrigin()));
             }
         }
@@ -284,7 +285,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
     private boolean checkVpnAvailability(InterVpnLinkKey key, Uuid vpnId) {
         Preconditions.checkNotNull(vpnId);
 
-        List<InterVpnLink> interVpnLinks = VpnUtil.getAllInterVpnLinks(dataBroker);
+        List<InterVpnLink> interVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(dataBroker);
         if ( interVpnLinks != null ) {
             for (InterVpnLink interVpnLink : interVpnLinks) {
                 if (!key.equals(interVpnLink.getKey())
@@ -319,14 +320,20 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         VpnUtil.removeVrfEntriesByOrigin(dataBroker, rd2, RouteOrigin.INTERVPN);
         VpnUtil.removeVrfEntriesByNexthop(dataBroker, rd2, del.getFirstEndpoint().getIpAddress().getValue());
 
-        InterVpnLinkState interVpnLinkState = VpnUtil.getInterVpnLinkState(dataBroker, del.getName());
-        Long firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
-        Long secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
-        removeVpnLinkEndpointFlows(del.getName(), rd1, vpn1Uuid, interVpnLinkState.getFirstEndpointState().getDpId(),
-                secondEndpointLportTag.intValue(),
-                del.getSecondEndpoint().getIpAddress().getValue());
-        removeVpnLinkEndpointFlows(del.getName(), rd2, vpn2Uuid, interVpnLinkState.getSecondEndpointState().getDpId(),
-                firstEndpointLportTag.intValue(), del.getFirstEndpoint().getIpAddress().getValue());
+        Optional<InterVpnLinkState> optIVpnLinkState = InterVpnLinkUtil.getInterVpnLinkState(dataBroker, del.getName());
+        if ( optIVpnLinkState.isPresent() ) {
+            InterVpnLinkState interVpnLinkState = optIVpnLinkState.get();
+            Long firstEndpointLportTag = interVpnLinkState.getFirstEndpointState().getLportTag();
+            Long secondEndpointLportTag = interVpnLinkState.getSecondEndpointState().getLportTag();
+            removeVpnLinkEndpointFlows(del.getName(), rd1, vpn1Uuid,
+                    interVpnLinkState.getFirstEndpointState().getDpId(),
+                    secondEndpointLportTag.intValue(),
+                    del.getSecondEndpoint().getIpAddress().getValue());
+            removeVpnLinkEndpointFlows(del.getName(), rd2, vpn2Uuid,
+                    interVpnLinkState.getSecondEndpointState().getDpId(),
+                    firstEndpointLportTag.intValue(),
+                    del.getFirstEndpoint().getIpAddress().getValue());
+        }
 
         // Release idManager with LPortTag associated to endpoints
         LOG.debug("Releasing InterVpnLink {} endpoints LportTags", del.getName());
@@ -342,7 +349,7 @@ public class InterVpnLinkListener extends AbstractDataChangeListener<InterVpnLin
         // Remove it in that case.
 
         // Removing the InterVpnLinkState
-        InstanceIdentifier<InterVpnLinkState> interVpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(del.getName());
+        InstanceIdentifier<InterVpnLinkState> interVpnLinkStateIid = InterVpnLinkUtil.getInterVpnLinkStateIid(del.getName());
         VpnUtil.delete(dataBroker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
     }
 
index ed8edd0cd4189a9681aeb2dd3fc6a74e47d242ce..3d07e5a7f991db3b907a426abd53ac587fd1fffa 100644 (file)
@@ -103,7 +103,7 @@ public class InterVpnLinkNodeAddTask implements Callable<List<ListenableFuture<V
                                                                 .build();
         WriteTransaction tx = broker.newWriteOnlyTransaction();
         tx.merge(LogicalDatastoreType.CONFIGURATION,
-                 VpnUtil.getInterVpnLinkStateIid(interVpnLinkState.getInterVpnLinkName()), newInterVpnLinkState, true);
+                 InterVpnLinkUtil.getInterVpnLinkStateIid(interVpnLinkState.getInterVpnLinkName()), newInterVpnLinkState, true);
         CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
         return futures;
     }
index 922fbceec8a035f6b61548559ed44079fea38b0f..be68ec994249b45842e2ebd225834ce8ef17d58c 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
 
+import com.google.common.base.Optional;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
@@ -122,22 +123,22 @@ public class InterVpnLinkNodeListener extends AbstractDataChangeListener<Node> i
         public List<ListenableFuture<Void>> call() throws Exception {
             List<ListenableFuture<Void>> result = new ArrayList<ListenableFuture<Void>>();
 
-            List<InterVpnLink> allInterVpnLinks = VpnUtil.getAllInterVpnLinks(broker);
+            List<InterVpnLink> allInterVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(broker);
             for ( InterVpnLink interVpnLink : allInterVpnLinks ) {
-                InterVpnLinkState interVpnLinkState = VpnUtil.getInterVpnLinkState(broker, interVpnLink.getName());
-                if ( interVpnLinkState == null ) {
+                Optional<InterVpnLinkState> optIVpnLinkState =
+                        InterVpnLinkUtil.getInterVpnLinkState(broker, interVpnLink.getName());
+                if ( !optIVpnLinkState.isPresent() ) {
                     LOG.warn("Could not find State info for InterVpnLink={}", interVpnLink.getName());
                     continue;
                 }
 
+                InterVpnLinkState interVpnLinkState = optIVpnLinkState.get();
                 if ( interVpnLinkState.getFirstEndpointState().getDpId().contains(dpnId)
                      || interVpnLinkState.getSecondEndpointState().getDpId().contains(dpnId) ) {
                     // InterVpnLink affected by Node DOWN.
                     // Lets move the InterVpnLink to some other place. Basically, remove it and create it again
                     InstanceIdentifier<InterVpnLink> interVpnLinkIid =
-                        InstanceIdentifier.builder(InterVpnLinks.class)
-                                          .child(InterVpnLink.class, new InterVpnLinkKey(interVpnLink.getName()))
-                                          .build();
+                            InterVpnLinkUtil.getInterVpnLinkPath(interVpnLink.getName());
                     // Remove it
                     MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinkIid);
                     // Create it again, but first we have to wait for everything to be removed from dataplane
index 711bb463ebf71ffb2b196f4e541e9267269e9cb4..1f118ad9133950b56e64ae6b9d3df6f8d786af71 100644 (file)
@@ -8,21 +8,34 @@
 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
 
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.genius.mdsalutil.*;
 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
 import org.opendaylight.genius.utils.ServiceIndex;
+import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
+import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
+import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateBuilder;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn
+        .link.states.InterVpnLinkStateKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.FirstEndpointState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.inter.vpn.link.state.SecondEndpointState;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
@@ -41,8 +54,35 @@ import java.util.List;
  *
  */
 public class InterVpnLinkUtil {
+
     private static final Logger LOG = LoggerFactory.getLogger(InterVpnLinkUtil.class);
 
+    /**
+     * Retrieves the Instance Identifier that points to an InterVpnLink object
+     * in MDSL
+     *
+     * @param iVpnLinkName The name of the InterVpnLink
+     * @return The requested InstanceIdentifier
+     */
+    public static InstanceIdentifier<InterVpnLink> getInterVpnLinkPath(String iVpnLinkName) {
+        return InstanceIdentifier.builder(InterVpnLinks.class)
+                .child(InterVpnLink.class, new InterVpnLinkKey(iVpnLinkName))
+                .build();
+    }
+
+    /**
+     * Retrieves the Instance Identifier that points to an InterVpnLinkState object
+     * in MDSL
+     *
+     * @param vpnLinkName The name of the InterVpnLink
+     * @return The requested InstanceIdentifier
+     */
+    public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
+        return InstanceIdentifier.builder(InterVpnLinkStates.class)
+                .child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName))
+                .build();
+    }
+
     /**
      * Updates VpnToDpn map by adding a fake VpnInterface related to an
      * InterVpnLink in the corresponding DPNs
@@ -59,8 +99,7 @@ public class InterVpnLinkUtil {
         if ( vpnInstOpData.isPresent() ) {
             for (BigInteger dpnId : dpnList) {
                 String linkIfaceName = String.format("InterVpnLink.%s.%s", vpnUuid.getValue(), dpnId.toString());
-                VpnUtil.mergeDpnInVpnToDpnMap(broker, vpnInstOpData.get(), dpnId,
-                                              Arrays.asList(linkIfaceName));
+                VpnUtil.mergeDpnInVpnToDpnMap(broker, vpnInstOpData.get(), dpnId, Arrays.asList(linkIfaceName));
             }
         }
     }
@@ -77,7 +116,7 @@ public class InterVpnLinkUtil {
     public static Optional<InterVpnLink> getInterVpnLinkByName(DataBroker broker, String vpnLinkName) {
         InstanceIdentifier<InterVpnLink> interVpnLinksIid =
                 InstanceIdentifier.builder(InterVpnLinks.class)
-                                  .child(InterVpnLink.class, new InterVpnLinkKey(vpnLinkName)).build();
+                        .child(InterVpnLink.class, new InterVpnLinkKey(vpnLinkName)).build();
         return  VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinksIid);
     }
 
@@ -95,13 +134,26 @@ public class InterVpnLinkUtil {
     public static void updateInterVpnLinkState(DataBroker broker, String vpnLinkName, InterVpnLinkState.State state,
                                                FirstEndpointState newFirstEndpointState,
                                                SecondEndpointState newSecondEndpointState) {
-        InterVpnLinkState oldVpnLinkState = VpnUtil.getInterVpnLinkState(broker, vpnLinkName);
-        InterVpnLinkState newVpnLinkState =
-                new InterVpnLinkStateBuilder(oldVpnLinkState).setState(state)
-                                                             .setFirstEndpointState(newFirstEndpointState)
-                                                             .setSecondEndpointState(newSecondEndpointState).build();
-        VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, VpnUtil.getInterVpnLinkStateIid(vpnLinkName),
-                           newVpnLinkState);
+        Optional<InterVpnLinkState> optOldVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
+        if ( optOldVpnLinkState.isPresent() ) {
+            InterVpnLinkState newVpnLinkState =
+                    new InterVpnLinkStateBuilder(optOldVpnLinkState.get()).setState(state)
+                            .setFirstEndpointState(newFirstEndpointState)
+                            .setSecondEndpointState(newSecondEndpointState)
+                            .build();
+            VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
+                    InterVpnLinkUtil.getInterVpnLinkStateIid(vpnLinkName), newVpnLinkState);
+        } else {
+            InterVpnLinkState newIVpnLinkState =
+                    new InterVpnLinkStateBuilder().setKey(new InterVpnLinkStateKey(vpnLinkName))
+                            .setInterVpnLinkName(vpnLinkName)
+                            .setFirstEndpointState(newFirstEndpointState)
+                            .setSecondEndpointState(newSecondEndpointState)
+                            .setState(InterVpnLinkState.State.Active)
+                            .build();
+            VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
+                    InterVpnLinkUtil.getInterVpnLinkStateIid(vpnLinkName), newIVpnLinkState);
+        }
     }
 
     /**
@@ -131,75 +183,293 @@ public class InterVpnLinkUtil {
         }
     }
 
-   /**
-    * Builds a Flow to be installed into LPortDispatcher table, that matches on
-    * SI=2 + vpnLinkEndpointPseudoPortTag and sends to FIB
-    *
-    * @param interVpnLinkName The name of the InterVpnLink
-    * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
-    * @param lportTag DataPlane identifier of the LogicalPort.
-    * @return the Flow ready to be installed
-    */
-   public static Flow buildLPortDispatcherFlow(String interVpnLinkName, long vpnId, int lportTag) {
-       LOG.info("Inter-vpn-link : buildLPortDispatcherFlow. vpnId {}   lportTag {} ", vpnId, lportTag);
-       List<MatchInfo> matches = Arrays.asList(new MatchInfo(MatchFieldType.metadata,
-                                                              new BigInteger[] {
-                                                                  MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
-                                                                  ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
-                                                                  MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
-       String flowRef = getLportDispatcherFlowRef(interVpnLinkName, lportTag);
-       Flow lPortDispatcherFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
-                                                         VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
-                                                         0, 0, VpnUtil.getCookieL3((int) vpnId), matches,
-                                                         buildLportDispatcherTableInstructions(vpnId));
-       return lPortDispatcherFlow;
-   }
-
-   /**
-   * Builds a flowRef to be assigned to the flow to be installed into
-   * LPortDispatcher table
-   *
-   * @param interVpnLinkName The name of the InterVpnLink
-   * @param lportTag Dataplane identifier of the LogicalPort
-   * @return the flow reference string
-   */
-   public static String getLportDispatcherFlowRef(String interVpnLinkName, Integer lportTag) {
-       String flowRef = new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append("INTERVPNLINK")
-                     .append(NwConstants.FLOWID_SEPARATOR).append(interVpnLinkName)
-                     .append(NwConstants.FLOWID_SEPARATOR).append(lportTag)
-                     .append(NwConstants.FLOWID_SEPARATOR).append(ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX))
-                     .append(NwConstants.FLOWID_SEPARATOR).append(VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY)
-                     .toString();
-       return flowRef;
-   }
-
-
-   public static List<Instruction> buildLportDispatcherTableInstructions (long vpnId) {
-       int instructionKey = 0;
-       List<Instruction> instructions = new ArrayList<Instruction>();
-       instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId),
-                                                                    MetaDataUtil.METADATA_MASK_VRFID,
-                                                                    ++instructionKey));
-       instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
-
-       return instructions;
-   }
-
-   /**
-    * Retrieves the States of all InterVpnLinks
-    *
-    * @param broker dataBroker service reference
-    * @return the list of objects that holds the InterVpnLink state information
-    */
-   public static List<InterVpnLinkState> getAllInterVpnLinkState(DataBroker broker) {
-       InstanceIdentifier<InterVpnLinkStates> interVpnLinkStateIid = InstanceIdentifier.builder(InterVpnLinkStates.class).build();
-
-       Optional<InterVpnLinkStates> interVpnLinkStateOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
-               interVpnLinkStateIid);
-
-       return (interVpnLinkStateOpData.isPresent()) ? interVpnLinkStateOpData.get().getInterVpnLinkState()
-               : new ArrayList<InterVpnLinkState>();
-   }
+    /**
+     * Builds a Flow to be installed into LPortDispatcher table, that matches on
+     * SI=2 + vpnLinkEndpointPseudoPortTag and sends to FIB
+     *
+     * @param interVpnLinkName The name of the InterVpnLink
+     * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
+     * @param lportTag DataPlane identifier of the LogicalPort.
+     * @return the Flow ready to be installed
+     */
+    public static Flow buildLPortDispatcherFlow(String interVpnLinkName, long vpnId, int lportTag) {
+        LOG.info("Inter-vpn-link : buildLPortDispatcherFlow. vpnId {}   lportTag {} ", vpnId, lportTag);
+        List<MatchInfo> matches = Arrays.asList(new MatchInfo(MatchFieldType.metadata,
+                new BigInteger[] {
+                        MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
+                                ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
+                        MetaDataUtil.getMetaDataMaskForLPortDispatcher() }));
+        String flowRef = getLportDispatcherFlowRef(interVpnLinkName, lportTag);
+        Flow lPortDispatcherFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
+                VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
+                0, 0, VpnUtil.getCookieL3((int) vpnId), matches,
+                buildLportDispatcherTableInstructions(vpnId));
+        return lPortDispatcherFlow;
+    }
+
+    /**
+     * Builds a flowRef to be assigned to the flow to be installed into
+     * LPortDispatcher table
+     *
+     * @param interVpnLinkName The name of the InterVpnLink
+     * @param lportTag Dataplane identifier of the LogicalPort
+     * @return the flow reference string
+     */
+    public static String getLportDispatcherFlowRef(String interVpnLinkName, Integer lportTag) {
+        String flowRef = new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append("INTERVPNLINK")
+                .append(NwConstants.FLOWID_SEPARATOR).append(interVpnLinkName)
+                .append(NwConstants.FLOWID_SEPARATOR).append(lportTag)
+                .append(NwConstants.FLOWID_SEPARATOR).append(ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX))
+                .append(NwConstants.FLOWID_SEPARATOR)
+                .append(VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY)
+                .toString();
+        return flowRef;
+    }
+
+
+    public static List<Instruction> buildLportDispatcherTableInstructions (long vpnId) {
+        int instructionKey = 0;
+        List<Instruction> instructions = new ArrayList<Instruction>();
+        instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId),
+                MetaDataUtil.METADATA_MASK_VRFID,
+                ++instructionKey));
+        instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
+
+        return instructions;
+    }
+
+    /**
+     * Retrieves the States of all InterVpnLinks
+     *
+     * @param broker dataBroker service reference
+     * @return the list of objects that holds the InterVpnLink state information
+     */
+    public static List<InterVpnLinkState> getAllInterVpnLinkState(DataBroker broker) {
+        InstanceIdentifier<InterVpnLinkStates> interVpnLinkStateIid =
+                InstanceIdentifier.builder(InterVpnLinkStates.class).build();
+
+        Optional<InterVpnLinkStates> interVpnLinkStateOpData =
+                MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
+
+        return (interVpnLinkStateOpData.isPresent()) ? interVpnLinkStateOpData.get().getInterVpnLinkState()
+                : new ArrayList<InterVpnLinkState>();
+    }
+
+    /**
+     * Retrieves the State of an InterVpnLink
+     *
+     * @param broker dataBroker service reference
+     * @param iVpnLinkName The name of the InterVpnLink
+     * @return the object that contains the State of the specified InterVpnLink
+     *         or Optional.absent() if it doesnt exist
+     */
+    public static Optional<InterVpnLinkState> getInterVpnLinkState(DataBroker broker, String iVpnLinkName) {
+        return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, getInterVpnLinkStateIid(iVpnLinkName));
+    }
+
+    /**
+     * Checks if the specified InterVpnLink is currently Active
+     *
+     * @param broker dataBroker service reference
+     * @param iVpnLinkName The name of the InterVpnLink
+     * @return true if the InterVpnLink is Active
+     */
+    public static boolean isInterVpnLinkActive(DataBroker broker, String iVpnLinkName) {
+        Optional<InterVpnLinkState> optIVpnLinkState = getInterVpnLinkState(broker, iVpnLinkName);
+        if ( ! optIVpnLinkState.isPresent() ) {
+            return false;
+        }
+        InterVpnLinkState iVpnLinkState = optIVpnLinkState.get();
+        return iVpnLinkState.getState() == InterVpnLinkState.State.Active;
+    }
+
+    /**
+     * Retrieves an InterVpnLink by searching by one of its endpoint's IP.
+     *
+     * @param broker dataBroker service reference
+     * @param endpointIp IP to serch for.
+     * @return the InterVpnLink or null if no InterVpnLink can be found
+     */
+    public static Optional<InterVpnLink> getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
+        List<InterVpnLink> allInterVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(broker);
+        for (InterVpnLink interVpnLink : allInterVpnLinks) {
+            if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
+                    || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
+                return Optional.of(interVpnLink);
+            }
+        }
+        return Optional.absent();
+    }
+
+
+    /**
+     * Retrieves the InterVpnLink that has one of its 2 endpoints installed in
+     * the specified DpnId
+     *
+     * @param broker dataBroker service reference
+     * @param dpnId Id of the DPN
+     * @return The InterVpnLink object if found, Optional.absent() otherwise
+     */
+    public static Optional<InterVpnLink> getInterVpnLinkByDpnId(DataBroker broker, BigInteger dpnId) {
+        List<InterVpnLink> allInterVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(broker);
+        for (InterVpnLink interVpnLink : allInterVpnLinks) {
+            Optional<InterVpnLinkState> optInterVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
+            if ( optInterVpnLinkState.isPresent()
+                    && ( optInterVpnLinkState.get().getFirstEndpointState().getDpId().contains(dpnId)
+                    || optInterVpnLinkState.get().getSecondEndpointState().getDpId().contains(dpnId) ) ) {
+                return Optional.fromNullable(interVpnLink);
+            }
+        }
+        return Optional.absent();
+    }
 
+    /**
+     * Retrieves all configured InterVpnLinks
+     *
+     * @param broker dataBroker service reference
+     * @return the list of InterVpnLinks
+     */
+    public static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
+        InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
+
+        Optional<InterVpnLinks> interVpnLinksOpData =
+                MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinksIid);
+
+        return (interVpnLinksOpData.isPresent()) ? interVpnLinksOpData.get().getInterVpnLink()
+                : new ArrayList<InterVpnLink>();
+    }
+
+    /**
+     * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated
+     *
+     * @param broker dataBroker service reference
+     * @param vpnLinkName the name of the InterVpnLink
+     * @param vpnUuid UUID of the VPN whose endpoint to be checked
+     * @return the list of DPN Ids
+     */
+    public static List<BigInteger> getVpnLinkEndpointDPNs(DataBroker broker, String vpnLinkName, String vpnUuid) {
+        Optional<InterVpnLinkState> interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
+        if ( interVpnLinkState.isPresent()) {
+            if (interVpnLinkState.get().getFirstEndpointState().getVpnUuid().getValue().equals(vpnUuid)) {
+                return interVpnLinkState.get().getFirstEndpointState().getDpId();
+            } else {
+                return interVpnLinkState.get().getSecondEndpointState().getDpId();
+            }
+        } else {
+            LOG.trace("Could not find InterVpnLinkState for interVpnLink {}", vpnLinkName);
+            return new ArrayList<BigInteger>();
+        }
+    }
 
+    /**
+     * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated
+     *
+     * @param broker dataBroker service reference
+     * @param endpointIp Ip of the endpoint specified in the InterVpnLink
+     * @return the list of DPN Ids
+     */
+    public static List<BigInteger> getVpnLinkEndpointDPNsByIp(DataBroker broker, String endpointIp) {
+        Optional<InterVpnLink> optIVpnLink = getInterVpnLinkByEndpointIp(broker, endpointIp);
+        if ( optIVpnLink.isPresent() ) {
+            InterVpnLink iVpnLink = optIVpnLink.get();
+            boolean isFirstEndpoint = iVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp);
+            return isFirstEndpoint ? getVpnLinkEndpointDPNs(broker, iVpnLink.getName(),
+                    iVpnLink.getFirstEndpoint().getVpnUuid().getValue())
+                    : getVpnLinkEndpointDPNs(broker, iVpnLink.getName(),
+                    iVpnLink.getSecondEndpoint().getVpnUuid().getValue());
+        } else {
+            LOG.trace("Could not find an InterVpnLink with endpoint IpAddr={}", endpointIp);
+            return new ArrayList<BigInteger>();
+        }
+    }
+
+
+    /**
+     * Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN
+     *
+     * @param broker           dataBroker service reference
+     * @param bgpManager       Used to advertise routes to the BGP Router
+     * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
+     * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
+     * @param dstVpnUuid       UUID of the VPN that is going to receive the route
+     * @param prefix           Prefix of the route
+     * @param label            Label of the route in the original VPN
+     */
+    public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
+                                 String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
+        leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, prefix, label, RouteOrigin.INTERVPN);
+    }
+
+    /**
+     * Leaks a route from one VPN to another.
+     *
+     * @param broker           dataBroker service reference
+     * @param bgpManager       Used to advertise routes to the BGP Router
+     * @param interVpnLink     Reference to the object that holds the info about the link between the 2 VPNs
+     * @param srcVpnUuid       UUID of the VPN that has the route that is going to be leaked to the other VPN
+     * @param dstVpnUuid       UUID of the VPN that is going to receive the route
+     * @param prefix           Prefix of the route
+     * @param label            Label of the route in the original VPN
+     * @param forcedOrigin     By default, origin for leaked routes should be INTERVPN, however it is possible to
+     *                         provide a different origin if desired.
+     */
+    public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
+                                 String srcVpnUuid, String dstVpnUuid, String prefix, Long label,
+                                 RouteOrigin forcedOrigin) {
+        Preconditions.checkNotNull(interVpnLink);
+
+        // The source VPN must participate in the InterVpnLink
+        Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid)
+                        || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid),
+                "The source VPN {} does not participate in the interVpnLink {}",
+                srcVpnUuid, interVpnLink.getName());
+        // The destination VPN must participate in the InterVpnLink
+        Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid)
+                        || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid),
+                "The destination VPN {} does not participate in the interVpnLink {}",
+                dstVpnUuid, interVpnLink.getName());
+
+        boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
+
+        String endpointIp = (destinationIs1stEndpoint) ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
+                : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
+
+        VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
+                .setLabel(label).setNextHopAddressList(Arrays.asList(endpointIp))
+                .setOrigin(RouteOrigin.INTERVPN.getValue())
+                .build();
+
+        String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
+        InstanceIdentifier<VrfEntry> newVrfEntryIid =
+                InstanceIdentifier.builder(FibEntries.class)
+                        .child(VrfTables.class, new VrfTablesKey(dstVpnRd))
+                        .child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix()))
+                        .build();
+        VpnUtil.asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
+
+        // Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
+        // endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
+        // VPN has been instantiated
+        Optional<InterVpnLinkState> optVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
+        if ( optVpnLinkState.isPresent() ) {
+            InterVpnLinkState vpnLinkState = optVpnLinkState.get();
+            List<BigInteger> dpnIdList = (destinationIs1stEndpoint) ? vpnLinkState.getFirstEndpointState().getDpId()
+                    : vpnLinkState.getSecondEndpointState().getDpId();
+            List<String> nexthops = new ArrayList<String>();
+            for (BigInteger dpnId : dpnIdList) {
+                nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
+            }
+            try {
+                LOG.debug("Advertising route in VPN={} [prefix={} label={}  nexthops={}] to DC-GW",
+                        dstVpnRd, newVrfEntry.getDestPrefix(), label.intValue(), nexthops);
+                bgpManager.advertisePrefix(dstVpnRd, newVrfEntry.getDestPrefix(), nexthops, label.intValue());
+            } catch (Exception exc) {
+                LOG.error("Could not advertise prefix {} with label {} to VPN rd={}",
+                        newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd);
+            }
+        } else {
+            LOG.warn("Error when advertising leaked routes: Could not find State for InterVpnLink={}",
+                    interVpnLink.getName());
+        }
+    }
 }
index 50cdaa789adb479ee4bf6c68b36e07f333998bb0..a7500fa75d262071648931099a9a3c08fbab162c 100644 (file)
     <argument ref="idManagerService" />
     <argument ref="vpnInterfaceManager" />
     <argument ref="fibManager" />
+    <argument ref="bgpmanager" />
   </bean>
   <service ref="vpnRpcServiceImpl"
            interface="org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.vpn.rpc.rev160201.VpnRpcService" />