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.intervpnlink.InterVpnLinkUtil;
59 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
60 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
61 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
70 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
71 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowId;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.TableKey;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
78 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
79 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
80 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
81 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
82 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
83 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
84 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
85 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
86 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
87 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
88 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeBuilder;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
92 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRouteBuilder;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
96 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
97 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
98 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
99 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
100 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
101 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEvent;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.AddDpnEventBuilder;
104 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
105 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.NeutronRouterDpns;
106 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEvent;
107 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.RemoveDpnEventBuilder;
108 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
109 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
110 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
111 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
112 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
113 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
114 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
115 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
116 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
117 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
118 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
119 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
120 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
121 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
122 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
123 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
124 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.id.to.vpn.instance.VpnIds;
125 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
126 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
127 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
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.IpAddresses;
129 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;
130 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;
131 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
132 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
133 import org.opendaylight.yangtools.concepts.ListenerRegistration;
134 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
135 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
136 import org.opendaylight.yangtools.yang.common.RpcError;
137 import org.opendaylight.yangtools.yang.common.RpcResult;
138 import org.slf4j.Logger;
139 import org.slf4j.LoggerFactory;
141 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
142 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
143 private ListenerRegistration<DataChangeListener> listenerRegistration;
144 private final DataBroker dataBroker;
145 private final IBgpManager bgpManager;
146 private final IFibManager fibManager;
147 private final IMdsalApiManager mdsalManager;
148 private final IdManagerService idManager;
149 private final OdlArputilService arpManager;
150 private final OdlInterfaceRpcService ifaceMgrRpcService;
151 private final NotificationPublishService notificationPublishService;
152 private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
153 private ExecutorService executorService = Executors.newSingleThreadExecutor();
155 public VpnInterfaceManager(final DataBroker dataBroker,
156 final IBgpManager bgpManager,
157 final OdlArputilService arpManager,
158 final IdManagerService idManager,
159 final IMdsalApiManager mdsalManager,
160 final IFibManager fibManager,
161 final OdlInterfaceRpcService ifaceMgrRpcService,
162 final NotificationPublishService notificationPublishService) {
163 super(VpnInterface.class);
164 this.dataBroker = dataBroker;
165 this.bgpManager = bgpManager;
166 this.arpManager = arpManager;
167 this.idManager = idManager;
168 this.mdsalManager = mdsalManager;
169 this.fibManager = fibManager;
170 this.ifaceMgrRpcService = ifaceMgrRpcService;
171 this.notificationPublishService = notificationPublishService;
174 public void start() {
175 LOG.info("{} start", getClass().getSimpleName());
176 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
177 getWildCardPath(), this, DataChangeScope.SUBTREE);
180 private InstanceIdentifier<VpnInterface> getWildCardPath() {
181 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
185 public void close() throws Exception {
186 if (listenerRegistration != null) {
187 listenerRegistration.close();
188 listenerRegistration = null;
190 LOG.info("{} close", getClass().getSimpleName());
193 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
194 return InstanceIdentifier.create(InterfacesState.class)
195 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
199 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
200 LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
201 LOG.info("VPN Interface add event - intfName {}" ,vpnInterface.getName());
202 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
203 final String interfaceName = key.getName();
205 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
206 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
207 if(interfaceState != null){
209 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
210 final int ifIndex = interfaceState.getIfIndex();
211 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
212 dataStoreCoordinator.enqueueJob("VPNINTERFACE-"+ interfaceName,
213 new Callable<List<ListenableFuture<Void>>>() {
215 public List<ListenableFuture<Void>> call() throws Exception {
216 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
217 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
218 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
219 processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false, writeConfigTxn, writeOperTxn, writeInvTxn);
220 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
221 futures.add(writeOperTxn.submit());
222 futures.add(writeConfigTxn.submit());
223 futures.add(writeInvTxn.submit());
227 }catch (Exception e){
228 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
232 LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
236 protected void processVpnInterfaceUp(final BigInteger dpId, VpnInterface vpnInterface,
237 final int lPortTag, boolean isInterfaceUp,
238 WriteTransaction writeConfigTxn,
239 WriteTransaction writeOperTxn,
240 WriteTransaction writeInvTxn) {
242 final String interfaceName = vpnInterface.getName();
243 if (!isInterfaceUp) {
244 final String vpnName = vpnInterface.getVpnInstanceName();
245 LOG.info("Binding vpn service to interface {} ", interfaceName);
246 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
247 if (vpnId == VpnConstants.INVALID_ID) {
248 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
251 boolean waitForVpnInterfaceOpRemoval = false;
252 VpnInterface opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, vpnInterface.getName());
253 if (opVpnInterface != null ) {
254 String opVpnName = opVpnInterface.getVpnInstanceName();
255 String primaryInterfaceIp = null;
256 if(opVpnName.equals(vpnName)) {
257 // Please check if the primary VRF Entry does not exist for VPNInterface
258 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
260 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
261 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(dataBroker, interfaceName);
263 LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
266 for (Adjacency adj : adjs) {
267 if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
268 primaryInterfaceIp = adj.getIpAddress();
272 if (primaryInterfaceIp == null) {
273 LOG.info("VPN Interface {} addition failed as primary adjacency "
274 + "for this vpn interface could not be obtained", interfaceName);
277 // Get the rd of the vpn instance
278 String rd = getRouteDistinguisher(opVpnName);
279 rd = (rd == null) ? opVpnName : rd;
280 VrfEntry vrf = VpnUtil.getVrfEntry(dataBroker, rd, primaryInterfaceIp);
282 LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
285 waitForVpnInterfaceOpRemoval = true;
287 LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
288 interfaceName, vpnName, opVpnName);
291 if (!waitForVpnInterfaceOpRemoval) {
292 // Add the VPNInterface and quit
293 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
294 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
295 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
299 // FIB didn't get a chance yet to clean up this VPNInterface
300 // Let us give it a chance here !
301 LOG.info("Trying to add VPN Interface {}, but waiting for FIB to clean up! ", interfaceName);
303 Runnable notifyTask = new VpnNotifyTask();
304 vpnIntfMap.put(interfaceName, notifyTask);
305 synchronized (notifyTask) {
307 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
308 } catch (InterruptedException e) {
312 vpnIntfMap.remove(interfaceName);
315 opVpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
316 if (opVpnInterface != null) {
317 LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
320 // VPNInterface got removed, proceed with Add
321 updateVpnToDpnMapping(dpId, vpnName, interfaceName, true /* add */);
322 bindService(dpId, vpnName, interfaceName, lPortTag, writeConfigTxn, writeInvTxn);
323 processVpnInterfaceAdjacencies(dpId, vpnName, interfaceName, writeConfigTxn, writeOperTxn);
325 // Interface is retained in the DPN, but its Link Up.
326 // Advertise prefixes again for this interface to BGP
327 advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
333 // private class UpdateDpnToVpnWorker implements Callable<List<ListenableFuture<Void>>> {
336 // String interfaceName;
340 // public UpdateDpnToVpnWorker(BigInteger dpnId, String vpnName, String interfaceName,
341 // int lPortTag, boolean addToDpn) {
342 // this.dpnId= dpnId;
343 // this.vpnName = vpnName;
344 // this.interfaceName = interfaceName;
345 // this.lPortTag = lPortTag;
346 // this.addToDpn = addToDpn;
350 // public List<ListenableFuture<Void>> call() throws Exception {
351 // // If another renderer(for eg : CSS) needs to be supported, check can be performed here
352 // // to call the respective helpers.
353 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
354 // updateDpnDbs(dpnId, vpnName, interfaceName, addToDpn, writeTxn);
355 // List<ListenableFuture<Void>> futures = new ArrayList<>();
356 // futures.add(writeTxn.submit());
357 // ListenableFuture<List<Void>> listenableFuture = Futures.allAsList(futures);
358 // Futures.addCallback(listenableFuture,
359 // new UpdateDpnToVpnCallback(dpnId, vpnName, interfaceName, lPortTag, addToDpn));
366 // * JobCallback class is used as a future callback for
367 // * main and rollback workers to handle success and failure.
369 // private class UpdateDpnToVpnCallback implements FutureCallback<List<Void>> {
372 // String interfaceName;
376 // public UpdateDpnToVpnCallback(BigInteger dpnId, String vpnName, String interfaceName,
377 // int lPortTag, boolean addToDpn) {
378 // this.dpnId= dpnId;
379 // this.vpnName = vpnName;
380 // this.interfaceName = interfaceName;
381 // this.lPortTag = lPortTag;
382 // this.addToDpn = addToDpn;
387 // * This implies that all the future instances have returned success. -- TODO: Confirm this
390 // public void onSuccess(List<Void> voids) {
391 // WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
392 // bindService(dpnId, vpnName, interfaceName, lPortTag, writeTxn);
393 // processVpnInterfaceAdjacencies(dpnId, vpnName, interfaceName, writeTxn);
394 // writeTxn.submit();
399 // * @param throwable
400 // * This method is used to handle failure callbacks.
401 // * If more retry needed, the retrycount is decremented and mainworker is executed again.
402 // * After retries completed, rollbackworker is executed.
403 // * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
407 // public void onFailure(Throwable throwable) {
408 // LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
415 private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
418 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
419 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
421 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
423 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
424 intf.getName(), intf.getVpnInstanceName());
427 if (rd.equals(intf.getVpnInstanceName())) {
428 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} as it is in " +
429 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
434 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} in vpn {} with rd {} ", intf.getName(),
435 intf.getVpnInstanceName(), rd);
437 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
438 if (nextHopIp == null){
439 LOG.trace("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} is null, returning", intf.getName());
443 if (adjacencies.isPresent()) {
444 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
446 if (!nextHops.isEmpty()) {
447 LOG.trace("NextHops are " + nextHops);
448 for (Adjacency nextHop : nextHops) {
449 long label = nextHop.getLabel();
451 LOG.info("VPN ADVERTISE: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
452 bgpManager.advertisePrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
453 LOG.info("VPN ADVERTISE: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
454 } catch(Exception e) {
455 LOG.error("Failed to advertise prefix {} in vpn {} with rd {} for interface {} ",
456 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
463 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
465 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
466 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
468 String rd = VpnUtil.getVpnRd(dataBroker, intf.getVpnInstanceName());
470 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
471 intf.getName(), intf.getVpnInstanceName());
474 if (rd.equals(intf.getVpnInstanceName())) {
475 LOG.info("withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in " +
476 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
480 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", intf.getName(),
481 intf.getVpnInstanceName(), rd);
482 if (adjacencies.isPresent()) {
483 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
485 if (!nextHops.isEmpty()) {
486 LOG.trace("NextHops are " + nextHops);
487 for (Adjacency nextHop : nextHops) {
489 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
490 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
491 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
492 } catch(Exception e) {
493 LOG.error("Failed to withdraw prefix {} in vpn {} with rd {} for interface {} ",
494 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
501 public void updateVpnToDpnMapping(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
502 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
504 dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
506 if(!dpId.equals(BigInteger.ZERO)) {
508 createOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
510 removeOrUpdateVpnToDpnList(vpnId, dpId, interfaceName, vpnName);
514 private void bindService(BigInteger dpId, final String vpnInstanceName, final String vpnInterfaceName,
515 int lPortTag, WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
516 final int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
517 final long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
519 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
520 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
521 new Callable<List<ListenableFuture<Void>>>() {
523 public List<ListenableFuture<Void>> call() throws Exception {
524 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
525 int instructionKey = 0;
526 List<Instruction> instructions = new ArrayList<Instruction>();
528 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(
529 MetaDataUtil.getVpnIdMetadata(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
530 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_GW_MAC_TABLE, ++instructionKey));
534 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
535 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX), priority,
536 NwConstants.COOKIE_VM_INGRESS_TABLE, instructions);
537 writeTxn.put(LogicalDatastoreType.CONFIGURATION,
538 InterfaceUtils.buildServiceId(vpnInterfaceName, ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)), serviceInfo, true);
539 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
540 futures.add(writeTxn.submit());
544 makeArpFlow(dpId, ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX), lPortTag, vpnInterfaceName,
545 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW, writeInvTxn);
546 setupGwMacIfExternalVpn(dpId, vpnInterfaceName, vpnId, writeInvTxn, NwConstants.ADD_FLOW);
547 makeArpFlow(dpId, ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX), lPortTag, vpnInterfaceName,
548 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW, writeInvTxn);
552 private void setupGwMacIfExternalVpn(BigInteger dpnId, String interfaceName, long vpnId,
553 WriteTransaction writeInvTxn, int addOrRemove) {
554 InstanceIdentifier<VpnIds> vpnIdsInstanceIdentifier = VpnUtil.getVpnIdToVpnInstanceIdentifier(vpnId);
555 Optional<VpnIds> vpnIdsOptional = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, vpnIdsInstanceIdentifier);
556 if (vpnIdsOptional.isPresent() && vpnIdsOptional.get().isExternalVpn()) {
557 Optional<String> gwMacAddressOptional = InterfaceUtils.getMacAddressForInterface(dataBroker, interfaceName);
558 if (!gwMacAddressOptional.isPresent()) {
559 LOG.error("Failed to get gwMacAddress for interface {}", interfaceName);
562 String gwMacAddress = gwMacAddressOptional.get();
563 FlowEntity flowEntity = VpnUtil.buildL3vpnGatewayFlow(dpnId, gwMacAddress, vpnId);
564 if (addOrRemove == NwConstants.ADD_FLOW) {
565 mdsalManager.addFlowToTx(flowEntity, writeInvTxn);
566 } else if (addOrRemove == NwConstants.DEL_FLOW) {
567 mdsalManager.removeFlowToTx(flowEntity, writeInvTxn);
572 protected void processVpnInterfaceAdjacencies(BigInteger dpnId, String vpnName, String interfaceName,
573 WriteTransaction writeConfigTxn,
574 WriteTransaction writeOperTxn) {
575 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
577 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
578 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, path);
580 if (adjacencies.isPresent()) {
581 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
582 List<Adjacency> value = new ArrayList<>();
584 // Get the rd of the vpn instance
585 String rd = getRouteDistinguisher(vpnName);
587 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
588 if (nextHopIp == null){
589 LOG.error("NextHop for interface {} is null", interfaceName);
593 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
595 LOG.trace("NextHops for interface {} are {}", interfaceName, nextHops);
596 for (Adjacency nextHop : nextHops) {
597 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
598 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
599 VpnUtil.getNextHopLabelKey((rd == null) ? vpnName
601 List<String> adjNextHop = nextHop.getNextHopIpList();
602 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
603 (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
604 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
606 if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
607 LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, interfaceName, vpnName);
609 LogicalDatastoreType.OPERATIONAL,
610 VpnUtil.getPrefixToInterfaceIdentifier(
611 VpnUtil.getVpnId(dataBroker, vpnName), prefix),
612 VpnUtil.getPrefixToInterface(dpnId, interfaceName, prefix), true);
614 //Extra route adjacency
615 LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), vpnName);
617 LogicalDatastoreType.OPERATIONAL,
618 VpnUtil.getVpnToExtrarouteIdentifier(
619 (rd != null) ? rd : vpnName, nextHop.getIpAddress()),
620 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()), true);
624 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
626 VpnInterface opInterface = VpnUtil.getVpnInterface(interfaceName, vpnName, aug, dpnId, Boolean.FALSE);
627 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
628 writeOperTxn.put(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, true);
629 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
631 for (Adjacency nextHop : aug.getAdjacency()) {
632 long label = nextHop.getLabel();
634 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), Arrays.asList(nextHopIp), vpnId,
635 interfaceName, null,false, rd, writeOperTxn);
636 addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label, writeConfigTxn);
637 //TODO: ERT - check for VPNs importing my route
638 for (VpnInstance vpn : vpnsToImportRoute) {
639 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
641 LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
642 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), Arrays.asList(nextHopIp), (int) label,
643 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
647 // ### add FIB route directly
648 fibManager.addOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), Arrays.asList(nextHopIp),
649 (int) label, RouteOrigin.STATIC, writeConfigTxn);
655 private List<VpnInstance> getVpnsImportingMyRoute(final String vpnName) {
656 List<VpnInstance> vpnsToImportRoute = new ArrayList<>();
658 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
659 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
660 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
661 final VpnInstance vpnInstance;
662 if (optVpnInstance.isPresent()) {
663 vpnInstance = optVpnInstance.get();
665 LOG.debug("Could not retrieve vpn instance {} to check for vpns importing the routes", vpnName);
666 return vpnsToImportRoute;
669 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
671 public boolean apply(VpnInstance input) {
672 return !input.getVpnInstanceName().equals(vpnName);
676 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
678 public boolean apply(VpnInstance input) {
679 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ExportExtcommunity),
680 getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
681 return Iterators.size(commonRTs.iterator()) > 0;
685 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
687 public String apply(VpnInstance vpnInstance) {
688 //return vpnInstance.getVpnInstanceName();
689 return vpnInstance.getIpv4Family().getRouteDistinguisher();
693 vpnsToImportRoute = FluentIterable.from(VpnUtil.getAllVpnInstances(dataBroker)).
695 filter(matchRTs).toList();
696 return vpnsToImportRoute;
699 private List<VpnInstance> getVpnsExportingMyRoute(final String vpnName) {
700 List<VpnInstance> vpnsToExportRoute = new ArrayList<>();
702 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
703 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
704 Optional<VpnInstance> optVpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
705 final VpnInstance vpnInstance;
706 if (optVpnInstance.isPresent()) {
707 vpnInstance = optVpnInstance.get();
709 LOG.debug("Could not retrieve vpn instance {} to check for vpns exporting the routes", vpnName);
710 return vpnsToExportRoute;
713 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
715 public boolean apply(VpnInstance input) {
716 return !input.getVpnInstanceName().equals(vpnName);
720 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
722 public boolean apply(VpnInstance input) {
723 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity),
724 getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
725 return Iterators.size(commonRTs.iterator()) > 0;
729 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
731 public String apply(VpnInstance vpnInstance) {
732 return vpnInstance.getVpnInstanceName();
736 vpnsToExportRoute = FluentIterable.from(VpnUtil.getAllVpnInstances(dataBroker)).
738 filter(matchRTs).toList();
739 return vpnsToExportRoute;
742 private <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
743 final Predicate<T> inPredicate = Predicates.<T>in(collection2);
744 return new Iterable<T>() {
746 public Iterator<T> iterator() {
747 return Iterators.filter(collection1.iterator(), inPredicate);
752 private List<String> getRts(VpnInstance vpnInstance, VpnTarget.VrfRTType rtType) {
753 String name = vpnInstance.getVpnInstanceName();
754 List<String> rts = new ArrayList<>();
755 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
756 if (vpnConfig == null) {
757 LOG.trace("vpn config is not available for {}", name);
760 VpnTargets targets = vpnConfig.getVpnTargets();
761 if (targets == null) {
762 LOG.trace("vpn targets not available for {}", name);
765 List<VpnTarget> vpnTargets = targets.getVpnTarget();
766 if (vpnTargets == null) {
767 LOG.trace("vpnTarget values not available for {}", name);
770 for (VpnTarget target : vpnTargets) {
771 //TODO: Check for RT type is Both
772 if(target.getVrfRTType().equals(rtType) ||
773 target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
774 String rtValue = target.getVrfRTValue();
781 private List<String> getExportRts(VpnInstance vpnInstance) {
782 List<String> exportRts = new ArrayList<>();
783 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
784 VpnTargets targets = vpnConfig.getVpnTargets();
785 List<VpnTarget> vpnTargets = targets.getVpnTarget();
786 for (VpnTarget target : vpnTargets) {
787 if (target.getVrfRTType().equals(VpnTarget.VrfRTType.ExportExtcommunity)) {
788 String rtValue = target.getVrfRTValue();
789 exportRts.add(rtValue);
795 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
796 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow,
797 WriteTransaction writeConfigTxn){
798 List<MatchInfo> matches = new ArrayList<MatchInfo>();
799 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, MetaDataUtil.getVpnIdMetadata(vpnId));
800 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
801 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
803 // Matching Arp reply flows
804 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
805 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
806 metadata, metadataMask }));
808 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
810 // Instruction to punt to controller
811 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
812 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
813 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
814 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
815 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
817 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
819 // Install the flow entry in L3_INTERFACE_TABLE
820 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
821 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
822 FlowEntity flowEntity;
823 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
824 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
825 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
827 Flow flow = flowEntity.getFlowBuilder().build();
828 String flowId = flowEntity.getFlowId();
829 FlowKey flowKey = new FlowKey( new FlowId(flowId));
830 Node nodeDpn = VpnUtil.buildDpnNode(dpId);
832 InstanceIdentifier<Flow> flowInstanceId = InstanceIdentifier.builder(Nodes.class)
833 .child(Node.class, nodeDpn.getKey()).augmentation(FlowCapableNode.class)
834 .child(Table.class, new TableKey(flow.getTableId())).child(Flow.class, flowKey).build();
836 if (writeConfigTxn != null) {
837 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
838 LOG.debug("Creating ARP Flow for interface {}", vpnInterfaceName);
839 writeConfigTxn.put(LogicalDatastoreType.CONFIGURATION, flowInstanceId, flow, true);
841 LOG.debug("Deleting ARP Flow for interface {}", vpnInterfaceName);
842 writeConfigTxn.delete(LogicalDatastoreType.CONFIGURATION, flowInstanceId);
845 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
846 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
847 mdsalManager.installFlow(flowEntity);
849 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
850 mdsalManager.removeFlow(flowEntity);
855 private String getRouteDistinguisher(String vpnName) {
856 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
857 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
858 Optional<VpnInstance> vpnInstance = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
860 if(vpnInstance.isPresent()) {
861 VpnInstance instance = vpnInstance.get();
862 VpnAfConfig config = instance.getIpv4Family();
863 rd = config.getRouteDistinguisher();
869 * JobCallback class is used as a future callback for
870 * main and rollback workers to handle success and failure.
872 private class DpnEnterExitVpnWorker implements FutureCallback<List<Void>> {
878 public DpnEnterExitVpnWorker(BigInteger dpnId, String vpnName, String rd, boolean entered) {
879 this.entered = entered;
881 this.vpnName = vpnName;
887 * This implies that all the future instances have returned success. -- TODO: Confirm this
890 public void onSuccess(List<Void> voids) {
892 publishAddNotification(dpnId, vpnName, rd);
894 publishRemoveNotification(dpnId, vpnName, rd);
901 * This method is used to handle failure callbacks.
902 * If more retry needed, the retrycount is decremented and mainworker is executed again.
903 * After retries completed, rollbackworker is executed.
904 * If rollbackworker fails, this is a double-fault. Double fault is logged and ignored.
907 public void onFailure(Throwable throwable) {
908 LOG.warn("Job: failed with exception: {}", throwable.getStackTrace());
912 private void createOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
913 String routeDistinguisher = getRouteDistinguisher(vpnName);
914 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
915 Boolean newDpnOnVpn = Boolean.FALSE;
917 synchronized (vpnName.intern()) {
918 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
919 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
920 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
921 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data
922 .entry.vpn.to.dpn.list.VpnInterfaces
923 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
925 if (dpnInVpn.isPresent()) {
926 VpnToDpnList vpnToDpnList = dpnInVpn.get();
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 = vpnToDpnList.getVpnInterfaces();
929 if (vpnInterfaces == null) {
930 vpnInterfaces = new ArrayList<>();
932 vpnInterfaces.add(vpnInterface);
933 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder(vpnToDpnList);
934 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
936 if (writeTxn != null) {
937 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
939 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
941 /* If earlier state was inactive, it is considered new DPN coming back to the
944 if (vpnToDpnList.getDpnState() == VpnToDpnList.DpnState.Inactive) {
945 newDpnOnVpn = Boolean.TRUE;
948 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
949 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
950 vpnInterfaces.add(vpnInterface);
951 VpnToDpnListBuilder vpnToDpnListBuilder = new VpnToDpnListBuilder().setDpnId(dpnId);
952 vpnToDpnListBuilder.setDpnState(VpnToDpnList.DpnState.Active).setVpnInterfaces(vpnInterfaces);
954 if (writeTxn != null) {
955 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build(), true);
957 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, vpnToDpnListBuilder.build());
959 newDpnOnVpn = Boolean.TRUE;
961 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
964 } catch (InterruptedException | ExecutionException e) {
965 LOG.error("Error adding to dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
966 throw new RuntimeException(e.getMessage());
970 * Informing the Fib only after writeTxn is submitted successfuly.
973 LOG.debug("Sending populateFib event for new dpn {} in VPN {}", dpnId, vpnName);
974 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, true /* entered */));
978 private void removeOrUpdateVpnToDpnList(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
979 Boolean lastDpnOnVpn = Boolean.FALSE;
980 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
981 synchronized (vpnName.intern()) {
982 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
983 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
984 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
985 if (dpnInVpn.isPresent()) {
986 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
987 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
988 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
989 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
991 if (vpnInterfaces.remove(currVpnInterface)) {
992 if (vpnInterfaces.isEmpty()) {
993 List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
994 if (ipAddresses == null || ipAddresses.isEmpty()) {
995 VpnToDpnListBuilder dpnInVpnBuilder =
996 new VpnToDpnListBuilder(dpnInVpn.get())
997 .setDpnState(VpnToDpnList.DpnState.Inactive)
998 .setVpnInterfaces(null);
999 if (writeTxn != null) {
1000 writeTxn.put(LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build(), true);
1002 VpnUtil.syncWrite(dataBroker, LogicalDatastoreType.OPERATIONAL, id, dpnInVpnBuilder.build());
1004 lastDpnOnVpn = Boolean.TRUE;
1006 LOG.warn("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
1009 if (writeTxn != null) {
1010 writeTxn.delete(LogicalDatastoreType.OPERATIONAL, id.child(
1011 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1012 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
1013 new VpnInterfacesKey(intfName)));
1015 VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL, id.child(
1016 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data
1017 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
1018 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
1023 CheckedFuture<Void, TransactionCommitFailedException> futures = writeTxn.submit();
1026 } catch (InterruptedException | ExecutionException e) {
1027 LOG.error("Error removing from dpnToVpnList for vpn {} interface {} dpn {}", vpnName, intfName, dpnId);
1028 throw new RuntimeException(e.getMessage());
1032 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
1033 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd, new DpnEnterExitVpnWorker(dpnId, vpnName, rd, false /* exited */));
1037 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
1038 List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
1039 for (VpnInstance vpn : vpnsToExportRoute) {
1040 String rd = vpn.getIpv4Family().getRouteDistinguisher();
1041 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(dataBroker, vpn.getIpv4Family().getRouteDistinguisher());
1042 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1043 if (vrfEntries != null) {
1044 for (VrfEntry vrfEntry : vrfEntries) {
1046 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) {
1049 String prefix = vrfEntry.getDestPrefix();
1050 long label = vrfEntry.getLabel();
1051 List<String> nextHops = vrfEntry.getNextHopAddressList();
1052 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
1053 for (String nh : nextHops) {
1054 if (route != null) {
1055 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1056 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route, writeConfigTxn);
1058 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
1059 fibManager.addOrUpdateFibEntry(dataBroker, vpnRd, prefix, Arrays.asList(nh), (int)label,
1060 RouteOrigin.SELF_IMPORTED, writeConfigTxn);
1063 } catch (Exception e) {
1064 LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
1067 writeConfigTxn.submit();
1069 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
1074 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label, WriteTransaction writeConfigTxn) {
1076 LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1077 fibManager.addOrUpdateFibEntry(dataBroker, rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC, writeConfigTxn);
1078 bgpManager.advertisePrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label);
1079 LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
1080 } catch(Exception e) {
1081 LOG.error("Add prefix failed", e);
1086 public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
1087 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
1088 LOG.info("VPN Interface remove event - intfName {}" ,vpnInterface.getName());
1089 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1090 final String interfaceName = key.getName();
1092 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1093 final Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, interfaceId);
1094 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
1095 InterfaceUtils.getInterfaceStateFromOperDS(dataBroker, interfaceName);
1096 if (optVpnInterface.isPresent()){
1097 BigInteger dpnId = BigInteger.ZERO;
1098 Boolean dpnIdRetrieved = Boolean.FALSE;
1099 if(interfaceState != null){
1101 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
1102 dpnIdRetrieved = Boolean.TRUE;
1103 }catch (Exception e){
1104 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
1107 LOG.error("Unable to retrieve interfaceState for interface {} , quitting ", interfaceName);
1110 final VpnInterface vpnOpInterface = optVpnInterface.get();
1111 if(dpnIdRetrieved == Boolean.FALSE){
1112 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
1113 dpnId = vpnOpInterface.getDpnId();
1115 final int ifIndex = interfaceState.getIfIndex();
1116 final BigInteger dpId = dpnId;
1117 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1118 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
1119 new Callable<List<ListenableFuture<Void>>>() {
1121 public List<ListenableFuture<Void>> call() throws Exception {
1122 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
1123 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
1124 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
1125 processVpnInterfaceDown(dpId, interfaceName, ifIndex, false, true, writeConfigTxn, writeOperTxn, writeInvTxn);
1126 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1127 futures.add(writeOperTxn.submit());
1128 futures.add(writeConfigTxn.submit());
1129 futures.add(writeInvTxn.submit());
1135 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
1139 protected void processVpnInterfaceDown(BigInteger dpId,
1140 String interfaceName,
1142 boolean isInterfaceStateDown,
1143 boolean isConfigRemoval,
1144 WriteTransaction writeConfigTxn,
1145 WriteTransaction writeOperTxn,
1146 WriteTransaction writeInvTxn) {
1147 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1148 if (!isInterfaceStateDown) {
1149 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1150 if(vpnInterface == null){
1151 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
1154 final String vpnName = vpnInterface.getVpnInstanceName();
1155 if(!vpnInterface.isScheduledForRemove()){
1156 VpnUtil.scheduleVpnInterfaceForRemoval(dataBroker, interfaceName, dpId, vpnName, Boolean.TRUE, writeOperTxn);
1157 removeAdjacenciesFromVpn(dpId, interfaceName, vpnInterface.getVpnInstanceName(), writeConfigTxn);
1158 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
1159 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval, writeConfigTxn, writeInvTxn);
1161 LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
1166 // Interface is retained in the DPN, but its Link Down.
1167 // Only withdraw the prefixes for this interface from BGP
1168 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(dataBroker, interfaceName);
1169 if(vpnInterface == null){
1170 LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
1173 withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
1178 private void waitForFibToRemoveVpnPrefix(String interfaceName) {
1179 // FIB didn't get a chance yet to clean up this VPNInterface
1180 // Let us give it a chance here !
1181 LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
1183 Runnable notifyTask = new VpnNotifyTask();
1184 vpnIntfMap.put(interfaceName, notifyTask);
1185 synchronized (notifyTask) {
1187 notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
1188 } catch (InterruptedException e) {
1192 vpnIntfMap.remove(interfaceName);
1196 private void removeAdjacenciesFromVpn(final BigInteger dpnId, final String interfaceName, final String vpnName,
1197 WriteTransaction writeConfigTxn) {
1199 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
1200 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1201 Optional<Adjacencies> adjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1203 String rd = VpnUtil.getVpnRd(dataBroker, vpnName);
1204 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", interfaceName,
1206 if (adjacencies.isPresent()) {
1207 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
1209 if (!nextHops.isEmpty()) {
1210 LOG.trace("NextHops are " + nextHops);
1211 for (Adjacency nextHop : nextHops) {
1212 List<String> nhList = new ArrayList<String>();
1213 if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
1214 // This is either an extra-route (or) a learned IP via subnet-route
1215 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1216 if (nextHopIp == null || nextHopIp.isEmpty()) {
1217 LOG.error("Unable to obtain nextHopIp for extra-route/learned-route in rd {} prefix {}",
1218 rd, nextHop.getIpAddress());
1221 nhList = Arrays.asList(nextHopIp);
1223 // This is a primary adjacency
1224 nhList = nextHop.getNextHopIpList();
1226 if (rd.equals(vpnName)) {
1227 //this is an internal vpn - the rd is assigned to the vpn instance name;
1228 //remove from FIB directly
1229 for(String nh : nhList) {
1230 fibManager.removeOrUpdateFibEntry(dataBroker, vpnName, nextHop.getIpAddress(), nh, writeConfigTxn);
1233 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1234 for (String nh : nhList) {
1235 //IRT: remove routes from other vpns importing it
1236 removePrefixFromBGP(rd, nextHop.getIpAddress(), nh, writeConfigTxn);
1237 for (VpnInstance vpn : vpnsToImportRoute) {
1238 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
1239 if (vpnRd != null) {
1240 LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
1241 fibManager.removeOrUpdateFibEntry(dataBroker, vpnRd, nextHop.getIpAddress(), nh, writeConfigTxn);
1246 String ip = nextHop.getIpAddress().split("/")[0];
1247 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(dataBroker,
1249 if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
1250 LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
1251 vpnPortipToPort.getPortName(),ip);
1252 VpnUtil.removeVpnPortFixedIpToPort(dataBroker, vpnName, ip);
1260 private void unbindService(BigInteger dpId, String vpnInstanceName, final String vpnInterfaceName,
1261 int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval,
1262 WriteTransaction writeConfigTxn, WriteTransaction writeInvTxn) {
1263 short l3vpn_service_index = ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX);
1264 if (!isInterfaceStateDown && isConfigRemoval) {
1265 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
1266 dataStoreCoordinator.enqueueJob(vpnInterfaceName,
1267 new Callable<List<ListenableFuture<Void>>>() {
1269 public List<ListenableFuture<Void>> call() throws Exception {
1270 WriteTransaction writeTxn = dataBroker.newWriteOnlyTransaction();
1271 writeTxn.delete(LogicalDatastoreType.CONFIGURATION,
1272 InterfaceUtils.buildServiceId(vpnInterfaceName,
1273 ServiceIndex.getIndex(NwConstants.L3VPN_SERVICE_NAME, NwConstants.L3VPN_SERVICE_INDEX)));
1275 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
1276 futures.add(writeTxn.submit());
1281 long vpnId = VpnUtil.getVpnId(dataBroker, vpnInstanceName);
1282 setupGwMacIfExternalVpn(dpId, vpnInterfaceName, vpnId, writeConfigTxn, NwConstants.DEL_FLOW);
1283 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1284 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW, writeInvTxn);
1285 makeArpFlow(dpId, l3vpn_service_index, lPortTag, vpnInterfaceName,
1286 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW, writeInvTxn);
1290 private void removePrefixFromBGP(String rd, String prefix, String nextHop, WriteTransaction writeConfigTxn) {
1292 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
1293 fibManager.removeOrUpdateFibEntry(dataBroker, rd, prefix, nextHop, writeConfigTxn);
1294 bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
1295 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
1296 } catch(Exception e) {
1297 LOG.error("Delete prefix failed", e);
1302 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1303 LOG.trace("Updating VPN Interface : key {}, original value={}, update value={}", identifier, original, update);
1304 LOG.info("VPN Interface update event - intfName {}" ,update.getName());
1305 String oldVpnName = original.getVpnInstanceName();
1306 String newVpnName = update.getVpnInstanceName();
1307 BigInteger dpnId = update.getDpnId();
1308 List<Adjacency> oldAdjsList = new ArrayList<>();
1309 List<Adjacency> newAdjsList = new ArrayList<>();
1310 Adjacencies oldAdjs = original.getAugmentation(Adjacencies.class);
1311 Adjacencies newAdjs = update.getAugmentation(Adjacencies.class);
1312 if (oldAdjs != null) {
1313 oldAdjsList = oldAdjs.getAdjacency();
1315 if (newAdjs != null) {
1316 newAdjsList = newAdjs.getAdjacency();
1318 //handles switching between <internal VPN - external VPN>
1319 if (!oldVpnName.equals(newVpnName)) {
1320 remove(identifier, original);
1321 waitForFibToRemoveVpnPrefix(update.getName());
1322 add(identifier, update);
1324 //handle both addition and removal of adjacencies
1325 //currently, new adjacency may be an extra route
1326 if (!oldAdjsList.equals(newAdjsList)) {
1327 for (Adjacency adj : newAdjsList) {
1328 if (oldAdjsList.contains(adj)) {
1329 oldAdjsList.remove(adj);
1331 // add new adjacency - right now only extra route will hit this path
1332 addNewAdjToVpnInterface(identifier, adj, dpnId);
1335 for (Adjacency adj : oldAdjsList) {
1336 delAdjFromVpnInterface(identifier, adj, dpnId);
1341 public void processArpRequest(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715
1342 .IpAddress srcIP, PhysAddress srcMac, org.opendaylight.yang.gen.v1.urn.ietf
1343 .params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress targetIP, PhysAddress targetMac, String srcInterface){
1344 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
1345 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
1346 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
1347 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
1348 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
1349 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
1351 public void onFailure(Throwable error) {
1352 LOG.error("Error - {}", msgFormat, error);
1356 public void onSuccess(RpcResult<Void> result) {
1357 if(!result.isSuccessful()) {
1358 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
1360 LOG.debug("Successful RPC Result - {}", msgFormat);
1366 private String getErrorText(Collection<RpcError> errors) {
1367 StringBuilder errorText = new StringBuilder();
1368 for(RpcError error : errors) {
1369 errorText.append(",").append(error.getErrorType()).append("-")
1370 .append(error.getMessage());
1372 return errorText.toString();
1375 private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
1376 String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd,
1377 WriteTransaction writeOperTxn) {
1378 Preconditions.checkNotNull(label, "label cannot be null or empty!");
1379 Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
1380 Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
1381 Preconditions.checkNotNull(rd, "rd cannot be null or empty!");
1382 if (!isSubnetRoute) {
1383 // NextHop must be present for non-subnetroute entries
1384 Preconditions.checkNotNull(nextHopIpList, "nextHopIp cannot be null or empty!");
1386 LOG.info("Adding to label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} vpnIntfcName {} rd {}", label, dpnId, prefix, nextHopIpList, vpnId, vpnInterfaceName, rd);
1387 if (dpnId != null) {
1388 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1389 .child(LabelRouteInfo.class, new LabelRouteInfoKey((long)label)).build();
1390 LabelRouteInfoBuilder lriBuilder = new LabelRouteInfoBuilder();
1391 lriBuilder.setLabel(label).setDpnId(dpnId).setPrefix(prefix).setNextHopIpList(nextHopIpList).setParentVpnid(vpnId)
1392 .setIsSubnetRoute(isSubnetRoute);
1393 if (elanTag != null) {
1394 lriBuilder.setElanTag(elanTag);
1396 if (vpnInterfaceName != null) {
1397 lriBuilder.setVpnInterfaceName(vpnInterfaceName);
1399 lriBuilder.setParentVpnRd(rd);
1400 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
1401 if (vpnInstanceOpDataEntry != null) {
1402 List<String> vpnInstanceNames = Arrays.asList(vpnInstanceOpDataEntry.getVpnInstanceName());
1403 lriBuilder.setVpnInstanceList(vpnInstanceNames);
1405 LabelRouteInfo lri = lriBuilder.build();
1406 LOG.trace("Adding route info to label map: {}", lri);
1407 if (writeOperTxn != null) {
1408 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, lriIid, lri, true);
1410 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
1413 LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
1417 public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
1418 long elantag, BigInteger dpnId, WriteTransaction writeTxn) {
1419 SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
1420 RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
1421 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1422 .setLabel((long)label).setOrigin(origin.getValue())
1423 .addAugmentation(SubnetRoute.class, route).build();
1425 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
1427 //TODO: What should be parentVpnId? Get it from RD?
1428 long vpnId = VpnUtil.getVpnId(dataBroker, vpnName);
1429 addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd, null);
1430 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1432 InstanceIdentifierBuilder<VrfTables> idBuilder =
1433 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1434 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1436 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1437 setVrfEntry(vrfEntryList).build();
1439 if (writeTxn != null) {
1440 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1442 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1445 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1446 if (vpnsToImportRoute.size() > 0) {
1447 VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1448 .setLabel((long) label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
1449 .addAugmentation(SubnetRoute.class, route).build();
1450 List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
1451 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1452 LOG.info("Exporting subnet route rd {} prefix {} nexthop {} label {} to vpn {}", rd, prefix, nextHop, label, vpnInstance.getVpnInstanceName());
1453 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1454 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
1455 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
1456 if (writeTxn != null) {
1457 writeTxn.merge(LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable, true);
1459 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
1465 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1466 SubnetRoute route, WriteTransaction writeConfigTxn) {
1468 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1469 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1470 .setLabel((long)label).setOrigin(origin.getValue())
1471 .addAugmentation(SubnetRoute.class, route).build();
1472 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, route.getElantag());
1473 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1474 InstanceIdentifierBuilder<VrfTables> idBuilder =
1475 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1476 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1477 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1478 setVrfEntry(vrfEntryList).build();
1479 if (writeConfigTxn != null) {
1480 writeConfigTxn.merge(LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew, true);
1482 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1486 public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
1487 fibManager.removeFibEntry(dataBroker, rd, prefix, null);
1488 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1489 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1490 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1491 LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
1492 fibManager.removeFibEntry(dataBroker, importingRd, prefix, null);
1496 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1498 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1500 if (optVpnInterface.isPresent()) {
1501 VpnInterface currVpnIntf = optVpnInterface.get();
1502 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1503 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1504 rd = (rd != null) ? rd : currVpnIntf.getVpnInstanceName();
1505 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
1506 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, adjPath);
1508 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1509 VpnUtil.getNextHopLabelKey(rd, prefix));
1511 List<Adjacency> adjacencies;
1512 if (optAdjacencies.isPresent()) {
1513 adjacencies = optAdjacencies.get().getAdjacency();
1515 //This code will not be hit since VM adjacency will always be there
1516 adjacencies = new ArrayList<>();
1519 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
1520 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
1522 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1523 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
1525 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1526 for (String nh : adj.getNextHopIpList()) {
1527 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
1528 currVpnIntf.getName());
1533 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1534 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier);
1536 if (optVpnInterface.isPresent()) {
1537 VpnInterface currVpnIntf = optVpnInterface.get();
1539 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1540 Optional<Adjacencies> optAdjacencies = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, path);
1541 if (optAdjacencies.isPresent()) {
1542 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1544 if (!adjacencies.isEmpty()) {
1545 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1546 rd = (rd != null) ? rd :currVpnIntf.getVpnInstanceName();
1547 LOG.trace("Adjacencies are " + adjacencies);
1548 Iterator<Adjacency> adjIt = adjacencies.iterator();
1549 while (adjIt.hasNext()) {
1550 Adjacency adjElem = adjIt.next();
1551 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1554 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1555 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
1556 currVpnIntf.getVpnInstanceName(),
1557 aug, dpnId, currVpnIntf.isScheduledForRemove());
1559 VpnUtil.syncUpdate(dataBroker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1561 for (String nh : adj.getNextHopIpList()) {
1562 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
1563 currVpnIntf.getName());
1575 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label,
1578 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
1581 LogicalDatastoreType.OPERATIONAL,
1582 VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
1583 VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
1585 BigInteger dpnId = null;
1586 if (intfName != null && !intfName.isEmpty()) {
1587 dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1588 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1589 if (nextHopIp == null || nextHopIp.isEmpty()) {
1590 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1591 intfName, destination);
1594 nextHop = nextHopIp;
1596 List<String> nextHopIpList = Arrays.asList(nextHop);
1598 /* Label mapper is required only for BGP VPN and not for Internal VPN */
1599 addToLabelMapper((long) label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(dataBroker, routerID),
1600 intfName, null, false, rd, null);
1603 // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
1604 // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
1606 Optional<InterVpnLink> optInterVpnLink = InterVpnLinkUtil.getInterVpnLinkByEndpointIp(dataBroker, nextHop);
1607 if ( optInterVpnLink.isPresent() ) {
1608 InterVpnLink interVpnLink = optInterVpnLink.get();
1609 // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
1610 // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
1611 // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
1612 // This is like leaking one of the Vpn2 routes towards Vpn1
1613 boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
1614 String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
1615 : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
1616 String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
1617 : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
1618 String dstVpnRd = VpnUtil.getVpnRd(dataBroker, dstVpnUuid);
1619 long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1620 VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
1621 InterVpnLinkUtil.leakRoute(dataBroker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
1624 addPrefixToBGP(rd, destination, nextHop, label, null);
1626 // ### add FIB route directly
1627 fibManager.addOrUpdateFibEntry(dataBroker, routerID, destination, Arrays.asList(nextHop), label, RouteOrigin.STATIC, null);
1632 protected void delExtraRoute(String destination, String nextHop, String rd, String routerID, String intfName) {
1633 if (intfName != null && !intfName.isEmpty()) {
1634 BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1635 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(dataBroker, dpnId);
1636 if (nextHopIp == null || nextHopIp.isEmpty()) {
1637 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1638 intfName, destination);
1640 nextHop = nextHopIp;
1644 removePrefixFromBGP(rd, destination, nextHop, null);
1646 // ### add FIB route directly
1647 fibManager.removeOrUpdateFibEntry(dataBroker, routerID, destination, nextHop, null);
1651 void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1652 LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
1653 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1654 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(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 add dpn {} in vpn {} event ", dpnId, vpnName, error);
1663 public void onSuccess(Object arg) {
1664 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
1669 void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1670 LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
1671 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1672 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
1673 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1674 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1676 public void onFailure(Throwable error) {
1677 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
1681 public void onSuccess(Object arg) {
1682 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
1687 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1688 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1689 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1690 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1693 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1694 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1695 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1698 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1699 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1700 if(dpId.equals(BigInteger.ZERO)) {
1701 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1704 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1706 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1707 .OPERATIONAL, routerDpnListIdentifier);
1708 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1709 if (optionalRouterDpnList.isPresent()) {
1710 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1711 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface, true);
1713 RouterDpnListBuilder builder = new RouterDpnListBuilder();
1714 builder.setRouterId(routerName);
1715 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1716 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1717 routerInterfaces.add(routerInterface);
1718 builder.setDpnVpninterfacesList(Arrays.asList(dpnVpnList.build()));
1719 writeOperTxn.merge(LogicalDatastoreType.OPERATIONAL,
1720 getRouterId(routerName),
1721 builder.build(), true);
1725 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, WriteTransaction writeOperTxn) {
1726 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1727 if(dpId.equals(BigInteger.ZERO)) {
1728 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1731 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1732 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1733 .OPERATIONAL, routerDpnListIdentifier);
1734 if (optionalRouterDpnList.isPresent()) {
1735 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1736 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1738 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1739 if (routerInterfaces.isEmpty()) {
1740 if (writeOperTxn != null) {
1741 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1743 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1746 if (writeOperTxn != null) {
1747 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1748 RouterInterfaces.class,
1749 new RouterInterfacesKey(vpnInterfaceName)));
1751 MDSALUtil.syncDelete(dataBroker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1752 RouterInterfaces.class,
1753 new RouterInterfacesKey(vpnInterfaceName)));
1760 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName, BigInteger dpId,
1761 WriteTransaction writeOperTxn) {
1762 if(dpId.equals(BigInteger.ZERO)) {
1763 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1766 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1767 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(dataBroker, LogicalDatastoreType
1768 .OPERATIONAL, routerDpnListIdentifier);
1769 if (optionalRouterDpnList.isPresent()) {
1770 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1771 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1772 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1773 if (routerInterfaces.isEmpty()) {
1774 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1776 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1777 RouterInterfaces.class,
1778 new RouterInterfacesKey(vpnInterfaceName)));
1784 void notifyTaskIfRequired(String intfName) {
1785 Runnable notifyTask = vpnIntfMap.remove(intfName);
1786 if (notifyTask == null) {
1789 executorService.execute(notifyTask);