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.Optional;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.List;
15 import java.util.concurrent.Callable;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ExecutionException;
18 import java.util.concurrent.ExecutorService;
19 import java.util.concurrent.Executors;
20 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
21 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
22 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
23 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
26 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
27 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
28 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
29 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
30 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterfaceKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.Adjacencies;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.adjacency.list.Adjacency;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.prefix.to._interface.vpn.ids.Prefixes;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.op.data.VpnInstanceOpDataEntry;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id.VpnInstance;
36 import org.opendaylight.yangtools.concepts.ListenerRegistration;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
41 public class VpnInterfaceOpListener extends AbstractDataChangeListener<VpnInterface> implements AutoCloseable {
42 private static final Logger LOG = LoggerFactory.getLogger(VpnInterfaceOpListener.class);
43 private ListenerRegistration<DataChangeListener> listenerRegistration;
44 private final DataBroker dataBroker;
45 private final VpnInterfaceManager vpnInterfaceManager;
46 private ConcurrentHashMap<String, Runnable> vpnIntfMap = new ConcurrentHashMap<String, Runnable>();
47 private ExecutorService executorService = Executors.newSingleThreadExecutor();
49 /*public VpnInterfaceOpListener(final DataBroker dataBroker) {
50 super(VpnInterface.class);
51 this.dataBroker = dataBroker;
54 public VpnInterfaceOpListener(final DataBroker dataBroker, final VpnInterfaceManager vpnInterfaceManager) {
55 super(VpnInterface.class);
56 this.dataBroker = dataBroker;
57 this.vpnInterfaceManager = vpnInterfaceManager;
61 LOG.info("{} start", getClass().getSimpleName());
62 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
63 getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
66 private InstanceIdentifier<VpnInterface> getWildCardPath() {
67 return InstanceIdentifier.create(VpnInterfaces.class).child(VpnInterface.class);
71 public void close() throws Exception {
72 if (listenerRegistration != null) {
73 listenerRegistration.close();
74 listenerRegistration = null;
76 LOG.info("{} close", getClass().getSimpleName());
80 protected void remove(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface del) {
81 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
82 final String interfaceName = key.getName();
83 final String vpnName = del.getVpnInstanceName();
84 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
85 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
86 new Callable<List<ListenableFuture<Void>>>() {
88 public List<ListenableFuture<Void>> call() throws Exception {
89 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
90 postProcessVpnInterfaceRemoval(identifier, del, writeOperTxn);
91 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
92 futures.add(writeOperTxn.submit());
98 private void postProcessVpnInterfaceRemoval(InstanceIdentifier<VpnInterface> identifier, VpnInterface del,
99 WriteTransaction writeOperTxn) {
100 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
101 String interfaceName = key.getName();
102 String vpnName = del.getVpnInstanceName();
104 LOG.info("VpnInterfaceOpListener removed: interface name {} vpnName {}", interfaceName, vpnName);
105 //decrement the vpn interface count in Vpn Instance Op Data
106 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
108 id = VpnUtil.getVpnInstanceToVpnIdIdentifier(vpnName);
109 Optional<VpnInstance> vpnInstance
110 = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, id);
112 if (vpnInstance.isPresent()) {
114 rd = vpnInstance.get().getVrfId();
115 //String rd = getRouteDistinguisher(del.getVpnInstanceName());
117 VpnInstanceOpDataEntry vpnInstOp = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
118 LOG.trace("VpnInterfaceOpListener removed: interface name {} rd {} vpnName {}",
119 interfaceName, rd, vpnName);
121 if (vpnInstOp != null) {
122 // Vpn Interface removed => No more adjacencies from it.
123 // Hence clean up interface from vpn-dpn-interface list.
124 Adjacency adjacency = del.getAugmentation(Adjacencies.class).getAdjacency().get(0);
125 List<Prefixes> prefixToInterface = new ArrayList<>();
126 Optional<Prefixes> prefix = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
127 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
128 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
129 if (prefix.isPresent()) {
130 prefixToInterface.add(prefix.get());
132 if (prefixToInterface.isEmpty()) {
133 for (String nh : adjacency.getNextHopIpList()) {
134 prefix = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
135 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
136 VpnUtil.getIpPrefix(nh)));
137 if (prefix.isPresent())
138 prefixToInterface.add(prefix.get());
141 for (Prefixes pref : prefixToInterface) {
142 if (writeOperTxn != null) {
143 writeOperTxn.delete(LogicalDatastoreType.OPERATIONAL,
144 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()));
146 VpnUtil.delete(dataBroker, LogicalDatastoreType.OPERATIONAL,
147 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(), pref.getIpAddress()),
148 VpnUtil.DEFAULT_CALLBACK);
150 vpnInterfaceManager.updateVpnToDpnMapping(pref.getDpnId(), del.getVpnInstanceName(),
151 interfaceName, false /* delete */);
155 LOG.error("rd not retrievable as vpninstancetovpnid for vpn {} is absent, trying rd as ", vpnName, vpnName);
157 notifyTaskIfRequired(interfaceName);
160 private void notifyTaskIfRequired(String intfName) {
161 Runnable notifyTask = vpnIntfMap.remove(intfName);
162 if (notifyTask == null) {
163 LOG.trace("VpnInterfaceOpListener update: No Notify Task queued for vpnInterface {}", intfName);
166 executorService.execute(notifyTask);
170 protected void update(final InstanceIdentifier<VpnInterface> identifier, final VpnInterface original,
171 final VpnInterface update) {
172 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
173 final String interfaceName = key.getName();
175 if (original.getVpnInstanceName().equals(update.getVpnInstanceName())) {
179 final String vpnName = update.getVpnInstanceName();
180 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
181 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
182 new Callable<List<ListenableFuture<Void>>>() {
184 public List<ListenableFuture<Void>> call() throws Exception {
185 postProcessVpnInterfaceUpdate(identifier, original, update);
191 private void postProcessVpnInterfaceUpdate(InstanceIdentifier<VpnInterface> identifier, VpnInterface original,
192 VpnInterface update) {
193 final VpnInterfaceKey key = identifier.firstKeyOf(VpnInterface.class, VpnInterfaceKey.class);
194 String interfaceName = key.getName();
196 //increment the vpn interface count in Vpn Instance Op Data
197 VpnInstanceOpDataEntry vpnInstOp = null;
198 InstanceIdentifier<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to
200 origId = VpnUtil.getVpnInstanceToVpnIdIdentifier(original.getVpnInstanceName());
201 Optional<org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.vpn.instance.to.vpn.id
202 .VpnInstance> origVpnInstance
203 = VpnUtil.read(dataBroker, LogicalDatastoreType.CONFIGURATION, origId);
205 if (origVpnInstance.isPresent()) {
207 rd = origVpnInstance.get().getVrfId();
209 vpnInstOp = VpnUtil.getVpnInstanceOpData(dataBroker, rd);
210 LOG.trace("VpnInterfaceOpListener updated: interface name {} original rd {} original vpnName {}",
211 interfaceName, rd, original.getVpnInstanceName());
213 if (vpnInstOp != null) {
214 Adjacency adjacency = original.getAugmentation(Adjacencies.class).getAdjacency().get(0);
215 List<Prefixes> prefixToInterfaceList = new ArrayList<>();
216 Optional<Prefixes> prefixToInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
217 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
218 VpnUtil.getIpPrefix(adjacency.getIpAddress())));
219 if (prefixToInterface.isPresent()) {
220 prefixToInterfaceList.add(prefixToInterface.get());
222 for (String adj : adjacency.getNextHopIpList()) {
223 prefixToInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL,
224 VpnUtil.getPrefixToInterfaceIdentifier(vpnInstOp.getVpnId(),
225 VpnUtil.getIpPrefix(adj)));
226 if (prefixToInterface.isPresent()) {
227 prefixToInterfaceList.add(prefixToInterface.get());
231 for (Prefixes prefix : prefixToInterfaceList) {
232 vpnInterfaceManager.updateVpnToDpnMapping(prefix.getDpnId(), original.getVpnInstanceName(),
233 interfaceName, false /* delete */);
237 notifyTaskIfRequired(interfaceName);
241 protected void add(InstanceIdentifier<VpnInterface> identifier, VpnInterface add) {