2 * Copyright (c) 2015 - 2016 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
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
9 package org.opendaylight.netvirt.vpnmanager;
11 import java.math.BigInteger;
12 import java.net.InetAddress;
14 import java.util.concurrent.ExecutionException;
15 import java.util.concurrent.Future;
17 import com.google.common.base.Optional;
18 import com.google.common.base.Preconditions;
19 import com.google.common.primitives.Ints;
20 import com.google.common.util.concurrent.CheckedFuture;
21 import com.google.common.util.concurrent.FutureCallback;
22 import com.google.common.util.concurrent.Futures;
24 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
25 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
26 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
27 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
28 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
29 import org.opendaylight.genius.mdsalutil.MDSALUtil;
30 import org.opendaylight.genius.mdsalutil.NwConstants;
31 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
32 import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
33 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
34 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
35 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
36 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
37 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
38 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
39 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
40 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
41 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
42 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
44 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanTagNameMap;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagName;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.tag.name.map.ElanTagNameKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.*;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AdjacenciesBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIds;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsBuilder;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.VpnIdsKey;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesBuilder;
64 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.PrefixesKey;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceBuilder;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterfaceKey;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryBuilder;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntryKey;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceBuilder;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.Vpn;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.VpnKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.Extraroute;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteBuilder;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.to.extraroute.vpn.ExtrarouteKey;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInputBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInputBuilder;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406.IfIndexesInterfaceMap;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterface;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.meta.rev160406._if.indexes._interface.map.IfIndexInterfaceKey;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.L3nexthop;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthops;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3nexthop.rev150409.l3nexthop.VpnNexthopsKey;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronVpnPortipPortData;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPortKey;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinkStates;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.InterVpnLinks;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkState;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.link.states.InterVpnLinkStateKey;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
107 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
108 import org.opendaylight.yangtools.yang.common.RpcResult;
109 import org.opendaylight.yangtools.yang.binding.DataObject;
110 import org.opendaylight.yangtools.yang.data.impl.schema.tree.SchemaValidationFailedException;
111 import org.slf4j.Logger;
112 import org.slf4j.LoggerFactory;
114 public class VpnUtil {
115 private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
116 private static final int DEFAULT_PREFIX_LENGTH = 32;
117 private static final String PREFIX_SEPARATOR = "/";
119 static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
120 return InstanceIdentifier.builder(VpnInterfaces.class)
121 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
124 static InstanceIdentifier<VpnInstance> getVpnInstanceIdentifier(String vpnName) {
125 return InstanceIdentifier.builder(VpnInstances.class)
126 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
129 static VpnInterface getVpnInterface(String intfName, String vpnName, Adjacencies aug, BigInteger dpnId, Boolean isSheduledForRemove) {
130 return new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(intfName)).setVpnInstanceName(vpnName).setDpnId(dpnId)
131 .setScheduledForRemove(isSheduledForRemove).addAugmentation(Adjacencies.class, aug)
135 static InstanceIdentifier<Prefixes> getPrefixToInterfaceIdentifier(long vpnId, String ipPrefix) {
136 return InstanceIdentifier.builder(PrefixToInterface.class)
137 .child(VpnIds.class, new VpnIdsKey(vpnId)).child(Prefixes.class,
138 new PrefixesKey(ipPrefix)).build();
141 static InstanceIdentifier<VpnIds> getPrefixToInterfaceIdentifier(long vpnId) {
142 return InstanceIdentifier.builder(PrefixToInterface.class)
143 .child(VpnIds.class, new VpnIdsKey(vpnId)).build();
146 static VpnIds getPrefixToInterface(long vpnId) {
147 return new VpnIdsBuilder().setKey(new VpnIdsKey(vpnId)).setVpnId(vpnId).build();
150 static Prefixes getPrefixToInterface(BigInteger dpId, String vpnInterfaceName, String ipPrefix) {
151 return new PrefixesBuilder().setDpnId(dpId).setVpnInterfaceName(
152 vpnInterfaceName).setIpAddress(ipPrefix).build();
155 static InstanceIdentifier<Extraroute> getVpnToExtrarouteIdentifier(String vrfId, String ipPrefix) {
156 return InstanceIdentifier.builder(VpnToExtraroute.class)
157 .child(Vpn.class, new VpnKey(vrfId)).child(Extraroute.class,
158 new ExtrarouteKey(ipPrefix)).build();
161 static InstanceIdentifier<Vpn> getVpnToExtrarouteIdentifier(String vrfId) {
162 return InstanceIdentifier.builder(VpnToExtraroute.class)
163 .child(Vpn.class, new VpnKey(vrfId)).build();
166 static Vpn getVpnToExtraRoute(String vrfId) {
167 return new VpnBuilder().setKey(new VpnKey(vrfId)).setVrfId(vrfId).build();
171 * Retrieves the Instance Identifier that points to an InterVpnLink object
174 * @param vpnLinkName The name of the InterVpnLink
175 * @return The requested InstanceIdentifier
177 public static InstanceIdentifier<InterVpnLinkState> getInterVpnLinkStateIid(String vpnLinkName) {
178 return InstanceIdentifier.builder(InterVpnLinkStates.class).child(InterVpnLinkState.class, new InterVpnLinkStateKey(vpnLinkName)).build();
182 * Get inter-VPN link state
184 * @param broker dataBroker service reference
185 * @param vpnLinkName The name of the InterVpnLink
186 * @return the object that contains the State of the specified InterVpnLink
188 public static InterVpnLinkState getInterVpnLinkState(DataBroker broker, String vpnLinkName) {
189 InstanceIdentifier<InterVpnLinkState> vpnLinkStateIid = VpnUtil.getInterVpnLinkStateIid(vpnLinkName);
190 Optional<InterVpnLinkState> vpnLinkState = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
192 if (vpnLinkState.isPresent()) {
193 return vpnLinkState.get();
199 * Get VRF table given a Route Distinguisher
201 * @param broker dataBroker service reference
202 * @param rd Route-Distinguisher
203 * @return VrfTables that holds the list of VrfEntries of the specified rd
205 public static VrfTables getVrfTable(DataBroker broker, String rd) {
206 InstanceIdentifier<VrfTables> id =
207 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
208 Optional<VrfTables> vrfTable = read(broker, LogicalDatastoreType.CONFIGURATION, id);
209 return vrfTable.isPresent() ? vrfTable.get() : null;
213 * Retrieves the VrfEntries that belong to a given VPN filtered out by
214 * Origin, searching by its Route-Distinguisher
216 * @param broker dataBroker service reference
217 * @param rd Route-distinguisher of the VPN
218 * @param originsToConsider Only entries whose origin is included in this
219 * list will be considered
220 * @return the list of VrfEntries
222 public static List<VrfEntry> getVrfEntriesByOrigin(DataBroker broker, String rd,
223 List<RouteOrigin> originsToConsider) {
224 List<VrfEntry> result = new ArrayList<VrfEntry>();
225 List<VrfEntry> allVpnVrfEntries = getAllVrfEntries(broker, rd);
226 for (VrfEntry vrfEntry : allVpnVrfEntries) {
227 if (originsToConsider.contains(RouteOrigin.value(vrfEntry.getOrigin()))) {
228 result.add(vrfEntry);
234 static List<Prefixes> getAllPrefixesToInterface(DataBroker broker, long vpnId) {
235 Optional<VpnIds> vpnIds = read(broker, LogicalDatastoreType.OPERATIONAL, getPrefixToInterfaceIdentifier(vpnId));
236 if (vpnIds.isPresent()) {
237 return vpnIds.get().getPrefixes();
239 return new ArrayList<Prefixes>();
242 static List<Extraroute> getAllExtraRoutes(DataBroker broker, String vrfId) {
243 Optional<Vpn> extraRoutes = read(broker, LogicalDatastoreType.OPERATIONAL, getVpnToExtrarouteIdentifier(vrfId));
244 if (extraRoutes.isPresent()) {
245 return extraRoutes.get().getExtraroute();
247 return new ArrayList<Extraroute>();
251 * Retrieves all the VrfEntries that belong to a given VPN searching by its
252 * Route-Distinguisher
254 * @param broker dataBroker service reference
255 * @param rd Route-distinguisher of the VPN
256 * @return the list of VrfEntries
258 public static List<VrfEntry> getAllVrfEntries(DataBroker broker, String rd) {
259 VrfTables vrfTables = VpnUtil.getVrfTable(broker, rd);
260 return (vrfTables != null) ? vrfTables.getVrfEntry() : new ArrayList<VrfEntry>();
263 //FIXME: Implement caches for DS reads
264 static VpnInstance getVpnInstance(DataBroker broker, String vpnInstanceName) {
265 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class).child(VpnInstance.class,
266 new VpnInstanceKey(vpnInstanceName)).build();
267 Optional<VpnInstance> vpnInstance = read(broker, LogicalDatastoreType.CONFIGURATION, id);
268 return (vpnInstance.isPresent()) ? vpnInstance.get() : null;
271 static List<VpnInstance> getAllVpnInstance(DataBroker broker) {
272 InstanceIdentifier<VpnInstances> id = InstanceIdentifier.builder(VpnInstances.class).build();
273 Optional<VpnInstances> optVpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
274 if (optVpnInstances.isPresent()) {
275 return optVpnInstances.get().getVpnInstance();
277 return new ArrayList<VpnInstance>();
281 static VrfEntry getVrfEntry(DataBroker broker, String rd, String ipPrefix) {
283 VrfTables vrfTable = getVrfTable(broker, rd);
284 // TODO: why check VrfTables if we later go for the specific VrfEntry?
285 if (vrfTable != null) {
286 InstanceIdentifier<VrfEntry> vrfEntryId =
287 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).
288 child(VrfEntry.class, new VrfEntryKey(ipPrefix)).build();
289 Optional<VrfEntry> vrfEntry = read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
290 if (vrfEntry.isPresent()) {
291 return (vrfEntry.get());
297 static List<Adjacency> getAdjacenciesForVpnInterfaceFromConfig(DataBroker broker, String intfName) {
298 final InstanceIdentifier<VpnInterface> identifier = getVpnInterfaceIdentifier(intfName);
299 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
300 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
302 if (adjacencies.isPresent()) {
303 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
309 static Extraroute getVpnToExtraroute(String ipPrefix, List<String> nextHopList) {
310 return new ExtrarouteBuilder().setPrefix(ipPrefix).setNexthopIpList(nextHopList).build();
313 public static List<Extraroute> getVpnExtraroutes(DataBroker broker, String vpnRd) {
314 InstanceIdentifier<Vpn> vpnExtraRoutesId =
315 InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnRd)).build();
316 Optional<Vpn> vpnOpc = read(broker, LogicalDatastoreType.OPERATIONAL, vpnExtraRoutesId);
317 return vpnOpc.isPresent() ? vpnOpc.get().getExtraroute() : new ArrayList<Extraroute>();
320 static Adjacencies getVpnInterfaceAugmentation(List<Adjacency> nextHopList) {
321 return new AdjacenciesBuilder().setAdjacency(nextHopList).build();
324 public static InstanceIdentifier<IdPool> getPoolId(String poolName) {
325 InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
326 InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
327 InstanceIdentifier<IdPool> id = idBuilder.build();
331 static InstanceIdentifier<VpnInterfaces> getVpnInterfacesIdentifier() {
332 return InstanceIdentifier.builder(VpnInterfaces.class).build();
335 static InstanceIdentifier<Interface> getInterfaceIdentifier(String interfaceName) {
336 return InstanceIdentifier.builder(Interfaces.class)
337 .child(Interface.class, new InterfaceKey(interfaceName)).build();
340 static InstanceIdentifier<VpnToDpnList> getVpnToDpnListIdentifier(String rd, BigInteger dpnId) {
341 return InstanceIdentifier.builder(VpnInstanceOpData.class)
342 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd))
343 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId)).build();
346 public static BigInteger getCookieArpFlow(int interfaceTag) {
347 return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0110000", 16)).add(
348 BigInteger.valueOf(interfaceTag));
351 public static BigInteger getCookieL3(int vpnId) {
352 return VpnConstants.COOKIE_L3_BASE.add(new BigInteger("0610000", 16)).add(BigInteger.valueOf(vpnId));
355 public static String getFlowRef(BigInteger dpnId, short tableId, int ethType, int lPortTag, int arpType) {
356 return new StringBuffer().append(VpnConstants.FLOWID_PREFIX).append(dpnId).append(NwConstants.FLOWID_SEPARATOR)
357 .append(tableId).append(NwConstants.FLOWID_SEPARATOR).append(ethType).append(lPortTag)
358 .append(NwConstants.FLOWID_SEPARATOR).append(arpType).toString();
361 public static int getUniqueId(IdManagerService idManager, String poolName, String idKey) {
362 AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
365 Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
366 RpcResult<AllocateIdOutput> rpcResult = result.get();
367 if (rpcResult.isSuccessful()) {
368 return rpcResult.getResult().getIdValue().intValue();
370 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
372 } catch (InterruptedException | ExecutionException e) {
373 LOG.warn("Exception when getting Unique Id", e);
378 public static void releaseId(IdManagerService idManager, String poolName, String idKey) {
379 ReleaseIdInput idInput = new ReleaseIdInputBuilder().setPoolName(poolName).setIdKey(idKey).build();
381 Future<RpcResult<Void>> result = idManager.releaseId(idInput);
382 RpcResult<Void> rpcResult = result.get();
383 if (!rpcResult.isSuccessful()) {
384 LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
386 } catch (InterruptedException | ExecutionException e) {
387 LOG.warn("Exception when getting Unique Id for key {}", idKey, e);
391 public static String getNextHopLabelKey(String rd, String prefix) {
392 return rd + VpnConstants.SEPARATOR + prefix;
396 * Retrieves the VpnInstance name (typically the VPN Uuid) out from the
397 * route-distinguisher
399 * @param broker dataBroker service reference
400 * @param rd Route-Distinguisher
401 * @return the VpnInstance name
403 public static String getVpnNameFromRd(DataBroker broker, String rd) {
404 VpnInstanceOpDataEntry vpnInstanceOpData = getVpnInstanceOpData(broker, rd);
405 return (vpnInstanceOpData != null) ? vpnInstanceOpData.getVpnInstanceName() : null;
409 * Retrieves the dataplane identifier of a specific VPN, searching by its
412 * @param broker dataBroker service reference
413 * @param vpnName Name of the VPN
414 * @return the dataplane identifier of the VPN, the VrfTag.
416 public static long getVpnId(DataBroker broker, String vpnName) {
418 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
419 = getVpnInstanceToVpnIdIdentifier(vpnName);
420 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
421 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
423 long vpnId = VpnConstants.INVALID_ID;
424 if (vpnInstance.isPresent()) {
425 vpnId = vpnInstance.get().getVpnId();
431 * Retrieves the VPN Route Distinguisher searching by its Vpn instance name
433 * @param broker dataBroker service reference
434 * @param vpnName Name of the VPN
435 * @return the route-distinguisher of the VPN
437 public static String getVpnRd(DataBroker broker, String vpnName) {
438 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> id
439 = getVpnInstanceToVpnIdIdentifier(vpnName);
440 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
441 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
444 if (vpnInstance.isPresent()) {
445 rd = vpnInstance.get().getVrfId();
451 * Get VPN Route Distinguisher from VPN Instance Configuration
453 * @param broker dataBroker service reference
454 * @param vpnName Name of the VPN
455 * @return the route-distinguisher of the VPN
457 public static String getVpnRdFromVpnInstanceConfig(DataBroker broker, String vpnName) {
458 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
459 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
460 Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
462 if (vpnInstance.isPresent()) {
463 VpnInstance instance = vpnInstance.get();
464 VpnAfConfig config = instance.getIpv4Family();
465 rd = config.getRouteDistinguisher();
471 * Writes in MDSAL a new VrfEntry for a VPN specified by its Route-Distinguisher. It performs a merge,
472 * that is, if the VrfEntry exists the nexthop is added the VrfEntry nexthop list. If the entry does not
473 * exist, it is created.
475 * @param broker dataBroker service reference
476 * @param rd Route-distinguisher of the VPN
477 * @param prefix Destination of the route. This, together with the RD, identifies the VrfEntry
478 * @param nextHop Nexthop of the route
479 * @param label Label of the route
481 public static void addFibEntryToDS(DataBroker broker, String rd, String prefix, String nextHop, int label, RouteOrigin origin) {
482 Preconditions.checkNotNull(rd, "RD cannot be null");
483 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nextHop, label);
484 synchronized (rd.intern()) {
485 InstanceIdentifier<VrfTables> vrfTableId =
486 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
487 VrfEntry vrfEntry = getVrfEntry(broker, rd, prefix);
488 if (vrfEntry != null) {
489 List<String> nextHopList = vrfEntry.getNextHopAddressList();
490 nextHopList.add(nextHop);
491 VrfEntryBuilder builder = new VrfEntryBuilder(vrfEntry).setNextHopAddressList(nextHopList);
492 VrfEntry newVrfEntry = builder.build();
493 // Just update the VrfEntry
494 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
495 vrfTableId.child(VrfEntry.class, new VrfEntryKey(prefix)), newVrfEntry);
497 List<VrfEntry> currentVrfEntries = new ArrayList<VrfEntry>();
498 VrfEntryBuilder builder = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
499 .setLabel((long) label).setOrigin(origin.getValue());
500 vrfEntry = builder.build();
501 currentVrfEntries.add(vrfEntry);
502 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).setVrfEntry(
503 currentVrfEntries).build();
504 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
506 LOG.info("ADD: Added Fib Entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHop, label);
512 * Removes a specific Nexthop from a VrfEntry. If Nexthop to remove is the
513 * last one in the VrfEntry, then the VrfEntry is removed too.
515 * @param broker dataBroker service reference
516 * @param rd Route-Distinguisher to which the VrfEntry belongs to
517 * @param prefix Destination of the route
518 * @param nextHopToRemove Specific nexthop within the Route to be removed.
519 * If null or empty, then the whole VrfEntry is removed
521 public static void removeFibEntryFromDS(DataBroker broker, String rd, String prefix, String nextHopToRemove) {
523 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
525 // Looking for existing prefix in MDSAL database
526 InstanceIdentifier<VrfEntry> vrfEntryId =
527 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd))
528 .child(VrfEntry.class, new VrfEntryKey(prefix)).build();
529 Optional<VrfEntry> entry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
531 if ( entry.isPresent() ) {
532 synchronized (rd.intern()) {
533 List<String> nhListRead = new ArrayList<>();
534 if ( nextHopToRemove != null && !nextHopToRemove.isEmpty()) {
535 nhListRead = entry.get().getNextHopAddressList();
536 if (nhListRead.contains(nextHopToRemove)) {
537 nhListRead.remove(nextHopToRemove);
541 if (nhListRead.isEmpty()) {
542 // Remove the whole entry
543 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
544 LOG.info("Removed Fib Entry rd {} prefix {}", rd, prefix);
546 // An update must be done, not including the current next hop
548 new VrfEntryBuilder(entry.get()).setDestPrefix(prefix).setNextHopAddressList(nhListRead)
549 .setKey(new VrfEntryKey(prefix)).build();
550 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId);
551 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, vrfEntry);
552 LOG.info("Removed Nexthop {} from Fib Entry rd {} prefix {}", nextHopToRemove, rd, prefix);
556 LOG.warn("Could not find VrfEntry for Route-Distinguisher={} and prefix={}", rd, prefix);
562 * Remove from MDSAL all those VrfEntries in a VPN that have an specific RouteOrigin
564 * @param broker dataBroker service reference
565 * @param rd Route Distinguisher
566 * @param origin Origin of the Routes to be removed (see {@link org.opendaylight.netvirt.bgpmanager.api.RouteOrigin})
568 public static void removeVrfEntriesByOrigin(DataBroker broker, String rd, RouteOrigin origin) {
569 InstanceIdentifier<VrfTables> vpnVrfTableIid =
570 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
571 Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
572 if (vrfTablesOpc.isPresent()) {
573 VrfTables vrfTables = vrfTablesOpc.get();
574 List<VrfEntry> newVrfEntries = new ArrayList<VrfEntry>();
575 for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
576 if (origin == RouteOrigin.value(vrfEntry.getOrigin())) {
577 delete(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class,
584 public static void removeVrfEntriesByNexthop(DataBroker broker, String rd, String nexthop) {
585 InstanceIdentifier<VrfTables> vpnVrfTableIid =
586 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).build();
587 Optional<VrfTables> vrfTablesOpc = read(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid);
588 if (vrfTablesOpc.isPresent()) {
589 VrfTables vrfTables = vrfTablesOpc.get();
590 for (VrfEntry vrfEntry : vrfTables.getVrfEntry()) {
591 if (vrfEntry.getNextHopAddressList() != null && vrfEntry.getNextHopAddressList().contains(nexthop)) {
592 // TODO: Removes all the VrfEntry if one of the nexthops is the specified nexthop
593 // should we only remove the specific nexthop, or all the VrfEnry?
594 delete(broker, LogicalDatastoreType.CONFIGURATION, vpnVrfTableIid.child(VrfEntry.class,
601 static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance
602 getVpnInstanceToVpnId(String vpnName, long vpnId, String rd) {
604 return new VpnInstanceBuilder().setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).build();
608 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
609 getVpnInstanceToVpnIdIdentifier(String vpnName) {
610 return InstanceIdentifier.builder(VpnInstanceToVpnId.class)
611 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance.class,
612 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstanceKey(vpnName)).build();
615 static org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds
616 getVpnIdToVpnInstance(long vpnId, String vpnName, String rd, boolean isExternalVpn) {
617 return new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsBuilder()
618 .setVpnId(vpnId).setVpnInstanceName(vpnName).setVrfId(rd).setExternalVpn(isExternalVpn).build();
622 static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds>
623 getVpnIdToVpnInstanceIdentifier(long vpnId) {
624 return InstanceIdentifier.builder(VpnIdToVpnInstance.class)
625 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds.class,
626 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIdsKey(Long.valueOf(vpnId))).build();
630 * Retrieves the Vpn Name searching by its VPN Tag.
632 * @param broker dataBroker service reference
633 * @param vpnId Dataplane identifier of the VPN
634 * @return the Vpn instance name
636 public static String getVpnName(DataBroker broker, long vpnId) {
638 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> id
639 = getVpnIdToVpnInstanceIdentifier(vpnId);
640 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds> vpnInstance
641 = read(broker, LogicalDatastoreType.CONFIGURATION, id);
643 String vpnName = null;
644 if (vpnInstance.isPresent()) {
645 vpnName = vpnInstance.get().getVpnInstanceName();
650 public static InstanceIdentifier<VpnInstanceOpDataEntry> getVpnInstanceOpDataIdentifier(String rd) {
651 return InstanceIdentifier.builder(VpnInstanceOpData.class)
652 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(rd)).build();
655 static VpnInstanceOpDataEntry getVpnInstanceOpDataBuilder(String rd, long vpnId, String vpnName) {
656 return new VpnInstanceOpDataEntryBuilder().setVrfId(rd).setVpnId(vpnId).setVpnInstanceName(vpnName).build();
659 static VpnInstanceOpDataEntry updateIntfCntInVpnInstOpData(Long newCount, String vrfId) {
660 return new VpnInstanceOpDataEntryBuilder().setVpnInterfaceCount(newCount).setVrfId(vrfId).build();
663 static InstanceIdentifier<RouterInterface> getRouterInterfaceId(String interfaceName) {
664 return InstanceIdentifier.builder(RouterInterfaces.class)
665 .child(RouterInterface.class, new RouterInterfaceKey(interfaceName)).build();
668 static RouterInterface getRouterInterface(String interfaceName, String routerName) {
669 return new RouterInterfaceBuilder().setKey(new RouterInterfaceKey(interfaceName))
670 .setInterfaceName(interfaceName).setRouterName(routerName).build();
673 static VpnInstanceOpDataEntry getVpnInstanceOpData(DataBroker broker, String rd) {
674 InstanceIdentifier<VpnInstanceOpDataEntry> id = VpnUtil.getVpnInstanceOpDataIdentifier(rd);
675 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData = read(broker, LogicalDatastoreType.OPERATIONAL, id);
676 if (vpnInstanceOpData.isPresent()) {
677 return vpnInstanceOpData.get();
682 static VpnInterface getConfiguredVpnInterface(DataBroker broker, String interfaceName) {
683 InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
684 Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
686 if (configuredVpnInterface.isPresent()) {
687 return configuredVpnInterface.get();
692 static VpnInterface getOperationalVpnInterface(DataBroker broker, String interfaceName) {
693 InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
694 Optional<VpnInterface> operationalVpnInterface = read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
696 if (operationalVpnInterface.isPresent()) {
697 return operationalVpnInterface.get();
702 static boolean isVpnInterfaceConfigured(DataBroker broker, String interfaceName) {
703 InstanceIdentifier<VpnInterface> interfaceId = getVpnInterfaceIdentifier(interfaceName);
704 Optional<VpnInterface> configuredVpnInterface = read(broker, LogicalDatastoreType.CONFIGURATION, interfaceId);
706 if (configuredVpnInterface.isPresent()) {
712 static String getIpPrefix(String prefix) {
713 String prefixValues[] = prefix.split("/");
714 if (prefixValues.length == 1) {
715 prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH;
720 static final FutureCallback<Void> DEFAULT_CALLBACK =
721 new FutureCallback<Void>() {
723 public void onSuccess(Void result) {
724 LOG.debug("Success in Datastore operation");
728 public void onFailure(Throwable error) {
729 LOG.error("Error in Datastore operation", error);
735 public static <T extends DataObject> Optional<T> read(DataBroker broker, LogicalDatastoreType datastoreType,
736 InstanceIdentifier<T> path) {
738 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
740 Optional<T> result = Optional.absent();
742 result = tx.read(datastoreType, path).get();
743 } catch (Exception e) {
744 throw new RuntimeException(e);
752 public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
753 InstanceIdentifier<T> path, T data) {
754 asyncUpdate(broker, datastoreType, path, data, DEFAULT_CALLBACK);
757 public static <T extends DataObject> void asyncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
758 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
759 WriteTransaction tx = broker.newWriteOnlyTransaction();
760 tx.merge(datastoreType, path, data, true);
761 Futures.addCallback(tx.submit(), callback);
764 public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
765 InstanceIdentifier<T> path, T data) {
766 asyncWrite(broker, datastoreType, path, data, DEFAULT_CALLBACK);
769 public static <T extends DataObject> void asyncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
770 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
771 WriteTransaction tx = broker.newWriteOnlyTransaction();
772 tx.put(datastoreType, path, data, true);
773 Futures.addCallback(tx.submit(), callback);
776 public static <T extends DataObject> void tryDelete(DataBroker broker, LogicalDatastoreType datastoreType,
777 InstanceIdentifier<T> path) {
779 delete(broker, datastoreType, path, DEFAULT_CALLBACK);
780 } catch ( SchemaValidationFailedException sve ) {
781 LOG.info("Could not delete {}. SchemaValidationFailedException: {}", path, sve.getMessage());
782 } catch ( Exception e) {
783 LOG.info("Could not delete {}. Unhandled error: {}", path, e.getMessage());
787 public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
788 InstanceIdentifier<T> path) {
789 delete(broker, datastoreType, path, DEFAULT_CALLBACK);
793 public static <T extends DataObject> void delete(DataBroker broker, LogicalDatastoreType datastoreType,
794 InstanceIdentifier<T> path, FutureCallback<Void> callback) {
795 WriteTransaction tx = broker.newWriteOnlyTransaction();
796 tx.delete(datastoreType, path);
797 Futures.addCallback(tx.submit(), callback);
800 public static <T extends DataObject> void syncWrite(DataBroker broker, LogicalDatastoreType datastoreType,
801 InstanceIdentifier<T> path, T data) {
802 WriteTransaction tx = broker.newWriteOnlyTransaction();
803 tx.put(datastoreType, path, data, true);
804 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
807 } catch (InterruptedException | ExecutionException e) {
808 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
809 throw new RuntimeException(e.getMessage());
813 public static <T extends DataObject> void syncUpdate(DataBroker broker, LogicalDatastoreType datastoreType,
814 InstanceIdentifier<T> path, T data) {
815 WriteTransaction tx = broker.newWriteOnlyTransaction();
816 tx.merge(datastoreType, path, data, true);
817 CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
820 } catch (InterruptedException | ExecutionException e) {
821 LOG.error("Error writing to datastore (path, data) : ({}, {})", path, data);
822 throw new RuntimeException(e.getMessage());
826 public static long getRemoteBCGroup(long elanTag) {
827 return VpnConstants.ELAN_GID_MIN + ((elanTag % VpnConstants.ELAN_GID_MIN) * 2);
830 // interface-index-tag operational container
831 public static IfIndexInterface getInterfaceInfoByInterfaceTag(DataBroker broker, long interfaceTag) {
832 InstanceIdentifier<IfIndexInterface> interfaceId = getInterfaceInfoEntriesOperationalDataPath(interfaceTag);
833 Optional<IfIndexInterface> existingInterfaceInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
834 if (existingInterfaceInfo.isPresent()) {
835 return existingInterfaceInfo.get();
840 private static InstanceIdentifier<IfIndexInterface> getInterfaceInfoEntriesOperationalDataPath(long interfaceTag) {
841 return InstanceIdentifier.builder(IfIndexesInterfaceMap.class).child(IfIndexInterface.class,
842 new IfIndexInterfaceKey((int) interfaceTag)).build();
845 public static ElanTagName getElanInfoByElanTag(DataBroker broker, long elanTag) {
846 InstanceIdentifier<ElanTagName> elanId = getElanInfoEntriesOperationalDataPath(elanTag);
847 Optional<ElanTagName> existingElanInfo = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, elanId);
848 if (existingElanInfo.isPresent()) {
849 return existingElanInfo.get();
854 private static InstanceIdentifier<ElanTagName> getElanInfoEntriesOperationalDataPath(long elanTag) {
855 return InstanceIdentifier.builder(ElanTagNameMap.class).child(ElanTagName.class,
856 new ElanTagNameKey(elanTag)).build();
860 // TODO: Move this to NwUtil
861 public static boolean isIpInSubnet(int ipAddress, String subnetCidr) {
862 String[] subSplit = subnetCidr.split("/");
863 if (subSplit.length < 2) {
867 String subnetStr = subSplit[0];
870 InetAddress subnetAddress = InetAddress.getByName(subnetStr);
871 subnet = Ints.fromByteArray(subnetAddress.getAddress());
872 } catch (Exception ex) {
873 LOG.error("Passed in Subnet IP string not convertible to InetAdddress " + subnetStr);
876 int prefixLength = Integer.valueOf(subSplit[1]);
877 int mask = -1 << (32 - prefixLength);
878 if ((subnet & mask) == (ipAddress & mask)) {
885 * Returns the Path identifier to reach a specific interface in a specific DPN in a given VpnInstance
887 * @param vpnRd Route-Distinguisher of the VpnInstance
888 * @param dpnId Id of the DPN where the interface is
889 * @param ifaceName Interface name
890 * @return the Instance Identifier
892 public static InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
893 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
894 getVpnToDpnInterfacePath(String vpnRd, BigInteger dpnId, String ifaceName) {
897 InstanceIdentifier.builder(VpnInstanceOpData.class)
898 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnRd))
899 .child(VpnToDpnList.class, new VpnToDpnListKey(dpnId))
900 .child(org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
901 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
902 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
903 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
908 * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
909 * This method is preferably over mergeDpnInVpnToDpnMap(DataBroker, String, String, BigInteger, List)
910 * when there are several DPNs to be merged since it saves some readings from MDSAL.
912 * @param broker dataBroker service reference
913 * @param vpnOpData Reference to the object that holds the Operational data of the VpnInstance
914 * @param dpnId Id of the DPN where the interfaces to be added to Operational data are located
915 * @param ifaceNames List of interface names
917 public static void mergeDpnInVpnToDpnMap(DataBroker broker, VpnInstanceOpDataEntry vpnOpData, BigInteger dpnId,
918 List<String> ifaceNames) {
919 Preconditions.checkNotNull(vpnOpData);
920 Preconditions.checkNotNull(ifaceNames);
922 for (String ifaceName : ifaceNames) {
923 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
924 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnDpnIfaceIid =
925 getVpnToDpnInterfacePath(vpnOpData.getKey().getVrfId(), dpnId, ifaceName);
927 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
928 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnDpnIface =
929 new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
930 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list
931 .VpnInterfacesBuilder().setKey(new org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
932 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey(ifaceName))
933 .setInterfaceName(ifaceName)
936 syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, vpnDpnIfaceIid, vpnDpnIface);
941 * Includes a DPN with the corresponding interface names in the VpnToDpn operational data.
943 * @param broker dataBroker service reference
944 * @param vpnName Name of the VPN
945 * @param rd Route-Distinguisher
946 * @param dpnId Id of the DPN that includes the list of Ifaces to be
947 * included in the Map
948 * @param ifaceNames List of interfaces to be included in the Map
950 public static void mergeDpnInVpnToDpnMap(DataBroker broker, String vpnName, String rd, BigInteger dpnId,
951 List<String> ifaceNames) {
952 InstanceIdentifier<VpnInstanceOpDataEntry> id = InstanceIdentifier.builder(VpnInstanceOpData.class)
953 .child(VpnInstanceOpDataEntry.class, new VpnInstanceOpDataEntryKey(vpnName))
956 Optional<VpnInstanceOpDataEntry> vpnInstanceOpData =
957 MDSALUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
958 if (vpnInstanceOpData.isPresent()) {
959 mergeDpnInVpnToDpnMap(broker, vpnInstanceOpData.get(), dpnId, ifaceNames);
964 * Removes a specific interface from the VpnToDpn operative map.
966 * @param broker dataBroker service reference
967 * @param rd Route-distinguisher of the VPN
968 * @param dpnId Id of the DPN where the interface is
969 * @param ifaceName interface name.
971 public static void removeIfaceFromVpnToDpnMap(DataBroker broker, String rd, BigInteger dpnId, String ifaceName) {
972 tryDelete(broker, LogicalDatastoreType.CONFIGURATION, getVpnToDpnInterfacePath(rd, dpnId, ifaceName));
973 // Note: tryDelete is a best-effort. Sometimes we want to update the VpnToDpnMap ifaces when the
974 // DPN has gone down (and the VpnToDpnMap has been removed in a different Thread)
977 public static void removePrefixToInterfaceForVpnId(DataBroker broker, long vpnId) {
979 // Clean up PrefixToInterface Operational DS
980 delete(broker, LogicalDatastoreType.OPERATIONAL,
981 InstanceIdentifier.builder(PrefixToInterface.class).child(VpnIds.class, new VpnIdsKey(vpnId)).build(),
983 } catch (Exception e) {
984 LOG.error("Exception during cleanup of PrefixToInterface for VPN ID {}", vpnId, e);
988 public static void removeVpnExtraRouteForVpn(DataBroker broker, String vpnName) {
990 // Clean up VPNExtraRoutes Operational DS
991 delete(broker, LogicalDatastoreType.OPERATIONAL,
992 InstanceIdentifier.builder(VpnToExtraroute.class).child(Vpn.class, new VpnKey(vpnName)).build(),
994 } catch (Exception e) {
995 LOG.error("Exception during cleanup of VPNToExtraRoute for VPN {}", vpnName, e);
999 public static void removeVpnOpInstance(DataBroker broker, String vpnName) {
1001 // Clean up VPNInstanceOpDataEntry
1002 delete(broker, LogicalDatastoreType.OPERATIONAL, getVpnInstanceOpDataIdentifier(vpnName),
1004 } catch (Exception e) {
1005 LOG.error("Exception during cleanup of VPNInstanceOpDataEntry for VPN {}", vpnName, e);
1009 public static void removeVpnInstanceToVpnId(DataBroker broker, String vpnName) {
1011 delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnInstanceToVpnIdIdentifier(vpnName),
1013 } catch (Exception e) {
1014 LOG.error("Exception during clean up of VpnInstanceToVpnId for VPN {}", vpnName, e);
1018 public static void removeVpnIdToVpnInstance(DataBroker broker, long vpnId) {
1020 delete(broker, LogicalDatastoreType.CONFIGURATION, getVpnIdToVpnInstanceIdentifier(vpnId),
1022 } catch (Exception e) {
1023 LOG.error("Exception during clean up of VpnIdToVpnInstance for VPNID {}", vpnId, e);
1027 public static void removeVrfTableForVpn(DataBroker broker, String vpnName) {
1028 // Clean up FIB Entries Config DS
1030 delete(broker, LogicalDatastoreType.CONFIGURATION,
1031 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(vpnName)).build(),
1033 } catch (Exception e) {
1034 LOG.error("Exception during clean up of VrfTable from FIB for VPN {}", vpnName, e);
1038 public static void removeL3nexthopForVpnId(DataBroker broker, long vpnId) {
1040 // Clean up L3NextHop Operational DS
1041 delete(broker, LogicalDatastoreType.OPERATIONAL,
1042 InstanceIdentifier.builder(L3nexthop.class).child(VpnNexthops.class, new VpnNexthopsKey(vpnId)).build(),
1044 } catch (Exception e) {
1045 LOG.error("Exception during cleanup of L3NextHop for VPN ID {}", vpnId, e);
1050 * Retrieves all configured InterVpnLinks
1052 * @param broker dataBroker service reference
1053 * @return the list of InterVpnLinks
1055 public static List<InterVpnLink> getAllInterVpnLinks(DataBroker broker) {
1056 InstanceIdentifier<InterVpnLinks> interVpnLinksIid = InstanceIdentifier.builder(InterVpnLinks.class).build();
1058 Optional<InterVpnLinks> interVpnLinksOpData = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION,
1061 return (interVpnLinksOpData.isPresent()) ? interVpnLinksOpData.get().getInterVpnLink()
1062 : new ArrayList<InterVpnLink>();
1066 * Retrieves the list of DPNs where the endpoint of a VPN in an InterVPNLink was instantiated
1068 * @param broker dataBroker service reference
1069 * @param vpnLinkName the name of the InterVpnLink
1070 * @param vpnUuid UUID of the VPN whose endpoint to be checked
1071 * @return the list of DPN Ids
1073 public static List<BigInteger> getVpnLinkEndpointDPNs(DataBroker broker, String vpnLinkName, String vpnUuid) {
1074 InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, vpnLinkName);
1075 if (interVpnLinkState.getFirstEndpointState().getVpnUuid().getValue().equals(vpnUuid)) {
1076 return interVpnLinkState.getFirstEndpointState().getDpId();
1078 return interVpnLinkState.getSecondEndpointState().getDpId();
1083 * Retrieves an InterVpnLink by searching by one of its endpoint's IP.
1085 * @param broker dataBroker service reference
1086 * @param endpointIp IP to serch for.
1087 * @return the InterVpnLink or null if no InterVpnLink can be found
1089 public static InterVpnLink getInterVpnLinkByEndpointIp(DataBroker broker, String endpointIp) {
1090 List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
1091 for (InterVpnLink interVpnLink : allInterVpnLinks) {
1092 if (interVpnLink.getFirstEndpoint().getIpAddress().getValue().equals(endpointIp)
1093 || interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(endpointIp)) {
1094 return interVpnLink;
1101 * Retrieves the InterVpnLink that has one of its 2 endpoints installed in
1102 * the specified DpnId
1104 * @param broker dataBroker service reference
1105 * @param dpnId Id of the DPN
1106 * @return The InterVpnLink object if found, Optional.absent() otherwise
1108 public static Optional<InterVpnLink> getInterVpnLinkByDpnId(DataBroker broker, BigInteger dpnId) {
1109 List<InterVpnLink> allInterVpnLinks = getAllInterVpnLinks(broker);
1110 for (InterVpnLink interVpnLink : allInterVpnLinks) {
1111 InterVpnLinkState interVpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
1112 if ( ( interVpnLinkState != null )
1113 && ( interVpnLinkState.getFirstEndpointState().getDpId().contains(dpnId)
1114 || interVpnLinkState.getSecondEndpointState().getDpId().contains(dpnId) ) ) {
1115 return Optional.fromNullable(interVpnLink);
1118 return Optional.absent();
1122 * Leaks a route from one VPN to another. By default, the origin for this leaked route is INTERVPN
1124 * @param broker dataBroker service reference
1125 * @param bgpManager Used to advertise routes to the BGP Router
1126 * @param interVpnLink Reference to the object that holds the info about the link between the 2 VPNs
1127 * @param srcVpnUuid UUID of the VPN that has the route that is going to be leaked to the other VPN
1128 * @param dstVpnUuid UUID of the VPN that is going to receive the route
1129 * @param prefix Prefix of the route
1130 * @param label Label of the route in the original VPN
1132 public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
1133 String srcVpnUuid, String dstVpnUuid, String prefix, Long label) {
1134 leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, prefix, label, RouteOrigin.INTERVPN);
1138 * Leaks a route from one VPN to another.
1140 * @param broker dataBroker service reference
1141 * @param bgpManager Used to advertise routes to the BGP Router
1142 * @param interVpnLink Reference to the object that holds the info about the link between the 2 VPNs
1143 * @param srcVpnUuid UUID of the VPN that has the route that is going to be leaked to the other VPN
1144 * @param dstVpnUuid UUID of the VPN that is going to receive the route
1145 * @param prefix Prefix of the route
1146 * @param label Label of the route in the original VPN
1147 * @param forcedOrigin By default, origin for leaked routes should be INTERVPN, however it is possible to
1148 * provide a different origin if desired.
1150 public static void leakRoute(DataBroker broker, IBgpManager bgpManager, InterVpnLink interVpnLink,
1151 String srcVpnUuid, String dstVpnUuid, String prefix, Long label,
1152 RouteOrigin forcedOrigin) {
1153 Preconditions.checkNotNull(interVpnLink);
1155 // The source VPN must participate in the InterVpnLink
1156 Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(srcVpnUuid)
1157 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(srcVpnUuid),
1158 "The source VPN {} does not participate in the interVpnLink {}",
1159 srcVpnUuid, interVpnLink.getName());
1160 // The destination VPN must participate in the InterVpnLink
1161 Preconditions.checkArgument(interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid)
1162 || interVpnLink.getSecondEndpoint().getVpnUuid().getValue().equals(dstVpnUuid),
1163 "The destination VPN {} does not participate in the interVpnLink {}",
1164 dstVpnUuid, interVpnLink.getName());
1166 boolean destinationIs1stEndpoint = interVpnLink.getFirstEndpoint().getVpnUuid().getValue().equals(dstVpnUuid);
1168 String endpointIp = (destinationIs1stEndpoint) ? interVpnLink.getSecondEndpoint().getIpAddress().getValue()
1169 : interVpnLink.getFirstEndpoint().getIpAddress().getValue();
1171 VrfEntry newVrfEntry = new VrfEntryBuilder().setKey(new VrfEntryKey(prefix)).setDestPrefix(prefix)
1172 .setLabel(label).setNextHopAddressList(Arrays.asList(endpointIp))
1173 .setOrigin(RouteOrigin.INTERVPN.getValue())
1176 String dstVpnRd = getVpnRd(broker, dstVpnUuid);
1177 InstanceIdentifier<VrfEntry> newVrfEntryIid =
1178 InstanceIdentifier.builder(FibEntries.class)
1179 .child(VrfTables.class, new VrfTablesKey(dstVpnRd))
1180 .child(VrfEntry.class, new VrfEntryKey(newVrfEntry.getDestPrefix()))
1182 asyncWrite(broker, LogicalDatastoreType.CONFIGURATION, newVrfEntryIid, newVrfEntry);
1184 // Finally, route is advertised it to the DC-GW. But while in the FibEntries the nexthop is the other
1185 // endpoint's IP, in the DC-GW the nexthop for those prefixes are the IPs of those DPNs where the target
1186 // VPN has been instantiated
1187 List<String> ecmpNexthops = new ArrayList<String>();
1188 InterVpnLinkState vpnLinkState = getInterVpnLinkState(broker, interVpnLink.getName());
1189 List<BigInteger> dpnIdList = (destinationIs1stEndpoint) ? vpnLinkState.getFirstEndpointState().getDpId()
1190 : vpnLinkState.getSecondEndpointState().getDpId();
1191 List<String> nexthops = new ArrayList<String>();
1192 for (BigInteger dpnId : dpnIdList) {
1193 nexthops.add(InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId));
1196 bgpManager.advertisePrefix(dstVpnRd, newVrfEntry.getDestPrefix(), nexthops, label.intValue());
1197 } catch (Exception exc) {
1198 LOG.error("Could not advertise prefix {} with label {} to VPN rd={}",
1199 newVrfEntry.getDestPrefix(), label.intValue(), dstVpnRd);
1205 * Retrieves the ids of the currently operative DPNs
1207 * @param dataBroker dataBroker service reference
1208 * @return the list of DPNs currently operative
1210 public static List<BigInteger> getOperativeDPNs(DataBroker dataBroker) {
1211 List<BigInteger> result = new LinkedList<BigInteger>();
1212 InstanceIdentifier<Nodes> nodesInstanceIdentifier = InstanceIdentifier.builder(Nodes.class).build();
1213 Optional<Nodes> nodesOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
1214 nodesInstanceIdentifier);
1215 if (!nodesOptional.isPresent()) {
1218 Nodes nodes = nodesOptional.get();
1219 List<Node> nodeList = nodes.getNode();
1220 for (Node node : nodeList) {
1221 NodeId nodeId = node.getId();
1222 if (nodeId != null) {
1223 BigInteger dpnId = MDSALUtil.getDpnIdFromNodeName(nodeId);
1231 * Retrieves a list of randomly selected DPNs, as many as specified.
1233 * @param dataBroker dataBroker service reference
1234 * @param numberOfDPNs Specifies how many Operative DPNs must be found
1235 * @param excludingDPNs Specifies a blacklist of DPNs
1236 * @return the list of DPN Ids
1238 public static List<BigInteger> pickRandomDPNs(DataBroker dataBroker, int numberOfDPNs,
1239 List<BigInteger> excludingDPNs) {
1240 List<BigInteger> dpnIdPool = getOperativeDPNs(dataBroker);
1241 int poolSize = dpnIdPool.size();
1242 if (poolSize <= numberOfDPNs) {
1243 // You requested more than there is, I give you all I have.
1248 Collections.shuffle(dpnIdPool);
1249 List<BigInteger> result = new ArrayList<BigInteger>();
1251 for (BigInteger dpId : dpnIdPool) {
1252 if (excludingDPNs == null || !excludingDPNs.contains(dpId)) {
1254 if (result.size() == numberOfDPNs)
1259 if (result.size() < numberOfDPNs) {
1260 // We still don't have all we need, so we have to pick up among the "prohibited" ones
1261 dpnIdPool.removeAll(result);
1263 int nbrOfProhibitedDpnsToPick = numberOfDPNs - result.size();
1264 for (int i = 0; i < nbrOfProhibitedDpnsToPick; i++) {
1265 result.add(dpnIdPool.get(i));
1271 public static void updateVpnInterface(DataBroker broker,String interfaceName, BigInteger dpnId, String vpnInstanceName, Boolean isScheduledToRemove){
1272 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1273 VpnInterface interfaceToUpdate = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(interfaceName)).setName(interfaceName)
1274 .setDpnId(dpnId).setVpnInstanceName(vpnInstanceName).setScheduledForRemove(isScheduledToRemove).build();
1275 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, interfaceToUpdate);
1278 protected static void createVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
1279 String portName, String macAddress, boolean isSubnetIp, boolean isConfig,
1281 InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1282 VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder().setKey(
1283 new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp).setPortName(portName)
1284 .setMacAddress(macAddress).setSubnetIp(isSubnetIp).setConfig(isConfig).setLearnt(isLearnt);
1285 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
1286 LOG.debug("ARP learned for fixedIp: {}, vpn {}, interface {}, mac {}, isSubnetIp {} added to VpnPortipToPort DS",
1287 fixedIp, vpnName, portName, macAddress, isLearnt);
1290 protected static void updateVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp,
1291 String portName, String macAddress, boolean isSubnetIp,boolean isConfig,
1293 InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1294 VpnPortipToPortBuilder builder = new VpnPortipToPortBuilder().setKey(
1295 new VpnPortipToPortKey(fixedIp, vpnName)).setVpnName(vpnName).setPortFixedip(fixedIp).setPortName(portName)
1296 .setMacAddress(macAddress).setSubnetIp(isSubnetIp).setConfig(isConfig).setLearnt(isLearnt);;
1297 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, id, builder.build());
1298 LOG.debug("Updated Arp learnt fixedIp: {}, vpn {}, interface {}, mac {}, isLearnt {} Updated to VpnPortipToPort DS",
1299 fixedIp, vpnName, portName, macAddress, isLearnt);
1302 protected static void removeVpnPortFixedIpToPort(DataBroker broker, String vpnName, String fixedIp) {
1303 InstanceIdentifier<VpnPortipToPort> id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1304 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, id);
1305 LOG.debug("Delete learned ARP for fixedIp: {}, vpn {} removed from VpnPortipToPort DS",
1309 static InstanceIdentifier<VpnPortipToPort> buildVpnPortipToPortIdentifier(String vpnName, String fixedIp) {
1310 InstanceIdentifier<VpnPortipToPort> id = InstanceIdentifier.builder(NeutronVpnPortipPortData.class).child
1311 (VpnPortipToPort.class, new VpnPortipToPortKey(fixedIp, vpnName)).build();
1315 static VpnPortipToPort getNeutronPortFromVpnPortFixedIp(DataBroker broker, String vpnName, String fixedIp) {
1316 InstanceIdentifier id = buildVpnPortipToPortIdentifier(vpnName, fixedIp);
1317 Optional<VpnPortipToPort> vpnPortipToPortData = read(broker, LogicalDatastoreType.CONFIGURATION, id);
1318 if (vpnPortipToPortData.isPresent()) {
1319 return (vpnPortipToPortData.get());