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 LOG.info("VPN Interface add event - intfName {}" ,vpnInterface.getName());
200 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
201 final String interfaceName = key.getName();
203 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
204 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
205 if(interfaceState != null){
207 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
208 final int ifIndex = interfaceState.getIfIndex();
209 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
210 dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
211 new Callable<List<ListenableFuture<Void>>>() {
213 public List<ListenableFuture<Void>> call() throws Exception {
214 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
215 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
216 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
217 processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeConfigTxn, writeOperTxn, writeInvTxn);
218 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
219 futures.add(writeOperTxn.submit());
220 futures.add(writeConfigTxn.submit());
221 futures.add(writeInvTxn.submit());
225 }catch (Exception e){
226 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
230 LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
234 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
235 final int lPortTag, boolean isInterfaceUp,
236 WriteTransaction writeConfigTxn,
237 WriteTransaction writeOperTxn,
238 WriteTransaction writeInvTxn) {
240 final String interfaceName = vpnInterface.getName();
241 if (!isInterfaceUp) {
242 final String vpnName = vpnInterface.getVpnInstanceName();
243 LOG.info("Binding vpn service to interface {} ", interfaceName);
244 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
245 if (vpnId == VpnConstants.INVALID_ID) {
246 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
249 boolean waitForVpnInterfaceOpRemoval = false;
250 VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
251 if (opVpnInterface != null ) {
252 String opVpnName = opVpnInterface.getVpnInstanceName();
253 String primaryInterfaceIp = null;
254 if(opVpnName.equals(vpnName)) {
255 // Please check if the primary VRF Entry does not exist for VPNInterface
256 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
258 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
259 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
261 LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
264 for (Adjacency adj : adjs) {
265 if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
266 primaryInterfaceIp = adj.getIpAddress();
270 if (primaryInterfaceIp == null) {
271 LOG.info("VPN Interface {} addition failed as primary adjacency "
272 + "for this vpn interface could not be obtained", interfaceName);
275 // Get the rd of the vpn instance
276 String rd = getRouteDistinguisher(opVpnName);
277 rd = (rd == null) ? opVpnName : rd;
278 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, rd, primaryInterfaceIp);
280 LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
283 waitForVpnInterfaceOpRemoval = true;
285 LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
286 interfaceName, vpnName, opVpnName);
289 if (!waitForVpnInterfaceOpRemoval) {
290 // Add the VPNInterface and quit
291 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
292 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
293 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
297 // FIB didn't get a chance yet to clean up this VPNInterface
298 // Let us give it a chance here !
299 LOG.info("Trying to add VPN Interface {}, but waiting for FIB to clean up! ", interfaceName);
301 Runnable notifyTask = new VpnNotifyTask();
302 vpnIntfMap.put(interfaceName, notifyTask);
303 synchronized (notifyTask) {
305 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
306 } catch (InterruptedException e) {
310 vpnIntfMap.remove(interfaceName);
313 opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
314 if (opVpnInterface != null) {
315 LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
318 // VPNInterface got removed, proceed with Add
319 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
320 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
321 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
323 // Interface is retained in the DPN, but its Link Up.
324 // Advertise prefixes again for this interface to BGP
325 advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
331 // private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
334 // String interfaceName;
338 // public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
339 // int lPortTag, boolean addToDpn) {
340 // this.dpnId= dpnId;
341 // this.vpnName = vpnName;
342 // this.interfaceName = interfaceName;
343 // this.lPortTag = lPortTag;
344 // this.addToDpn = addToDpn;
348 // public List<ListenableFuture<Void>> call() throws Exception {
349 // // If another renderer(for eg : CSS) needs to be supported, check can be performed here
350 // // to call the respective helpers.
351 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
352 // updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
353 // List<ListenableFuture<Void>> futures = new ArrayList<>();
354 // futures.add(writeTxn.submit());
355 // ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
356 // Futures.addCallback(listenableFuture,
357 // new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
364 // * JobCallback class is used as a future callback for
365 // * main and rollback workers to handle success and failure.
367 // private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
370 // String interfaceName;
374 // public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
375 // int lPortTag, boolean addToDpn) {
376 // this.dpnId= dpnId;
377 // this.vpnName = vpnName;
378 // this.interfaceName = interfaceName;
379 // this.lPortTag = lPortTag;
380 // this.addToDpn = addToDpn;
385 // * This implies that all the future instances have returned success. -- TODO: Confirm this
388 // public void onSuccess(List<Void> voids) {
389 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
390 // bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
391 // processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
392 // writeTxn.submit();
397 // * @param throwable
398 // * This method is used to handle failure callbacks.
399 // * If more retry needed, the retrycount is decremented and mainworker is executed again.
400 // * After retries completed, rollbackworker is executed.
401 // * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
405 // public void onFailure(Throwable throwable) {
406 // LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
413 private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
416 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
417 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
419 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
421 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
422 intf.getName(), intf.getVpnInstanceName());
425 if (rd.equals(intf.getVpnInstanceName())) {
426 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} as it is in " +
427 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
432 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} in vpn {} with rd {} ", intf.getName(),
433 intf.getVpnInstanceName(), rd);
435 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
436 if (nextHopIp == null){
437 LOG.trace("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} is null, returning", intf.getName());
441 if (adjacencies.isPresent()) {
442 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
444 if (!nextHops.isEmpty()) {
445 LOG.trace("NextHops are " + nextHops);
446 for (Adjacency nextHop : nextHops) {
447 long label = nextHop.getLabel();
449 LOG.info("VPN ADVERTISE: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
450 bgpManager.advertisePrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
451 LOG.info("VPN ADVERTISE: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
452 } catch(Exception e) {
453 LOG.error("Failed to advertise prefix {} in vpn {} with rd {} for interface {} ",
454 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
461 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
463 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
464 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
466 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
468 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
469 intf.getName(), intf.getVpnInstanceName());
472 if (rd.equals(intf.getVpnInstanceName())) {
473 LOG.info("withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in " +
474 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
478 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", intf.getName(),
479 intf.getVpnInstanceName(), rd);
480 if (adjacencies.isPresent()) {
481 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
483 if (!nextHops.isEmpty()) {
484 LOG.trace("NextHops are " + nextHops);
485 for (Adjacency nextHop : nextHops) {
487 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
488 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
489 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
490 } catch(Exception e) {
491 LOG.error("Failed to withdraw prefix {} in vpn {} with rd {} for interface {} ",
492 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
499 public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
500 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
502 dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
504 if(!dpId.equals(BigInteger.ZERO)) {
506 createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
508 removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
512 private void bindService(BigInteger dpId, final String vpnInstanceName, final String vpnInterfaceName,
513 int lPortTag, WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
514 final int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
515 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
517 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
518 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
519 new Callable<List<ListenableFuture<Void>>>() {
521 public List<ListenableFuture<Void>> call() throws Exception {
522 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
523 int instructionKey = 0;
524 List<Instruction> instructions = new ArrayList<Instruction>();
526 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(
527 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
528 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
532 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
533 NwConstants.L3VPN_SERVICE_INDEX, priority,
534 NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
535 writeTxn.put(LogicalDatastoreType.CONFIGURATION,
536 InterfaceUtils.buildServiceId(vpnInterfaceName, NwConstants.L3VPN_SERVICE_INDEX), serviceInfo, true);
537 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
538 futures.add(writeTxn.submit());
542 makeArpFlow(dpId, NwConstants.L3VPN_SERVICE_INDEX, lPortTag, vpnInterfaceName,
543 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeInvTxn);
544 makeArpFlow(dpId, NwConstants.L3VPN_SERVICE_INDEX, lPortTag, vpnInterfaceName,
545 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeInvTxn);
549 private void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
550 WriteTransaction writeConfigTxn,
551 WriteTransaction writeOperTxn) {
552 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
554 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
555 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
557 if (adjacencies.isPresent()) {
558 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
559 List<Adjacency> value = new ArrayList<>();
561 // Get the rd of the vpn instance
562 String rd = getRouteDistinguisher(vpnName);
564 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
565 if (nextHopIp == null){
566 LOG.error("NextHop for interface {} is null", interfaceName);
570 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
572 LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
573 for (Adjacency nextHop : nextHops) {
574 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
575 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
576 VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
578 List<String> adjNextHop = nextHop.getNextHopIpList();
579 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
580 (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
581 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
583 if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
584 LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
586 LogicalDatastoreType.OPERATIONAL,
587 VpnUtil.getPrefixToInterfaceIdentifier(
588 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
589 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
591 //Extra route adjacency
592 LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
594 LogicalDatastoreType.OPERATIONAL,
595 VpnUtil.getVpnToExtrarouteIdentifier(
596 (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
597 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
601 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
603 VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
604 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
605 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
606 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
608 for (Adjacency nextHop : aug.getAdjacency()) {
609 long label = nextHop.getLabel();
611 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), Arrays.asList(nextHopIp), vpnId,
612 interfaceName, null,false, rd, writeOperTxn);
613 addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeConfigTxn);
614 //TODO: ERT - check for VPNs importing my route
615 for (VpnInstance vpn : vpnsToImportRoute) {
616 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
618 LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
619 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), Arrays.asList(nextHopIp), (int) label,
620 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
624 // ### add FIB route directly
625 fibManager.addOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), Arrays.asList(nextHopIp),
626 (int) label, RouteOrigin.STATIC, writeConfigTxn);
632 private List<VpnInstance> getVpnsImportingMyRoute(final String vpnName) {
633 List<VpnInstance> vpnsToImportRoute = new ArrayList<>();
635 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
636 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
637 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
638 final VpnInstance vpnInstance;
639 if (optVpnInstance.isPresent()) {
640 vpnInstance = optVpnInstance.get();
642 LOG.debug("Could not retrieve vpn instance {} to check for vpns importing the routes", vpnName);
643 return vpnsToImportRoute;
646 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
648 public boolean apply(VpnInstance input) {
649 return !input.getVpnInstanceName().equals(vpnName);
653 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
655 public boolean apply(VpnInstance input) {
656 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ExportExtcommunity),
657 getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
658 return Iterators.size(commonRTs.iterator()) > 0;
662 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
664 public String apply(VpnInstance vpnInstance) {
665 //return vpnInstance.getVpnInstanceName();
666 return vpnInstance.getIpv4Family().getRouteDistinguisher();
670 vpnsToImportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
672 filter(matchRTs).toList();
673 return vpnsToImportRoute;
676 private List<VpnInstance> getVpnsExportingMyRoute(final String vpnName) {
677 List<VpnInstance> vpnsToExportRoute = new ArrayList<>();
679 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
680 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
681 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
682 final VpnInstance vpnInstance;
683 if (optVpnInstance.isPresent()) {
684 vpnInstance = optVpnInstance.get();
686 LOG.debug("Could not retrieve vpn instance {} to check for vpns exporting the routes", vpnName);
687 return vpnsToExportRoute;
690 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
692 public boolean apply(VpnInstance input) {
693 return !input.getVpnInstanceName().equals(vpnName);
697 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
699 public boolean apply(VpnInstance input) {
700 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity),
701 getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
702 return Iterators.size(commonRTs.iterator()) > 0;
706 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
708 public String apply(VpnInstance vpnInstance) {
709 return vpnInstance.getVpnInstanceName();
713 vpnsToExportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(dataBroker)).
715 filter(matchRTs).toList();
716 return vpnsToExportRoute;
719 private <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
720 final Predicate<T> inPredicate = Predicates.<T>in(collection2);
721 return new Iterable<T>() {
723 public Iterator<T> iterator() {
724 return Iterators.filter(collection1.iterator(), inPredicate);
729 private List<String> getRts(VpnInstance vpnInstance, VpnTarget.VrfRTType rtType) {
730 String name = vpnInstance.getVpnInstanceName();
731 List<String> rts = new ArrayList<>();
732 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
733 if (vpnConfig == null) {
734 LOG.trace("vpn config is not available for {}", name);
737 VpnTargets targets = vpnConfig.getVpnTargets();
738 if (targets == null) {
739 LOG.trace("vpn targets not available for {}", name);
742 List<VpnTarget> vpnTargets = targets.getVpnTarget();
743 if (vpnTargets == null) {
744 LOG.trace("vpnTarget values not available for {}", name);
747 for (VpnTarget target : vpnTargets) {
748 //TODO: Check for RT type is Both
749 if(target.getVrfRTType().equals(rtType) ||
750 target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
751 String rtValue = target.getVrfRTValue();
758 private List<String> getExportRts(VpnInstance vpnInstance) {
759 List<String> exportRts = new ArrayList<>();
760 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
761 VpnTargets targets = vpnConfig.getVpnTargets();
762 List<VpnTarget> vpnTargets = targets.getVpnTarget();
763 for (VpnTarget target : vpnTargets) {
764 if (target.getVrfRTType().equals(VpnTarget.VrfRTType.ExportExtcommunity)) {
765 String rtValue = target.getVrfRTValue();
766 exportRts.add(rtValue);
772 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
773 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow,
774 WriteTransaction writeConfigTxn){
775 List<MatchInfo> matches = new ArrayList<MatchInfo>();
776 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, MetaDataUtil.getVpnIdMetadata(vpnId));
777 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
778 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
780 // Matching Arp reply flows
781 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
782 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
783 metadata, metadataMask }));
785 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
787 // Instruction to punt to controller
788 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
789 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
790 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
791 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
792 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
794 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
796 // Install the flow entry in L3_INTERFACE_TABLE
797 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
798 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
799 FlowEntity flowEntity;
800 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
801 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
802 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
804 Flow flow = flowEntity.getFlowBuilder().build();
805 String flowId = flowEntity.getFlowId();
806 FlowKey flowKey = new FlowKey( new FlowId(flowId));
807 Node nodeDpn = buildDpnNode(dpId);
809 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
810 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
811 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
813 if (writeConfigTxn != null) {
814 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
815 LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
816 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
818 LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
819 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
822 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
823 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
824 mdsalManager.installFlow(flowEntity);
826 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
827 mdsalManager.removeFlow(flowEntity);
832 //TODO: How to handle the below code, its a copy paste from MDSALManager.java
833 private Node buildDpnNode(BigInteger dpnId) {
834 NodeId nodeId = new NodeId("openflow:" + dpnId);
835 Node nodeDpn = new NodeBuilder().setId(nodeId).setKey(new NodeKey(nodeId)).build();
840 private String getRouteDistinguisher(String vpnName) {
841 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
842 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
843 Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
845 if(vpnInstance.isPresent()) {
846 VpnInstance instance = vpnInstance.get();
847 VpnAfConfig config = instance.getIpv4Family();
848 rd = config.getRouteDistinguisher();
854 * JobCallback class is used as a future callback for
855 * main and rollback workers to handle success and failure.
857 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
863 public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
864 this.entered = entered;
866 this.vpnName = vpnName;
872 * This implies that all the future instances have returned success. -- TODO: Confirm this
875 public void onSuccess(List<Void> voids) {
877 publishAddNotification(dpnId, vpnName, rd);
879 publishRemoveNotification(dpnId, vpnName, rd);
886 * This method is used to handle failure callbacks.
887 * If more retry needed, the retrycount is decremented and mainworker is executed again.
888 * After retries completed, rollbackworker is executed.
889 * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
893 public void onFailure(Throwable throwable) {
894 LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
898 private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
899 String routeDistinguisher = getRouteDistinguisher(vpnName);
900 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
901 Boolean newDpnOnVpn = Boolean.FALSE;
903 synchronized (vpnName.intern()) {
904 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
905 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
906 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
907 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
908 .entry.vpn.to.dpn.list.VpnInterfaces
909 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
911 if (dpnInVpn.isPresent()) {
912 VpnToDpnList vpnToDpnList = dpnInVpn.get();
913 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
914 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = vpnToDpnList.getVpnInterfaces();
915 if (vpnInterfaces == null) {
916 vpnInterfaces = new ArrayList<>();
918 vpnInterfaces.add(vpnInterface);
919 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
920 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
921 if (writeTxn != null) {
922 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
924 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
926 /* If earlier state was inactive, it is considered new DPN coming back to the
929 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
930 newDpnOnVpn = Boolean.TRUE;
933 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
934 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
935 vpnInterfaces.add(vpnInterface);
936 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
937 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
939 if (writeTxn != null) {
940 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
942 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
944 newDpnOnVpn = Boolean.TRUE;
946 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
949 } catch (InterruptedException | ExecutionException e) {
950 LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
951 throw new RuntimeException(e.getMessage());
956 * Informing the Fib only after writeTxn is submitted successfuly.
959 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
960 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, true /* entered */));
961 publishAddNotification(dpnId, vpnName, rd);
965 private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
966 Boolean lastDpnOnVpn = Boolean.FALSE;
967 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
968 synchronized (vpnName.intern()) {
969 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
970 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
971 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
972 if (dpnInVpn.isPresent()) {
973 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
974 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
975 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
976 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
978 if (vpnInterfaces.remove(currVpnInterface)) {
979 if (vpnInterfaces.isEmpty()) {
980 List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
981 if (ipAddresses == null || ipAddresses.isEmpty()) {
982 VpnToDpnListBuilder dpnInVpnBuilder =
983 new VpnToDpnListBuilder(dpnInVpn.get())
984 .setDpnState(VpnToDpnList.DpnState.Inactive)
985 .setVpnInterfaces(null);
986 if (writeTxn != null) {
987 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
989 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
991 lastDpnOnVpn = Boolean.TRUE;
993 LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
996 if (writeTxn != null) {
997 writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
998 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
999 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
1000 new VpnInterfacesKey(intfName)));
1002 VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
1003 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1004 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
1005 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
1010 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
1013 } catch (InterruptedException | ExecutionException e) {
1014 LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
1015 throw new RuntimeException(e.getMessage());
1019 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
1020 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
1021 publishRemoveNotification(dpnId, vpnName, rd);
1025 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1026 List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1027 for (VpnInstance vpn : vpnsToExportRoute) {
1028 String rd = vpn.getIpv4Family().getRouteDistinguisher();
1029 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getIpv4Family().getRouteDistinguisher());
1030 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1031 if (vrfEntries != null) {
1032 for (VrfEntry vrfEntry : vrfEntries) {
1034 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) {
1037 String prefix = vrfEntry.getDestPrefix();
1038 long label = vrfEntry.getLabel();
1039 List<String> nextHops = vrfEntry.getNextHopAddressList();
1040 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1041 for (String nh : nextHops) {
1042 if (route != null) {
1043 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1044 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route, writeConfigTxn);
1046 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1047 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, prefix, Arrays.asList(nh), (int)label,
1048 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
1051 } catch (Exception e) {
1052 LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
1055 writeConfigTxn.submit();
1057 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
1062 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeConfigTxn) {
1064 LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1065 fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC, writeConfigTxn);
1066 bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
1067 LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1068 } catch(Exception e) {
1069 LOG.error("Add prefix failed", e);
1074 public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1075 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
1076 LOG.info("VPN Interface remove event - intfName {}" ,vpnInterface.getName());
1077 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1078 final String interfaceName = key.getName();
1080 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1081 final Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1082 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
1083 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1084 if (optVpnInterface.isPresent()){
1085 BigInteger dpnId = BigInteger.ZERO;
1086 Boolean dpnIdRetrieved = Boolean.FALSE;
1087 if(interfaceState != null){
1089 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1090 dpnIdRetrieved = Boolean.TRUE;
1091 }catch (Exception e){
1092 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
1095 LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
1098 final VpnInterface vpnOpInterface = optVpnInterface.get();
1099 if(dpnIdRetrieved == Boolean.FALSE){
1100 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
1101 dpnId = vpnOpInterface.getDpnId();
1103 final int ifIndex = interfaceState.getIfIndex();
1104 final BigInteger dpId = dpnId;
1105 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1106 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1107 new Callable<List<ListenableFuture<Void>>>() {
1109 public List<ListenableFuture<Void>> call() throws Exception {
1110 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1111 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1112 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
1113 processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeConfigTxn, writeOperTxn, writeInvTxn);
1114 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1115 futures.add(writeOperTxn.submit());
1116 futures.add(writeConfigTxn.submit());
1117 futures.add(writeInvTxn.submit());
1123 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
1127 protected void processVpnInterfaceDown(BigInteger dpId,
1128 String interfaceName,
1130 boolean isInterfaceStateDown,
1131 boolean isConfigRemoval,
1132 WriteTransaction writeConfigTxn,
1133 WriteTransaction writeOperTxn,
1134 WriteTransaction writeInvTxn) {
1135 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1136 if (!isInterfaceStateDown) {
1137 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1138 if(vpnInterface == null){
1139 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
1142 final String vpnName = vpnInterface.getVpnInstanceName();
1143 if(!vpnInterface.isScheduledForRemove()){
1144 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE, writeOperTxn);
1145 removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeConfigTxn);
1146 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
1147 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeConfigTxn, writeInvTxn);
1149 LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
1154 // Interface is retained in the DPN, but its Link Down.
1155 // Only withdraw the prefixes for this interface from BGP
1156 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1157 if(vpnInterface == null){
1158 LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
1161 withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
1166 private void waitForFibToRemoveVpnPrefix(String interfaceName) {
1167 // FIB didn't get a chance yet to clean up this VPNInterface
1168 // Let us give it a chance here !
1169 LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
1171 Runnable notifyTask = new VpnNotifyTask();
1172 vpnIntfMap.put(interfaceName, notifyTask);
1173 synchronized (notifyTask) {
1175 notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
1176 } catch (InterruptedException e) {
1180 vpnIntfMap.remove(interfaceName);
1184 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
1185 WriteTransaction writeConfigTxn) {
1187 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1188 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1189 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1191 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1192 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
1194 if (adjacencies.isPresent()) {
1195 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1197 if (!nextHops.isEmpty()) {
1198 LOG.trace("NextHops are " + nextHops);
1199 for (Adjacency nextHop : nextHops) {
1200 List<String> nhList = new ArrayList<String>();
1201 if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
1202 // This is either an extra-route (or) a learned IP via subnet-route
1203 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1204 if (nextHopIp == null || nextHopIp.isEmpty()) {
1205 LOG.error("Unable to obtain nextHopIp for extra-route/learned-route in rd {} prefix {}",
1206 rd, nextHop.getIpAddress());
1209 nhList = Arrays.asList(nextHopIp);
1211 // This is a primary adjacency
1212 nhList = nextHop.getNextHopIpList();
1214 if (rd.equals(vpnName)) {
1215 //this is an internal vpn - the rd is assigned to the vpn instance name;
1216 //remove from FIB directly
1217 for(String nh : nhList) {
1218 fibManager.removeOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), nh, writeConfigTxn);
1221 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1222 for (String nh : nhList) {
1223 //IRT: remove routes from other vpns importing it
1224 removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
1225 for (VpnInstance vpn : vpnsToImportRoute) {
1226 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
1227 if (vpnRd != null) {
1228 LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
1229 fibManager.removeOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), nh, writeConfigTxn);
1234 String ip = nextHop.getIpAddress().split("/")[0];
1235 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
1237 if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
1238 LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
1239 vpnPortipToPort.getPortName(),ip);
1240 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip);
1248 private void unbindService(BigInteger dpId, String vpnInstanceName, final String vpnInterfaceName,
1249 int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
1250 WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
1251 short l3vpn_service_index = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX);
1252 if (!isInterfaceStateDown && isConfigRemoval) {
1253 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1254 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
1255 new Callable<List<ListenableFuture<Void>>>() {
1257 public List<ListenableFuture<Void>> call() throws Exception {
1258 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
1259 writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
1260 InterfaceUtils.buildServiceId(vpnInterfaceName,
1261 NwConstants.L3VPN_SERVICE_INDEX));
1263 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1264 futures.add(writeTxn.submit());
1269 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
1270 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1271 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeInvTxn);
1272 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1273 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeInvTxn);
1277 private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeConfigTxn) {
1279 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
1280 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, nextHop, writeConfigTxn);
1281 bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
1282 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
1283 } catch(Exception e) {
1284 LOG.error("Delete prefix failed", e);
1289 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1290 LOG.trace("Updating VPN Interface : key {}, original value={}, update value={}", identifier, original, update);
1291 LOG.info("VPN Interface update event - intfName {}" ,update.getName());
1292 String oldVpnName = original.getVpnInstanceName();
1293 String newVpnName = update.getVpnInstanceName();
1294 BigInteger dpnId = update.getDpnId();
1295 List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
1296 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
1297 if (oldAdjs == null) {
1298 oldAdjs = new ArrayList<>();
1300 if (newAdjs == null) {
1301 newAdjs = new ArrayList<>();
1303 //handles switching between <internal VPN - external VPN>
1304 if (!oldVpnName.equals(newVpnName)) {
1305 remove(identifier, original);
1306 waitForFibToRemoveVpnPrefix(update.getName());
1307 add(identifier, update);
1309 //handle both addition and removal of adjacencies
1310 //currently, new adjacency may be an extra route
1311 if (!oldAdjs.equals(newAdjs)) {
1312 for (Adjacency adj : newAdjs) {
1313 if (oldAdjs.contains(adj)) {
1314 oldAdjs.remove(adj);
1316 // add new adjacency - right now only extra route will hit this path
1317 addNewAdjToVpnInterface(identifier, adj, dpnId);
1320 for (Adjacency adj : oldAdjs) {
1321 delAdjFromVpnInterface(identifier, adj, dpnId);
1326 public void processArpRequest(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
1327 .IpAddress srcIP, PhysAddress srcMac, org.opendaylight.yang.gen.v1.urn.ietf
1328 .params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, PhysAddress targetMac, String srcInterface){
1329 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
1330 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
1331 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
1332 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
1333 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
1334 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
1336 public void onFailure(Throwable error) {
1337 LOG.error("Error - {}", msgFormat, error);
1341 public void onSuccess(RpcResult<Void> result) {
1342 if(!result.isSuccessful()) {
1343 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
1345 LOG.debug("Successful RPC Result - {}", msgFormat);
1351 private String getErrorText(Collection<RpcError> errors) {
1352 StringBuilder errorText = new StringBuilder();
1353 for(RpcError error : errors) {
1354 errorText.append(",").append(error.getErrorType()).append("-")
1355 .append(error.getMessage());
1357 return errorText.toString();
1360 private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
1361 String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd,
1362 WriteTransaction writeOperTxn) {
1363 Preconditions.checkNotNull(label, "label cannot be null or empty!");
1364 Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
1365 Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
1366 Preconditions.checkNotNull(rd, "rd cannot be null or empty!");
1367 if (!isSubnetRoute) {
1368 // NextHop must be present for non-subnetroute entries
1369 Preconditions.checkNotNull(nextHopIpList, "nextHopIp cannot be null or empty!");
1371 LOG.info("Adding to label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} vpnIntfcName {} rd {}", label, dpnId, prefix, nextHopIpList, vpnId, vpnInterfaceName, rd);
1372 if (dpnId != null) {
1373 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1374 .child(LabelRouteInfo.class, new LabelRouteInfoKey((long)label)).build();
1375 LabelRouteInfoBuilder lriBuilder = new LabelRouteInfoBuilder();
1376 lriBuilder.setLabel(label).setDpnId(dpnId).setPrefix(prefix).setNextHopIpList(nextHopIpList).setParentVpnid(vpnId)
1377 .setIsSubnetRoute(isSubnetRoute);
1378 if (elanTag != null) {
1379 lriBuilder.setElanTag(elanTag);
1381 if (vpnInterfaceName != null) {
1382 lriBuilder.setVpnInterfaceName(vpnInterfaceName);
1384 lriBuilder.setParentVpnRd(rd);
1385 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
1386 if (vpnInstanceOpDataEntry != null) {
1387 List<String> vpnInstanceNames = Arrays.asList(vpnInstanceOpDataEntry.getVpnInstanceName());
1388 lriBuilder.setVpnInstanceList(vpnInstanceNames);
1390 LabelRouteInfo lri = lriBuilder.build();
1391 LOG.trace("Adding route info to label map: {}", lri);
1392 if (writeOperTxn != null) {
1393 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, lriIid, lri, true);
1395 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
1398 LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
1402 public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
1403 long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
1404 SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
1405 RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
1406 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1407 .setLabel((long)label).setOrigin(origin.getValue())
1408 .addAugmentation(SubnetRoute.class, route).build();
1410 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
1412 //TODO: What should be parentVpnId? Get it from RD?
1413 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1414 addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd, null);
1415 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1417 InstanceIdentifierBuilder<VrfTables> idBuilder =
1418 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1419 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1421 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1422 setVrfEntry(vrfEntryList).build();
1424 if (writeTxn != null) {
1425 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1427 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1430 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1431 if (vpnsToImportRoute.size() > 0) {
1432 VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1433 .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
1434 .addAugmentation(SubnetRoute.class, route).build();
1435 List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
1436 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1437 LOG.info("Exporting subnet route rd {} prefix {} nexthop {} label {} to vpn {}", rd, prefix, nextHop, label, vpnInstance.getVpnInstanceName());
1438 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1439 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
1440 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
1441 if (writeTxn != null) {
1442 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
1444 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
1450 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1451 SubnetRoute route, WriteTransaction writeConfigTxn) {
1453 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1454 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1455 .setLabel((long)label).setOrigin(origin.getValue())
1456 .addAugmentation(SubnetRoute.class, route).build();
1457 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, route.getElantag());
1458 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1459 InstanceIdentifierBuilder<VrfTables> idBuilder =
1460 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1461 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1462 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1463 setVrfEntry(vrfEntryList).build();
1464 if (writeConfigTxn != null) {
1465 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1467 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1471 public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
1472 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, null /* nextHopToRemove */, null);
1473 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1474 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1475 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1476 LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
1477 fibManager.removeOrUpdateFibEntry(dataBroker, importingRd, prefix, null /* nextHopToRemove */, null);
1481 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1483 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1485 if (optVpnInterface.isPresent()) {
1486 VpnInterface currVpnIntf = optVpnInterface.get();
1487 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1488 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1489 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
1490 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath);
1492 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1493 VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
1495 List<Adjacency> adjacencies;
1496 if (optAdjacencies.isPresent()) {
1497 adjacencies = optAdjacencies.get().getAdjacency();
1499 //This code will not be hit since VM adjacency will always be there
1500 adjacencies = new ArrayList<>();
1503 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
1504 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
1506 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1507 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
1509 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1510 for (String nh : adj.getNextHopIpList()) {
1511 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
1512 currVpnIntf.getName());
1517 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1518 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1520 if (optVpnInterface.isPresent()) {
1521 VpnInterface currVpnIntf = optVpnInterface.get();
1523 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1524 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1525 if (optAdjacencies.isPresent()) {
1526 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1528 if (!adjacencies.isEmpty()) {
1529 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1530 LOG.trace("Adjacencies are " + adjacencies);
1531 Iterator<Adjacency> adjIt = adjacencies.iterator();
1532 while (adjIt.hasNext()) {
1533 Adjacency adjElem = adjIt.next();
1534 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1537 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1538 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
1539 currVpnIntf.getVpnInstanceName(),
1540 aug, dpnId, currVpnIntf.isScheduledForRemove());
1542 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1544 for (String nh : adj.getNextHopIpList()) {
1545 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
1546 currVpnIntf.getName());
1558 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label,
1561 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
1564 LogicalDatastoreType.OPERATIONAL,
1565 VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
1566 VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
1568 BigInteger dpnId = null;
1569 if (intfName != null && !intfName.isEmpty()) {
1570 dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1571 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1572 if (nextHopIp == null || nextHopIp.isEmpty()) {
1573 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1574 intfName, destination);
1577 nextHop = nextHopIp;
1579 List<String> nextHopIpList = Arrays.asList(nextHop);
1581 /* Label mapper is required only for BGP VPN and not for Internal VPN */
1582 addToLabelMapper((long) label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(dataBroker, routerID),
1583 intfName, null, false, rd, null);
1586 // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
1587 // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
1589 InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
1590 if ( interVpnLink != null ) {
1591 // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
1592 // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
1593 // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
1594 // This is like leaking one of the Vpn2 routes towards Vpn1
1595 boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
1596 String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
1597 : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
1598 String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
1599 : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
1600 String dstVpnRd = VpnUtil.getVpnRd(dataBroker, dstVpnUuid);
1601 long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1602 VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
1603 VpnUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
1606 addPrefixToBGP(rd, destination, nextHop, label, null);
1608 // ### add FIB route directly
1609 fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, Arrays.asList(nextHop), label, RouteOrigin.STATIC, null);
1614 protected void delExtraRoute(String destination, String nextHop, String rd, String routerID, String intfName) {
1615 if (intfName != null && !intfName.isEmpty()) {
1616 BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1617 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1618 if (nextHopIp == null || nextHopIp.isEmpty()) {
1619 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1620 intfName, destination);
1622 nextHop = nextHopIp;
1626 removePrefixFromBGP(rd, destination, nextHop, null);
1628 // ### add FIB route directly
1629 fibManager.removeOrUpdateFibEntry(dataBroker, routerID, destination, nextHop, null);
1633 void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1634 LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
1635 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1636 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
1637 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1638 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1640 public void onFailure(Throwable error) {
1641 LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
1645 public void onSuccess(Object arg) {
1646 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
1651 void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1652 LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
1653 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1654 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
1655 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1656 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1658 public void onFailure(Throwable error) {
1659 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
1663 public void onSuccess(Object arg) {
1664 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
1669 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1670 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1671 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1672 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1675 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1676 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1677 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1680 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1681 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1682 if(dpId.equals(BigInteger.ZERO)) {
1683 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1686 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1688 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1689 .OPERATIONAL, routerDpnListIdentifier);
1690 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1691 if (optionalRouterDpnList.isPresent()) {
1692 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1693 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1695 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1696 builder.setRouterId(routerName);
1697 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1698 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1699 routerInterfaces.add(routerInterface);
1700 builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
1701 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1702 getRouterId(routerName),
1703 builder.build(), true);
1707 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1708 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1709 if(dpId.equals(BigInteger.ZERO)) {
1710 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1713 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1714 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1715 .OPERATIONAL, routerDpnListIdentifier);
1716 if (optionalRouterDpnList.isPresent()) {
1717 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1718 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1720 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1721 if (routerInterfaces.isEmpty()) {
1722 if (writeOperTxn != null) {
1723 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1725 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1728 if (writeOperTxn != null) {
1729 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1730 RouterInterfaces.class,
1731 new RouterInterfacesKey(vpnInterfaceName)));
1733 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1734 RouterInterfaces.class,
1735 new RouterInterfacesKey(vpnInterfaceName)));
1742 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1743 WriteTransaction writeOperTxn) {
1744 if(dpId.equals(BigInteger.ZERO)) {
1745 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1748 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1749 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1750 .OPERATIONAL, routerDpnListIdentifier);
1751 if (optionalRouterDpnList.isPresent()) {
1752 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1753 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1754 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1755 if (routerInterfaces.isEmpty()) {
1756 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1758 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1759 RouterInterfaces.class,
1760 new RouterInterfacesKey(vpnInterfaceName)));
1766 public void addMIPAdjacency(String vpnName,String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params.xml
1767 .ns.yang.ietf.inet.types.rev130715.IpAddress prefix){
1769 LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
1770 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1771 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1772 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
1773 String nextHopIpAddr = null;
1774 String nextHopMacAddress = null;
1775 String ip = prefix.getIpv4Address().getValue();
1776 if (adjacencies.isPresent()) {
1777 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
1778 ip = VpnUtil.getIpPrefix(ip);
1779 for (Adjacency adjacs : adjacencyList) {
1780 if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
1781 nextHopIpAddr = adjacs.getIpAddress();
1782 nextHopMacAddress = adjacs.getMacAddress();
1786 if (nextHopMacAddress != null && ip != null) {
1787 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1789 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1790 VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnName, ip));
1791 String nextHopIp = nextHopIpAddr.split("/")[0];
1792 Adjacency newAdj = new AdjacencyBuilder().setIpAddress(ip).setKey
1793 (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp)).build();
1794 adjacencyList.add(newAdj);
1795 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
1796 VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface)).
1797 setName(vpnInterface).setVpnInstanceName(vpnName).addAugmentation(Adjacencies.class, aug).build();
1798 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIfId, newVpnIntf);
1799 LOG.debug(" Successfully stored subnetroute Adjacency into VpnInterface {}", vpnInterface);
1805 public void removeMIPAdjacency(String vpnName, String vpnInterface, org.opendaylight.yang.gen.v1.urn.ietf.params
1806 .xml.ns.yang.ietf.inet.types.rev130715.IpAddress prefix) {
1807 String ip = VpnUtil.getIpPrefix(prefix.getIpv4Address().getValue());
1808 LOG.trace("Removing {} adjacency from Old VPN Interface {} ",ip,vpnInterface);
1809 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1810 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1811 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1812 if (adjacencies.isPresent()) {
1813 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
1814 child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class)
1815 .child(Adjacency.class, new AdjacencyKey(ip)).build();
1816 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1817 LOG.trace("Successfully Deleted Adjacency into VpnInterface {}", vpnInterface);
1821 void notifyTaskIfRequired(String intfName) {
1822 Runnable notifyTask = vpnIntfMap.remove(intfName);
1823 if (notifyTask == null) {
1826 executorService.execute(notifyTask);