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.vpnservice;
10 import org.opendaylight.vpnservice.utilities.InterfaceUtils;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.JdkFutureAdapters;
16 import org.opendaylight.controller.md.sal.binding.api.*;
17 import org.opendaylight.vpnservice.mdsalutil.*;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.NeutronRouterDpns;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
21 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.PhysAddress;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.PrefixToInterface;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyKey;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnList;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnListBuilder;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.RouterDpnListKey;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.DpnVpninterfacesListKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfaces;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.neutron.router.dpns.router.dpn.list.dpn.vpninterfaces.list.RouterInterfacesKey;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnList;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.VpnToDpnListBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesBuilder;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfacesKey;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.OdlArputilService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInput;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.arputil.rev151126.SendArpResponseInputBuilder;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.servicebinding.rev151015.service.bindings.services.info.BoundServices;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.FibEntries;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesBuilder;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryBuilder;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntryKey;
51 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
53 import java.math.BigInteger;
54 import java.util.Collection;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.ArrayList;
58 import java.util.concurrent.*;
60 import com.google.common.base.Optional;
62 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.neutronvpn.rev150602.NeutronvpnService;
63 import org.opendaylight.bgpmanager.api.IBgpManager;
64 import org.opendaylight.fibmanager.api.IFibManager;
65 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.rpcs.rev151003.OdlInterfaceRpcService;
66 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.itm.rpcs.rev151217.ItmRpcService;
67 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
68 import org.opendaylight.yangtools.concepts.ListenerRegistration;
69 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
70 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
71 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
72 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
73 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
74 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
75 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
76 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
77 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
78 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
79 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
80 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
81 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
82 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
83 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
84 import org.opendaylight.yangtools.yang.common.RpcError;
85 import org.opendaylight.yangtools.yang.common.RpcResult;
86 import org.slf4j.Logger;
87 import org.slf4j.LoggerFactory;
89 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
90 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
91 private ListenerRegistration<DataChangeListener> listenerRegistration, opListenerRegistration;
92 private ConcurrentMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
93 private ExecutorService executorService = Executors.newSingleThreadExecutor();
94 private final DataBroker broker;
95 private final IBgpManager bgpManager;
96 private IFibManager fibManager;
97 private IMdsalApiManager mdsalManager;
98 private OdlInterfaceRpcService interfaceManager;
99 private ItmRpcService itmProvider;
100 private IdManagerService idManager;
101 private OdlArputilService arpManager;
102 private NeutronvpnService neuService;
103 private VpnSubnetRouteHandler vpnSubnetRouteHandler;
104 private InterfaceStateChangeListener interfaceListener;
105 private VpnInterfaceOpListener vpnInterfaceOpListener;
106 private ArpNotificationHandler arpNotificationHandler;
107 protected enum UpdateRouteAction {
108 ADVERTISE_ROUTE, WITHDRAW_ROUTE
111 * Responsible for listening to data change related to VPN Interface
112 * Bind VPN Service on the interface and informs the BGP service
114 * @param db - dataBroker service reference
116 public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager, NotificationService notificationService) {
117 super(VpnInterface.class);
119 this.bgpManager = bgpManager;
120 interfaceListener = new InterfaceStateChangeListener(db, this);
121 vpnInterfaceOpListener = new VpnInterfaceOpListener();
122 arpNotificationHandler = new ArpNotificationHandler(this, broker);
123 notificationService.registerNotificationListener(arpNotificationHandler);
124 vpnSubnetRouteHandler = new VpnSubnetRouteHandler(broker, bgpManager, this);
125 notificationService.registerNotificationListener(vpnSubnetRouteHandler);
126 registerListener(db);
129 public void setMdsalManager(IMdsalApiManager mdsalManager) {
130 this.mdsalManager = mdsalManager;
133 public void setInterfaceManager(OdlInterfaceRpcService interfaceManager) {
134 this.interfaceManager = interfaceManager;
135 interfaceListener.setInterfaceManager(interfaceManager);
138 public void setITMProvider(ItmRpcService itmProvider) {
139 this.itmProvider = itmProvider;
142 public void setFibManager(IFibManager fibManager) {
143 this.fibManager = fibManager;
146 public void setIdManager(IdManagerService idManager) {
147 this.idManager = idManager;
148 vpnSubnetRouteHandler.setIdManager(idManager);
151 public void setArpManager(OdlArputilService arpManager) {
152 this.arpManager = arpManager;
155 public void setNeutronvpnManager(NeutronvpnService neuService) { this.neuService = neuService; }
157 public VpnSubnetRouteHandler getVpnSubnetRouteHandler() {
158 return this.vpnSubnetRouteHandler;
162 public void close() throws Exception {
163 if (listenerRegistration != null) {
165 listenerRegistration.close();
166 opListenerRegistration.close();
167 } catch (final Exception e) {
168 LOG.error("Error when cleaning up DataChangeListener.", e);
170 listenerRegistration = null;
171 opListenerRegistration = null;
173 LOG.info("VPN Interface Manager Closed");
176 private void registerListener(final DataBroker db) {
178 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
179 getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
180 opListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
181 getWildCardPath(), vpnInterfaceOpListener, DataChangeScope.SUBTREE);
182 } catch (final Exception e) {
183 LOG.error("VPN Service DataChange listener registration fail!", e);
184 throw new IllegalStateException("VPN Service registration Listener failed.", e);
188 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
189 return InstanceIdentifier.create(InterfacesState.class)
190 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
194 protected void add(final InstanceIdentifier<VpnInterface> identifier,
195 final VpnInterface vpnInterface) {
196 LOG.trace("VPN Interface key: {} , value: {}", identifier, vpnInterface );
197 addInterface(identifier, vpnInterface);
200 private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
201 final VpnInterface vpnInterface) {
202 LOG.trace("VPN Interface add event - key: {}, value: {}" ,identifier, vpnInterface );
203 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
204 String interfaceName = key.getName();
206 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
207 InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
208 if (interfaceState != null) {
209 // Interface state is up
210 processVpnInterfaceUp(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex());
212 LOG.trace("VPN interfaces are not yet operational.");
216 protected void processVpnInterfaceUp(BigInteger dpId, String interfaceName, int lPortTag) {
218 VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(broker, interfaceName);
219 if(vpnInterface == null) {
220 LOG.info("Unable to process add/up for interface {} as it is not configured", interfaceName);
223 String vpnName = vpnInterface.getVpnInstanceName();
224 LOG.info("Binding vpn service to interface {} ", interfaceName);
225 long vpnId = VpnUtil.getVpnId(broker, vpnName);
226 if (vpnId == VpnConstants.INVALID_ID) {
227 LOG.trace("VpnInstance to VPNId mapping is not yet available, bailing out now.");
230 synchronized (interfaceName.intern()) {
231 if (VpnUtil.getOperationalVpnInterface(broker, vpnInterface.getName()) != null) {
232 LOG.trace("VPN Interface already provisioned , bailing out from here.");
235 bindService(dpId, vpnName, interfaceName, lPortTag);
236 updateDpnDbs(dpId, vpnName, interfaceName, true);
237 processVpnInterfaceAdjacencies(dpId, VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
242 private void updateDpnDbs(BigInteger dpId, String vpnName, String interfaceName, boolean add) {
243 long vpnId = VpnUtil.getVpnId(broker, vpnName);
245 dpId = InterfaceUtils.getDpnForInterface(interfaceManager, interfaceName);
247 if(!dpId.equals(BigInteger.ZERO)) {
249 updateMappingDbs(vpnId, dpId, interfaceName, vpnName);
251 removeFromMappingDbs(vpnId, dpId, interfaceName, vpnName);
256 private void bindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName, int lPortTag) {
257 int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
258 long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
260 int instructionKey = 0;
261 List<Instruction> instructions = new ArrayList<Instruction>();
263 instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID, ++instructionKey));
264 instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(NwConstants.L3_FIB_TABLE, ++instructionKey));
268 InterfaceUtils.getBoundServices(String.format("%s.%s.%s", "vpn",vpnInstanceName, vpnInterfaceName),
269 VpnConstants.L3VPN_SERVICE_IDENTIFIER, priority,
270 VpnConstants.COOKIE_VM_INGRESS_TABLE, instructions);
271 VpnUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION,
272 InterfaceUtils.buildServiceId(vpnInterfaceName, VpnConstants.L3VPN_SERVICE_IDENTIFIER), serviceInfo);
273 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
274 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.ADD_FLOW);
275 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
276 vpnId, ArpReplyOrRequest.REPLY, NwConstants.ADD_FLOW);
280 private void processVpnInterfaceAdjacencies(BigInteger dpnId, final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
281 String intfName = intf.getName();
283 synchronized (intfName) {
285 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
286 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, path);
288 if (adjacencies.isPresent()) {
289 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
290 List<Adjacency> value = new ArrayList<>();
292 // Get the rd of the vpn instance
293 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
295 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
296 if (nextHopIp == null){
297 LOG.error("NextHop for interface {} is null", intfName);
300 LOG.trace("NextHops are {}", nextHops);
301 for (Adjacency nextHop : nextHops) {
302 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
303 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
304 .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
305 String adjNextHop = nextHop.getNextHopIp();
306 value.add(new AdjacencyBuilder(nextHop).setLabel(label).setNextHopIp((adjNextHop != null && !adjNextHop.isEmpty()) ? adjNextHop : nextHopIp)
307 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
308 if(nextHop.getMacAddress() != null && !nextHop.getMacAddress().isEmpty()) {
311 LogicalDatastoreType.OPERATIONAL,
312 VpnUtil.getPrefixToInterfaceIdentifier(
313 VpnUtil.getVpnId(broker, intf.getVpnInstanceName()), prefix),
314 VpnUtil.getPrefixToInterface(dpnId, intf.getName(), prefix));
316 //Extra route adjacency
319 LogicalDatastoreType.OPERATIONAL,
320 VpnUtil.getVpnToExtrarouteIdentifier(
321 (rd != null) ? rd : intf.getVpnInstanceName(), nextHop.getIpAddress()),
322 VpnUtil.getVpnToExtraroute(nextHop.getIpAddress(), nextHop.getNextHopIp()));
327 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
328 VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
329 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
330 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface);
331 for (Adjacency nextHop : aug.getAdjacency()) {
332 long label = nextHop.getLabel();
333 //String adjNextHop = nextHop.getNextHopIp();
335 addPrefixToBGP(rd, nextHop.getIpAddress(),
338 // ### add FIB route directly
339 addFibEntryToDS(intf.getVpnInstanceName(), nextHop.getIpAddress(),
340 nextHopIp, (int) label);
347 private void makeArpFlow(BigInteger dpId,short sIndex, int lPortTag, String vpnInterfaceName,
348 long vpnId, ArpReplyOrRequest replyOrRequest, int addOrRemoveFlow){
349 List<MatchInfo> matches = new ArrayList<MatchInfo>();
350 BigInteger metadata = MetaDataUtil.getMetaDataForLPortDispatcher(lPortTag, ++sIndex, BigInteger.valueOf(vpnId));
351 BigInteger metadataMask = MetaDataUtil.getMetaDataMaskForLPortDispatcher(MetaDataUtil.METADATA_MASK_SERVICE_INDEX,
352 MetaDataUtil.METADATA_MASK_LPORT_TAG, MetaDataUtil.METADATA_MASK_VRFID);
354 // Matching Arp reply flows
355 matches.add(new MatchInfo(MatchFieldType.eth_type, new long[] { NwConstants.ETHTYPE_ARP }));
356 matches.add(new MatchInfo(MatchFieldType.metadata, new BigInteger[] {
357 metadata, metadataMask }));
359 matches.add(new MatchInfo(MatchFieldType.arp_op, new long[] { replyOrRequest.getArpOperation() }));
361 // Instruction to punt to controller
362 List<InstructionInfo> instructions = new ArrayList<InstructionInfo>();
363 List<ActionInfo> actionsInfos = new ArrayList<ActionInfo>();
364 actionsInfos.add(new ActionInfo(ActionType.punt_to_controller, new String[] {}));
365 instructions.add(new InstructionInfo(InstructionType.apply_actions, actionsInfos));
367 // Install the flow entry in L3_INTERFACE_TABLE
368 String flowRef = VpnUtil.getFlowRef(dpId, NwConstants.L3_INTERFACE_TABLE,
369 NwConstants.ETHTYPE_ARP, lPortTag, replyOrRequest.getArpOperation());
370 FlowEntity flowEntity;
371 flowEntity = MDSALUtil.buildFlowEntity(dpId, NwConstants.L3_INTERFACE_TABLE, flowRef,
372 NwConstants.DEFAULT_ARP_FLOW_PRIORITY, replyOrRequest.getName(), 0, 0,
373 VpnUtil.getCookieArpFlow(lPortTag), matches, instructions);
375 if (addOrRemoveFlow == NwConstants.ADD_FLOW) {
376 LOG.debug("Creating ARP Flow for interface {}",vpnInterfaceName);
377 mdsalManager.installFlow(flowEntity);
379 LOG.debug("Deleting ARP Flow for interface {}",vpnInterfaceName);
380 mdsalManager.removeFlow(flowEntity);
384 private String getRouteDistinguisher(String vpnName) {
385 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
386 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
387 Optional<VpnInstance> vpnInstance = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
389 if(vpnInstance.isPresent()) {
390 VpnInstance instance = vpnInstance.get();
391 VpnAfConfig config = instance.getIpv4Family();
392 rd = config.getRouteDistinguisher();
397 private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
398 String routeDistinguisher = getRouteDistinguisher(vpnName);
399 String rd = (routeDistinguisher == null) ? vpnName : routeDistinguisher;
400 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
401 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
402 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
403 vpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
405 if (dpnInVpn.isPresent()) {
406 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id.child(
407 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance
408 .op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
409 new VpnInterfacesKey(intfName)), vpnInterface);
411 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
412 VpnUtil.getVpnInstanceOpDataIdentifier(rd),
413 VpnUtil.getVpnInstanceOpDataBuilder(rd, vpnId));
414 VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
415 List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
416 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = new ArrayList<>();
417 vpnInterfaces.add(vpnInterface);
418 VpnUtil.syncWrite(broker, LogicalDatastoreType.OPERATIONAL, id,
419 vpnToDpnList.setVpnInterfaces(vpnInterfaces).build());
422 * FIXME: DC Gateway tunnel should be built dynamically
423 //this is the first VM in this VPN on the DPN, may be a new DPN has come up,
424 //if tunnel to DC GW does not exist, create it
425 //if(!tunnelExists(dpnID, bgpManager.getDCGWIP()))
426 String dcGW = bgpManager.getDCGwIP();
427 if(dcGW != null && !dcGW.isEmpty())
429 LOG.debug("Building tunnel from DPN {} to DC GW {}", dpnId, dcGW);
430 itmProvider.buildTunnelFromDPNToDCGW(dpnId, new IpAddress(dcGW.toCharArray()));
432 fibManager.populateFibOnNewDpn(dpnId, vpnId, (rd == null) ? vpnName : rd);
436 private synchronized void removeFromMappingDbs(long vpnId, BigInteger dpnId, String intfName, String vpnName) {
437 //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
438 String rd = VpnUtil.getVpnRd(broker, vpnName);
439 InstanceIdentifier<VpnToDpnList> id = VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
440 Optional<VpnToDpnList> dpnInVpn = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
441 if (dpnInVpn.isPresent()) {
442 List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
443 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces> vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
444 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data.vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces
445 currVpnInterface = new VpnInterfacesBuilder().setInterfaceName(intfName).build();
447 if (vpnInterfaces.remove(currVpnInterface)) {
448 if (vpnInterfaces.isEmpty()) {
449 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id, VpnUtil.DEFAULT_CALLBACK);
450 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
452 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL, id.child(
453 org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
454 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces.class,
455 new VpnInterfacesKey(intfName)), VpnUtil.DEFAULT_CALLBACK);
461 private void addPrefixToBGP(String rd, String prefix, String nextHopIp, long label) {
463 bgpManager.addPrefix(rd, prefix, nextHopIp, (int)label);
464 } catch(Exception e) {
465 LOG.error("Add prefix failed", e);
470 private InstanceIdentifier<VpnInterface> getWildCardPath() {
471 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
475 protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
476 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
477 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
478 String interfaceName = key.getName();
480 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
481 Optional<VpnInterface> existingVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, interfaceId);
482 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface interfaceState =
483 InterfaceUtils.getInterfaceStateFromOperDS(broker, interfaceName);
485 if (existingVpnInterface.isPresent() && interfaceState != null) {
486 processVpnInterfaceDown(InterfaceUtils.getDpIdFromInterface(interfaceState), interfaceName, interfaceState.getIfIndex(), false);
488 LOG.warn("VPN interface {} was unavailable in operational data store to handle remove event", interfaceName);
492 protected void processVpnInterfaceDown(BigInteger dpId, String interfaceName, int lPortTag, boolean isInterfaceStateDown) {
493 VpnInterface vpnInterface = VpnUtil.getOperationalVpnInterface(broker, interfaceName);
494 if(vpnInterface == null) {
495 LOG.info("Unable to process delete/down for interface {} as it is not available in operational data store", interfaceName);
498 String vpnName = vpnInterface.getVpnInstanceName();
499 InstanceIdentifier<VpnInterface> identifier = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
501 synchronized (interfaceName.intern()) {
502 removeAdjacenciesFromVpn(identifier, vpnInterface);
503 LOG.info("Unbinding vpn service from interface {} ", interfaceName);
504 unbindService(dpId, vpnName, interfaceName, lPortTag, isInterfaceStateDown);
506 //wait till DCN for removal of vpn interface in operational DS arrives
507 Runnable notifyTask = new VpnNotifyTask();
508 synchronized (interfaceName.intern()) {
509 vpnIntfMap.put(interfaceName, notifyTask);
510 synchronized (notifyTask) {
512 notifyTask.wait(VpnConstants.MIN_WAIT_TIME_IN_MILLISECONDS);
513 } catch (InterruptedException e) {
521 private void removeAdjacenciesFromVpn(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
523 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
524 Optional<Adjacencies> adjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
526 String rd = VpnUtil.getVpnRd(broker, intf.getVpnInstanceName());
527 LOG.trace("removeAdjacenciesFromVpn: For interface {} RD recovered for vpn {} as rd {}", intf.getName(),
528 intf.getVpnInstanceName(), rd);
529 if (adjacencies.isPresent()) {
530 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
532 if (!nextHops.isEmpty()) {
533 LOG.trace("NextHops are " + nextHops);
534 for (Adjacency nextHop : nextHops) {
535 // Commenting the release of ID here as it will be released by FIB
536 /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
537 VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
538 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
539 VpnUtil.getPrefixToInterfaceIdentifier(
540 VpnUtil.getVpnId(broker, intf.getVpnInstanceName()),
541 nextHop.getIpAddress()),
542 VpnUtil.DEFAULT_CALLBACK);*/
543 if (rd.equals(intf.getVpnInstanceName())) {
544 //this is an internal vpn - the rd is assigned to the vpn instance name;
545 //remove from FIB directly
546 removeFibEntryFromDS(intf.getVpnInstanceName(), nextHop.getIpAddress());
548 removePrefixFromBGP(rd, nextHop.getIpAddress());
556 private void unbindService(BigInteger dpId, String vpnInstanceName, String vpnInterfaceName,
557 int lPortTag, boolean isInterfaceStateDown) {
558 if (!isInterfaceStateDown) {
559 VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION,
560 InterfaceUtils.buildServiceId(vpnInterfaceName,
561 VpnConstants.L3VPN_SERVICE_IDENTIFIER),
562 VpnUtil.DEFAULT_CALLBACK);
564 long vpnId = VpnUtil.getVpnId(broker, vpnInstanceName);
565 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
566 vpnId, ArpReplyOrRequest.REQUEST, NwConstants.DEL_FLOW);
567 makeArpFlow(dpId, VpnConstants.L3VPN_SERVICE_IDENTIFIER, lPortTag, vpnInterfaceName,
568 vpnId, ArpReplyOrRequest.REPLY, NwConstants.DEL_FLOW);
572 private void removePrefixFromBGP(String rd, String prefix) {
574 bgpManager.deletePrefix(rd, prefix);
575 } catch(Exception e) {
576 LOG.error("Delete prefix failed", e);
581 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
582 if (LOG.isTraceEnabled()) {
583 LOG.trace("Updating VPN Interface : key " + identifier + ", original value=" + original + ", update " +
586 String oldVpnName = original.getVpnInstanceName();
587 String newVpnName = update.getVpnInstanceName();
588 List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
589 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
590 if (oldAdjs == null) {
591 oldAdjs = new ArrayList<>();
593 if (newAdjs == null) {
594 newAdjs = new ArrayList<>();
596 //handles switching between <internal VPN - external VPN>
597 if (!oldVpnName.equals(newVpnName)) {
598 remove(identifier, original);
599 add(identifier, update);
601 //handle both addition and removal of adjacencies
602 //currently, new adjacency may be an extra route
603 if (!oldAdjs.equals(newAdjs)) {
604 for (Adjacency adj : newAdjs) {
605 if (oldAdjs.contains(adj)) {
608 // add new adjacency - right now only extra route will hit this path
609 addNewAdjToVpnInterface(identifier, adj);
612 for (Adjacency adj : oldAdjs) {
613 delAdjFromVpnInterface(identifier, adj);
618 public void processArpRequest(IpAddress srcIP, PhysAddress srcMac, IpAddress targetIP, String srcInterface){
619 SendArpResponseInput input = new SendArpResponseInputBuilder().setInterface(srcInterface)
620 .setIpaddress(srcIP).setSrcIpAddress(targetIP).setMacaddress(srcMac).build();
621 final String msgFormat = String.format("Send ARP Response on interface %s to destination %s", srcInterface, srcIP);
622 Future<RpcResult<Void>> future = arpManager.sendArpResponse(input);
623 Futures.addCallback(JdkFutureAdapters.listenInPoolThread(future), new FutureCallback<RpcResult<Void>>() {
625 public void onFailure(Throwable error) {
626 LOG.error("Error - {}", msgFormat, error);
630 public void onSuccess(RpcResult<Void> result) {
631 if(!result.isSuccessful()) {
632 LOG.warn("Rpc call to {} failed", msgFormat, getErrorText(result.getErrors()));
634 LOG.debug("Successful RPC Result - {}", msgFormat);
640 private String getErrorText(Collection<RpcError> errors) {
641 StringBuilder errorText = new StringBuilder();
642 for(RpcError error : errors) {
643 errorText.append(",").append(error.getErrorType()).append("-")
644 .append(error.getMessage());
646 return errorText.toString();
649 private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
650 return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
655 public synchronized void addFibEntryToDS(String rd, String prefix,
656 String nexthop, int label) {
658 VrfEntry vrfEntry = new VrfEntryBuilder().setDestPrefix(prefix).
659 setNextHopAddress(nexthop).setLabel((long)label).build();
660 LOG.debug("Created vrfEntry for {} nexthop {} label {}", prefix, nexthop, label);
662 List<VrfEntry> vrfEntryList = new ArrayList<VrfEntry>();
663 vrfEntryList.add(vrfEntry);
665 InstanceIdentifierBuilder<VrfTables> idBuilder =
666 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
667 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
669 VrfTables vrfTableNew = new VrfTablesBuilder().setRouteDistinguisher(rd).
670 setVrfEntry(vrfEntryList).build();
672 VpnUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, vrfTableNew);
675 public synchronized void removeFibEntryFromDS(String rd, String prefix) {
677 LOG.debug("Removing fib entry with destination prefix {} from vrf table for rd {}", prefix, rd);
679 InstanceIdentifierBuilder<VrfEntry> idBuilder =
680 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd)).child(VrfEntry.class, new VrfEntryKey(prefix));
681 InstanceIdentifier<VrfEntry> vrfEntryId = idBuilder.build();
682 VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfEntryId, VpnUtil.DEFAULT_CALLBACK);
686 public synchronized void removeVrfFromDS(String rd) {
687 LOG.debug("Removing vrf table for rd {}", rd);
689 InstanceIdentifierBuilder<VrfTables> idBuilder =
690 InstanceIdentifier.builder(FibEntries.class).child(VrfTables.class, new VrfTablesKey(rd));
691 InstanceIdentifier<VrfTables> vrfTableId = idBuilder.build();
693 VpnUtil.delete(broker, LogicalDatastoreType.CONFIGURATION, vrfTableId, VpnUtil.DEFAULT_CALLBACK);
697 protected void addNewAdjToVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
699 Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
701 if (optVpnInterface.isPresent()) {
702 VpnInterface currVpnIntf = optVpnInterface.get();
703 String prefix = VpnUtil.getIpPrefix(adj.getIpAddress());
704 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
705 InstanceIdentifier<Adjacencies> adjPath = identifier.augmentation(Adjacencies.class);
706 Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, adjPath);
708 VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
709 VpnUtil.getNextHopLabelKey((rd != null) ? rd : currVpnIntf.getVpnInstanceName(), prefix));
711 List<Adjacency> adjacencies;
712 if (optAdjacencies.isPresent()) {
713 adjacencies = optAdjacencies.get().getAdjacency();
715 //This code will not be hit since VM adjacency will always be there
716 adjacencies = new ArrayList<>();
719 adjacencies.add(new AdjacencyBuilder(adj).setLabel(label).setNextHopIp(adj.getNextHopIp())
720 .setIpAddress(prefix).setKey(new AdjacencyKey(prefix)).build());
722 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
723 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(), currVpnIntf.getVpnInstanceName(), aug);
725 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
726 addExtraRoute(adj.getIpAddress(), adj.getNextHopIp(), rd, currVpnIntf.getVpnInstanceName(), (int) label, currVpnIntf.getName());
732 protected void delAdjFromVpnInterface(InstanceIdentifier<VpnInterface> identifier, Adjacency adj) {
733 Optional<VpnInterface> optVpnInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, identifier);
735 if (optVpnInterface.isPresent()) {
736 VpnInterface currVpnIntf = optVpnInterface.get();
738 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
739 Optional<Adjacencies> optAdjacencies = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
740 if (optAdjacencies.isPresent()) {
741 List<Adjacency> adjacencies = optAdjacencies.get().getAdjacency();
743 if (!adjacencies.isEmpty()) {
744 String rd = getRouteDistinguisher(currVpnIntf.getVpnInstanceName());
745 LOG.trace("Adjacencies are " + adjacencies);
746 Iterator<Adjacency> adjIt = adjacencies.iterator();
747 while (adjIt.hasNext()) {
748 Adjacency adjElem = adjIt.next();
749 if (adjElem.getIpAddress().equals(adj.getIpAddress())) {
750 // Commenting the release of ID here as it will be released by FIB
751 /* VpnUtil.releaseId(idManager, VpnConstants.VPN_IDPOOL_NAME,
752 VpnUtil.getNextHopLabelKey(rd, adj.getIpAddress()));*/
755 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(adjacencies);
756 VpnInterface newVpnIntf = VpnUtil.getVpnInterface(currVpnIntf.getName(),
757 currVpnIntf.getVpnInstanceName(),
760 VpnUtil.syncUpdate(broker, LogicalDatastoreType.OPERATIONAL, identifier, newVpnIntf);
762 delExtraRoute(adj.getIpAddress(), rd, currVpnIntf.getVpnInstanceName());
773 protected void addExtraRoute(String destination, String nextHop, String rd, String routerID, int label, String intfName) {
775 //add extra route to vpn mapping; advertise with nexthop as tunnel ip
778 LogicalDatastoreType.OPERATIONAL,
779 VpnUtil.getVpnToExtrarouteIdentifier(
780 (rd != null) ? rd : routerID, destination),
781 VpnUtil.getVpnToExtraroute(destination, nextHop));
783 if (intfName != null && !intfName.isEmpty()) {
784 BigInteger dpnId = InterfaceUtils.getDpnForInterface(interfaceManager, intfName);
785 String nextHopIp = InterfaceUtils.getEndpointIpAddressForDPN(broker, dpnId);
786 if (nextHopIp == null || nextHopIp.isEmpty()) {
787 LOG.warn("NextHop for interface {} is null / empty. Failed advertising extra route for prefix {}", intfName, destination);
792 addPrefixToBGP(rd, destination, nextHop, label);
794 // ### add FIB route directly
795 addFibEntryToDS(routerID, destination, nextHop, label);
799 protected void delExtraRoute(String destination, String rd, String routerID) {
801 removePrefixFromBGP(rd, destination);
803 // ### add FIB route directly
804 removeFibEntryFromDS(routerID, destination);
808 class VpnInterfaceOpListener extends org.opendaylight.vpnservice.mdsalutil.AbstractDataChangeListener<VpnInterface> {
810 public VpnInterfaceOpListener() {
811 super(VpnInterface.class);
815 protected void remove(InstanceIdentifier<VpnInterface> identifier, VpnInterface del) {
816 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
817 String interfaceName = key.getName();
818 String vpnName = del.getVpnInstanceName();
820 LOG.trace("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
821 //decrement the vpn interface count in Vpn Instance Op Data
822 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance>
823 id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
824 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance> vpnInstance
825 = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, id);
827 if (vpnInstance.isPresent()) {
829 rd = vpnInstance.get().getVrfId();
830 //String rd = getRouteDistinguisher(del.getVpnInstanceName());
832 VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
833 LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} in Vpn Op Instance {}",
834 interfaceName, rd, vpnName, vpnInstOp);
836 if (vpnInstOp != null) {
837 // Vpn Interface removed => No more adjacencies from it.
838 // Hence clean up interface from vpn-dpn-interface list.
839 Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
840 Optional<Prefixes> prefixToInterface = Optional.absent();
841 prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
842 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
843 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
844 if (!prefixToInterface.isPresent()) {
845 prefixToInterface = VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL,
846 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
847 VpnUtil.getIpPrefix(adjacency.getNextHopIp())));
849 if (prefixToInterface.isPresent()) {
850 VpnUtil.delete(broker, LogicalDatastoreType.OPERATIONAL,
851 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
852 prefixToInterface.get().getIpAddress()),
853 VpnUtil.DEFAULT_CALLBACK);
854 updateDpnDbs(prefixToInterface.get().getDpnId(), del.getVpnInstanceName(), interfaceName, false);
857 ifCnt = vpnInstOp.getVpnInterfaceCount();
858 LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {} Intf count {}",
859 interfaceName, rd, vpnName, ifCnt);
860 if ((ifCnt != null) && (ifCnt > 0)) {
861 VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
862 VpnUtil.getVpnInstanceOpDataIdentifier(rd),
863 VpnUtil.updateIntfCntInVpnInstOpData(ifCnt - 1, rd), VpnUtil.DEFAULT_CALLBACK);
867 LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
869 notifyTaskIfRequired(interfaceName);
872 private void notifyTaskIfRequired(String intfName) {
873 Runnable notifyTask = vpnIntfMap.remove(intfName);
874 if (notifyTask == null) {
877 executorService.execute(notifyTask);
881 protected void update(InstanceIdentifier<VpnInterface> identifier, VpnInterface original, VpnInterface update) {
885 protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {
886 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
887 String interfaceName = key.getName();
889 //increment the vpn interface count in Vpn Instance Op Data
891 String rd = getRouteDistinguisher(add.getVpnInstanceName());
892 if(rd == null || rd.isEmpty()) rd = add.getVpnInstanceName();
893 VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(broker, rd);
894 if(vpnInstOp != null && vpnInstOp.getVpnInterfaceCount() != null) {
895 ifCnt = vpnInstOp.getVpnInterfaceCount();
898 LOG.trace("VpnInterfaceOpListener add: interface name {} rd {} interface count in Vpn Op Instance {}", interfaceName, rd, ifCnt);
900 VpnUtil.asyncUpdate(broker, LogicalDatastoreType.OPERATIONAL,
901 VpnUtil.getVpnInstanceOpDataIdentifier(rd),
902 VpnUtil.updateIntfCntInVpnInstOpData(ifCnt + 1, rd), VpnUtil.DEFAULT_CALLBACK);
908 protected void updatePrefixesForDPN(BigInteger dpnId, UpdateRouteAction action) {
910 LOG.info("Tunnel event triggered {} for Dpn:{} ", action.name(), dpnId);
911 InstanceIdentifierBuilder<VpnInstances> idBuilder = InstanceIdentifier.builder(VpnInstances.class);
912 InstanceIdentifier<VpnInstances> vpnInstancesId = idBuilder.build();
913 Optional<VpnInstances> vpnInstances = VpnUtil.read(broker, LogicalDatastoreType.CONFIGURATION, vpnInstancesId);
915 if (vpnInstances.isPresent()) {
916 List<VpnInstance> vpnInstanceList = vpnInstances.get().getVpnInstance();
917 Iterator<VpnInstance> vpnInstIter = vpnInstanceList.iterator();
918 while (vpnInstIter.hasNext()) {
919 VpnInstance vpnInstance = vpnInstIter.next();
921 VpnAfConfig vpnConfig = vpnInstance.getIpv4Family();
922 String rd = vpnConfig.getRouteDistinguisher();
923 if (rd == null || rd.isEmpty()) {
924 rd = vpnInstance.getVpnInstanceName();
926 InstanceIdentifier<VpnToDpnList> id =
927 VpnUtil.getVpnToDpnListIdentifier(rd, dpnId);
928 Optional<VpnToDpnList> dpnInVpn =
929 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, id);
930 if (dpnInVpn.isPresent()) {
931 // if (action == UpdateRouteAction.ADVERTISE_ROUTE) {
932 // fibManager.populateFibOnNewDpn(dpnId, VpnUtil
933 // .getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
935 List<org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
936 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces>
937 vpnInterfaces = dpnInVpn.get().getVpnInterfaces();
938 for (org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.vpn.instance.op.data
939 .vpn.instance.op.data.entry.vpn.to.dpn.list.VpnInterfaces vpnInterface : vpnInterfaces) {
940 InstanceIdentifier<VpnInterface> vpnIntfId =
941 VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getInterfaceName());
942 InstanceIdentifier<Adjacencies> path =
943 vpnIntfId.augmentation(Adjacencies.class);
944 Optional<Adjacencies> adjacencies =
945 VpnUtil.read(broker, LogicalDatastoreType.OPERATIONAL, path);
947 if (adjacencies.isPresent()) {
948 List<Adjacency> adjacencyList = adjacencies.get().getAdjacency();
949 Iterator<Adjacency> adjacencyIterator = adjacencyList.iterator();
951 while (adjacencyIterator.hasNext()) {
952 Adjacency adjacency = adjacencyIterator.next();
954 if (action == UpdateRouteAction.ADVERTISE_ROUTE)
955 bgpManager.addPrefix(rd, adjacency.getIpAddress(),
956 adjacency.getNextHopIp(),
957 adjacency.getLabel().intValue());
958 else if (action == UpdateRouteAction.WITHDRAW_ROUTE)
959 bgpManager.deletePrefix(rd, adjacency.getIpAddress());
960 } catch (Exception e) {
961 LOG.error("Exception when updating prefix {} in vrf {} to BGP",
962 adjacency.getIpAddress(), rd);
968 // if (action == UpdateRouteAction.WITHDRAW_ROUTE) {
969 // fibManager.cleanUpDpnForVpn(dpnId, VpnUtil.getVpnId(broker, vpnInstance.getVpnInstanceName()), rd);
972 } catch (Exception e) {
973 LOG.error("updatePrefixesForDPN {} in vpn {} failed", dpnId, vpnInstance.getVpnInstanceName(), e);
979 InstanceIdentifier<DpnVpninterfacesList> getRouterDpnId(String routerName, BigInteger dpnId) {
980 return InstanceIdentifier.builder(NeutronRouterDpns.class)
981 .child(RouterDpnList.class, new RouterDpnListKey(routerName))
982 .child(DpnVpninterfacesList.class, new DpnVpninterfacesListKey(dpnId)).build();
985 InstanceIdentifier<RouterDpnList> getRouterId(String routerName) {
986 return InstanceIdentifier.builder(NeutronRouterDpns.class)
987 .child(RouterDpnList.class, new RouterDpnListKey(routerName)).build();
990 protected void addToNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
991 BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
992 if(dpId.equals(BigInteger.ZERO)) {
993 LOG.warn("Could not retrieve dp id for interface {} to handle router {} association model", vpnInterfaceName, routerName);
996 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
998 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
999 .CONFIGURATION, routerDpnListIdentifier);
1000 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1001 if (optionalRouterDpnList.isPresent()) {
1002 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
1003 RouterInterfaces.class, new RouterInterfacesKey(vpnInterfaceName)), routerInterface);
1005 MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION,
1006 getRouterId(routerName),
1007 new RouterDpnListBuilder().setRouterId(routerName).build());
1008 //VpnToDpnListBuilder vpnToDpnList = new VpnToDpnListBuilder().setDpnId(dpnId);
1009 DpnVpninterfacesListBuilder dpnVpnList = new DpnVpninterfacesListBuilder().setDpnId(dpId);
1010 List<RouterInterfaces> routerInterfaces = new ArrayList<>();
1011 routerInterfaces.add(routerInterface);
1012 MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier,
1013 dpnVpnList.setRouterInterfaces(routerInterfaces).build());
1017 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName) {
1018 BigInteger dpId = InterfaceUtils.getDpnForInterface(interfaceManager, vpnInterfaceName);
1019 if(dpId.equals(BigInteger.ZERO)) {
1020 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1023 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1024 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1025 .CONFIGURATION, routerDpnListIdentifier);
1026 if (optionalRouterDpnList.isPresent()) {
1027 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1028 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1030 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1031 if (routerInterfaces.isEmpty()) {
1032 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier);
1034 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
1035 RouterInterfaces.class,
1036 new RouterInterfacesKey(vpnInterfaceName)));
1042 protected void removeFromNeutronRouterDpnsMap(String routerName, String vpnInterfaceName,BigInteger dpId) {
1043 if(dpId.equals(BigInteger.ZERO)) {
1044 LOG.warn("Could not retrieve dp id for interface {} to handle router {} dissociation model", vpnInterfaceName, routerName);
1047 InstanceIdentifier<DpnVpninterfacesList> routerDpnListIdentifier = getRouterDpnId(routerName, dpId);
1048 Optional<DpnVpninterfacesList> optionalRouterDpnList = VpnUtil.read(broker, LogicalDatastoreType
1049 .CONFIGURATION, routerDpnListIdentifier);
1050 if (optionalRouterDpnList.isPresent()) {
1051 List<RouterInterfaces> routerInterfaces = optionalRouterDpnList.get().getRouterInterfaces();
1052 RouterInterfaces routerInterface = new RouterInterfacesBuilder().setKey(new RouterInterfacesKey(vpnInterfaceName)).setInterface(vpnInterfaceName).build();
1054 if (routerInterfaces != null && routerInterfaces.remove(routerInterface)) {
1055 if (routerInterfaces.isEmpty()) {
1056 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier);
1058 MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, routerDpnListIdentifier.child(
1059 RouterInterfaces.class,
1060 new RouterInterfacesKey(vpnInterfaceName)));