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
8 package org.opendaylight.netvirt.vpnmanager;
10 import com.google.common.base.Function;
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.base.Predicate;
14 import com.google.common.base.Predicates;
15 import com.google.common.collect.FluentIterable;
16 import com.google.common.collect.Iterators;
17 import com.google.common.util.concurrent.CheckedFuture;
18 import com.google.common.util.concurrent.FutureCallback;
19 import com.google.common.util.concurrent.Futures;
20 import com.google.common.util.concurrent.JdkFutureAdapters;
21 import com.google.common.util.concurrent.ListenableFuture;
22 import java.math.BigInteger;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.concurrent.Callable;
29 import java.util.concurrent.ConcurrentHashMap;
30 import java.util.concurrent.ExecutionException;
31 import java.util.concurrent.ExecutorService;
32 import java.util.concurrent.Executors;
33 import java.util.concurrent.Future;
34 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
35 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
36 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
37 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
38 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
39 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
40 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
41 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
42 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
43 import org.opendaylight.genius.mdsalutil.ActionInfo;
44 import org.opendaylight.genius.mdsalutil.ActionType;
45 import org.opendaylight.genius.mdsalutil.FlowEntity;
46 import org.opendaylight.genius.mdsalutil.InstructionInfo;
47 import org.opendaylight.genius.mdsalutil.InstructionType;
48 import org.opendaylight.genius.mdsalutil.MDSALUtil;
49 import org.opendaylight.genius.mdsalutil.MatchFieldType;
50 import org.opendaylight.genius.mdsalutil.MatchInfo;
51 import org.opendaylight.genius.mdsalutil.MetaDataUtil;
52 import org.opendaylight.genius.mdsalutil.NwConstants;
53 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
54 import org.opendaylight.genius.utils.ServiceIndex;
55 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
56 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
57 import org.opendaylight.netvirt.fibmanager.api.RouteOrigin;
58 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
59 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
69 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRouteBuilder;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.IpAddresses;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
128 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
129 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
130 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
131 import org.opendaylight.yangtools.concepts.ListenerRegistration;
132 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
133 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
134 import org.opendaylight.yangtools.yang.common.RpcError;
135 import org.opendaylight.yangtools.yang.common.RpcResult;
136 import org.slf4j.Logger;
137 import org.slf4j.LoggerFactory;
139 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
140 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
141 private ListenerRegistration<DataChangeListener> listenerRegistration;
142 private final DataBroker dataBroker;
143 private final IBgpManager bgpManager;
144 private final IFibManager fibManager;
145 private final IMdsalApiManager mdsalManager;
146 private final IdManagerService idManager;
147 private final OdlArputilService arpManager;
148 private final OdlInterfaceRpcService ifaceMgrRpcService;
149 private final NotificationPublishService notificationPublishService;
150 private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
151 private ExecutorService executorService = Executors.newSingleThreadExecutor();
153 public VpnInterfaceManager(final DataBroker dataBroker,
154 final IBgpManager bgpManager,
155 final OdlArputilService arpManager,
156 final IdManagerService idManager,
157 final IMdsalApiManager mdsalManager,
158 final IFibManager fibManager,
159 final OdlInterfaceRpcService ifaceMgrRpcService,
160 final NotificationPublishService notificationPublishService) {
161 super(VpnInterface.class);
162 this.dataBroker = dataBroker;
163 this.bgpManager = bgpManager;
164 this.arpManager = arpManager;
165 this.idManager = idManager;
166 this.mdsalManager = mdsalManager;
167 this.fibManager = fibManager;
168 this.ifaceMgrRpcService = ifaceMgrRpcService;
169 this.notificationPublishService = notificationPublishService;
172 public void start() {
173 LOG.info("{} start", getClass().getSimpleName());
174 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
175 getWildCardPath(), this, DataChangeScope.SUBTREE);
178 private InstanceIdentifier<VpnInterface> getWildCardPath() {
179 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
183 public void close() throws Exception {
184 if (listenerRegistration != null) {
185 listenerRegistration.close();
186 listenerRegistration = null;
188 LOG.info("{} close", getClass().getSimpleName());
191 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
192 return InstanceIdentifier.create(InterfacesState.class)
193 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
197 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
198 LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
199 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
200 final String interfaceName = key.getName();
202 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
203 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
204 if(interfaceState != null){
206 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
207 final int ifIndex = interfaceState.getIfIndex();
208 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
209 dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
210 new Callable<List<ListenableFuture<Void>>>() {
212 public List<ListenableFuture<Void>> call() throws Exception {
213 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
214 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
215 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
216 processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeConfigTxn, writeOperTxn, writeInvTxn);
217 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
220 } catch (InterruptedException | ExecutionException e) {
221 LOG.error("Error adding oper data for interface {} to vpn {} on dpn {}", interfaceName,
222 vpnInterface.getVpnInstanceName(), dpnId);
223 throw new RuntimeException(e.getMessage());
225 futures = writeConfigTxn.submit();
228 } catch (InterruptedException | ExecutionException e) {
229 LOG.error("Error adding config data for interface {} to vpn {} on dpn {}", interfaceName,
230 vpnInterface.getVpnInstanceName(), dpnId);
231 throw new RuntimeException(e.getMessage());
233 futures = writeInvTxn.submit();
236 } catch (InterruptedException | ExecutionException e) {
237 LOG.error("Error adding inventory/flow data for interface {} to vpn {} on dpn {}", interfaceName,
238 vpnInterface.getVpnInstanceName(), dpnId);
239 throw new RuntimeException(e.getMessage());
244 }catch (Exception e){
245 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
249 LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
253 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
254 final int lPortTag, boolean isInterfaceUp,
255 WriteTransaction writeConfigTxn,
256 WriteTransaction writeOperTxn,
257 WriteTransaction writeInvTxn) {
259 final String interfaceName = vpnInterface.getName();
260 if (!isInterfaceUp) {
261 final String vpnName = vpnInterface.getVpnInstanceName();
262 LOG.info("Binding vpn service to interface {} ", interfaceName);
263 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
264 if (vpnId == VpnConstants.INVALID_ID) {
265 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
268 boolean waitForVpnInterfaceOpRemoval = false;
269 VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
270 if (opVpnInterface != null ) {
271 String opVpnName = opVpnInterface.getVpnInstanceName();
272 String primaryInterfaceIp = null;
273 if(opVpnName.equals(vpnName)) {
274 // Please check if the primary VRF Entry does not exist for VPNInterface
275 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
277 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
278 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
280 LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
283 for (Adjacency adj : adjs) {
284 if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
285 primaryInterfaceIp = adj.getIpAddress();
289 if (primaryInterfaceIp == null) {
290 LOG.info("VPN Interface {} addition failed as primary adjacency "
291 + "for this vpn interface could not be obtained", interfaceName);
294 // Get the rd of the vpn instance
295 String rd = getRouteDistinguisher(opVpnName);
296 rd = (rd == null) ? opVpnName : rd;
297 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, rd, primaryInterfaceIp);
299 LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
302 waitForVpnInterfaceOpRemoval = true;
304 LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
305 interfaceName, vpnName, opVpnName);
308 if (!waitForVpnInterfaceOpRemoval) {
309 // Add the VPNInterface and quit
310 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
311 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
312 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
316 // FIB didn't get a chance yet to clean up this VPNInterface
317 // Let us give it a chance here !
318 LOG.info("VPN Interface {} waiting for FIB to clean up! ", interfaceName);
320 Runnable notifyTask = new VpnNotifyTask();
321 vpnIntfMap.put(interfaceName, notifyTask);
322 synchronized (notifyTask) {
324 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
325 } catch (InterruptedException e) {
329 vpnIntfMap.remove(interfaceName);
332 opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
333 if (opVpnInterface != null) {
334 LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
337 // VPNInterface got removed, proceed with Add
338 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
339 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
340 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
342 // Interface is retained in the DPN, but its Link Up.
343 // Advertise prefixes again for this interface to BGP
344 advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
350 // private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
353 // String interfaceName;
357 // public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
358 // int lPortTag, boolean addToDpn) {
359 // this.dpnId= dpnId;
360 // this.vpnName = vpnName;
361 // this.interfaceName = interfaceName;
362 // this.lPortTag = lPortTag;
363 // this.addToDpn = addToDpn;
367 // public List<ListenableFuture<Void>> call() throws Exception {
368 // // If another renderer(for eg : CSS) needs to be supported, check can be performed here
369 // // to call the respective helpers.
370 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
371 // updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
372 // List<ListenableFuture<Void>> futures = new ArrayList<>();
373 // futures.add(writeTxn.submit());
374 // ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
375 // Futures.addCallback(listenableFuture,
376 // new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
383 // * JobCallback class is used as a future callback for
384 // * main and rollback workers to handle success and failure.
386 // private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
389 // String interfaceName;
393 // public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
394 // int lPortTag, boolean addToDpn) {
395 // this.dpnId= dpnId;
396 // this.vpnName = vpnName;
397 // this.interfaceName = interfaceName;
398 // this.lPortTag = lPortTag;
399 // this.addToDpn = addToDpn;
404 // * This implies that all the future instances have returned success. -- TODO: Confirm this
407 // public void onSuccess(List<Void> voids) {
408 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
409 // bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
410 // processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
411 // writeTxn.submit();
416 // * @param throwable
417 // * This method is used to handle failure callbacks.
418 // * If more retry needed, the retrycount is decremented and mainworker is executed again.
419 // * After retries completed, rollbackworker is executed.
420 // * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
424 // public void onFailure(Throwable throwable) {
425 // LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
430 private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
433 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
434 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
436 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
438 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
439 intf.getName(), intf.getVpnInstanceName());
442 if (rd.equals(intf.getVpnInstanceName())) {
443 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} as it is in " +
444 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
449 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} in vpn {} with rd {} ", intf.getName(),
450 intf.getVpnInstanceName(), rd);
452 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
453 if (nextHopIp == null){
454 LOG.trace("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} is null, returning", intf.getName());
458 if (adjacencies.isPresent()) {
459 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
461 if (!nextHops.isEmpty()) {
462 LOG.trace("NextHops are " + nextHops);
463 for (Adjacency nextHop : nextHops) {
464 long label = nextHop.getLabel();
466 LOG.info("VPN ADVERTISE: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
467 bgpManager.advertisePrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
468 LOG.info("VPN ADVERTISE: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
469 } catch(Exception e) {
470 LOG.error("Failed to advertise prefix {} in vpn {} with rd {} for interface {} ",
471 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
478 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
480 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
481 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
483 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
485 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
486 intf.getName(), intf.getVpnInstanceName());
489 if (rd.equals(intf.getVpnInstanceName())) {
490 LOG.info("withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in " +
491 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
495 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", intf.getName(),
496 intf.getVpnInstanceName(), rd);
497 if (adjacencies.isPresent()) {
498 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
500 if (!nextHops.isEmpty()) {
501 LOG.trace("NextHops are " + nextHops);
502 for (Adjacency nextHop : nextHops) {
504 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
505 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
506 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
507 } catch(Exception e) {
508 LOG.error("Failed to withdraw prefix {} in vpn {} with rd {} for interface {} ",
509 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
516 public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
517 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
519 dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
521 if(!dpId.equals(BigInteger.ZERO)) {
523 createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
525 removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
529 private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag,
530 WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
531 int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
532 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
534 int instructionKey = 0;
535 List<Instruction> instructions = new ArrayList<Instruction>();
537 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(MetaDataUtil.getVpnIdMetadata(vpnId),
538 MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
539 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
541 short l3vpn_service_index = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX);
544 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
545 l3vpn_service_index, priority,
546 NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
547 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION,
548 InterfaceUtils.buildServiceId(vpnInterfaceName, l3vpn_service_index), serviceInfo, true);
549 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
550 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeInvTxn);
551 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
552 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeInvTxn);
556 private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
557 WriteTransaction writeConfigTxn,
558 WriteTransaction writeOperTxn) {
559 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
561 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
562 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
564 if (adjacencies.isPresent()) {
565 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
566 List<Adjacency> value = new ArrayList<>();
568 // Get the rd of the vpn instance
569 String rd = getRouteDistinguisher(vpnName);
571 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
572 if (nextHopIp == null){
573 LOG.error("NextHop for interface {} is null", interfaceName);
577 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
579 LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
580 for (Adjacency nextHop : nextHops) {
581 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
582 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
583 VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
585 List<String> adjNextHop = nextHop.getNextHopIpList();
586 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
587 (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
588 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
590 if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
591 LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
593 LogicalDatastoreType.OPERATIONAL,
594 VpnUtil.getPrefixToInterfaceIdentifier(
595 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
596 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
598 //Extra route adjacency
599 LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
601 LogicalDatastoreType.OPERATIONAL,
602 VpnUtil.getVpnToExtrarouteIdentifier(
603 (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
604 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
608 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
610 VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
611 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
612 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
613 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
615 for (Adjacency nextHop : aug.getAdjacency()) {
616 long label = nextHop.getLabel();
617 List<String> nextHopList = new ArrayList<>(nextHop.getNextHopIpList());
619 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nextHopList, vpnId,
620 interfaceName, null,false, rd, writeOperTxn);
621 addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeConfigTxn);
622 //TODO: ERT - check for VPNs importing my route
623 for (VpnInstance vpn : vpnsToImportRoute) {
624 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
626 LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
627 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), Arrays.asList(nextHopIp), (int) label,
628 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
632 // ### add FIB route directly
633 fibManager.addOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), Arrays.asList(nextHopIp),
634 (int) label, RouteOrigin.STATIC, writeConfigTxn);
640 private List<VpnInstance> getVpnsImportingMyRoute(final String vpnName) {
641 List<VpnInstance> vpnsToImportRoute = new ArrayList<>();
643 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
644 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
645 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
646 final VpnInstance vpnInstance;
647 if (optVpnInstance.isPresent()) {
648 vpnInstance = optVpnInstance.get();
650 LOG.debug("Could not retrieve vpn instance {} to check for vpns importing the routes", vpnName);
651 return vpnsToImportRoute;
654 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
656 public boolean apply(VpnInstance input) {
657 return !input.getVpnInstanceName().equals(vpnName);
661 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
663 public boolean apply(VpnInstance input) {
664 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ExportExtcommunity),
665 getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
666 return Iterators.size(commonRTs.iterator()) > 0;
670 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
672 public String apply(VpnInstance vpnInstance) {
673 //return vpnInstance.getVpnInstanceName();
674 return vpnInstance.getIpv4Family().getRouteDistinguisher();
678 vpnsToImportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
680 filter(matchRTs).toList();
681 return vpnsToImportRoute;
684 private List<VpnInstance> getVpnsExportingMyRoute(final String vpnName) {
685 List<VpnInstance> vpnsToExportRoute = new ArrayList<>();
687 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
688 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
689 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
690 final VpnInstance vpnInstance;
691 if (optVpnInstance.isPresent()) {
692 vpnInstance = optVpnInstance.get();
694 LOG.debug("Could not retrieve vpn instance {} to check for vpns exporting the routes", vpnName);
695 return vpnsToExportRoute;
698 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
700 public boolean apply(VpnInstance input) {
701 return !input.getVpnInstanceName().equals(vpnName);
705 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
707 public boolean apply(VpnInstance input) {
708 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity),
709 getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
710 return Iterators.size(commonRTs.iterator()) > 0;
714 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
716 public String apply(VpnInstance vpnInstance) {
717 return vpnInstance.getVpnInstanceName();
721 vpnsToExportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
723 filter(matchRTs).toList();
724 return vpnsToExportRoute;
727 private <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
728 final Predicate<T> inPredicate = Predicates.<T>in(collection2);
729 return new Iterable<T>() {
731 public Iterator<T> iterator() {
732 return Iterators.filter(collection1.iterator(), inPredicate);
737 private List<String> getRts(VpnInstance vpnInstance, VpnTarget.VrfRTType rtType) {
738 String name = vpnInstance.getVpnInstanceName();
739 List<String> rts = new ArrayList<>();
740 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
741 if (vpnConfig == null) {
742 LOG.trace("vpn config is not available for {}", name);
745 VpnTargets targets = vpnConfig.getVpnTargets();
746 if (targets == null) {
747 LOG.trace("vpn targets not available for {}", name);
750 List<VpnTarget> vpnTargets = targets.getVpnTarget();
751 if (vpnTargets == null) {
752 LOG.trace("vpnTarget values not available for {}", name);
755 for (VpnTarget target : vpnTargets) {
756 //TODO: Check for RT type is Both
757 if(target.getVrfRTType().equals(rtType) ||
758 target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
759 String rtValue = target.getVrfRTValue();
766 private List<String> getExportRts(VpnInstance vpnInstance) {
767 List<String> exportRts = new ArrayList<>();
768 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
769 VpnTargets targets = vpnConfig.getVpnTargets();
770 List<VpnTarget> vpnTargets = targets.getVpnTarget();
771 for (VpnTarget target : vpnTargets) {
772 if (target.getVrfRTType().equals(VpnTarget.VrfRTType.ExportExtcommunity)) {
773 String rtValue = target.getVrfRTValue();
774 exportRts.add(rtValue);
780 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
781 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow,
782 WriteTransaction writeConfigTxn){
783 List<MatchInfo> matches = new ArrayList<MatchInfo>();
784 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, MetaDataUtil.getVpnIdMetadata(vpnId));
785 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
786 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
788 // Matching Arp reply flows
789 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
790 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
791 metadata, metadataMask }));
793 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
795 // Instruction to punt to controller
796 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
797 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
798 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
799 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
800 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
802 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
804 // Install the flow entry in L3_INTERFACE_TABLE
805 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
806 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
807 FlowEntity flowEntity;
808 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
809 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
810 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
812 Flow flow = flowEntity.getFlowBuilder().build();
813 String flowId = flowEntity.getFlowId();
814 FlowKey flowKey = new FlowKey( new FlowId(flowId));
815 Node nodeDpn = buildDpnNode(dpId);
817 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
818 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
819 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
821 if (writeConfigTxn != null) {
822 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
823 LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
824 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
826 LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
827 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
830 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
831 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
832 mdsalManager.installFlow(flowEntity);
834 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
835 mdsalManager.removeFlow(flowEntity);
840 //TODO: How to handle the below code, its a copy paste from MDSALManager.java
841 private Node buildDpnNode(BigInteger dpnId) {
842 NodeId nodeId = new NodeId("openflow:" + dpnId);
843 Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
848 private String getRouteDistinguisher(String vpnName) {
849 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
850 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
851 Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
853 if(vpnInstance.isPresent()) {
854 VpnInstance instance = vpnInstance.get();
855 VpnAfConfig config = instance.getIpv4Family();
856 rd = config.getRouteDistinguisher();
861 private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
862 String routeDistinguisher = getRouteDistinguisher(vpnName);
863 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
864 Boolean newDpnOnVpn = Boolean.FALSE;
866 synchronized (vpnName.intern()) {
867 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
868 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
869 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
870 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
871 .entry.vpn.to.dpn.list.VpnInterfaces
872 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
874 if (dpnInVpn.isPresent()) {
875 if (writeTxn != null) {
876 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id.child(
877 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
878 .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
879 new VpnInterfacesKey(intfName)), vpnInterface, true);
881 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
882 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance
883 .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
884 new VpnInterfacesKey(intfName)), vpnInterface);
887 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
888 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
889 vpnInterfaces.add(vpnInterface);
890 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
891 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
893 if (writeTxn != null) {
894 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
896 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
898 newDpnOnVpn = Boolean.TRUE;
900 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
903 } catch (InterruptedException | ExecutionException e) {
904 LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
905 throw new RuntimeException(e.getMessage());
908 * Informing the Fib only after writeTxn is submitted successfuly.
911 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
912 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
913 publishAddNotification(dpnId, vpnName, rd);
918 private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
919 Boolean lastDpnOnVpn = Boolean.FALSE;
921 synchronized (vpnName.intern()) {
922 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
923 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
924 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
925 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
926 if (dpnInVpn.isPresent()) {
927 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
928 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
929 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
930 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
932 if (vpnInterfaces.remove(currVpnInterface)) {
933 if (vpnInterfaces.isEmpty()) {
934 List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
935 if (ipAddresses == null || ipAddresses.isEmpty()) {
936 VpnToDpnListBuilder dpnInVpnBuilder =
937 new VpnToDpnListBuilder(dpnInVpn.get())
938 .setDpnState(VpnToDpnList.DpnState.Inactive)
939 .setVpnInterfaces(null);
940 if (writeTxn != null) {
941 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
943 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
945 lastDpnOnVpn = Boolean.TRUE;
947 LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
950 if (writeTxn != null) {
951 writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
952 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
953 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
954 new VpnInterfacesKey(intfName)));
956 VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
957 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
958 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
959 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
964 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
967 } catch (InterruptedException | ExecutionException e) {
968 LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
969 throw new RuntimeException(e.getMessage());
972 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
973 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
974 publishRemoveNotification(dpnId, vpnName, rd);
979 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
980 List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
981 for (VpnInstance vpn : vpnsToExportRoute) {
982 String rd = vpn.getIpv4Family().getRouteDistinguisher();
983 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getIpv4Family().getRouteDistinguisher());
984 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
985 if (vrfEntries != null) {
986 for (VrfEntry vrfEntry : vrfEntries) {
988 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) {
991 String prefix = vrfEntry.getDestPrefix();
992 long label = vrfEntry.getLabel();
993 List<String> nextHops = vrfEntry.getNextHopAddressList();
994 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
995 for (String nh : nextHops) {
997 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
998 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route, writeConfigTxn);
1000 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1001 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, prefix, Arrays.asList(nh), (int)label,
1002 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
1005 } catch (Exception e) {
1006 LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
1009 writeConfigTxn.submit();
1011 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
1016 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeConfigTxn) {
1018 LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1019 fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC, writeConfigTxn);
1020 bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
1021 LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1022 } catch(Exception e) {
1023 LOG.error("Add prefix failed", e);
1028 public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1029 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
1030 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1031 final String interfaceName = key.getName();
1033 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1034 final Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1035 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
1036 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1037 if (optVpnInterface.isPresent()){
1038 BigInteger dpnId = BigInteger.ZERO;
1039 Boolean dpnIdRetrieved = Boolean.FALSE;
1040 if(interfaceState != null){
1042 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1043 dpnIdRetrieved = Boolean.TRUE;
1044 }catch (Exception e){
1045 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
1048 LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
1051 final VpnInterface vpnOpInterface = optVpnInterface.get();
1052 if(dpnIdRetrieved == Boolean.FALSE){
1053 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
1054 dpnId = vpnOpInterface.getDpnId();
1056 final int ifIndex = interfaceState.getIfIndex();
1057 final BigInteger dpId = dpnId;
1058 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1059 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1060 new Callable<List<ListenableFuture<Void>>>() {
1062 public List<ListenableFuture<Void>> call() throws Exception {
1063 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1064 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1065 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
1066 processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeConfigTxn, writeOperTxn, writeInvTxn);
1067 CheckedFuture<Void, TransactionCommitFailedException> futures = writeOperTxn.submit();
1070 } catch (InterruptedException | ExecutionException e) {
1071 LOG.error("Error removing Oper data for interface {} from vpn {} on dpn {}", interfaceName,
1072 vpnOpInterface.getVpnInstanceName(), dpId);
1073 throw new RuntimeException(e.getMessage());
1075 futures = writeConfigTxn.submit();
1078 } catch (InterruptedException | ExecutionException e) {
1079 LOG.error("Error removing Config data for interface {} from vpn {} on dpn {}", interfaceName,
1080 vpnOpInterface.getVpnInstanceName(), dpId);
1081 throw new RuntimeException(e.getMessage());
1083 futures = writeInvTxn.submit();
1086 } catch (InterruptedException | ExecutionException e) {
1087 LOG.error("Error removing Inventory/Flow data for interface {} from vpn {} on dpn {}", interfaceName,
1088 vpnOpInterface.getVpnInstanceName(), dpId);
1089 throw new RuntimeException(e.getMessage());
1096 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
1100 protected void processVpnInterfaceDown(BigInteger dpId,
1101 String interfaceName,
1103 boolean isInterfaceStateDown,
1104 boolean isConfigRemoval,
1105 WriteTransaction writeConfigTxn,
1106 WriteTransaction writeOperTxn,
1107 WriteTransaction writeInvTxn) {
1108 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1109 if (!isInterfaceStateDown) {
1110 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1111 if(vpnInterface == null){
1112 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
1115 final String vpnName = vpnInterface.getVpnInstanceName();
1116 if(!vpnInterface.isScheduledForRemove()){
1117 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE, writeOperTxn);
1118 removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeConfigTxn);
1119 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
1120 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeConfigTxn, writeInvTxn);
1122 LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
1127 // Interface is retained in the DPN, but its Link Down.
1128 // Only withdraw the prefixes for this interface from BGP
1129 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1130 if(vpnInterface == null){
1131 LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
1134 withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
1139 private void waitForFibToRemoveVpnPrefix(String interfaceName) {
1140 // FIB didn't get a chance yet to clean up this VPNInterface
1141 // Let us give it a chance here !
1142 LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
1144 Runnable notifyTask = new VpnNotifyTask();
1145 vpnIntfMap.put(interfaceName, notifyTask);
1146 synchronized (notifyTask) {
1148 notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
1149 } catch (InterruptedException e) {
1153 vpnIntfMap.remove(interfaceName);
1157 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
1158 WriteTransaction writeConfigTxn) {
1160 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1161 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1162 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1164 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1165 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
1167 if (adjacencies.isPresent()) {
1168 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1170 if (!nextHops.isEmpty()) {
1171 LOG.trace("NextHops are " + nextHops);
1172 for (Adjacency nextHop : nextHops) {
1173 List<String> nhList = new ArrayList<String>();
1174 if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
1175 // This is either an extra-route (or) a learned IP via subnet-route
1176 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1177 if (nextHopIp == null || nextHopIp.isEmpty()) {
1178 LOG.error("Unable to obtain nextHopIp for extra-route/learned-route in rd {} prefix {}",
1179 rd, nextHop.getIpAddress());
1182 nhList = Arrays.asList(nextHopIp);
1184 // This is a primary adjacency
1185 nhList = nextHop.getNextHopIpList();
1187 if (rd.equals(vpnName)) {
1188 //this is an internal vpn - the rd is assigned to the vpn instance name;
1189 //remove from FIB directly
1190 for(String nh : nhList) {
1191 fibManager.removeOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), nh, writeConfigTxn);
1194 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1195 for (String nh : nhList) {
1196 //IRT: remove routes from other vpns importing it
1197 removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
1198 for (VpnInstance vpn : vpnsToImportRoute) {
1199 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
1200 if (vpnRd != null) {
1201 LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
1202 fibManager.removeOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), nh, writeConfigTxn);
1207 String ip = nextHop.getIpAddress().split("/")[0];
1208 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
1210 if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
1211 LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
1212 vpnPortipToPort.getPortName(),ip);
1213 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip);
1221 private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
1222 int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
1223 WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
1224 short l3vpn_service_index = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX);
1225 if (!isInterfaceStateDown && isConfigRemoval) {
1226 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION,
1227 InterfaceUtils.buildServiceId(vpnInterfaceName,
1228 l3vpn_service_index));
1230 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
1231 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1232 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeInvTxn);
1233 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1234 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeInvTxn);
1238 private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeConfigTxn) {
1240 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
1241 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, nextHop, writeConfigTxn);
1242 bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
1243 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
1244 } catch(Exception e) {
1245 LOG.error("Delete prefix failed", e);
1250 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1251 LOG.trace("Updating VPN Interface : key {}, original value={}, update value={}", identifier, original, update);
1252 String oldVpnName = original.getVpnInstanceName();
1253 String newVpnName = update.getVpnInstanceName();
1254 BigInteger dpnId = update.getDpnId();
1255 List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
1256 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
1257 if (oldAdjs == null) {
1258 oldAdjs = new ArrayList<>();
1260 if (newAdjs == null) {
1261 newAdjs = new ArrayList<>();
1263 //handles switching between <internal VPN - external VPN>
1264 if (!oldVpnName.equals(newVpnName)) {
1265 remove(identifier, original);
1266 waitForFibToRemoveVpnPrefix(update.getName());
1267 add(identifier, update);
1269 //handle both addition and removal of adjacencies
1270 //currently, new adjacency may be an extra route
1271 if (!oldAdjs.equals(newAdjs)) {
1272 for (Adjacency adj : newAdjs) {
1273 if (oldAdjs.contains(adj)) {
1274 oldAdjs.remove(adj);
1276 // add new adjacency - right now only extra route will hit this path
1277 addNewAdjToVpnInterface(identifier, adj, dpnId);
1280 for (Adjacency adj : oldAdjs) {
1281 delAdjFromVpnInterface(identifier, adj, dpnId);
1286 public void processArpRequest(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
1287 .IpAddress srcIP, PhysAddress srcMac, org.opendaylight.yang.gen.v1.urn.ietf
1288 .params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, PhysAddress targetMac, String srcInterface){
1289 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
1290 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
1291 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
1292 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
1293 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
1294 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
1296 public void onFailure(Throwable error) {
1297 LOG.error("Error - {}", msgFormat, error);
1301 public void onSuccess(RpcResult<Void> result) {
1302 if(!result.isSuccessful()) {
1303 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
1305 LOG.debug("Successful RPC Result - {}", msgFormat);
1311 private String getErrorText(Collection<RpcError> errors) {
1312 StringBuilder errorText = new StringBuilder();
1313 for(RpcError error : errors) {
1314 errorText.append(",").append(error.getErrorType()).append("-")
1315 .append(error.getMessage());
1317 return errorText.toString();
1320 private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
1321 String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd,
1322 WriteTransaction writeOperTxn) {
1323 Preconditions.checkNotNull(label, "label cannot be null or empty!");
1324 Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
1325 Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
1326 Preconditions.checkNotNull(rd, "rd cannot be null or empty!");
1327 if (!isSubnetRoute) {
1328 // NextHop must be present for non-subnetroute entries
1329 Preconditions.checkNotNull(nextHopIpList, "nextHopIp cannot be null or empty!");
1331 LOG.info("Adding to label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} vpnIntfcName {} rd {}", label, dpnId, prefix, nextHopIpList, vpnId, vpnInterfaceName, rd);
1332 if (dpnId != null) {
1333 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1334 .child(LabelRouteInfo.class, new LabelRouteInfoKey((long)label)).build();
1335 LabelRouteInfoBuilder lriBuilder = new LabelRouteInfoBuilder();
1336 lriBuilder.setLabel(label).setDpnId(dpnId).setPrefix(prefix).setNextHopIpList(nextHopIpList).setParentVpnid(vpnId)
1337 .setIsSubnetRoute(isSubnetRoute);
1338 if (elanTag != null) {
1339 lriBuilder.setElanTag(elanTag);
1341 if (vpnInterfaceName != null) {
1342 lriBuilder.setVpnInterfaceName(vpnInterfaceName);
1344 lriBuilder.setParentVpnRd(rd);
1345 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
1346 if (vpnInstanceOpDataEntry != null) {
1347 List<String> vpnInstanceNames = Arrays.asList(vpnInstanceOpDataEntry.getVpnInstanceName());
1348 lriBuilder.setVpnInstanceList(vpnInstanceNames);
1350 LabelRouteInfo lri = lriBuilder.build();
1351 LOG.trace("Adding route info to label map: {}", lri);
1352 if (writeOperTxn != null) {
1353 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, lriIid, lri, true);
1355 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
1358 LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
1362 public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
1363 long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
1364 SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
1365 RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
1366 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1367 .setLabel((long)label).setOrigin(origin.getValue())
1368 .addAugmentation(SubnetRoute.class, route).build();
1370 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
1372 //TODO: What should be parentVpnId? Get it from RD?
1373 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1374 addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd, null);
1375 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1377 InstanceIdentifierBuilder<VrfTables> idBuilder =
1378 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1379 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1381 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1382 setVrfEntry(vrfEntryList).build();
1384 if (writeTxn != null) {
1385 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1387 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1390 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1391 if (vpnsToImportRoute.size() > 0) {
1392 VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1393 .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
1394 .addAugmentation(SubnetRoute.class, route).build();
1395 List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
1396 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1397 LOG.info("Exporting subnet route rd {} prefix {} nexthop {} label {} to vpn {}", rd, prefix, nextHop, label, vpnInstance.getVpnInstanceName());
1398 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1399 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
1400 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
1401 if (writeTxn != null) {
1402 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
1404 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
1410 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1411 SubnetRoute route, WriteTransaction writeConfigTxn) {
1413 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1414 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1415 .setLabel((long)label).setOrigin(origin.getValue())
1416 .addAugmentation(SubnetRoute.class, route).build();
1417 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, route.getElantag());
1418 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1419 InstanceIdentifierBuilder<VrfTables> idBuilder =
1420 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1421 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1422 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1423 setVrfEntry(vrfEntryList).build();
1424 if (writeConfigTxn != null) {
1425 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1427 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1431 public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
1432 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, null /* nextHopToRemove */, null);
1433 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1434 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1435 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1436 LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
1437 fibManager.removeOrUpdateFibEntry(dataBroker, importingRd, prefix, null /* nextHopToRemove */, null);
1441 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1443 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1445 if (optVpnInterface.isPresent()) {
1446 VpnInterface currVpnIntf = optVpnInterface.get();
1447 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1448 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1449 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
1450 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath);
1452 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1453 VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
1455 List<Adjacency> adjacencies;
1456 if (optAdjacencies.isPresent()) {
1457 adjacencies = optAdjacencies.get().getAdjacency();
1459 //This code will not be hit since VM adjacency will always be there
1460 adjacencies = new ArrayList<>();
1463 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
1464 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
1466 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1467 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
1469 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1470 for (String nh : adj.getNextHopIpList()) {
1471 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
1472 currVpnIntf.getName());
1477 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1478 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1480 if (optVpnInterface.isPresent()) {
1481 VpnInterface currVpnIntf = optVpnInterface.get();
1483 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1484 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1485 if (optAdjacencies.isPresent()) {
1486 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1488 if (!adjacencies.isEmpty()) {
1489 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1490 LOG.trace("Adjacencies are " + adjacencies);
1491 Iterator<Adjacency> adjIt = adjacencies.iterator();
1492 while (adjIt.hasNext()) {
1493 Adjacency adjElem = adjIt.next();
1494 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1497 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1498 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
1499 currVpnIntf.getVpnInstanceName(),
1500 aug, dpnId, currVpnIntf.isScheduledForRemove());
1502 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1504 for (String nh : adj.getNextHopIpList()) {
1505 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
1506 currVpnIntf.getName());
1518 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label,
1521 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
1524 LogicalDatastoreType.OPERATIONAL,
1525 VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
1526 VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
1528 BigInteger dpnId = null;
1529 if (intfName != null && !intfName.isEmpty()) {
1530 dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1531 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1532 if (nextHopIp == null || nextHopIp.isEmpty()) {
1533 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1534 intfName, destination);
1537 nextHop = nextHopIp;
1539 List<String> nextHopIpList = Arrays.asList(nextHop);
1541 /* Label mapper is required only for BGP VPN and not for Internal VPN */
1542 addToLabelMapper((long) label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(dataBroker, routerID),
1543 intfName, null, false, rd, null);
1546 // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
1547 // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
1549 InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
1550 if ( interVpnLink != null ) {
1551 // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
1552 // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
1553 // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
1554 // This is like leaking one of the Vpn2 routes towards Vpn1
1555 boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
1556 String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
1557 : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
1558 String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
1559 : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
1560 String dstVpnRd = VpnUtil.getVpnRd(dataBroker, dstVpnUuid);
1561 long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1562 VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
1563 VpnUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
1566 addPrefixToBGP(rd, destination, nextHop, label, null);
1568 // ### add FIB route directly
1569 fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, Arrays.asList(nextHop), label, RouteOrigin.STATIC, null);
1574 protected void delExtraRoute(String destination, String nextHop, String rd, String routerID, String intfName) {
1575 if (intfName != null && !intfName.isEmpty()) {
1576 BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1577 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1578 if (nextHopIp == null || nextHopIp.isEmpty()) {
1579 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1580 intfName, destination);
1582 nextHop = nextHopIp;
1586 removePrefixFromBGP(rd, destination, nextHop, null);
1588 // ### add FIB route directly
1589 fibManager.removeOrUpdateFibEntry(dataBroker, routerID, destination, nextHop, null);
1593 void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1594 LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
1595 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1596 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
1597 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1598 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1600 public void onFailure(Throwable error) {
1601 LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
1605 public void onSuccess(Object arg) {
1606 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
1611 void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1612 LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
1613 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1614 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
1615 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1616 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1618 public void onFailure(Throwable error) {
1619 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
1623 public void onSuccess(Object arg) {
1624 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
1629 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1630 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1631 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1632 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1635 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1636 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1637 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1640 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1641 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1642 if(dpId.equals(BigInteger.ZERO)) {
1643 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1646 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1648 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1649 .OPERATIONAL, routerDpnListIdentifier);
1650 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1651 if (optionalRouterDpnList.isPresent()) {
1652 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1653 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1655 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1656 builder.setRouterId(routerName);
1657 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1658 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1659 routerInterfaces.add(routerInterface);
1660 builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
1661 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1662 getRouterId(routerName),
1663 builder.build(), true);
1667 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1668 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1669 if(dpId.equals(BigInteger.ZERO)) {
1670 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1673 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1674 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1675 .OPERATIONAL, routerDpnListIdentifier);
1676 if (optionalRouterDpnList.isPresent()) {
1677 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1678 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1680 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1681 if (routerInterfaces.isEmpty()) {
1682 if (writeOperTxn != null) {
1683 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1685 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1688 if (writeOperTxn != null) {
1689 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1690 RouterInterfaces.class,
1691 new RouterInterfacesKey(vpnInterfaceName)));
1693 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1694 RouterInterfaces.class,
1695 new RouterInterfacesKey(vpnInterfaceName)));
1702 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1703 WriteTransaction writeOperTxn) {
1704 if(dpId.equals(BigInteger.ZERO)) {
1705 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1708 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1709 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1710 .OPERATIONAL, routerDpnListIdentifier);
1711 if (optionalRouterDpnList.isPresent()) {
1712 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1713 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1714 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1715 if (routerInterfaces.isEmpty()) {
1716 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1718 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1719 RouterInterfaces.class,
1720 new RouterInterfacesKey(vpnInterfaceName)));
1726 public void addMIPAdjacency(String vpnName,String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params.xml
1727 .ns.yang.ietf.inet.types.rev130715.IpAddress prefix){
1729 LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
1730 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1731 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1732 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
1733 String nextHopIpAddr = null;
1734 String nextHopMacAddress = null;
1735 String ip = prefix.getIpv4Address().getValue();
1736 if (adjacencies.isPresent()) {
1737 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
1738 ip = VpnUtil.getIpPrefix(ip);
1739 for (Adjacency adjacs : adjacencyList) {
1740 if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
1741 nextHopIpAddr = adjacs.getIpAddress();
1742 nextHopMacAddress = adjacs.getMacAddress();
1746 if (nextHopMacAddress != null && ip != null) {
1747 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1749 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1750 VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnName, ip));
1751 String nextHopIp = nextHopIpAddr.split("/")[0];
1752 Adjacency newAdj = new AdjacencyBuilder().setIpAddress(ip).setKey
1753 (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp)).build();
1754 adjacencyList.add(newAdj);
1755 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
1756 VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface)).
1757 setName(vpnInterface).setVpnInstanceName(vpnName).addAugmentation(Adjacencies.class, aug).build();
1758 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfId, newVpnIntf);
1759 LOG.debug(" Successfully stored subnetroute Adjacency into VpnInterface {}", vpnInterface);
1765 public void removeMIPAdjacency(String vpnName, String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params
1766 .xml.ns.yang.ietf.inet.types.rev130715.IpAddress prefix) {
1767 String ip = VpnUtil.getIpPrefix(prefix.getIpv4Address().getValue());
1768 LOG.trace("Removing {} adjacency from Old VPN Interface {} ",ip,vpnInterface);
1769 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1770 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1771 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1772 if (adjacencies.isPresent()) {
1773 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
1774 child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class)
1775 .child(Adjacency.class, new AdjacencyKey(ip)).build();
1776 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1777 LOG.trace("Successfully Deleted Adjacency into VpnInterface {}", vpnInterface);
1781 void notifyTaskIfRequired(String intfName) {
1782 Runnable notifyTask = vpnIntfMap.remove(intfName);
1783 if (notifyTask == null) {
1786 executorService.execute(notifyTask);