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;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.ListenableFuture;
14 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
15 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
16 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
17 import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker.DataChangeScope;
18 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
19 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
20 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
21 import org.opendaylight.netvirt.vpnmanager.utilities.InterfaceUtils;
22 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.interfaces.VpnInterface;
23 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
24 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
25 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.router.interfaces.RouterInterface;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.Ports;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
31 import org.opendaylight.yangtools.concepts.ListenerRegistration;
32 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
36 import java.math.BigInteger;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.concurrent.Callable;
40 import java.util.concurrent.ExecutionException;
42 public class InterfaceStateChangeListener extends AbstractDataChangeListener<Interface> implements AutoCloseable {
43 private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateChangeListener.class);
44 private ListenerRegistration<DataChangeListener> listenerRegistration;
45 private final DataBroker dataBroker;
46 private final VpnInterfaceManager vpnInterfaceManager;
48 public InterfaceStateChangeListener(final DataBroker dataBroker, VpnInterfaceManager vpnInterfaceManager) {
49 super(Interface.class);
50 this.dataBroker = dataBroker;
51 this.vpnInterfaceManager = vpnInterfaceManager;
55 LOG.info("{} start", getClass().getSimpleName());
56 listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.OPERATIONAL,
57 getWildCardPath(), this, DataChangeScope.SUBTREE);
60 private InstanceIdentifier<Interface> getWildCardPath() {
61 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
65 public void close() throws Exception {
66 if (listenerRegistration != null) {
67 listenerRegistration.close();
68 listenerRegistration = null;
70 LOG.info("{} close", getClass().getSimpleName());
74 protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
75 LOG.trace("Received interface {} add event", intrf);
76 LOG.info("Received interface {} add event", intrf.getName());
78 final String interfaceName = intrf.getName();
79 LOG.info("Received interface add event for interface {} ", interfaceName);
80 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface
81 configInterface = InterfaceUtils.getInterface(dataBroker, interfaceName);
82 if (configInterface != null) {
83 if (!configInterface.getType().equals(Tunnel.class)) {
84 // We service only VM interfaces and Router interfaces here.
85 // We donot service Tunnel Interfaces here.
86 // Tunnel events are directly serviced
87 // by TunnelInterfacesStateListener present as part of VpnInterfaceManager
88 LOG.debug("Config Interface Name {}", configInterface.getName());
89 final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
90 if (vpnInterface != null) {
91 LOG.debug("VPN Interface Name {}", vpnInterface);
92 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
93 final int ifIndex = intrf.getIfIndex();
94 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
95 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
96 new Callable<List<ListenableFuture<Void>>>() {
98 public List<ListenableFuture<Void>> call() throws Exception {
99 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
100 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
101 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
102 vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex, false,
103 writeConfigTxn, writeOperTxn, writeInvTxn);
104 String routerName = VpnUtil.getNeutronRouterFromInterface(dataBroker, interfaceName);
105 if (routerName != null) {
106 LOG.debug("Router Name {} ", routerName);
107 handleRouterInterfacesUpEvent(routerName, interfaceName, writeOperTxn);
109 LOG.info("Unable to process add for interface {} for NAT service", interfaceName);
111 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
112 futures.add(writeOperTxn.submit());
113 futures.add(writeConfigTxn.submit());
114 futures.add(writeInvTxn.submit());
121 LOG.error("Unable to process add for interface {} ," +
122 "since Interface ConfigDS entry absent for the same", interfaceName);
124 } catch (Exception e) {
125 LOG.error("Exception caught in Interface Operational State Up event", e);
130 protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
131 LOG.trace("Received interface {} down event", intrf);
132 LOG.info("Received interface {} remove event", intrf.getName());
134 final String interfaceName = intrf.getName();
135 LOG.info("Received port DOWN event for interface {} ", interfaceName);
136 if (intrf != null && intrf.getType() != null && intrf.getType().equals(Tunnel.class)) {
137 //withdraw all prefixes in all vpns for this dpn from bgp
138 // FIXME: Blocked until tunnel event[vxlan/gre] support is available
139 // vpnInterfaceManager.updatePrefixesForDPN(dpId, VpnInterfaceManager.UpdateRouteAction.WITHDRAW_ROUTE);
141 BigInteger dpId = BigInteger.ZERO;
142 InstanceIdentifier<VpnInterface> id = VpnUtil.getVpnInterfaceIdentifier(interfaceName);
143 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, id);
144 if (!optVpnInterface.isPresent()) {
145 LOG.debug("Interface {} is not a vpninterface, ignoring.", intrf.getName());
148 final VpnInterface vpnInterface = optVpnInterface.get();
150 dpId = InterfaceUtils.getDpIdFromInterface(intrf);
151 } catch (Exception e){
152 LOG.warn("Unable to retrieve dpnId from interface operational data store for interface {}. Fetching from vpn interface op data store. ", intrf.getName(), e);
153 dpId = vpnInterface.getDpnId();
155 final BigInteger dpnId = dpId;
156 final int ifIndex = intrf.getIfIndex();
157 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
158 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + intrf.getName(),
159 new Callable<List<ListenableFuture<Void>>>() {
161 public List<ListenableFuture<Void>> call() throws Exception {
162 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
163 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
164 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
165 vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, false, false,
166 writeConfigTxn, writeOperTxn, writeInvTxn);
167 RouterInterface routerInterface = VpnUtil.getConfiguredRouterInterface(dataBroker, interfaceName);
168 if (routerInterface != null) {
169 handleRouterInterfacesDownEvent(routerInterface.getRouterName(), interfaceName, dpnId, writeOperTxn);
171 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
172 futures.add(writeOperTxn.submit());
173 futures.add(writeConfigTxn.submit());
174 futures.add(writeInvTxn.submit());
179 } catch (Exception e) {
180 LOG.error("Exception observed in handling deletion of VPN Interface {}. ", intrf.getName(), e);
185 protected void update(InstanceIdentifier<Interface> identifier,
186 Interface original, Interface update) {
187 LOG.trace("Operation Interface update event - Old: {}, New: {}", original, update);
188 final String interfaceName = update.getName();
189 if (original.getOperStatus().equals(Interface.OperStatus.Unknown) ||
190 update.getOperStatus().equals(Interface.OperStatus.Unknown)){
191 LOG.debug("Interface {} state change is from/to UNKNOWN. Ignoring the update event.", interfaceName);
194 final BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(update);
195 final int ifIndex = update.getIfIndex();
196 if (update != null) {
197 if (!update.getType().equals(Tunnel.class)) {
198 final VpnInterface vpnInterface = VpnUtil.getConfiguredVpnInterface(dataBroker, interfaceName);
199 if (vpnInterface != null) {
200 if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
201 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
202 dataStoreCoordinator.enqueueJob("VPNINTERFACE-" + interfaceName,
203 new Callable<List<ListenableFuture<Void>>>() {
205 public List<ListenableFuture<Void>> call() throws Exception {
206 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
207 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
208 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
209 vpnInterfaceManager.processVpnInterfaceUp(dpnId, vpnInterface, ifIndex,
210 true, writeConfigTxn, writeOperTxn, writeInvTxn);
211 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
212 futures.add(writeOperTxn.submit());
213 futures.add(writeConfigTxn.submit());
214 futures.add(writeInvTxn.submit());
218 } else if (update.getOperStatus().equals(Interface.OperStatus.Down)) {
219 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
220 dataStoreCoordinator.enqueueJob(interfaceName,
221 new Callable<List<ListenableFuture<Void>>>() {
223 public List<ListenableFuture<Void>> call() throws Exception {
224 WriteTransaction writeConfigTxn = dataBroker.newWriteOnlyTransaction();
225 WriteTransaction writeOperTxn = dataBroker.newWriteOnlyTransaction();
226 WriteTransaction writeInvTxn = dataBroker.newWriteOnlyTransaction();
227 vpnInterfaceManager.processVpnInterfaceDown(dpnId, interfaceName, ifIndex, true, false,
228 writeConfigTxn, writeOperTxn, writeInvTxn);
229 List<ListenableFuture<Void>> futures = new ArrayList<ListenableFuture<Void>>();
230 futures.add(writeOperTxn.submit());
231 futures.add(writeConfigTxn.submit());
232 futures.add(writeInvTxn.submit());
242 void handleRouterInterfacesUpEvent(String routerName, String interfaceName, WriteTransaction writeOperTxn) {
243 LOG.debug("Handling UP event for router interface {} in Router {}", interfaceName, routerName);
244 vpnInterfaceManager.addToNeutronRouterDpnsMap(routerName, interfaceName, writeOperTxn);
247 void handleRouterInterfacesDownEvent(String routerName, String interfaceName, BigInteger dpnId,
248 WriteTransaction writeOperTxn) {
249 LOG.debug("Handling DOWN event for router interface {} in Router {}", interfaceName, routerName);
250 vpnInterfaceManager.removeFromNeutronRouterDpnsMap(routerName, interfaceName, dpnId, writeOperTxn);