2 * Copyright (c) 2015 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
12 import java.math.BigInteger;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.ArrayList;
19 import java.util.concurrent.ConcurrentHashMap;
20 import java.util.concurrent.ExecutionException;
21 import java.util.concurrent.Future;
22 import com.google.common.base.Optional;
23 import com.google.common.collect.ImmutableList;
24 import com.google.common.util.concurrent.Futures;
25 import com.google.common.util.concurrent.FutureCallback;
26 import org.opendaylight.bgpmanager.api.IBgpManager;
27 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
28 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
29 import org.opendaylight.fibmanager.api.IFibManager;
30 import org.opendaylight.vpnservice.interfacemgr.interfaces.IInterfaceManager;
31 import org.opendaylight.vpnservice.mdsalutil.FlowEntity;
32 import org.opendaylight.vpnservice.mdsalutil.InstructionInfo;
33 import org.opendaylight.vpnservice.mdsalutil.InstructionType;
34 import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
35 import org.opendaylight.vpnservice.mdsalutil.MatchFieldType;
36 import org.opendaylight.vpnservice.mdsalutil.MatchInfo;
37 import org.opendaylight.vpnservice.mdsalutil.MetaDataUtil;
38 import org.opendaylight.vpnservice.mdsalutil.NwConstants;
39 import org.opendaylight.vpnservice.mdsalutil.interfaces.IMdsalApiManager;
40 import org.opendaylight.yangtools.concepts.ListenerRegistration;
41 import org.opendaylight.yangtools.yang.binding.DataObject;
42 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
43 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
44 import org.opendaylight.yangtools.yang.common.RpcResult;
45 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
46 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
47 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
48 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
49 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
50 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
51 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
52 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
53 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
54 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyList;
55 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
56 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
57 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
58 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
59 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
60 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
61 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
62 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
63 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
64 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
65 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInstances;
66 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstance;
67 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
68 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
69 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
70 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceBuilder;
71 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
72 import org.slf4j.Logger;
73 import org.slf4j.LoggerFactory;
75 public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
76 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceManager.class);
77 private ListenerRegistration<DataChangeListener> listenerRegistration, interfaceListenerRegistration;
78 private final DataBroker broker;
79 private final IBgpManager bgpManager;
80 private IFibManager fibManager;
81 private IMdsalApiManager mdsalManager;
82 private IInterfaceManager interfaceManager;
83 private IdManagerService idManager;
84 private Map<Long, Collection<BigInteger>> vpnToDpnsDb;
85 private Map<BigInteger, Collection<String>> dpnToInterfaceDb;
86 private InterfaceListener interfaceListener;
88 private static final FutureCallback<Void> DEFAULT_CALLBACK =
89 new FutureCallback<Void>() {
90 public void onSuccess(Void result) {
91 LOG.debug("Success in Datastore operation");
94 public void onFailure(Throwable error) {
95 LOG.error("Error in Datastore operation", error);
100 * Responsible for listening to data change related to VPN Interface
101 * Bind VPN Service on the interface and informs the BGP service
103 * @param db - dataBroker service reference
105 public VpnInterfaceManager(final DataBroker db, final IBgpManager bgpManager) {
106 super(VpnInterface.class);
108 this.bgpManager = bgpManager;
109 vpnToDpnsDb = new ConcurrentHashMap<>();
110 dpnToInterfaceDb = new ConcurrentHashMap<>();
111 interfaceListener = new InterfaceListener();
112 registerListener(db);
115 public void setMdsalManager(IMdsalApiManager mdsalManager) {
116 this.mdsalManager = mdsalManager;
119 public void setInterfaceManager(IInterfaceManager interfaceManager) {
120 this.interfaceManager = interfaceManager;
123 public void setFibManager(IFibManager fibManager) {
124 this.fibManager = fibManager;
127 public void setIdManager(IdManagerService idManager) {
128 this.idManager = idManager;
132 public void close() throws Exception {
133 if (listenerRegistration != null) {
135 listenerRegistration.close();
136 interfaceListenerRegistration.close();
137 } catch (final Exception e) {
138 LOG.error("Error when cleaning up DataChangeListener.", e);
140 listenerRegistration = null;
141 interfaceListenerRegistration = null;
143 LOG.info("VPN Interface Manager Closed");
146 private void registerListener(final DataBroker db) {
148 listenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
149 getWildCardPath(), VpnInterfaceManager.this, DataChangeScope.SUBTREE);
150 interfaceListenerRegistration = db.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
151 getInterfaceListenerPath(), interfaceListener, DataChangeScope.SUBTREE);
152 } catch (final Exception e) {
153 LOG.error("VPN Service DataChange listener registration fail!", e);
154 throw new IllegalStateException("VPN Service registration Listener failed.", e);
158 private InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> getInterfaceListenerPath() {
159 return InstanceIdentifier.create(InterfacesState.class)
160 .child(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
164 protected void add(final InstanceIdentifier<VpnInterface> identifier,
165 final VpnInterface vpnInterface) {
166 LOG.trace("key: {} , value: {}", identifier, vpnInterface );
167 addInterface(identifier, vpnInterface);
170 private void addInterface(final InstanceIdentifier<VpnInterface> identifier,
171 final VpnInterface vpnInterface) {
172 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
173 String interfaceName = key.getName();
174 InstanceIdentifierBuilder<Interface> idBuilder =
175 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
176 InstanceIdentifier<Interface> id = idBuilder.build();
177 Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
178 if (port.isPresent()) {
179 Interface interf = port.get();
180 bindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
181 updateNextHops(identifier, vpnInterface);
185 private void updateNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
187 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
188 Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.CONFIGURATION, path);
189 String intfName = intf.getName();
191 if (adjacencies.isPresent()) {
192 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
193 List<Adjacency> value = new ArrayList<>();
195 //Get the rd of the vpn instance
196 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
198 BigInteger dpnId = interfaceManager.getDpnForInterface(intfName);
199 String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
202 LOG.trace("NextHops are {}", nextHops);
203 for (Adjacency nextHop : nextHops) {
204 String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
205 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
206 // long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
207 // .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
208 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
209 VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
210 value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
213 Adjacencies aug = VpnUtil.getVpnInterfaceAugmentation(value);
214 VpnInterface opInterface = VpnUtil.getVpnInterface(intfName, intf.getVpnInstanceName(), aug);
215 InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(intfName);
216 syncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
217 for (Adjacency nextHop : nextHops) {
218 String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
219 String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
220 // long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
221 // .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
222 long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
223 VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
224 updatePrefixToBGP(rd, nextHop, nextHopIp, label);
229 private long getVpnId(String vpnName) {
230 //TODO: This should be a Util function
231 InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
232 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).augmentation(VpnInstance1.class).build();
233 Optional<VpnInstance1> vpnInstance = read(LogicalDatastoreType.OPERATIONAL, id);
235 long vpnId = VpnConstants.INVALID_ID;
236 if(vpnInstance.isPresent()) {
237 vpnId = vpnInstance.get().getVpnId();
242 private String getRouteDistinguisher(String vpnName) {
243 InstanceIdentifier<VpnInstance> id = InstanceIdentifier.builder(VpnInstances.class)
244 .child(VpnInstance.class, new VpnInstanceKey(vpnName)).build();
245 Optional<VpnInstance> vpnInstance = read(LogicalDatastoreType.CONFIGURATION, id);
247 if(vpnInstance.isPresent()) {
248 VpnInstance instance = vpnInstance.get();
249 VpnAfConfig config = instance.getIpv4Family();
250 rd = config.getRouteDistinguisher();
255 private synchronized void updateMappingDbs(long vpnId, BigInteger dpnId, String intfName, String rd) {
256 Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
258 dpnIds = new HashSet<>();
260 if(dpnIds.add(dpnId)) {
261 vpnToDpnsDb.put(vpnId, dpnIds);
262 fibManager.populateFibOnNewDpn(dpnId, vpnId, rd);
265 Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
266 if(intfNames == null) {
267 intfNames = new ArrayList<>();
269 intfNames.add(intfName);
270 dpnToInterfaceDb.put(dpnId, intfNames);
273 private synchronized void remoteFromMappingDbs(long vpnId, BigInteger dpnId, String inftName, String rd) {
274 Collection<String> intfNames = dpnToInterfaceDb.get(dpnId);
275 if(intfNames == null) {
278 intfNames.remove(inftName);
279 dpnToInterfaceDb.put(dpnId, intfNames);
280 //TODO: Delay 'DPN' removal so that other services can cleanup the entries for this dpn
281 if(intfNames.isEmpty()) {
282 Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
286 dpnIds.remove(dpnId);
287 vpnToDpnsDb.put(vpnId, dpnIds);
288 fibManager.cleanUpDpnForVpn(dpnId, vpnId, rd);
292 private void bindServiceOnInterface(Interface intf, String vpnName) {
293 LOG.trace("Bind service on interface {} for VPN: {}", intf, vpnName);
295 long vpnId = getVpnId(vpnName);
296 BigInteger dpId = interfaceManager.getDpnForInterface(intf.getName());
297 if(dpId.equals(BigInteger.ZERO)) {
298 LOG.warn("DPN for interface {} not found. Bind service on this interface aborted.", intf.getName());
301 String rd = getRouteDistinguisher(vpnName);
302 updateMappingDbs(vpnId, dpId, intf.getName(), rd);
305 long portNo = interfaceManager.getPortForInterface(intf.getName());
306 String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
308 String flowName = intf.getName();
309 BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
311 int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
312 short gotoTableId = VpnConstants.FIB_TABLE;
313 if(intf.getType().equals(Tunnel.class)){
314 gotoTableId = VpnConstants.LFIB_TABLE;
317 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
318 mkInstructions.add(new InstructionInfo(InstructionType.write_metadata, new BigInteger[] {
319 BigInteger.valueOf(vpnId), MetaDataUtil.METADATA_MASK_VRFID }));
321 mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] { gotoTableId }));
323 List<MatchInfo> matches = new ArrayList<MatchInfo>();
324 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
325 dpId, BigInteger.valueOf(portNo) }));
327 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
328 priority, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
330 mdsalManager.installFlow(flowEntity);
333 private String getVpnInterfaceFlowRef(BigInteger dpId, short tableId,
334 long vpnId, long portNo) {
335 return new StringBuilder().append(dpId).append(tableId).append(vpnId).append(portNo).toString();
338 private void updatePrefixToBGP(String rd, Adjacency nextHop, String nextHopIp, long label) {
340 bgpManager.addPrefix(rd, nextHop.getIpAddress(), nextHopIp, (int)label);
341 } catch(Exception e) {
342 LOG.error("Add prefix failed", e);
346 private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
347 InstanceIdentifier<T> path) {
349 ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
351 Optional<T> result = Optional.absent();
353 result = tx.read(datastoreType, path).get();
354 } catch (Exception e) {
355 throw new RuntimeException(e);
361 private InstanceIdentifier<VpnInterface> getWildCardPath() {
362 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
366 protected void remove( InstanceIdentifier<VpnInterface> identifier, VpnInterface vpnInterface) {
367 LOG.trace("Remove event - key: {}, value: {}" ,identifier, vpnInterface );
368 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
369 String interfaceName = key.getName();
370 InstanceIdentifierBuilder<Interface> idBuilder =
371 InstanceIdentifier.builder(Interfaces.class).child(Interface.class, new InterfaceKey(interfaceName));
372 InstanceIdentifier<Interface> id = idBuilder.build();
373 Optional<Interface> port = read(LogicalDatastoreType.CONFIGURATION, id);
374 if (port.isPresent()) {
375 Interface interf = port.get();
376 removeNextHops(identifier, vpnInterface);
377 unbindServiceOnInterface(interf, vpnInterface.getVpnInstanceName());
378 //InstanceIdentifier<VpnInterface> interfaceId = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
379 delete(LogicalDatastoreType.OPERATIONAL, identifier);
381 LOG.warn("No nexthops were available to handle remove event {}", interfaceName);
385 private void removeNextHops(final InstanceIdentifier<VpnInterface> identifier, VpnInterface intf) {
387 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
388 Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
389 String intfName = intf.getName();
390 String rd = getRouteDistinguisher(intf.getVpnInstanceName());
391 if (adjacencies.isPresent()) {
392 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
394 if (!nextHops.isEmpty()) {
395 LOG.trace("NextHops are " + nextHops);
396 for (Adjacency nextHop : nextHops) {
397 removePrefixFromBGP(rd, nextHop);
403 private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
404 WriteTransaction tx = broker.newWriteOnlyTransaction();
405 tx.delete(datastoreType, path);
406 Futures.addCallback(tx.submit(), DEFAULT_CALLBACK);
409 private void unbindServiceOnInterface(Interface intf, String vpnName) {
410 LOG.trace("Unbind service on interface {} for VPN: {}", intf, vpnName);
412 long vpnId = getVpnId(vpnName);
413 BigInteger dpId = interfaceManager.getDpnForInterface(intf);
414 if(dpId.equals(BigInteger.ZERO)) {
415 LOG.warn("DPN for interface {} not found. Unbind service on this interface aborted.", intf.getName());
418 String rd = getRouteDistinguisher(vpnName);
419 remoteFromMappingDbs(vpnId, dpId, intf.getName(), rd);
420 LOG.debug("removed vpn mapping for interface {} from VPN RD {}", intf.getName(), rd);
423 long portNo = interfaceManager.getPortForInterface(intf);
424 String flowRef = getVpnInterfaceFlowRef(dpId, VpnConstants.LPORT_INGRESS_TABLE, vpnId, portNo);
426 String flowName = intf.getName();
428 int priority = VpnConstants.DEFAULT_FLOW_PRIORITY;
430 List<MatchInfo> matches = new ArrayList<MatchInfo>();
431 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
432 dpId, BigInteger.valueOf(portNo) }));
434 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
435 priority, flowName, 0, 0, null, matches, null);
436 LOG.debug("Remove ingress flow for port {} in dpn {}", portNo, dpId.intValue());
438 mdsalManager.removeFlow(flowEntity);
441 private void removePrefixFromBGP(String rd, Adjacency nextHop) {
443 bgpManager.deletePrefix(rd, nextHop.getIpAddress());
444 } catch(Exception e) {
445 LOG.error("Delete prefix failed", e);
450 protected void update(InstanceIdentifier<VpnInterface> identifier,
451 VpnInterface original, VpnInterface update) {
452 LOG.trace("Update VPN Interface {} , original {}, update {}",
453 identifier, original, update);
454 String vpnName = original.getVpnInstanceName();
456 boolean vpnNameChanged = false;
457 String rd = getRouteDistinguisher(vpnName);
459 if(!vpnName.equals(update.getVpnInstanceName())) {
460 //VPN for this interface got changed.
461 //Remove the interface from old VPN and add it to new VPN
462 String newVpnName = update.getVpnInstanceName();
463 newRd = getRouteDistinguisher(newVpnName);
464 if(newRd.equals("")) {
465 LOG.warn("VPN Instance {} not found. Update operation aborted", newVpnName);
468 vpnNameChanged = true;
469 LOG.debug("New VPN Name for the interface {} is {}", newVpnName, original.getName());
472 BigInteger dpnId = interfaceManager.getDpnForInterface(original.getName());
473 String nextHopIp = interfaceManager.getEndpointIpForDpn(dpnId);
474 //List<Adjacency> oldAdjs = original.getAugmentation(Adjacencies.class).getAdjacency();
475 List<Adjacency> newAdjs = update.getAugmentation(Adjacencies.class).getAdjacency();
476 if(vpnNameChanged && newAdjs != null && !newAdjs.isEmpty()) {
477 long label = VpnConstants.INVALID_ID;
478 InstanceIdentifier<Adjacencies> path = identifier.augmentation(Adjacencies.class);
479 Optional<Adjacencies> adjacencies = read(LogicalDatastoreType.OPERATIONAL, path);
480 if (adjacencies.isPresent()) {
481 List<Adjacency> nextHops = adjacencies.get().getAdjacency();
482 for(Adjacency nextHop : nextHops) {
483 label = nextHop.getLabel();
484 if(label == VpnConstants.INVALID_ID) {
485 //Generate label using ID Manager
486 String key = newRd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
487 // label = getUniqueId(key);
489 removePrefixFromBGP(rd, nextHop);
490 //updatePrefixToBGP(newRd, nextHop, nextHopIp, label);
492 updateNextHops(identifier, update);
493 asyncUpdate(LogicalDatastoreType.OPERATIONAL, identifier, update, DEFAULT_CALLBACK);
496 LOG.debug("No Update information is available for VPN Interface to proceed");
500 protected <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
501 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
502 WriteTransaction tx = broker.newWriteOnlyTransaction();
503 tx.merge(datastoreType, path, data, true);
504 Futures.addCallback(tx.submit(), callback);
507 private <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
508 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
509 WriteTransaction tx = broker.newWriteOnlyTransaction();
510 tx.put(datastoreType, path, data, true);
511 Futures.addCallback(tx.submit(), callback);
514 private <T extends DataObject> void syncWrite(LogicalDatastoreType datastoreType,
515 InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
516 WriteTransaction tx = broker.newWriteOnlyTransaction();
517 tx.put(datastoreType, path, data, true);
521 synchronized Collection<BigInteger> getDpnsForVpn(long vpnId) {
522 Collection<BigInteger> dpnIds = vpnToDpnsDb.get(vpnId);
524 return ImmutableList.copyOf(dpnIds);
526 return Collections.emptyList();
530 VpnInterface getVpnInterface(String interfaceName) {
531 Optional<VpnInterfaces> optVpnInterfaces = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getVpnInterfacesIdentifier());
532 if(optVpnInterfaces.isPresent()) {
533 List<VpnInterface> interfaces = optVpnInterfaces.get().getVpnInterface();
534 for(VpnInterface intf : interfaces) {
535 if(intf.getName().equals(interfaceName)) {
543 private Interface getInterface(String interfaceName) {
544 Optional<Interface> optInterface = read(LogicalDatastoreType.CONFIGURATION, VpnUtil.getInterfaceIdentifier(interfaceName));
545 if(optInterface.isPresent()) {
546 return optInterface.get();
551 private String getTunnelInterfaceFlowRef(BigInteger dpnId, short tableId, String ifName) {
552 return new StringBuilder().append(dpnId).append(tableId).append(ifName).toString();
556 protected void makeTunnelIngressFlow(BigInteger dpnId, String ifName, int addOrRemoveFlow) {
558 String flowName = ifName;
559 String flowRef = getTunnelInterfaceFlowRef(dpnId, VpnConstants.LPORT_INGRESS_TABLE, ifName);
560 List<MatchInfo> matches = new ArrayList<MatchInfo>();
561 List<InstructionInfo> mkInstructions = new ArrayList<InstructionInfo>();
562 if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
563 portNo = interfaceManager.getPortForInterface(ifName);
564 matches.add(new MatchInfo(MatchFieldType.in_port, new BigInteger[] {
565 dpnId, BigInteger.valueOf(portNo) }));
566 mkInstructions.add(new InstructionInfo(InstructionType.goto_table, new long[] {VpnConstants.LFIB_TABLE}));
569 BigInteger COOKIE_VM_INGRESS_TABLE = new BigInteger("8000001", 16);
570 FlowEntity flowEntity = MDSALUtil.buildFlowEntity(dpnId, VpnConstants.LPORT_INGRESS_TABLE, flowRef,
571 VpnConstants.DEFAULT_FLOW_PRIORITY, flowName, 0, 0, COOKIE_VM_INGRESS_TABLE, matches, mkInstructions);
573 if (NwConstants.ADD_FLOW == addOrRemoveFlow) {
574 mdsalManager.installFlow(flowEntity);
576 mdsalManager.removeFlow(flowEntity);
580 private class InterfaceListener extends AbstractDataChangeListener<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> {
582 public InterfaceListener() {
583 super(org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.class);
587 protected void remove(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
588 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface del) {
589 LOG.trace("Operational Interface remove event - {}", del);
593 protected void update(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
594 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface original,
595 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface update) {
596 LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
597 String interfaceName = update.getName();
598 Interface intf = getInterface(interfaceName);
599 if (intf != null && intf.getType().equals(Tunnel.class)) {
600 BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
601 if(update.getOperStatus().equals(OperStatus.Up)) {
602 //Create ingress to LFIB
603 LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
604 makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
605 } else if(update.getOperStatus().equals(OperStatus.Down)) {
606 LOG.debug("Removing Ingress flow for tunnel interface {}", interfaceName);
607 makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.DEL_FLOW);
610 VpnInterface vpnInterface = getVpnInterface(interfaceName);
611 if(vpnInterface != null) {
612 if(update.getOperStatus().equals(OperStatus.Up)) {
613 LOG.debug("Installing VPN related rules for interface {}", interfaceName);
614 addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
615 } else if(update.getOperStatus().equals(OperStatus.Down)) {
616 LOG.debug("Removing VPN related rules for interface {}", interfaceName);
617 VpnInterfaceManager.this.remove(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
620 LOG.debug("No VPN Interface associated with interface {} to handle Update Operation", interfaceName);
626 protected void add(InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface> identifier,
627 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface add) {
628 LOG.trace("Operational Interface add event - {}", add);
629 String interfaceName = add.getName();
630 Interface intf = getInterface(interfaceName);
631 if (intf != null && intf.getType().equals(Tunnel.class)) {
632 BigInteger dpnId = interfaceManager.getDpnForInterface(interfaceName);
633 if(add.getOperStatus().equals(OperStatus.Up)) {
634 //Create ingress to LFIB
635 LOG.debug("Installing Ingress for tunnel interface {}", interfaceName);
636 makeTunnelIngressFlow(dpnId, interfaceName, NwConstants.ADD_FLOW);
639 VpnInterface vpnInterface = getVpnInterface(interfaceName);
640 if(vpnInterface != null) {
641 if(add.getOperStatus().equals(OperStatus.Up)) {
642 LOG.debug("Installing VPN related rules for interface {}", interfaceName);
643 addInterface(VpnUtil.getVpnInterfaceIdentifier(vpnInterface.getName()), vpnInterface);
646 LOG.debug("No VPN Interface associated with interface {} to handle add Operation", interfaceName);