Cleanup ivpnLink unused code + small modifications
[netvirt.git] / vpnservice / vpnmanager / vpnmanager-impl / src / main / java / org / opendaylight / netvirt / vpnmanager / intervpnlink / InterVpnLinkUtil.java
1 /*
2  * Copyright (c) 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.netvirt.vpnmanager.intervpnlink;
9
10 import com.google.common.base.Optional;
11 import com.google.common.base.Preconditions;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collections;
16 import java.util.List;
17 import java.util.stream.Collectors;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
20 import org.opendaylight.genius.mdsalutil.MDSALUtil;
21 import org.opendaylight.genius.mdsalutil.MatchInfo;
22 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
23 import org.opendaylight.genius.mdsalutil.NwConstants;
24 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
25 import org.opendaylight.genius.mdsalutil.matches.MatchMetadata;
26 import org.opendaylight.genius.utils.ServiceIndex;
27 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
28 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
29 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
30 import org.opendaylight.netvirt.vpnmanager.VpnConstants;
31 import org.opendaylight.netvirt.vpnmanager.VpnFootprintService;
32 import org.opendaylight.netvirt.vpnmanager.VpnUtil;
33 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkCache;
34 import org.opendaylight.netvirt.vpnmanager.api.intervpnlink.InterVpnLinkDataComposite;
35 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateBuilder;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateKey;
49 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;
50 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;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLinkKey;
53 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
54 import org.slf4j.Logger;
55 import org.slf4j.LoggerFactory;
56
57 /**
58  * This class contains methods to be used as utilities related with inter-vpn-link.
59  */
60 public class InterVpnLinkUtil {
61
62     private static final Logger LOG = LoggerFactory.getLogger(InterVpnLinkUtil.class);
63
64     /**
65      * Retrieves the Instance Identifier that points to an InterVpnLink object
66      * in MD-SAL.
67      *
68      * @param interVpnLinkName The name of the InterVpnLink
69      * @return The requested InstanceIdentifier
70      */
71     public static InstanceIdentifier<InterVpnLink> getInterVpnLinkPath(String interVpnLinkName) {
72         return InstanceIdentifier.builder(InterVpnLinks.class)
73             .child(InterVpnLink.class, new InterVpnLinkKey(interVpnLinkName))
74             .build();
75     }
76
77     /**
78      * Retrieves the Instance Identifier that points to an InterVpnLinkState object
79      * in MD-SAL.
80      *
81      * @param vpnLinkName The name of the InterVpnLink
82      * @return The requested InstanceIdentifier
83      */
84     public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
85         return InstanceIdentifier.builder(InterVpnLinkStates.class)
86             .child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName))
87             .build();
88     }
89
90     public static String buildInterVpnLinkIfaceName(String vpnName, BigInteger dpnId) {
91         return String.format("InterVpnLink.%s.%s", vpnName, dpnId.toString());
92     }
93
94     /**
95      * Updates VpnToDpn map by adding a fake VpnInterface related to an
96      * InterVpnLink in the corresponding DPNs. If the fake iface is the
97      * first one on the any of the specified DPNs, the installation of
98      * Fib flows on that DPN will be triggered.
99      *
100      * @param vpnFootprintService VpnFootprintService service reference
101      * @param vpnName Name of the VPN to which the fake interfaces belong
102      * @param dpnList List of DPNs where the fake InterVpnLink interface must be added
103      */
104     public static void updateVpnFootprint(VpnFootprintService vpnFootprintService, String vpnName,
105         List<BigInteger> dpnList) {
106         LOG.debug("updateVpnFootprint (add):  vpn={}  dpnList={}", vpnName, dpnList);
107         // Note: when a set of DPNs is calculated for Vpn1, these DPNs are added to the VpnToDpn map of Vpn2. Why?
108         // because we do the handover from Vpn1 to Vpn2 in those DPNs, so in those DPNs we must know how to reach
109         // to Vpn2 targets. If new Vpn2 targets are added later, the Fib will be maintained in these DPNs even if
110         // Vpn2 is not physically present there.
111         for (BigInteger dpnId : dpnList) {
112             String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
113             vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, true /* addition */);
114         }
115     }
116
117     /**
118      * Updates VpnToDpn map by removing the fake VpnInterface related to an
119      * InterVpnLink in the corresponding DPNs.
120      *
121      * @param vpnFootprintService VpnFootprintService service reference
122      * @param vpnName Name of the VPN to which the fake interfaces belong
123      * @param dpnId DPN where the fake InterVpnLink interface must be removed from
124      */
125     public static void removeIVpnLinkIfaceFromVpnFootprint(VpnFootprintService vpnFootprintService,
126         String vpnName, BigInteger dpnId) {
127         String ifaceName = buildInterVpnLinkIfaceName(vpnName, dpnId);
128         LOG.debug("updateVpnFootprint (remove):  vpn={}  dpn={}  ifaceName={}", vpnName, dpnId, ifaceName);
129         vpnFootprintService.updateVpnToDpnMapping(dpnId, vpnName, ifaceName, false /* removal */);
130     }
131
132     /**
133      * Retrieves the InterVpnLink object searching by its name.
134      *
135      * @param broker dataBroker service reference
136      * @param vpnLinkName Name of the InterVpnLink
137      * @return the InterVpnLink or Optional.absent() if there is no InterVpnLink with the specified name
138      */
139     public static Optional<InterVpnLink> getInterVpnLinkByName(DataBroker broker, String vpnLinkName) {
140         InstanceIdentifier<InterVpnLink> interVpnLinksIid =
141             InstanceIdentifier.builder(InterVpnLinks.class)
142                 .child(InterVpnLink.class, new InterVpnLinkKey(vpnLinkName)).build();
143         return VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinksIid);
144     }
145
146     /**
147      * Updates inter-VPN link state.
148      *
149      * @param broker dataBroker service reference
150      * @param vpnLinkName The name of the InterVpnLink
151      * @param state Sets the state of the InterVpnLink to Active or Error
152      * @param newFirstEndpointState Updates the lportTag and/or DPNs of the 1st endpoint of the InterVpnLink
153      * @param newSecondEndpointState Updates the lportTag and/or DPNs of the 2nd endpoint of the InterVpnLink
154      */
155     public static void updateInterVpnLinkState(DataBroker broker, String vpnLinkName, InterVpnLinkState.State state,
156         FirstEndpointState newFirstEndpointState,
157         SecondEndpointState newSecondEndpointState) {
158         Optional<InterVpnLinkState> optOldVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
159         if (optOldVpnLinkState.isPresent()) {
160             InterVpnLinkState newVpnLinkState =
161                 new InterVpnLinkStateBuilder(optOldVpnLinkState.get()).setState(state)
162                             .setFirstEndpointState(newFirstEndpointState)
163                             .setSecondEndpointState(newSecondEndpointState)
164                             .build();
165             VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
166                 InterVpnLinkUtil.getInterVpnLinkStateIid(vpnLinkName), newVpnLinkState);
167             InterVpnLinkCache.addInterVpnLinkStateToCaches(newVpnLinkState);
168         } else {
169             InterVpnLinkState newIVpnLinkState =
170                 new InterVpnLinkStateBuilder().setKey(new InterVpnLinkStateKey(vpnLinkName))
171                     .setInterVpnLinkName(vpnLinkName)
172                     .setFirstEndpointState(newFirstEndpointState)
173                     .setSecondEndpointState(newSecondEndpointState)
174                     .setState(InterVpnLinkState.State.Active)
175                     .build();
176             VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
177                 InterVpnLinkUtil.getInterVpnLinkStateIid(vpnLinkName), newIVpnLinkState);
178             InterVpnLinkCache.addInterVpnLinkStateToCaches(newIVpnLinkState);
179         }
180     }
181
182     /**
183      * Installs a Flow in LPortDispatcher table that matches on SI=2 and
184      * the lportTag of one InterVpnLink's endpoint and sets the vrfTag of the
185      * other endpoint and sends to FIB table.
186      *
187      * @param broker dataBroker service reference
188      * @param mdsalManager MDSAL API accessor
189      * @param interVpnLinkName Name of the InterVpnLink.
190      * @param dpnList The list of DPNs where this flow must be installed
191      * @param vpnUuidOtherEndpoint UUID of the other endpoint of the InterVpnLink
192      * @param lportTagOfOtherEndpoint Dataplane identifier of the other endpoint of the InterVpnLink
193      * @return the list of Futures for each and every flow that has been installed
194      */
195     public static List<ListenableFuture<Void>> installLPortDispatcherTableFlow(DataBroker broker,
196                                                                                IMdsalApiManager mdsalManager,
197                                                                                String interVpnLinkName,
198                                                                                List<BigInteger> dpnList,
199                                                                                String vpnUuidOtherEndpoint,
200                                                                                Long lportTagOfOtherEndpoint) {
201         List<ListenableFuture<Void>> result = new ArrayList<>();
202         long vpnId = VpnUtil.getVpnId(broker, vpnUuidOtherEndpoint);
203         for ( BigInteger dpnId : dpnList ) {
204             // insert into LPortDispatcher table
205             Flow lportDispatcherFlow = buildLPortDispatcherFlow(interVpnLinkName, vpnId,
206                                                                 lportTagOfOtherEndpoint.intValue());
207             result.add(mdsalManager.installFlow(dpnId, lportDispatcherFlow));
208         }
209
210         return result;
211     }
212
213     /**
214      * Builds a Flow to be installed into LPortDispatcher table, that matches on
215      * SI=2 + vpnLinkEndpointPseudoPortTag and sends to FIB.
216      *
217      * @param interVpnLinkName The name of the InterVpnLink
218      * @param vpnId Dataplane identifier of the VPN, the Vrf Tag.
219      * @param lportTag DataPlane identifier of the LogicalPort.
220      * @return the Flow ready to be installed
221      */
222     public static Flow buildLPortDispatcherFlow(String interVpnLinkName, long vpnId, int lportTag) {
223         LOG.info("Inter-vpn-link : buildLPortDispatcherFlow. vpnId {}   lportTag {} ", vpnId, lportTag);
224         List<MatchInfo> matches = Collections.singletonList(new MatchMetadata(
225                         MetaDataUtil.getMetaDataForLPortDispatcher(lportTag,
226                                 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)),
227                         MetaDataUtil.getMetaDataMaskForLPortDispatcher()));
228         String flowRef = getLportDispatcherFlowRef(interVpnLinkName, lportTag);
229         Flow lportDispatcherFlow = MDSALUtil.buildFlowNew(NwConstants.LPORT_DISPATCHER_TABLE, flowRef,
230             VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY, flowRef,
231             0, 0, VpnUtil.getCookieL3((int) vpnId), matches,
232             buildLportDispatcherTableInstructions(vpnId));
233         return lportDispatcherFlow;
234     }
235
236     /**
237      * Builds a flowRef to be assigned to the flow to be installed into
238      * LPortDispatcher table.
239      *
240      * @param interVpnLinkName The name of the InterVpnLink
241      * @param lportTag Dataplane identifier of the LogicalPort
242      * @return the flow reference string
243      */
244     public static String getLportDispatcherFlowRef(String interVpnLinkName, Integer lportTag) {
245         return new StringBuffer()
246             .append(VpnConstants.FLOWID_PREFIX).append("INTERVPNLINK")
247             .append(NwConstants.FLOWID_SEPARATOR).append(interVpnLinkName)
248             .append(NwConstants.FLOWID_SEPARATOR).append(lportTag)
249             .append(NwConstants.FLOWID_SEPARATOR).append(ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME,
250                 NwConstants.L3VPN_SERVICE_INDEX))
251             .append(NwConstants.FLOWID_SEPARATOR)
252             .append(VpnConstants.DEFAULT_LPORT_DISPATCHER_FLOW_PRIORITY)
253             .toString();
254     }
255
256
257     public static List<Instruction> buildLportDispatcherTableInstructions(long vpnId) {
258         int instructionKey = 0;
259         List<Instruction> instructions = new ArrayList<>();
260         instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId),
261             MetaDataUtil.METADATA_MASK_VRFID,
262             ++instructionKey));
263         instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
264
265         return instructions;
266     }
267
268     /**
269      * Retrieves the States of all InterVpnLinks.
270      *
271      * @param broker dataBroker service reference
272      * @return the list of objects that holds the InterVpnLink state information
273      */
274     public static List<InterVpnLinkState> getAllInterVpnLinkState(DataBroker broker) {
275         InstanceIdentifier<InterVpnLinkStates> interVpnLinkStateIid =
276             InstanceIdentifier.builder(InterVpnLinkStates.class).build();
277
278         Optional<InterVpnLinkStates> interVpnLinkStateOpData =
279             MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinkStateIid);
280
281         return (interVpnLinkStateOpData.isPresent()) ? interVpnLinkStateOpData.get().getInterVpnLinkState()
282             : new ArrayList<>();
283     }
284
285     /**
286      * Retrieves the State of an InterVpnLink.
287      *
288      * @param broker dataBroker service reference
289      * @param interVpnLinkName The name of the InterVpnLink
290      * @return the object that contains the State of the specified InterVpnLink or Optional.absent() if it doesnt exist
291      */
292     public static Optional<InterVpnLinkState> getInterVpnLinkState(DataBroker broker, String interVpnLinkName) {
293         return MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, getInterVpnLinkStateIid(interVpnLinkName));
294     }
295
296     /**
297      * Checks if the specified InterVpnLink is currently Active.
298      *
299      * @param broker dataBroker service reference
300      * @param interVpnLinkName The name of the InterVpnLink
301      * @return true if the InterVpnLink is Active
302      */
303     public static boolean isInterVpnLinkActive(DataBroker broker, String interVpnLinkName) {
304         Optional<InterVpnLinkState> optIVpnLinkState = getInterVpnLinkState(broker, interVpnLinkName);
305         if (!optIVpnLinkState.isPresent()) {
306             return false;
307         }
308         InterVpnLinkState interVpnLinkState = optIVpnLinkState.get();
309         return interVpnLinkState.getState() == InterVpnLinkState.State.Active;
310     }
311
312     /**
313      * Retrieves an InterVpnLink by searching by one of its endpoint's IP.
314      *
315      * @param broker dataBroker service reference
316      * @param endpointIp IP to serch for.
317      * @return the InterVpnLink or null if no InterVpnLink can be found
318      */
319     public static Optional<InterVpnLink> getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
320         List<InterVpnLink> allInterVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(broker);
321         for (InterVpnLink interVpnLink : allInterVpnLinks) {
322             if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
323                 || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
324                 return Optional.of(interVpnLink);
325             }
326         }
327         return Optional.absent();
328     }
329
330
331     /**
332      * Retrieves the InterVpnLink that has one of its 2 endpoints installed in
333      * the specified DpnId.
334      *
335      * @param broker dataBroker service reference
336      * @param dpnId Id of the DPN
337      * @return The InterVpnLink object if found, Optional.absent() otherwise
338      */
339     public static Optional<InterVpnLink> getInterVpnLinkByDpnId(DataBroker broker, BigInteger dpnId) {
340         List<InterVpnLink> allInterVpnLinks = InterVpnLinkUtil.getAllInterVpnLinks(broker);
341         for (InterVpnLink interVpnLink : allInterVpnLinks) {
342             Optional<InterVpnLinkState> optInterVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
343             if (optInterVpnLinkState.isPresent()
344                 && (optInterVpnLinkState.get().getFirstEndpointState().getDpId().contains(dpnId)
345                         || optInterVpnLinkState.get().getSecondEndpointState().getDpId().contains(dpnId))) {
346                 return Optional.fromNullable(interVpnLink);
347             }
348         }
349         return Optional.absent();
350     }
351
352     /**
353      * Retrieves all configured InterVpnLinks.
354      *
355      * @param broker dataBroker service reference
356      * @return the list of InterVpnLinks
357      */
358     public static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
359         InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
360
361         Optional<InterVpnLinks> interVpnLinksOpData =
362             MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, interVpnLinksIid);
363
364         return interVpnLinksOpData.isPresent() ? interVpnLinksOpData.get().getInterVpnLink()
365             : new ArrayList<>();
366     }
367
368     /**
369      * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated.
370      *
371      * @param broker dataBroker service reference
372      * @param vpnLinkName the name of the InterVpnLink
373      * @param vpnUuid UUID of the VPN whose endpoint to be checked
374      * @return the list of DPN Ids
375      */
376     public static List<BigInteger> getVpnLinkEndpointDPNs(DataBroker broker, String vpnLinkName, String vpnUuid) {
377         Optional<InterVpnLinkState> interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
378         if (interVpnLinkState.isPresent()) {
379             if (interVpnLinkState.get().getFirstEndpointState().getVpnUuid().getValue().equals(vpnUuid)) {
380                 return interVpnLinkState.get().getFirstEndpointState().getDpId();
381             } else {
382                 return interVpnLinkState.get().getSecondEndpointState().getDpId();
383             }
384         } else {
385             LOG.trace("Could not find InterVpnLinkState for interVpnLink {}", vpnLinkName);
386             return new ArrayList<>();
387         }
388     }
389
390     /**
391      * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated.
392      *
393      * @param broker dataBroker service reference
394      * @param endpointIp Ip of the endpoint specified in the InterVpnLink
395      * @return the list of DPN Ids
396      */
397     public static List<BigInteger> getVpnLinkEndpointDPNsByIp(DataBroker broker, String endpointIp) {
398         Optional<InterVpnLink> optIVpnLink = getInterVpnLinkByEndpointIp(broker, endpointIp);
399         if (optIVpnLink.isPresent()) {
400             InterVpnLink interVpnLink = optIVpnLink.get();
401             boolean isFirstEndpoint = interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp);
402             return isFirstEndpoint ? getVpnLinkEndpointDPNs(broker, interVpnLink.getName(),
403                 interVpnLink.getFirstEndpoint().getVpnUuid().getValue())
404                 : getVpnLinkEndpointDPNs(broker, interVpnLink.getName(),
405                 interVpnLink.getSecondEndpoint().getVpnUuid().getValue());
406         } else {
407             LOG.trace("Could not find an InterVpnLink with endpoint IpAddr={}", endpointIp);
408             return new ArrayList<>();
409         }
410     }
411
412
413     /**
414      * Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN.
415      *
416      * @param broker dataBroker service reference
417      * @param bgpManager Used to advertise routes to the BGP Router
418      * @param interVpnLink Reference to the object that holds the info about the link between the 2 VPNs
419      * @param srcVpnUuid UUID of the VPN that has the route that is going to be leaked to the other VPN
420      * @param dstVpnUuid UUID of the VPN that is going to receive the route
421      * @param prefix Prefix of the route
422      * @param label Label of the route in the original VPN
423      */
424     public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
425         String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
426         leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, prefix, label, RouteOrigin.INTERVPN);
427     }
428
429     /**
430      * Leaks a route from one VPN to another.
431      *
432      * @param broker dataBroker service reference
433      * @param bgpManager Used to advertise routes to the BGP Router
434      * @param interVpnLink Reference to the object that holds the info about the link between the 2 VPNs
435      * @param srcVpnUuid UUID of the VPN that has the route that is going to be leaked to the other VPN
436      * @param dstVpnUuid UUID of the VPN that is going to receive the route
437      * @param prefix Prefix of the route
438      * @param label Label of the route in the original VPN
439      * @param forcedOrigin By default, origin for leaked routes should be INTERVPN, however it is possible to provide
440      *     a different origin if desired.
441      */
442     // TODO Clean up the exception handling
443     @SuppressWarnings("checkstyle:IllegalCatch")
444     public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
445         String srcVpnUuid, String dstVpnUuid, String prefix, Long label,
446         RouteOrigin forcedOrigin) {
447         Preconditions.checkNotNull(interVpnLink);
448
449         // The source VPN must participate in the InterVpnLink
450         Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid)
451                 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid),
452             "The source VPN {} does not participate in the interVpnLink {}",
453             srcVpnUuid, interVpnLink.getName());
454         // The destination VPN must participate in the InterVpnLink
455         Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid)
456                 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid),
457             "The destination VPN {} does not participate in the interVpnLink {}",
458             dstVpnUuid, interVpnLink.getName());
459
460         boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
461
462         String endpointIp = destinationIs1stEndpoint ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
463             : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
464
465         VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
466             .setLabel(label).setNextHopAddressList(Collections.singletonList(endpointIp))
467             .setOrigin(RouteOrigin.INTERVPN.getValue())
468             .build();
469
470         String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
471         InstanceIdentifier<VrfEntry> newVrfEntryIid =
472             InstanceIdentifier.builder(FibEntries.class)
473                 .child(VrfTables.class, new VrfTablesKey(dstVpnRd))
474                 .child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix()))
475                 .build();
476         VpnUtil.asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
477
478         // Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
479         // endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
480         // VPN has been instantiated
481         Optional<InterVpnLinkState> optVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
482         if (optVpnLinkState.isPresent()) {
483             InterVpnLinkState vpnLinkState = optVpnLinkState.get();
484             List<BigInteger> dpnIdList = destinationIs1stEndpoint ? vpnLinkState.getFirstEndpointState().getDpId()
485                 : vpnLinkState.getSecondEndpointState().getDpId();
486             List<String> nexthops = new ArrayList<>();
487             for (BigInteger dpnId : dpnIdList) {
488                 nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
489             }
490             try {
491                 LOG.debug("Advertising route in VPN={} [prefix={} label={}  nexthops={}] to DC-GW",
492                     dstVpnRd, newVrfEntry.getDestPrefix(), label.intValue(), nexthops);
493                 bgpManager.advertisePrefix(dstVpnRd, null /*macAddress*/, newVrfEntry.getDestPrefix(), nexthops,
494                         VrfEntry.EncapType.Mplsgre, label.intValue(), 0 /*l3vni*/, null /*gatewayMacAddress*/);
495             } catch (Exception exc) {
496                 LOG.error("Could not advertise prefix {} with label {} to VPN rd={}",
497                     newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd);
498             }
499         } else {
500             LOG.warn("Error when advertising leaked routes: Could not find State for InterVpnLink={}",
501                 interVpnLink.getName());
502         }
503     }
504
505     public static void handleStaticRoute(InterVpnLinkDataComposite interVpnLink, String vpnName,
506         String destination, String nexthop, int label,
507         DataBroker dataBroker, IFibManager fibManager, IBgpManager bgpManager) throws Exception {
508
509         LOG.debug("handleStaticRoute [vpnLink={} srcVpn={} destination={} nextHop={} label={}]",
510             interVpnLink.getInterVpnLinkName(), vpnName, destination, nexthop, label);
511
512         String vpnRd = VpnUtil.getVpnRd(dataBroker, vpnName);
513         if (vpnRd == null) {
514             LOG.warn("Could not find Route-Distinguisher for VpnName {}", vpnName);
515             return;
516         }
517         LOG.debug("Writing FibEntry to DS:  vpnRd={}, prefix={}, label={}, nexthop={} (interVpnLink)",
518             vpnRd, destination, label, nexthop);
519         fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, null /*macAddress*/, destination,
520                 Collections.singletonList(nexthop), VrfEntry.EncapType.Mplsgre, label,
521                 0 /*l3vni*/, null /*gatewayMacAddress*/, RouteOrigin.STATIC, null /*writeTxn*/);
522
523         // Now advertise to BGP. The nexthop that must be advertised to BGP are the IPs of the DPN where the
524         // VPN's endpoint have been instantiated
525         // List<String> nexthopList = new ArrayList<>(); // The nexthops to be advertised to BGP
526         List<BigInteger> endpointDpns = interVpnLink.getEndpointDpnsByVpnName(vpnName);
527         List<String> nexthopList =
528             endpointDpns.stream().map(dpnId -> InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId))
529                 .collect(Collectors.toList());
530         LOG.debug("advertising IVpnLink route to BGP:  vpnRd={}, prefix={}, label={}, nexthops={}",
531             vpnRd, destination, label, nexthopList);
532         bgpManager.advertisePrefix(vpnRd, null /*macAddress*/, destination, nexthopList,
533                 VrfEntry.EncapType.Mplsgre, label, 0 /*l3vni*/, null /*gatewayMacAddress*/);
534     }
535 }