2 * Copyright (c) 2015, 2017 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.ListenableFuture;
12 import java.math.BigInteger;
13 import java.util.ArrayList;
14 import java.util.List;
15 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
18 import org.opendaylight.genius.datastoreutils.DataStoreJobCoordinator;
19 import org.opendaylight.netvirt.neutronvpn.api.utils.NeutronUtils;
20 import org.opendaylight.netvirt.neutronvpn.interfaces.INeutronVpnManager;
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.L2vlan;
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.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.l3vpn.rev130911.port.op.data.PortOpDataEntry;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.ports.attributes.ports.Port;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class SubnetRouteInterfaceStateChangeListener extends AsyncDataTreeChangeListenerBase<Interface,
34 SubnetRouteInterfaceStateChangeListener> implements AutoCloseable {
35 private static final Logger LOG = LoggerFactory.getLogger(SubnetRouteInterfaceStateChangeListener.class);
36 private static final String LOGGING_PREFIX = "SUBNETROUTE:";
37 private final DataBroker dataBroker;
38 private final VpnInterfaceManager vpnInterfaceManager;
39 private final VpnSubnetRouteHandler vpnSubnetRouteHandler;
40 private final SubnetOpDpnManager subOpDpnManager;
41 private final INeutronVpnManager neutronVpnManager;
43 public SubnetRouteInterfaceStateChangeListener(final DataBroker dataBroker,
44 final VpnInterfaceManager vpnInterfaceManager,
45 final VpnSubnetRouteHandler vpnSubnetRouteHandler,
46 final SubnetOpDpnManager subnetOpDpnManager,
47 final INeutronVpnManager neutronVpnService) {
48 super(Interface.class, SubnetRouteInterfaceStateChangeListener.class);
49 this.dataBroker = dataBroker;
50 this.vpnInterfaceManager = vpnInterfaceManager;
51 this.vpnSubnetRouteHandler = vpnSubnetRouteHandler;
52 this.subOpDpnManager = subnetOpDpnManager;
53 this.neutronVpnManager = neutronVpnService;
57 LOG.info("{} start", getClass().getSimpleName());
58 registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
62 protected InstanceIdentifier<Interface> getWildCardPath() {
63 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
67 protected SubnetRouteInterfaceStateChangeListener getDataTreeChangeListener() {
68 return SubnetRouteInterfaceStateChangeListener.this;
71 // TODO Clean up the exception handling
72 @SuppressWarnings("checkstyle:IllegalCatch")
74 protected void add(InstanceIdentifier<Interface> identifier, Interface intrf) {
75 LOG.trace("{} add: Received interface {} up event", LOGGING_PREFIX, intrf);
78 if (L2vlan.class.equals(intrf.getType())) {
79 LOG.trace("SubnetRouteInterfaceListener add: Received interface {} up event", intrf);
80 if (intrf.getOperStatus().equals(Interface.OperStatus.Up)) {
81 subnetId = getSubnetId(intrf);
82 if (subnetId == null) {
83 LOG.error("SubnetRouteInterfaceListener add: Port {} doesnt exist in configDS",
87 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
88 dataStoreCoordinator.enqueueJob("SUBNETROUTE-" + subnetId,
90 List<ListenableFuture<Void>> futures = new ArrayList<>();
91 String interfaceName = intrf.getName();
92 LOG.info("{} add: Received port UP event for interface {} subnetId {}",
93 LOGGING_PREFIX, interfaceName, subnetId.getValue());
95 BigInteger dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
96 vpnSubnetRouteHandler.onInterfaceUp(dpnId, intrf.getName(), subnetId);
97 } catch (Exception e) {
98 LOG.error("{} add: Unable to obtain dpnId for interface {} in subnet {},"
99 + " subnetroute inclusion for this interface failed with exception {}",
100 LOGGING_PREFIX, interfaceName, subnetId.getValue(), e);
106 LOG.info("{} add: Processed interface {} up event", LOGGING_PREFIX, intrf.getName());
107 } catch (Exception e) {
108 LOG.error("{} add: Exception observed in handling addition for VPN Interface {}.", LOGGING_PREFIX,
113 // TODO Clean up the exception handling
114 @SuppressWarnings("checkstyle:IllegalCatch")
116 protected void remove(InstanceIdentifier<Interface> identifier, Interface intrf) {
119 if (L2vlan.class.equals(intrf.getType())) {
120 LOG.trace("SubnetRouteInterfaceListener remove: Received interface {} down event", intrf);
121 subnetId = getSubnetId(intrf);
122 if (subnetId == null) {
123 LOG.error("SubnetRouteInterfaceListener add: Port {} doesnt exist in configDS",
127 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
128 dataStoreCoordinator.enqueueJob("SUBNETROUTE-" + subnetId,
130 String interfaceName = intrf.getName();
131 BigInteger dpnId = BigInteger.ZERO;
132 LOG.info("{} remove: Received port DOWN event for interface {} in subnet {} ",
133 LOGGING_PREFIX, interfaceName, subnetId.getValue());
135 dpnId = InterfaceUtils.getDpIdFromInterface(intrf);
136 } catch (Exception e) {
137 LOG.error("{} remove: Unable to retrieve dpnId for interface {} in subnet {}. "
138 + "Fetching from vpn interface itself due to exception {}",
139 LOGGING_PREFIX, intrf.getName(), subnetId.getValue(), e);
140 InstanceIdentifier<VpnInterface> id = VpnUtil
141 .getVpnInterfaceIdentifier(interfaceName);
142 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker,
143 LogicalDatastoreType.OPERATIONAL, id);
144 if (optVpnInterface.isPresent()) {
145 dpnId = optVpnInterface.get().getDpnId();
148 if (!dpnId.equals(BigInteger.ZERO)) {
149 vpnSubnetRouteHandler.onInterfaceDown(dpnId, intrf.getName(), subnetId);
151 List<ListenableFuture<Void>> futures = new ArrayList<>();
155 LOG.info("{} remove: Processed interface {} down event in ", LOGGING_PREFIX, intrf.getName());
156 } catch (Exception e) {
157 LOG.error("{} remove: Exception observed in handling deletion of VPN Interface {}.", LOGGING_PREFIX,
162 // TODO Clean up the exception handling
163 @SuppressWarnings("checkstyle:IllegalCatch")
165 protected void update(InstanceIdentifier<Interface> identifier,
166 Interface original, Interface update) {
169 String interfaceName = update.getName();
170 if (L2vlan.class.equals(update.getType())) {
171 LOG.trace("{} update: Operation Interface update event - Old: {}, New: {}", LOGGING_PREFIX,
173 subnetId = getSubnetId(update);
174 if (subnetId == null) {
175 LOG.error("SubnetRouteInterfaceListener update: Port {} doesnt exist in configDS",
179 DataStoreJobCoordinator dataStoreCoordinator = DataStoreJobCoordinator.getInstance();
180 dataStoreCoordinator.enqueueJob("SUBNETROUTE-" + subnetId,
182 List<ListenableFuture<Void>> futures = new ArrayList<>();
183 BigInteger dpnId = BigInteger.ZERO;
185 dpnId = InterfaceUtils.getDpIdFromInterface(update);
186 } catch (Exception e) {
187 LOG.error("{} remove: Unable to retrieve dpnId for interface {} in subnet {}. "
188 + "Fetching from vpn interface itself due to exception {}", LOGGING_PREFIX,
189 update.getName(), subnetId.getValue(), e);
190 InstanceIdentifier<VpnInterface> id = VpnUtil
191 .getVpnInterfaceIdentifier(interfaceName);
192 Optional<VpnInterface> optVpnInterface = VpnUtil.read(dataBroker,
193 LogicalDatastoreType.OPERATIONAL, id);
194 if (optVpnInterface.isPresent()) {
195 dpnId = optVpnInterface.get().getDpnId();
198 if (!dpnId.equals(BigInteger.ZERO)) {
199 if (update.getOperStatus().equals(Interface.OperStatus.Up)) {
200 LOG.info("{} update: Received port UP event for interface {} in subnet {}",
201 LOGGING_PREFIX, update.getName(), subnetId.getValue());
202 vpnSubnetRouteHandler.onInterfaceUp(dpnId, update.getName(), subnetId);
203 } else if (update.getOperStatus().equals(Interface.OperStatus.Down)
204 || update.getOperStatus().equals(Interface.OperStatus.Unknown)) {
206 * If the interface went down voluntarily (or) if the interface is not
207 * reachable from control-path involuntarily, trigger subnetRoute election
209 LOG.info("{} update: Received port {} event for interface {} in subnet {} ",
210 LOGGING_PREFIX, update.getOperStatus().equals(Interface.OperStatus.Unknown)
211 ? "UNKNOWN" : "DOWN", update.getName(), subnetId.getValue());
212 vpnSubnetRouteHandler.onInterfaceDown(dpnId, update.getName(), subnetId);
218 LOG.info("{} update: Processed Interface {} update event", LOGGING_PREFIX, update.getName());
219 } catch (Exception e) {
220 LOG.error("{} update: Exception observed in handling deletion of VPNInterface {}", LOGGING_PREFIX,
221 update.getName(), e);
225 protected Uuid getSubnetId(Interface intrf) {
227 if (!NeutronUtils.isUuid(intrf.getName())) {
228 LOG.debug("SubnetRouteInterfaceListener: Interface {} doesnt have valid uuid pattern", intrf.getName());
232 PortOpDataEntry portOpEntry = subOpDpnManager.getPortOpDataEntry(intrf.getName());
233 if (portOpEntry != null) {
234 return portOpEntry.getSubnetId();
236 LOG.trace("SubnetRouteInterfaceListener : Received Port {} event for {} that is not part of subnetRoute",
237 intrf.getOperStatus(), intrf.getName());
238 Port port = neutronVpnManager.getNeutronPort(intrf.getName());
239 if (port != null && port.getFixedIps() != null && port.getFixedIps().size() > 0) {
240 return port.getFixedIps().get(0).getSubnetId();