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.*;
11 import com.google.common.collect.FluentIterable;
12 import com.google.common.collect.Iterators;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.netvirt.bgpmanager.api.IBgpManager;
15 import org.opendaylight.netvirt.bgpmanager.api.RouteOrigin;
16 import org.opendaylight.netvirt.fibmanager.api.IFibManager;
17 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
19 import com.google.common.util.concurrent.FutureCallback;
20 import com.google.common.util.concurrent.Futures;
21 import com.google.common.util.concurrent.JdkFutureAdapters;
23 import org.opendaylight.controller.md.sal.binding.api.*;
24 import org.opendaylight.genius.mdsalutil.*;
25 import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
26 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.VpnTargets;
27 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.af.config.vpntargets.VpnTarget;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
29 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fib.rpc.rev160121.FibRpcService;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.LabelRouteMap;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRoute;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.SubnetRouteBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfo;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoBuilder;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.label.route.map.LabelRouteInfoKey;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.*;
43 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventData;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.add.dpn.event.AddEventDataBuilder;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
52 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
53 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventData;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.remove.dpn.event.RemoveEventDataBuilder;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
62 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;
63 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;
64 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;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.FibEntries;
67 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTables;
68 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesBuilder;
69 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.fibentries.VrfTablesKey;
70 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntry;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
72 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.fibmanager.rev150330.vrfentries.VrfEntryKey;
73 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.OdlArputilService;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInput;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.arputil.rev160406.SendArpResponseInputBuilder;
76 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
78 import java.math.BigInteger;
79 import java.util.Collection;
80 import java.util.List;
81 import java.util.ArrayList;
82 import java.util.Arrays;
83 import java.util.Iterator;
84 import java.util.concurrent.ConcurrentHashMap;
85 import java.util.concurrent.Executors;
86 import java.util.concurrent.ExecutorService;
87 import java.util.concurrent.Future;
89 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
90 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.servicebinding.rev160406.service.bindings.services.info.BoundServices;
91 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.rpcs.rev160406.ItmRpcService;
92 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
93 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.NeutronvpnService;
94 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.neutronvpn.rev150602.neutron.vpn.portip.port.data.VpnPortipToPort;
95 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.netvirt.inter.vpn.link.rev160311.inter.vpn.links.InterVpnLink;
96 import org.opendaylight.yangtools.concepts.ListenerRegistration;
97 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
98 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
99 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
100 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
101 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
102 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
103 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
104 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
105 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
106 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
107 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
108 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
109 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
110 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
111 import org.opendaylight.yangtools.yang.common.RpcError;
112 import org.opendaylight.yangtools.yang.common.RpcResult;
113 import org.slf4j.Logger;
114 import org.slf4j.LoggerFactory;
116 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
117 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
118 private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration, tunnelInterfaceStateListenerRegistration;
119 private final DataBroker broker;
120 private final IBgpManager bgpManager;
121 private IFibManager fibManager;
122 private IMdsalApiManager mdsalManager;
123 private OdlInterfaceRpcService ifaceMgrRpcService;
124 private ItmRpcService itmProvider;
125 private IdManagerService idManager;
126 private OdlArputilService arpManager;
127 private NeutronvpnService neuService;
128 private VpnSubnetRouteHandler vpnSubnetRouteHandler;
129 private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
130 private ExecutorService executorService = Executors.newSingleThreadExecutor();
131 private InterfaceStateChangeListener interfaceListener;
132 private TunnelInterfaceStateListener tunnelInterfaceStateListener;
133 private VpnInterfaceOpListener vpnInterfaceOpListener;
134 private ArpNotificationHandler arpNotificationHandler;
135 private NotificationPublishService notificationPublishService;
136 private FibRpcService fibService;
137 protected enum UpdateRouteAction {
138 ADVERTISE_ROUTE, WITHDRAW_ROUTE
142 * Responsible for listening to data change related to VPN Interface
143 * Bind VPN Service on the interface and informs the BGP service
145 * @param db - dataBroker service reference
146 * @param bgpManager Used to advertise routes to the BGP Router
147 * @param notificationService Used to subscribe to notification events
149 public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
150 super(VpnInterface.class);
152 this.bgpManager = bgpManager;
153 interfaceListener = new InterfaceStateChangeListener(db, this);
154 vpnInterfaceOpListener = new VpnInterfaceOpListener();
155 arpNotificationHandler = new ArpNotificationHandler(this, broker);
156 vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
157 tunnelInterfaceStateListener = new TunnelInterfaceStateListener(broker, this);
158 notificationService.registerNotificationListener(vpnSubnetRouteHandler);
159 notificationService.registerNotificationListener(arpNotificationHandler);
160 registerListener(db);
163 public void setMdsalManager(IMdsalApiManager mdsalManager) {
164 this.mdsalManager = mdsalManager;
167 public void setIfaceMgrRpcService(OdlInterfaceRpcService ifMgrRpcService) {
168 this.ifaceMgrRpcService = ifMgrRpcService;
169 interfaceListener.setIfaceMgrRpcService(ifMgrRpcService);
172 public void setITMProvider(ItmRpcService itmProvider) {
173 this.itmProvider = itmProvider;
177 public void setFibManager(IFibManager fibManager) {
178 this.fibManager = fibManager;
181 public IFibManager getFibManager() {
182 return this.fibManager;
186 public void setIdManager(IdManagerService idManager) {
187 this.idManager = idManager;
188 vpnSubnetRouteHandler.setIdManager(idManager);
191 public void setArpManager(OdlArputilService arpManager) {
192 this.arpManager = arpManager;
195 void setNotificationPublishService(NotificationPublishService notificationPublishService) {
196 this.notificationPublishService = notificationPublishService;
199 public void setNeutronvpnManager(NeutronvpnService neuService) { this.neuService = neuService; }
201 public void setFibRpcService(FibRpcService fibService) {
202 this.fibService = fibService;
205 public FibRpcService getFibRpcService() {
209 public VpnSubnetRouteHandler getVpnSubnetRouteHandler() {
210 return this.vpnSubnetRouteHandler;
214 public void close() throws Exception {
215 if (listenerRegistration != null) {
217 listenerRegistration.close();
218 opListenerRegistration.close();
219 } catch (final Exception e) {
220 LOG.error("Error when cleaning up DataChangeListener.", e);
222 listenerRegistration = null;
223 opListenerRegistration = null;
225 LOG.info("VPN Interface Manager Closed");
228 private void registerListener(final DataBroker db) {
230 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
231 getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
232 opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
233 getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
234 tunnelInterfaceStateListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
235 getTunnelInterfaceStateListenerPath(), tunnelInterfaceStateListener, DataChangeScope.SUBTREE);
236 } catch (final Exception e) {
237 LOG.error("VPN Service DataChange listener registration fail!", e);
238 throw new IllegalStateException("VPN Service registration Listener failed.", e);
242 private InstanceIdentifier<StateTunnelList> getTunnelInterfaceStateListenerPath() {
243 return InstanceIdentifier.create(TunnelsState.class).child(StateTunnelList.class);
246 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
247 return InstanceIdentifier.create(InterfacesState.class)
248 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
252 public void add(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface vpnInterface) {
253 LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
254 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
255 String interfaceName = key.getName();
257 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
258 InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
259 if(interfaceState != null){
260 BigInteger dpnId = BigInteger.ZERO;
262 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
263 }catch (Exception e){
264 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. ", interfaceName, e);
267 processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName,
268 interfaceState.getIfIndex(), false);
270 LOG.info("Handling addition of VPN interface {} skipped as interfaceState is not available", interfaceName);
274 protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceUp) {
276 VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
277 if(vpnInterface == null) {
278 LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
281 if (!isInterfaceUp) {
282 String vpnName = vpnInterface.getVpnInstanceName();
283 LOG.info("Binding vpn service to interface {} ", interfaceName);
284 long vpnId = VpnUtil.getVpnId(broker, vpnName);
285 if (vpnId == VpnConstants.INVALID_ID) {
286 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
289 boolean waitForVpnInterfaceOpRemoval = false;
291 VpnInterface opVpnInterface = null;
292 synchronized (interfaceName.intern()) {
293 opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName());
294 if (opVpnInterface != null ) {
295 String opVpnName = opVpnInterface.getVpnInstanceName();
296 String primaryInterfaceIp = null;
297 if(opVpnName.equals(vpnName)) {
298 // Please check if the primary VRF Entry does not exist for VPNInterface
299 // If so, we have to process ADD, as this might be a DPN Restart with Remove and Add triggered
301 // However, if the primary VRF Entry for this VPNInterface exists, please continue bailing out !
302 List<Adjacency> adjs = VpnUtil.getAdjacenciesForVpnInterfaceFromConfig(broker, interfaceName);
304 LOG.info("VPN Interface {} addition failed as adjacencies for this vpn interface could not be obtained", interfaceName);
307 numAdjs = adjs.size();
308 for (Adjacency adj : adjs) {
309 if (adj.getMacAddress() != null && !adj.getMacAddress().isEmpty()) {
310 primaryInterfaceIp = adj.getIpAddress();
314 if (primaryInterfaceIp == null) {
315 LOG.info("VPN Interface {} addition failed as primary adjacency for this vpn interface could not be obtained", interfaceName);
318 // Get the rd of the vpn instance
319 String rd = getRouteDistinguisher(opVpnName);
320 VrfEntry vrf = VpnUtil.getVrfEntry(broker, rd, primaryInterfaceIp);
322 LOG.info("VPN Interface {} already provisioned , bailing out from here.", interfaceName);
325 waitForVpnInterfaceOpRemoval = true;
327 LOG.info("vpn interface {} to go to configured vpn {}, but in operational vpn {}",
328 interfaceName, vpnName, opVpnName);
331 if (!waitForVpnInterfaceOpRemoval) {
332 // Add the VPNInterface and quit
333 bindService(dpId, vpnName, interfaceName, lPortTag);
334 updateDpnDbs(dpId, vpnName, interfaceName, true);
335 processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
341 // FIB didn't get a chance yet to clean up this VPNInterface
342 // Let us give it a chance here !
343 LOG.info("VPN Interface {} waiting for FIB to clean up! ", interfaceName);
345 Runnable notifyTask = new VpnNotifyTask();
346 vpnIntfMap.put(interfaceName, notifyTask);
347 synchronized (notifyTask) {
349 notifyTask.wait(VpnConstants.MAX_WAIT_TIME_IN_MILLISECONDS);
350 } catch (InterruptedException e) {
354 vpnIntfMap.remove(interfaceName);
357 opVpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
358 if (opVpnInterface != null) {
359 LOG.error("VPN Interface {} removal by FIB did not complete on time, bailing addition ...", interfaceName);
362 // VPNInterface got removed, proceed with Add
363 synchronized (interfaceName.intern()) {
364 bindService(dpId, vpnName, interfaceName, lPortTag);
365 updateDpnDbs(dpId, vpnName, interfaceName, true);
366 processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
370 synchronized (interfaceName.intern()) {
371 // Interface is retained in the DPN, but its Link Up.
372 // Advertise prefixes again for this interface to BGP
373 advertiseAdjacenciesForVpnToBgp(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()),
379 private void advertiseAdjacenciesForVpnToBgp(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
381 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
382 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
384 String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
386 LOG.error("advertiseAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
387 intf.getName(), intf.getVpnInstanceName());
390 if (rd.equals(intf.getVpnInstanceName())) {
391 LOG.info("advertiseAdjacenciesForVpnFromBgp: Ignoring BGP advertisement for interface {} as it is in " +
392 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
397 LOG.info("advertiseAdjacenciesForVpnToBgp: Advertising interface {} in vpn {} with rd {} ", intf.getName(),
398 intf.getVpnInstanceName(), rd);
400 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
401 if (nextHopIp == null){
402 LOG.trace("advertiseAdjacenciesForVpnToBgp: NextHop for interface {} is null, returning", intf.getName());
406 if (adjacencies.isPresent()) {
407 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
409 if (!nextHops.isEmpty()) {
410 LOG.trace("NextHops are " + nextHops);
411 for (Adjacency nextHop : nextHops) {
412 long label = nextHop.getLabel();
414 LOG.info("VPN ADVERTISE: Adding Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
415 bgpManager.advertisePrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
416 LOG.info("VPN ADVERTISE: Added Fib Entry rd {} prefix {} nexthop {} label {}", rd, nextHop.getIpAddress(), nextHopIp, label);
417 } catch(Exception e) {
418 LOG.error("Failed to advertise prefix {} in vpn {} with rd {} for interface {} ",
419 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
426 private void withdrawAdjacenciesForVpnFromBgp(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
428 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
429 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
431 String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
433 LOG.error("withdrawAdjacenciesForVpnFromBgp: Unable to recover rd for interface {} in vpn {}",
434 intf.getName(), intf.getVpnInstanceName());
437 if (rd.equals(intf.getVpnInstanceName())) {
438 LOG.info("withdrawAdjacenciesForVpnFromBgp: Ignoring BGP withdrawal for interface {} as it is in " +
439 "internal vpn{} with rd {}", intf.getName(), intf.getVpnInstanceName(), rd);
443 LOG.info("withdrawAdjacenciesForVpnFromBgp: For interface {} in vpn {} with rd {}", intf.getName(),
444 intf.getVpnInstanceName(), rd);
445 if (adjacencies.isPresent()) {
446 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
448 if (!nextHops.isEmpty()) {
449 LOG.trace("NextHops are " + nextHops);
450 for (Adjacency nextHop : nextHops) {
452 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
453 bgpManager.withdrawPrefix(rd, nextHop.getIpAddress());
454 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, nextHop.getIpAddress());
455 } catch(Exception e) {
456 LOG.error("Failed to withdraw prefix {} in vpn {} with rd {} for interface {} ",
457 nextHop.getIpAddress(), intf.getVpnInstanceName(), rd, intf.getName(), e);
464 private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
465 long vpnId = VpnUtil.getVpnId(broker, vpnName);
467 dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, interfaceName);
469 if(!dpId.equals(BigInteger.ZERO)) {
471 updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
473 removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
478 private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
479 int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
480 long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
482 int instructionKey = 0;
483 List<Instruction> instructions = new ArrayList<Instruction>();
485 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
486 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
490 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
491 VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
492 VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
493 VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
494 InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
495 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
496 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
497 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
498 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
502 private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier,
504 String intfName = intf.getName();
505 synchronized (intfName) {
507 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
508 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
510 if (adjacencies.isPresent()) {
511 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
512 List<Adjacency> value = new ArrayList<>();
514 // Get the rd of the vpn instance
515 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
517 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
518 if (nextHopIp == null){
519 LOG.error("NextHop for interface {} is null", intfName);
522 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
523 LOG.trace("NextHops for interface {} are {}", intfName, nextHops);
524 for (Adjacency nextHop : nextHops) {
525 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
526 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
527 .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
528 List<String> adjNextHop = nextHop.getNextHopIpList();
529 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIpList(
530 (adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : Arrays.asList(nextHopIp))
531 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
532 if (nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
533 LOG.trace("Adding prefix {} to interface {} for vpn {}", prefix, intfName, intf.getVpnInstanceName());
536 LogicalDatastoreType.OPERATIONAL,
537 VpnUtil.getPrefixToInterfaceIdentifier(
538 VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
539 VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
541 //Extra route adjacency
542 // FIXME 4: To be fixed with VPNManager patch
543 LOG.trace("Adding prefix {} and nexthopList {} as extra-route for vpn", nextHop.getIpAddress(), nextHop.getNextHopIpList(), intf.getVpnInstanceName() );
546 LogicalDatastoreType.OPERATIONAL,
547 VpnUtil.getVpnToExtrarouteIdentifier(
548 (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
549 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIpList()));
554 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
555 VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug, dpnId, Boolean.FALSE);
556 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
557 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
558 long vpnId = VpnUtil.getVpnId(broker, intf.getVpnInstanceName());
559 for (Adjacency nextHop : aug.getAdjacency()) {
560 long label = nextHop.getLabel();
561 List<String> nextHopList = new ArrayList<>(nextHop.getNextHopIpList());
563 addToLabelMapper(label, dpnId, nextHop.getIpAddress(), nextHopList, vpnId,
564 intfName, null,false, rd);
565 addPrefixToBGP(rd, nextHop.getIpAddress(), nextHopIp, label);
566 //TODO: ERT - check for VPNs importing my route
567 for (VpnInstance vpn : vpnsToImportRoute) {
568 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
570 LOG.debug("Exporting route with rd {} prefix {} nexthop {} label {} to VPN {}", vpnRd, nextHop.getIpAddress(), nextHopIp, label, vpn);
571 VpnUtil.addFibEntryToDS(broker, vpnRd, nextHop.getIpAddress(), nextHopIp, (int) label, RouteOrigin.SELF_IMPORTED);
575 // ### add FIB route directly
576 VpnUtil.addFibEntryToDS(broker, intf.getVpnInstanceName(), nextHop.getIpAddress(), nextHopIp,
577 (int) label, RouteOrigin.STATIC);
584 private List<VpnInstance> getVpnsImportingMyRoute(final String vpnName) {
585 List<VpnInstance> vpnsToImportRoute = new ArrayList<>();
587 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
588 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
589 Optional<VpnInstance> optVpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
590 final VpnInstance vpnInstance;
591 if (optVpnInstance.isPresent()) {
592 vpnInstance = optVpnInstance.get();
594 LOG.debug("Could not retrieve vpn instance {} to check for vpns importing the routes", vpnName);
595 return vpnsToImportRoute;
598 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
600 public boolean apply(VpnInstance input) {
601 return !input.getVpnInstanceName().equals(vpnName);
605 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
607 public boolean apply(VpnInstance input) {
608 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ExportExtcommunity),
609 getRts(input, VpnTarget.VrfRTType.ImportExtcommunity));
610 return Iterators.size(commonRTs.iterator()) > 0;
614 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
616 public String apply(VpnInstance vpnInstance) {
617 //return vpnInstance.getVpnInstanceName();
618 return vpnInstance.getIpv4Family().getRouteDistinguisher();
622 vpnsToImportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(broker)).
624 filter(matchRTs).toList();
625 return vpnsToImportRoute;
628 private List<VpnInstance> getVpnsExportingMyRoute(final String vpnName) {
629 List<VpnInstance> vpnsToExportRoute = new ArrayList<>();
631 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
632 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
633 Optional<VpnInstance> optVpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
634 final VpnInstance vpnInstance;
635 if (optVpnInstance.isPresent()) {
636 vpnInstance = optVpnInstance.get();
638 LOG.debug("Could not retrieve vpn instance {} to check for vpns exporting the routes", vpnName);
639 return vpnsToExportRoute;
642 Predicate<VpnInstance> excludeVpn = new Predicate<VpnInstance>() {
644 public boolean apply(VpnInstance input) {
645 return !input.getVpnInstanceName().equals(vpnName);
649 Predicate<VpnInstance> matchRTs = new Predicate<VpnInstance>() {
651 public boolean apply(VpnInstance input) {
652 Iterable<String> commonRTs = intersection(getRts(vpnInstance, VpnTarget.VrfRTType.ImportExtcommunity),
653 getRts(input, VpnTarget.VrfRTType.ExportExtcommunity));
654 return Iterators.size(commonRTs.iterator()) > 0;
658 Function<VpnInstance, String> toInstanceName = new Function<VpnInstance, String>() {
660 public String apply(VpnInstance vpnInstance) {
661 return vpnInstance.getVpnInstanceName();
665 vpnsToExportRoute = FluentIterable.from(VpnUtil.getAllVpnInstance(broker)).
667 filter(matchRTs).toList();
668 return vpnsToExportRoute;
671 private <T> Iterable<T> intersection(final Collection<T> collection1, final Collection<T> collection2) {
672 final Predicate<T> inPredicate = Predicates.<T>in(collection2);
673 return new Iterable<T>() {
675 public Iterator<T> iterator() {
676 return Iterators.filter(collection1.iterator(), inPredicate);
681 private List<String> getRts(VpnInstance vpnInstance, VpnTarget.VrfRTType rtType) {
682 String name = vpnInstance.getVpnInstanceName();
683 List<String> rts = new ArrayList<>();
684 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
685 if (vpnConfig == null) {
686 LOG.trace("vpn config is not available for {}", name);
689 VpnTargets targets = vpnConfig.getVpnTargets();
690 if (targets == null) {
691 LOG.trace("vpn targets not available for {}", name);
694 List<VpnTarget> vpnTargets = targets.getVpnTarget();
695 if (vpnTargets == null) {
696 LOG.trace("vpnTarget values not available for {}", name);
699 for (VpnTarget target : vpnTargets) {
700 //TODO: Check for RT type is Both
701 if(target.getVrfRTType().equals(rtType) ||
702 target.getVrfRTType().equals(VpnTarget.VrfRTType.Both)) {
703 String rtValue = target.getVrfRTValue();
710 private List<String> getExportRts(VpnInstance vpnInstance) {
711 List<String> exportRts = new ArrayList<>();
712 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
713 VpnTargets targets = vpnConfig.getVpnTargets();
714 List<VpnTarget> vpnTargets = targets.getVpnTarget();
715 for (VpnTarget target : vpnTargets) {
716 if (target.getVrfRTType().equals(VpnTarget.VrfRTType.ExportExtcommunity)) {
717 String rtValue = target.getVrfRTValue();
718 exportRts.add(rtValue);
724 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
725 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
726 List<MatchInfo> matches = new ArrayList<MatchInfo>();
727 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
728 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
729 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
731 // Matching Arp reply flows
732 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
733 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
734 metadata, metadataMask }));
736 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
738 // Instruction to punt to controller
739 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
740 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
741 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
742 actionsInfos.add(new ActionInfo(ActionType.nx_resubmit, new String[]{
743 Short.toString(NwConstants.LPORT_DISPATCHER_TABLE)}));
745 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
747 // Install the flow entry in L3_INTERFACE_TABLE
748 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
749 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
750 FlowEntity flowEntity;
751 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
752 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
753 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
755 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
756 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
757 mdsalManager.installFlow(flowEntity);
759 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
760 mdsalManager.removeFlow(flowEntity);
764 private String getRouteDistinguisher(String vpnName) {
765 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
766 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
767 Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
769 if(vpnInstance.isPresent()) {
770 VpnInstance instance = vpnInstance.get();
771 VpnAfConfig config = instance.getIpv4Family();
772 rd = config.getRouteDistinguisher();
777 private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
778 String routeDistinguisher = getRouteDistinguisher(vpnName);
779 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
780 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
781 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
782 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
783 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
785 if (dpnInVpn.isPresent()) {
786 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
787 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
788 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
789 new VpnInterfacesKey(intfName)), vpnInterface);
791 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
792 VpnUtil.getVpnInstanceOpDataIdentifier(rd),
793 VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId, vpnName));
794 VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
795 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
796 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
797 vpnInterfaces.add(vpnInterface);
798 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
799 vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
802 * FIXME: DC Gateway tunnel should be built dynamically
803 //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
804 //if tunnel to DC GW does not exist, create it
805 //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
806 String dcGW = bgpManager.getDCGwIP();
807 if(dcGW != null && !dcGW.isEmpty())
809 LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
810 itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
812 fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
813 publishAddNotification(dpnId, vpnName, rd);
814 //TODO: IRT - import local routes to vpn. check for the VPNs exporting the routes
815 //FIXME: do we need to handle here. since already routes are imported to this vpn
820 void handleVpnsExportingRoutes(String vpnName, String vpnRd) {
821 List<VpnInstance> vpnsToExportRoute = getVpnsExportingMyRoute(vpnName);
822 long vpnId = VpnUtil.getVpnId(broker, vpnName);
823 for (VpnInstance vpn : vpnsToExportRoute) {
824 String rd = vpn.getIpv4Family().getRouteDistinguisher();
825 long exportingVpnId = VpnUtil.getVpnId(broker, vpn.getVpnInstanceName());
826 List<VrfEntry> vrfEntries = VpnUtil.getAllVrfEntries(broker, vpn.getIpv4Family().getRouteDistinguisher());
827 if (vrfEntries != null) {
828 for (VrfEntry vrfEntry : vrfEntries) {
830 if (RouteOrigin.value(vrfEntry.getOrigin()) != RouteOrigin.STATIC) {
833 String prefix = vrfEntry.getDestPrefix();
834 long label = vrfEntry.getLabel();
835 List<String> nextHops = vrfEntry.getNextHopAddressList();
836 SubnetRoute route = vrfEntry.getAugmentation(SubnetRoute.class);
837 for (String nh : nextHops) {
839 LOG.info("Importing subnet route fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
840 importSubnetRouteForNewVpn(rd, prefix, nh, (int)label, route);
842 LOG.info("Importing fib entry rd {} prefix {} nexthop {} label {} to vpn {}", vpnRd, prefix, nh, label, vpn.getVpnInstanceName());
843 VpnUtil.addFibEntryToDS(broker, vpnRd, prefix, nh, (int)label, RouteOrigin.SELF_IMPORTED);
846 } catch (Exception e) {
847 LOG.error("Exception occurred while importing route with prefix {} label {} nexthop {} from vpn {} to vpn {}", vrfEntry.getDestPrefix(), vrfEntry.getLabel(), vrfEntry.getNextHopAddressList(), vpn.getVpnInstanceName(), vpnName);
851 LOG.info("No vrf entries to import from vpn {} with rd {}", vpn.getVpnInstanceName(), vpn.getIpv4Family().getRouteDistinguisher());
856 private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
857 //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
858 String rd = VpnUtil.getVpnRd(broker, vpnName);
859 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
860 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
861 if (dpnInVpn.isPresent()) {
862 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
863 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
864 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
865 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
867 if (vpnInterfaces.remove(currVpnInterface)) {
868 if (vpnInterfaces.isEmpty()) {
869 List<IpAddresses> ipAddresses = dpnInVpn.get().getIpAddresses();
870 if (ipAddresses == null || ipAddresses.isEmpty()) {
871 LOG.debug("Sending cleanup event for dpn {} in VPN {}", dpnId, vpnName);
872 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
873 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
874 publishRemoveNotification(dpnId, vpnName, rd);
876 LOG.debug("vpn interfaces are empty but ip addresses are present for the vpn {} in dpn {}", vpnName, dpnId);
879 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
880 org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
881 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
882 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
888 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
890 LOG.info("ADD: Adding Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
891 bgpManager.addPrefix(rd, prefix, Arrays.asList(nextHopIp), (int)label, RouteOrigin.STATIC);
892 LOG.info("ADD: Added Fib entry rd {} prefix {} nextHop {} label {}", rd, prefix, nextHopIp, label);
893 } catch(Exception e) {
894 LOG.error("Add prefix failed", e);
899 private InstanceIdentifier<VpnInterface> getWildCardPath() {
900 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
904 public void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
905 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
906 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
907 String interfaceName = key.getName();
909 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
910 Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
911 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
912 InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
913 if(existingVpnInterface.isPresent()){
914 BigInteger dpnId = BigInteger.ZERO;
915 Boolean dpnIdRetrieved = Boolean.FALSE;
916 if(interfaceState != null){
918 dpnId = InterfaceUtils.getDpIdFromInterface(interfaceState);
919 dpnIdRetrieved = Boolean.TRUE;
920 }catch (Exception e){
921 LOG.error("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", interfaceName, e);
924 if(dpnIdRetrieved == Boolean.FALSE){
925 LOG.info("dpnId for {} has not been retrieved yet. Fetching from vpn interface operational DS", interfaceName);
926 dpnId = existingVpnInterface.get().getDpnId();
928 processVpnInterfaceDown(dpnId, interfaceName, interfaceState.getIfIndex(), false, true);
930 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
934 protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval) {
935 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
936 if (!isInterfaceStateDown) {
937 synchronized (interfaceName.intern()) {
938 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
939 if(vpnInterface == null){
940 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
943 String vpnName = vpnInterface.getVpnInstanceName();
944 if(!vpnInterface.isScheduledForRemove()){
945 VpnUtil.updateVpnInterface(broker, vpnInterface.getName(), vpnInterface.getDpnId(), vpnInterface.getVpnInstanceName(), Boolean.TRUE);
946 removeAdjacenciesFromVpn(dpId, identifier, vpnInterface);
947 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
948 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown, isConfigRemoval);
950 LOG.info("Unbinding vpn service for interface {} has already been scheduled by a different event ", interfaceName);
956 // FIB didn't get a chance yet to clean up this VPNInterface
957 // Let us give it a chance here !
958 LOG.info("VPN Interface {} removal waiting for FIB to clean up ! ", interfaceName);
960 Runnable notifyTask = new VpnNotifyTask();
961 vpnIntfMap.put(interfaceName, notifyTask);
962 synchronized (notifyTask) {
964 notifyTask.wait(VpnConstants.PER_INTERFACE_MAX_WAIT_TIME_IN_MILLISECONDS);
965 } catch (InterruptedException e) {
969 vpnIntfMap.remove(interfaceName);
972 synchronized (interfaceName.intern()) {
973 // Interface is retained in the DPN, but its Link Down.
974 // Only withdraw the prefixes for this interface from BGP
975 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
976 if(vpnInterface == null){
977 LOG.info("Unable to withdraw adjacencies for vpn interface {} from BGP as it is not available in operational data store", interfaceName);
980 withdrawAdjacenciesForVpnFromBgp(identifier, vpnInterface);
987 private void removeAdjacenciesFromVpn(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
989 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
990 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
992 String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
993 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
994 intf.getVpnInstanceName(), rd);
995 if (adjacencies.isPresent()) {
996 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
998 if (!nextHops.isEmpty()) {
999 LOG.trace("NextHops are " + nextHops);
1000 for (Adjacency nextHop : nextHops) {
1001 List<String> nhList = new ArrayList<String>();
1002 if (nextHop.getMacAddress() == null || nextHop.getMacAddress().isEmpty()) {
1003 // This is either an extra-route (or) a learned IP via subnet-route
1004 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
1005 if (nextHopIp == null || nextHopIp.isEmpty()) {
1006 LOG.error("Unable to obtain nextHopIp for extra-route/learned-route in rd {} prefix {}",
1007 rd, nextHop.getIpAddress());
1010 nhList = Arrays.asList(nextHopIp);
1012 // This is a primary adjacency
1013 nhList = nextHop.getNextHopIpList();
1015 if (rd.equals(intf.getVpnInstanceName())) {
1016 //this is an internal vpn - the rd is assigned to the vpn instance name;
1017 //remove from FIB directly
1018 for(String nh : nhList) {
1019 VpnUtil.removeFibEntryFromDS(broker, intf.getVpnInstanceName(), nextHop.getIpAddress(), nh);
1023 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(intf.getVpnInstanceName());
1024 for (String nh : nextHop.getNextHopIpList()) {
1025 //IRT: remove routes from other vpns importing it
1026 removePrefixFromBGP(rd, nextHop.getIpAddress(), nh);
1027 for (VpnInstance vpn : vpnsToImportRoute) {
1028 String vpnRd = vpn.getIpv4Family().getRouteDistinguisher();
1029 if (vpnRd != null) {
1030 LOG.info("Removing Exported route with rd {} prefix {} from VPN {}", vpnRd, nextHop.getIpAddress(), vpn.getVpnInstanceName());
1031 VpnUtil.removeFibEntryFromDS(broker, vpnRd, nextHop.getIpAddress(), nh);
1036 String ip = nextHop.getIpAddress().split("/")[0];
1037 VpnPortipToPort vpnPortipToPort = VpnUtil.getNeutronPortFromVpnPortFixedIp(broker,
1038 intf.getVpnInstanceName(), ip);
1039 if (vpnPortipToPort != null && !vpnPortipToPort.isConfig()) {
1040 LOG.trace("VpnInterfaceManager removing adjacency for Interface {} ip {} from VpnPortData Entry",
1041 vpnPortipToPort.getPortName(),ip);
1042 VpnUtil.removeVpnPortFixedIpToPort(broker, intf.getVpnInstanceName(), ip);
1050 private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
1051 int lPortTag, boolean isInterfaceStateDown, boolean isConfigRemoval) {
1052 if (!isInterfaceStateDown && isConfigRemoval) {
1053 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION,
1054 InterfaceUtils.buildServiceId(vpnInterfaceName,
1055 VpnConstants.L3VPN_SERVICE_IDENTIFIER));
1057 long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
1058 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
1059 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
1060 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
1061 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
1065 private void removePrefixFromBGP(String rd, String prefix, String nextHop) {
1066 VpnUtil.removeFibEntryFromDS(broker, rd, prefix, nextHop);
1068 LOG.info("VPN WITHDRAW: Removing Fib Entry rd {} prefix {}", rd, prefix);
1069 bgpManager.withdrawPrefix(rd, prefix); // TODO: Might be needed to include nextHop here
1070 LOG.info("VPN WITHDRAW: Removed Fib Entry rd {} prefix {}", rd, prefix);
1071 } catch(Exception e) {
1072 LOG.error("Delete prefix failed", e);
1077 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1078 LOG.trace("Updating VPN Interface : key {}, original value={}, update value={}", identifier, original, update);
1079 String oldVpnName = original.getVpnInstanceName();
1080 String newVpnName = update.getVpnInstanceName();
1081 BigInteger dpnId = update.getDpnId();
1082 List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
1083 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
1084 if (oldAdjs == null) {
1085 oldAdjs = new ArrayList<>();
1087 if (newAdjs == null) {
1088 newAdjs = new ArrayList<>();
1090 //handles switching between <internal VPN - external VPN>
1091 if (!oldVpnName.equals(newVpnName)) {
1092 remove(identifier, original);
1093 add(identifier, update);
1095 //handle both addition and removal of adjacencies
1096 //currently, new adjacency may be an extra route
1097 if (!oldAdjs.equals(newAdjs)) {
1098 for (Adjacency adj : newAdjs) {
1099 if (oldAdjs.contains(adj)) {
1100 oldAdjs.remove(adj);
1102 // add new adjacency - right now only extra route will hit this path
1103 addNewAdjToVpnInterface(identifier, adj, dpnId);
1106 for (Adjacency adj : oldAdjs) {
1107 delAdjFromVpnInterface(identifier, adj, dpnId);
1112 public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, PhysAddress targetMac,String srcInterface){
1113 //Build ARP response with ARP requests TargetIp TargetMac as the Arp Response SrcIp and SrcMac
1114 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
1115 .setDstIpaddress(srcIP).setDstMacaddress(srcMac).setSrcIpaddress(targetIP).setSrcMacaddress(targetMac).build();
1116 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
1117 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
1118 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
1120 public void onFailure(Throwable error) {
1121 LOG.error("Error - {}", msgFormat, error);
1125 public void onSuccess(RpcResult<Void> result) {
1126 if(!result.isSuccessful()) {
1127 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
1129 LOG.debug("Successful RPC Result - {}", msgFormat);
1135 private String getErrorText(Collection<RpcError> errors) {
1136 StringBuilder errorText = new StringBuilder();
1137 for(RpcError error : errors) {
1138 errorText.append(",").append(error.getErrorType()).append("-")
1139 .append(error.getMessage());
1141 return errorText.toString();
1144 private void addToLabelMapper(Long label, BigInteger dpnId, String prefix, List<String> nextHopIpList, Long vpnId,
1145 String vpnInterfaceName, Long elanTag, boolean isSubnetRoute, String rd) {
1146 Preconditions.checkNotNull(label, "label cannot be null or empty!");
1147 Preconditions.checkNotNull(prefix, "prefix cannot be null or empty!");
1148 Preconditions.checkNotNull(vpnId, "vpnId cannot be null or empty!");
1149 Preconditions.checkNotNull(rd, "rd cannot be null or empty!");
1150 if (!isSubnetRoute) {
1151 // NextHop must be present for non-subnetroute entries
1152 Preconditions.checkNotNull(nextHopIpList, "nextHopIp cannot be null or empty!");
1154 LOG.info("Adding to label mapper : label {} dpn {} prefix {} nexthoplist {} vpnid {} vpnIntfcName {} rd {}", label, dpnId, prefix, nextHopIpList, vpnId, vpnInterfaceName, rd);
1155 if (dpnId != null) {
1156 InstanceIdentifier<LabelRouteInfo> lriIid = InstanceIdentifier.builder(LabelRouteMap.class)
1157 .child(LabelRouteInfo.class, new LabelRouteInfoKey((long)label)).build();
1158 LabelRouteInfoBuilder lriBuilder = new LabelRouteInfoBuilder();
1159 lriBuilder.setLabel(label).setDpnId(dpnId).setPrefix(prefix).setNextHopIpList(nextHopIpList).setParentVpnid(vpnId)
1160 .setIsSubnetRoute(isSubnetRoute);
1161 if (elanTag != null) {
1162 lriBuilder.setElanTag(elanTag);
1164 if (vpnInterfaceName != null) {
1165 lriBuilder.setVpnInterfaceName(vpnInterfaceName);
1167 lriBuilder.setParentVpnRd(rd);
1168 VpnInstanceOpDataEntry vpnInstanceOpDataEntry = VpnUtil.getVpnInstanceOpData(broker, rd);
1169 if (vpnInstanceOpDataEntry != null) {
1170 List<String> vpnInstanceNames = Arrays.asList(vpnInstanceOpDataEntry.getVpnInstanceName());
1171 lriBuilder.setVpnInstanceList(vpnInstanceNames);
1173 LabelRouteInfo lri = lriBuilder.build();
1174 LOG.trace("Adding route info to label map: {}", lri);
1175 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, lriIid, lri);
1177 LOG.trace("Can't add entry to label map for lable {},dpnId is null", label);
1181 public synchronized void addSubnetRouteFibEntryToDS(String rd, String vpnName, String prefix, String nextHop, int label,
1182 long elantag, BigInteger dpnId) {
1184 SubnetRoute route = new SubnetRouteBuilder().setElantag(elantag).build();
1185 RouteOrigin origin = RouteOrigin.STATIC; // Only case when a route is considered as directly connected
1186 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1187 .setLabel((long)label).setOrigin(origin.getValue())
1188 .addAugmentation(SubnetRoute.class, route).build();
1190 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, elantag);
1192 //TODO: What should be parentVpnId? Get it from RD?
1193 long vpnId = VpnUtil.getVpnId(broker, vpnName);
1194 addToLabelMapper((long)label, dpnId, prefix, Arrays.asList(nextHop), vpnId, null, elantag, true, rd);
1195 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1197 InstanceIdentifierBuilder<VrfTables> idBuilder =
1198 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1199 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1201 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1202 setVrfEntry(vrfEntryList).build();
1204 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1206 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1207 if (vpnsToImportRoute.size() > 0) {
1208 VrfEntry importingVrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1209 .setLabel((long)label).setOrigin(RouteOrigin.SELF_IMPORTED.getValue())
1210 .addAugmentation(SubnetRoute.class, route).build();
1211 List<VrfEntry> importingVrfEntryList = Arrays.asList(importingVrfEntry);
1212 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1213 LOG.info("Exporting subnet route rd {} prefix {} nexthop {} label {} to vpn {}", rd, prefix, nextHop, label, vpnInstance.getVpnInstanceName());
1214 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1215 InstanceIdentifier<VrfTables> importingVrfTableId = InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(importingRd)).build();
1216 VrfTables importingVrfTable = new VrfTablesBuilder().setRouteDistinguisher(importingRd).setVrfEntry(importingVrfEntryList).build();
1217 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, importingVrfTableId, importingVrfTable);
1222 public synchronized void importSubnetRouteForNewVpn(String rd, String prefix, String nextHop, int label,
1223 SubnetRoute route) {
1225 RouteOrigin origin = RouteOrigin.SELF_IMPORTED;
1226 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).setNextHopAddressList(Arrays.asList(nextHop))
1227 .setLabel((long)label).setOrigin(origin.getValue())
1228 .addAugmentation(SubnetRoute.class, route).build();
1229 LOG.debug("Created vrfEntry for {} nexthop {} label {} and elantag {}", prefix, nextHop, label, route.getElantag());
1230 List<VrfEntry> vrfEntryList = Arrays.asList(vrfEntry);
1231 InstanceIdentifierBuilder<VrfTables> idBuilder =
1232 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1233 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1234 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
1235 setVrfEntry(vrfEntryList).build();
1236 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
1239 public synchronized void deleteSubnetRouteFibEntryFromDS(String rd, String prefix, String vpnName){
1240 VpnUtil.removeFibEntryFromDS(broker, rd, prefix, null /* nextHopToRemove */);
1241 List<VpnInstance> vpnsToImportRoute = getVpnsImportingMyRoute(vpnName);
1242 for (VpnInstance vpnInstance : vpnsToImportRoute) {
1243 String importingRd = vpnInstance.getIpv4Family().getRouteDistinguisher();
1244 LOG.info("Deleting imported subnet route rd {} prefix {} from vpn {}", rd, prefix, vpnInstance.getVpnInstanceName());
1245 VpnUtil.removeFibEntryFromDS(broker, importingRd, prefix, null);
1249 public synchronized void removeVrfFromDS(String rd) {
1250 LOG.debug("Removing vrf table for rd {}", rd);
1252 InstanceIdentifierBuilder<VrfTables> idBuilder =
1253 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
1254 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
1256 VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
1260 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1262 Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
1264 if (optVpnInterface.isPresent()) {
1265 VpnInterface currVpnIntf = optVpnInterface.get();
1266 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
1267 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1268 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
1269 Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
1271 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1272 VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
1274 List<Adjacency> adjacencies;
1275 if (optAdjacencies.isPresent()) {
1276 adjacencies = optAdjacencies.get().getAdjacency();
1278 //This code will not be hit since VM adjacency will always be there
1279 adjacencies = new ArrayList<>();
1283 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIpList(adj.getNextHopIpList())
1284 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
1285 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1286 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug, dpnId, currVpnIntf.isScheduledForRemove());
1287 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1288 for (String nh : adj.getNextHopIpList()) {
1289 addExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(), (int) label,
1290 currVpnIntf.getName());
1297 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj, BigInteger dpnId) {
1298 Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
1300 if (optVpnInterface.isPresent()) {
1301 VpnInterface currVpnIntf = optVpnInterface.get();
1303 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
1304 Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
1305 if (optAdjacencies.isPresent()) {
1306 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
1308 if (!adjacencies.isEmpty()) {
1309 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
1310 LOG.trace("Adjacencies are " + adjacencies);
1311 Iterator<Adjacency> adjIt = adjacencies.iterator();
1312 while (adjIt.hasNext()) {
1313 Adjacency adjElem = adjIt.next();
1314 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
1317 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
1318 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
1319 currVpnIntf.getVpnInstanceName(),
1320 aug, dpnId, currVpnIntf.isScheduledForRemove());
1322 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
1324 for (String nh : adj.getNextHopIpList()) {
1325 delExtraRoute(adj.getIpAddress(), nh, rd, currVpnIntf.getVpnInstanceName(),
1326 currVpnIntf.getName());
1338 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label,
1341 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
1344 LogicalDatastoreType.OPERATIONAL,
1345 VpnUtil.getVpnToExtrarouteIdentifier( (rd != null) ? rd : routerID, destination),
1346 VpnUtil.getVpnToExtraroute(destination, Arrays.asList(nextHop)));
1348 BigInteger dpnId = null;
1349 if (intfName != null && !intfName.isEmpty()) {
1350 dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1351 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
1352 if (nextHopIp == null || nextHopIp.isEmpty()) {
1353 LOG.error("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1354 intfName, destination);
1357 nextHop = nextHopIp;
1359 List<String> nextHopIpList = Arrays.asList(nextHop);
1360 addToLabelMapper((long)label, dpnId, destination, nextHopIpList, VpnUtil.getVpnId(broker, routerID),
1361 intfName, null, false, rd);
1363 // TODO (eperefr): This is a limitation to be stated in docs. When configuring static route to go to
1364 // another VPN, there can only be one nexthop or, at least, the nexthop to the interVpnLink should be in
1366 InterVpnLink interVpnLink = VpnUtil.getInterVpnLinkByEndpointIp(broker, nextHop);
1367 if ( interVpnLink != null ) {
1368 // If the nexthop is the endpoint of Vpn2, then prefix must be advertised to Vpn1 in DC-GW, with nexthops
1369 // pointing to the DPNs where Vpn1 is instantiated. LFIB in these DPNS must have a flow entry, with lower
1370 // priority, where if Label matches then sets the lportTag of the Vpn2 endpoint and goes to LportDispatcher
1371 // This is like leaking one of the Vpn2 routes towards Vpn1
1372 boolean nexthopIsVpn2 = ( interVpnLink.getSecondEndpoint().getIpAddress().getValue().equals(nextHop) );
1373 String srcVpnUuid = (nexthopIsVpn2) ? interVpnLink.getSecondEndpoint().getVpnUuid().getValue()
1374 : interVpnLink.getFirstEndpoint().getVpnUuid().getValue();
1375 String dstVpnUuid = (nexthopIsVpn2) ? interVpnLink.getFirstEndpoint().getVpnUuid().getValue()
1376 : interVpnLink.getSecondEndpoint().getVpnUuid().getValue();
1377 String dstVpnRd = VpnUtil.getVpnRd(broker, dstVpnUuid);
1378 long newLabel = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1379 VpnUtil.getNextHopLabelKey(dstVpnRd, destination));
1380 VpnUtil.leakRoute(broker, bgpManager, interVpnLink, srcVpnUuid, dstVpnUuid, destination, newLabel);
1383 addPrefixToBGP(rd, destination, nextHop, label);
1385 // ### add FIB route directly
1386 VpnUtil.addFibEntryToDS(broker, routerID, destination, nextHop, label, RouteOrigin.STATIC);
1391 protected void delExtraRoute(String destination, String nextHop, String rd, String routerID, String intfName) {
1392 if (intfName != null && !intfName.isEmpty()) {
1393 BigInteger dpnId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, intfName);
1394 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
1395 if (nextHopIp == null || nextHopIp.isEmpty()) {
1396 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}",
1397 intfName, destination);
1399 nextHop = nextHopIp;
1403 removePrefixFromBGP(rd, destination, nextHop);
1405 // ### add FIB route directly
1406 VpnUtil.removeFibEntryFromDS(broker, routerID, destination, nextHop);
1410 class VpnInterfaceOpListener extends AbstractDataChangeListener<VpnInterface> {
1412 public VpnInterfaceOpListener() {
1413 super(VpnInterface.class);
1417 protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
1418 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1419 String interfaceName = key.getName();
1420 String vpnName = del.getVpnInstanceName();
1422 LOG.trace("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
1423 //decrement the vpn interface count in Vpn Instance Op Data
1424 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
1425 id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
1426 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
1427 = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
1429 if (vpnInstance.isPresent()) {
1431 rd = vpnInstance.get().getVrfId();
1432 //String rd = getRouteDistinguisher(del.getVpnInstanceName());
1434 VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1435 LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} in Vpn Op Instance {}",
1436 interfaceName, rd, vpnName, vpnInstOp);
1438 if (vpnInstOp != null) {
1439 // Vpn Interface removed => No more adjacencies from it.
1440 // Hence clean up interface from vpn-dpn-interface list.
1441 Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
1442 List<Prefixes> prefixToInterface = new ArrayList<>();
1443 Optional<Prefixes> prefix = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1444 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1445 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
1446 if (prefix.isPresent()) {
1447 prefixToInterface.add(prefix.get());
1449 if (prefixToInterface.isEmpty()) {
1450 for (String nh : adjacency.getNextHopIpList()) {
1451 prefix = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1452 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1453 VpnUtil.getIpPrefix(nh)));
1454 if (prefix.isPresent())
1455 prefixToInterface.add(prefix.get());
1458 for (Prefixes pref : prefixToInterface) {
1459 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
1460 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
1461 VpnUtil.DEFAULT_CALLBACK);
1462 synchronized (interfaceName.intern()) {
1463 updateDpnDbs(pref.getDpnId(), del.getVpnInstanceName(), interfaceName, false);
1467 // //ifCnt = vpnInstOp.getVpnInterfaceCount();
1468 // LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
1469 // interfaceName, rd, vpnName, ifCnt);
1470 // if ((ifCnt != null) && (ifCnt > 0)) {
1471 // VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1472 // VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1473 // VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
1477 LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
1479 notifyTaskIfRequired(interfaceName);
1482 private void notifyTaskIfRequired(String intfName) {
1483 Runnable notifyTask = vpnIntfMap.remove(intfName);
1484 if (notifyTask == null) {
1485 LOG.trace("VpnInterfaceOpListener update: No Notify Task queued for vpnInterface {}", intfName);
1488 executorService.execute(notifyTask);
1492 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
1493 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1494 String interfaceName = key.getName();
1496 if (original.getVpnInstanceName().equals(update.getVpnInstanceName())) {
1500 //increment the vpn interface count in Vpn Instance Op Data
1502 VpnInstanceOpDataEntry vpnInstOp = null;
1503 // InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
1504 // updId = VpnUtil.getVpnInstanceToVpnIdIdentifier(update.getVpnInstanceName());
1505 // Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> updVpnInstance
1506 // = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, updId);
1508 // if (updVpnInstance.isPresent()) {
1509 // String rd = null;
1510 // rd = updVpnInstance.get().getVrfId();
1512 // vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1514 // if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
1515 // ifCnt = vpnInstOp.getVpnInterfaceCount();
1518 // LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in updated Vpn Op Instance {}", interfaceName, rd, ifCnt);
1520 // VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1521 // VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1522 // VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
1525 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
1526 origId = VpnUtil.getVpnInstanceToVpnIdIdentifier(original.getVpnInstanceName());
1527 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> origVpnInstance
1528 = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, origId);
1530 if (origVpnInstance.isPresent()) {
1532 rd = origVpnInstance.get().getVrfId();
1534 vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1535 LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
1536 interfaceName, rd, original.getVpnInstanceName());
1538 if (vpnInstOp != null) {
1539 Adjacency adjacency = original.getAugmentation(Adjacencies.class).getAdjacency().get(0);
1540 List<Prefixes> prefixToInterfaceList = new ArrayList<>();
1541 Optional<Prefixes> prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1542 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1543 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
1544 if (prefixToInterface.isPresent()) {
1545 prefixToInterfaceList.add(prefixToInterface.get());
1547 for (String adj : adjacency.getNextHopIpList()) {
1548 prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
1549 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1550 VpnUtil.getIpPrefix(adj)));
1551 if (prefixToInterface.isPresent()) {
1552 prefixToInterfaceList.add(prefixToInterface.get());
1556 // VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
1557 // VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
1558 // prefixToInterface.get().getIpAddress()),
1559 // VpnUtil.DEFAULT_CALLBACK);
1560 synchronized (interfaceName.intern()) {
1561 for (Prefixes prefix : prefixToInterfaceList) {
1562 updateDpnDbs(prefix.getDpnId(), original.getVpnInstanceName(), interfaceName, false);
1567 notifyTaskIfRequired(interfaceName);
1568 // if (vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
1569 // ifCnt = vpnInstOp.getVpnInterfaceCount();
1571 // LOG.debug("VpnInterfaceOpListener update: Vpn interface count not recoverable from original, to handle update for rd {}", rd);
1574 // LOG.trace("VpnInterfaceOpListener update: interface name {} rd {} interface count in original Vpn Op Instance {}", interfaceName, rd, ifCnt);
1577 // VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1578 // VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1579 // VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
1585 protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
1586 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
1587 String interfaceName = key.getName();
1589 //increment the vpn interface count in Vpn Instance Op Data
1591 // String rd = getRouteDistinguisher(add.getVpnInstanceName());
1592 // if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
1593 // VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
1594 // if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
1595 // ifCnt = vpnInstOp.getVpnInterfaceCount();
1598 // LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
1600 // VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1601 // VpnUtil.getVpnInstanceOpDataIdentifier(rd),
1602 // VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
1608 protected void handlePrefixesForDPNs(StateTunnelList stateTunnelList, UpdateRouteAction action) {
1609 BigInteger srcDpnId = new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId());
1610 BigInteger destDpnId;
1611 String srcTepIp = String.valueOf(stateTunnelList.getSrcInfo().getTepIp().getValue());
1612 String destTepIp = String.valueOf(stateTunnelList.getDstInfo().getTepIp().getValue());
1614 InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
1615 InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
1616 Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
1617 long tunTypeVal = 0, vpnId;
1619 if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeInternal.class) {
1620 tunTypeVal = VpnConstants.ITMTunnelLocType.Internal.getValue();
1621 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeExternal.class) {
1622 tunTypeVal = VpnConstants.ITMTunnelLocType.External.getValue();
1623 } else if (stateTunnelList.getDstInfo().getTepDeviceType() == TepTypeHwvtep.class){
1624 tunTypeVal = VpnConstants.ITMTunnelLocType.Hwvtep.getValue();
1626 tunTypeVal = VpnConstants.ITMTunnelLocType.Invalid.getValue();
1628 LOG.trace("tunTypeVal is {}", tunTypeVal);
1630 if (vpnInstances.isPresent()) {
1631 List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
1632 Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
1633 LOG.trace("vpnInstIter {}", vpnInstIter);
1634 while (vpnInstIter.hasNext()) {
1635 VpnInstance vpnInstance = vpnInstIter.next();
1636 LOG.trace("vpnInstance {}", vpnInstance);
1637 vpnId = VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName());
1639 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
1640 LOG.trace("vpnConfig {}", vpnConfig);
1641 String rd = vpnConfig.getRouteDistinguisher();
1642 if (rd == null || rd.isEmpty()) {
1643 rd = vpnInstance.getVpnInstanceName();
1644 LOG.trace("rd is null or empty. Assigning VpnInstanceName to rd {}", rd);
1646 InstanceIdentifier<VpnToDpnList> srcId =
1647 VpnUtil.getVpnToDpnListIdentifier(rd, srcDpnId);
1648 Optional<VpnToDpnList> srcDpnInVpn =
1649 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, srcId);
1650 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
1651 destDpnId = new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId());
1652 InstanceIdentifier<VpnToDpnList> destId =
1653 VpnUtil.getVpnToDpnListIdentifier(rd, destDpnId);
1654 Optional<VpnToDpnList> destDpnInVpn =
1655 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, destId);
1656 if (!(srcDpnInVpn.isPresent() &&
1657 destDpnInVpn.isPresent())) {
1658 LOG.trace(" srcDpn {} - destDPN {}, do not share the VPN {} with rd {}.",
1659 srcDpnId, destDpnId, vpnInstance.getVpnInstanceName(), rd);
1663 if (srcDpnInVpn.isPresent()) {
1664 List<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
1665 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
1666 vpnInterfaces = srcDpnInVpn.get().getVpnInterfaces();
1667 for (org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn
1668 .instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
1669 InstanceIdentifier<VpnInterface> vpnIntfId =
1670 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
1671 LOG.trace("vpnInterface {}", vpnInterface);
1672 InstanceIdentifier<Adjacencies> path =
1673 vpnIntfId.augmentation(Adjacencies.class);
1674 Optional<Adjacencies> adjacencies =
1675 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
1676 LOG.trace("adjacencies {}", adjacencies);
1677 if (adjacencies.isPresent()) {
1678 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
1679 Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
1681 while (adjacencyIterator.hasNext()) {
1682 Adjacency adjacency = adjacencyIterator.next();
1684 if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
1685 LOG.info("VPNInterfaceManager : Added Fib Entry rd {} prefix {} nextHop {} label {}",
1686 rd, adjacency.getIpAddress(), adjacency.getNextHopIpList(),
1687 adjacency.getLabel());
1688 // vrf = new VrfEntryBuilder().set
1689 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
1690 fibManager.handleRemoteRoute(true,
1691 new BigInteger(stateTunnelList.getSrcInfo().getTepDeviceId()),
1692 new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
1693 VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()),
1694 rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
1696 if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
1697 bgpManager.advertisePrefix( rd, adjacency.getIpAddress(),
1698 adjacency.getNextHopIpList(),
1699 adjacency.getLabel().intValue());
1700 fibManager.populateFibOnDpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
1703 else if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
1704 LOG.info("VPNInterfaceManager : Removed Fib entry rd {} prefix {}",
1705 rd, adjacency.getIpAddress());
1706 if (tunTypeVal == VpnConstants.ITMTunnelLocType.Internal.getValue()) {
1707 fibManager.handleRemoteRoute(false, srcDpnId,
1708 new BigInteger(stateTunnelList.getDstInfo().getTepDeviceId()),
1709 vpnId, rd, adjacency.getIpAddress(), srcTepIp, destTepIp);
1711 if (tunTypeVal == VpnConstants.ITMTunnelLocType.External.getValue()) {
1712 bgpManager.withdrawPrefix(rd, adjacency.getIpAddress());
1713 fibManager.cleanUpDpnForVpn(srcDpnId, vpnId, rd, srcTepIp, destTepIp);
1716 } catch (Exception e) {
1717 LOG.error("Exception when updating prefix {} in vrf {} to BGP",
1718 adjacency.getIpAddress(), rd);
1722 LOG.trace("no adjacencies present for path {}.", path);
1726 // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
1727 // fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
1730 LOG.trace("dpnInVpn check failed for srcDpnId {}.", srcDpnId);
1732 } catch (Exception e) {
1733 LOG.error("updatePrefixesForDPN {} in vpn {} failed", 0, vpnInstance.getVpnInstanceName(), e);
1737 LOG.trace("No vpn instances present.");
1741 void publishAddNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1742 LOG.debug("Sending notification for add dpn {} in vpn {} event ", dpnId, vpnName);
1743 AddEventData data = new AddEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1744 AddDpnEvent event = new AddDpnEventBuilder().setAddEventData(data).build();
1745 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1746 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1748 public void onFailure(Throwable error) {
1749 LOG.warn("Error in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName, error);
1753 public void onSuccess(Object arg) {
1754 LOG.trace("Successful in notifying listeners for add dpn {} in vpn {} event ", dpnId, vpnName);
1759 void publishRemoveNotification(final BigInteger dpnId, final String vpnName, final String rd) {
1760 LOG.debug("Sending notification for remove dpn {} in vpn {} event ", dpnId, vpnName);
1761 RemoveEventData data = new RemoveEventDataBuilder().setVpnName(vpnName).setRd(rd).setDpnId(dpnId).build();
1762 RemoveDpnEvent event = new RemoveDpnEventBuilder().setRemoveEventData(data).build();
1763 final ListenableFuture<? extends Object> eventFuture = notificationPublishService.offerNotification(event);
1764 Futures.addCallback(eventFuture, new FutureCallback<Object>() {
1766 public void onFailure(Throwable error) {
1767 LOG.warn("Error in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName, error);
1771 public void onSuccess(Object arg) {
1772 LOG.trace("Successful in notifying listeners for remove dpn {} in vpn {} event ", dpnId, vpnName);
1777 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
1778 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1779 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
1780 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
1783 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
1784 return InstanceIdentifier.builder(NeutronRouterDpns.class)
1785 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
1788 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
1789 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1790 if(dpId.equals(BigInteger.ZERO)) {
1791 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
1794 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1796 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1797 .OPERATIONAL, routerDpnListIdentifier);
1798 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1799 if (optionalRouterDpnList.isPresent()) {
1800 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1801 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
1803 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
1804 getRouterId(routerName),
1805 new RouterDpnListBuilder().setRouterId(routerName).build());
1806 //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
1807 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1808 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1809 routerInterfaces.add(routerInterface);
1810 MDSALUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier,
1811 dpnVpnList.setRouterInterfaces(routerInterfaces).build());
1815 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
1816 BigInteger dpId = InterfaceUtils.getDpnForInterface(ifaceMgrRpcService, vpnInterfaceName);
1817 if(dpId.equals(BigInteger.ZERO)) {
1818 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1821 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1822 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1823 .OPERATIONAL, routerDpnListIdentifier);
1824 if (optionalRouterDpnList.isPresent()) {
1825 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1826 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1828 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1829 if (routerInterfaces.isEmpty()) {
1830 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1832 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1833 RouterInterfaces.class,
1834 new RouterInterfacesKey(vpnInterfaceName)));
1840 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
1841 if(dpId.equals(BigInteger.ZERO)) {
1842 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1845 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1846 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1847 .OPERATIONAL, routerDpnListIdentifier);
1848 if (optionalRouterDpnList.isPresent()) {
1849 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1850 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1852 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1853 if (routerInterfaces.isEmpty()) {
1854 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier);
1856 MDSALUtil.syncDelete(broker, LogicalDatastoreType.OPERATIONAL, routerDpnListIdentifier.child(
1857 RouterInterfaces.class,
1858 new RouterInterfacesKey(vpnInterfaceName)));
1864 public void addMIPAdjacency(String vpnName,String vpnInterface, IpAddress prefix){
1866 LOG.trace("Adding {} adjacency to VPN Interface {} ",prefix,vpnInterface);
1867 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1868 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1869 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
1870 String nextHopIpAddr = null;
1871 String nextHopMacAddress = null;
1872 String ip = prefix.getIpv4Address().getValue();
1873 if (adjacencies.isPresent()) {
1874 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
1875 ip = VpnUtil.getIpPrefix(ip);
1876 for (Adjacency adjacs : adjacencyList) {
1877 if (adjacs.getMacAddress() != null && !adjacs.getMacAddress().isEmpty()) {
1878 nextHopIpAddr = adjacs.getIpAddress();
1879 nextHopMacAddress = adjacs.getMacAddress();
1883 if (nextHopMacAddress != null && ip != null) {
1884 synchronized (vpnInterface.intern()) {
1885 String rd = VpnUtil.getVpnRd(broker, vpnName);
1887 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
1888 VpnUtil.getNextHopLabelKey((rd != null) ? rd : vpnName, ip));
1889 String nextHopIp = nextHopIpAddr.split("/")[0];
1890 Adjacency newAdj = new AdjacencyBuilder().setIpAddress(ip).setKey
1891 (new AdjacencyKey(ip)).setNextHopIpList(Arrays.asList(nextHopIp)).build();
1892 adjacencyList.add(newAdj);
1893 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencyList);
1894 VpnInterface newVpnIntf = new VpnInterfaceBuilder().setKey(new VpnInterfaceKey(vpnInterface)).
1895 setName(vpnInterface).setVpnInstanceName(vpnName).addAugmentation(Adjacencies.class, aug).build();
1896 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vpnIfId, newVpnIntf);
1898 LOG.debug(" Successfully stored subnetroute Adjacency into VpnInterface {}", vpnInterface);
1904 public void removeMIPAdjacency(String vpnName, String vpnInterface, IpAddress prefix) {
1905 String ip = VpnUtil.getIpPrefix(prefix.getIpv4Address().getValue());
1906 LOG.trace("Removing {} adjacency from Old VPN Interface {} ",ip,vpnInterface);
1907 InstanceIdentifier<VpnInterface> vpnIfId = VpnUtil.getVpnInterfaceIdentifier(vpnInterface);
1908 InstanceIdentifier<Adjacencies> path = vpnIfId.augmentation(Adjacencies.class);
1909 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
1910 if (adjacencies.isPresent()) {
1911 synchronized (vpnInterface.intern()) {
1912 InstanceIdentifier<Adjacency> adjacencyIdentifier = InstanceIdentifier.builder(VpnInterfaces.class).
1913 child(VpnInterface.class, new VpnInterfaceKey(vpnInterface)).augmentation(Adjacencies.class)
1914 .child(Adjacency.class, new AdjacencyKey(ip)).build();
1915 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, adjacencyIdentifier);
1917 LOG.trace("Successfully Deleted Adjacency into VpnInterface {}", vpnInterface);
1921 class TunnelInterfaceStateListener extends AbstractDataChangeListener<StateTunnelList> {
1922 public TunnelInterfaceStateListener(final DataBroker db, VpnInterfaceManager vpnIfMgr) {
1923 super(StateTunnelList.class);
1928 protected void remove(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList del) {
1929 LOG.trace("Tunnel deletion---- {}", del);
1930 handlePrefixesForDPNs(del, UpdateRouteAction.WITHDRAW_ROUTE);
1934 protected void update(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList original, StateTunnelList update) {
1935 LOG.trace("Tunnel updation---- {}", update);
1936 LOG.trace("ITM Tunnel {} of type {} state event changed from :{} to :{}",
1937 update.getTunnelInterfaceName(),
1938 fibManager.getTransportTypeStr(update.getTransportType().toString()),
1939 original.isTunnelState(), update.isTunnelState());
1940 //withdraw all prefixes in all vpns for this dpn
1941 boolean isTunnelUp = update.isTunnelState();
1942 handlePrefixesForDPNs(update,isTunnelUp ? UpdateRouteAction.ADVERTISE_ROUTE :
1943 UpdateRouteAction.WITHDRAW_ROUTE);
1947 protected void add(InstanceIdentifier<StateTunnelList> identifier, StateTunnelList add) {
1948 LOG.trace("Tunnel addition---- {}", add);
1950 if(!add.isTunnelState()) {
1951 LOG.trace( "Tunnel {} is not yet UP.",
1952 add.getTunnelInterfaceName());
1955 LOG.trace("ITM Tunnel ,type {} ,State is UP b/w src: {} and dest: {}",
1956 fibManager.getTransportTypeStr(add.getTransportType().toString()),
1957 add.getSrcInfo().getTepDeviceId(), add.getDstInfo().getTepDeviceId());
1958 handlePrefixesForDPNs(add, UpdateRouteAction.ADVERTISE_ROUTE);