2 * Copyright (c) 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
9 package org.opendaylight.genius.itm.listeners;
11 import com.google.common.base.Optional;
12 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
13 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
14 import org.opendaylight.genius.itm.impl.ItmUtils;
15 import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
16 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
17 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
18 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface.OperStatus;
19 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.IfTunnel;
20 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.ParentRefs;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeBase;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeExternal;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeHwvtep;
24 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TepTypeInternal;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelsState;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.external.tunnel.list.ExternalTunnel;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnel.list.InternalTunnel;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.state.tunnel.list.DstInfoBuilder;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.state.tunnel.list.SrcInfoBuilder;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.*;
34 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
38 public class InterfaceStateListener extends AsyncDataTreeChangeListenerBase<Interface, InterfaceStateListener> implements AutoCloseable {
39 private static final Logger LOG = LoggerFactory.getLogger(InterfaceStateListener.class);
41 private final DataBroker broker;
43 public InterfaceStateListener(final DataBroker db) {
44 super(Interface.class, InterfaceStateListener.class);
46 registerListener(broker);
50 public void close() throws Exception {
52 LOG.info("Interface state listener Closed");
55 private void registerListener(final DataBroker db) {
57 registerListener(LogicalDatastoreType.OPERATIONAL,db);
58 } catch (final Exception e) {
59 LOG.error("ITM Interfaces State listener registration fail!", e);
60 throw new IllegalStateException("ITM Interfaces State listener registration failed.", e);
65 protected InstanceIdentifier<Interface> getWildCardPath() {
66 return InstanceIdentifier.create(InterfacesState.class).child(Interface.class);
70 protected InterfaceStateListener getDataTreeChangeListener() {
75 protected void add(InstanceIdentifier<Interface> identifier, Interface iface) {
76 LOG.trace("Interface added: {}", iface);
77 if (ItmUtils.isItmIfType(iface.getType())) {
78 LOG.debug("Interface of type Tunnel added: {}", iface.getName());
79 updateItmState(iface);
84 protected void remove(InstanceIdentifier<Interface> identifier, Interface iface) {
85 LOG.trace("Interface deleted: {}", iface);
86 if (ItmUtils.isItmIfType(iface.getType())) {
87 LOG.debug("Tunnel interface deleted: {}", iface.getName());
88 StateTunnelListKey tlKey = ItmUtils.getTunnelStateKey(iface);
89 InstanceIdentifier<StateTunnelList> stListId = buildStateTunnelListId(tlKey);
90 LOG.trace("Deleting tunnel_state for Id: {}", stListId);
91 ItmUtils.asyncDelete(LogicalDatastoreType.OPERATIONAL, stListId, broker, ItmUtils.DEFAULT_CALLBACK);
96 protected void update(InstanceIdentifier<Interface> identifier, Interface original, Interface update) {
98 * update contains only delta, may not include iftype Note: This assumes
99 * type can't be edited on the fly
101 if (ItmUtils.isItmIfType(original.getType())) {
102 LOG.trace("Interface updated. Old: {} New: {}", original, update);
103 OperStatus operStatus = update.getOperStatus();
104 if (operStatus != null) {
105 LOG.debug("Tunnel Interface {} changed state to {}", original.getName(), operStatus);
106 updateItmState(update);
111 private void updateItmState(Interface iface) {
112 StateTunnelListKey tlKey = ItmUtils.getTunnelStateKey(iface);
113 LOG.trace("TunnelStateKey: {} for interface: {}", tlKey, iface.getName());
114 InstanceIdentifier<StateTunnelList> stListId = buildStateTunnelListId(tlKey);
115 Optional<StateTunnelList> tunnelsState = ItmUtils.read(LogicalDatastoreType.OPERATIONAL, stListId, broker);
116 StateTunnelList tunnelStateList;
117 StateTunnelListBuilder stlBuilder;
118 TunnelOperStatus tunnelOperStatus;
119 boolean tunnelState = iface.getOperStatus().equals(OperStatus.Up);
120 switch (iface.getOperStatus()) {
122 tunnelOperStatus = TunnelOperStatus.Up;
125 tunnelOperStatus = TunnelOperStatus.Down;
128 tunnelOperStatus = TunnelOperStatus.Unknown;
131 tunnelOperStatus = TunnelOperStatus.Ignore;
133 if(tunnelsState.isPresent()) {
134 tunnelStateList = tunnelsState.get();
135 stlBuilder = new StateTunnelListBuilder(tunnelStateList);
136 stlBuilder.setTunnelState(tunnelState);
137 stlBuilder.setOperState(tunnelOperStatus);
138 StateTunnelList stList = stlBuilder.build();
139 LOG.trace("Updating tunnel_state: {} for Id: {}", stList, stListId);
140 ItmUtils.asyncUpdate(LogicalDatastoreType.OPERATIONAL, stListId, stList, broker, ItmUtils.DEFAULT_CALLBACK);
142 // Create new Tunnel State
145 * FIXME: A defensive try-catch to find issues without
146 * disrupting existing behavior.
148 tunnelStateList = buildStateTunnelList(tlKey, iface.getName(), tunnelState, tunnelOperStatus);
149 LOG.trace("Creating tunnel_state: {} for Id: {}", tunnelStateList, stListId);
150 ItmUtils.asyncUpdate(LogicalDatastoreType.OPERATIONAL, stListId, tunnelStateList, broker,
151 ItmUtils.DEFAULT_CALLBACK);
152 } catch (Exception e) {
153 LOG.warn("Exception trying to create tunnel state for {}", iface.getName(), e);
159 private StateTunnelList buildStateTunnelList(StateTunnelListKey tlKey, String name, boolean state, TunnelOperStatus tunOpStatus) {
160 StateTunnelListBuilder stlBuilder = new StateTunnelListBuilder();
161 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface iface = ItmUtils
162 .getInterface(name, broker);
163 IfTunnel ifTunnel = iface.getAugmentation(IfTunnel.class);
164 ParentRefs parentRefs = iface.getAugmentation(ParentRefs.class);
165 if (ifTunnel == null && parentRefs == null) {
168 DstInfoBuilder dstInfoBuilder = new DstInfoBuilder();
169 SrcInfoBuilder srcInfoBuilder = new SrcInfoBuilder();
170 dstInfoBuilder.setTepIp(ifTunnel.getTunnelDestination());
171 srcInfoBuilder.setTepIp(ifTunnel.getTunnelSource());
172 // TODO: Add/Improve logic for device type
173 InternalTunnel internalTunnel = ItmUtils.itmCache.getInternalTunnel(name);
174 ExternalTunnel externalTunnel = ItmUtils.itmCache.getExternalTunnel(name);
175 if (internalTunnel == null && externalTunnel == null) {
176 // both not present in cache. let us update and try again.
177 ItmUtils.updateTunnelsCache(broker);
178 internalTunnel = ItmUtils.itmCache.getInternalTunnel(name);
179 externalTunnel = ItmUtils.itmCache.getExternalTunnel(name);
181 if (internalTunnel != null) {
182 srcInfoBuilder.setTepDeviceId(internalTunnel.getSourceDPN().toString())
183 .setTepDeviceType(TepTypeInternal.class);
184 dstInfoBuilder.setTepDeviceId(internalTunnel.getDestinationDPN().toString())
185 .setTepDeviceType(TepTypeInternal.class);
186 stlBuilder.setTransportType(internalTunnel.getTransportType());
187 } else if (externalTunnel != null) {
188 ExternalTunnel tunnel = ItmUtils.itmCache.getExternalTunnel(name);
189 srcInfoBuilder.setTepDeviceId(tunnel.getSourceDevice())
190 .setTepDeviceType(getDeviceType(tunnel.getSourceDevice()));
191 dstInfoBuilder.setTepDeviceId(tunnel.getDestinationDevice())
192 .setTepDeviceType(getDeviceType(tunnel.getDestinationDevice()))
193 .setTepIp(ifTunnel.getTunnelDestination());
194 stlBuilder.setTransportType(tunnel.getTransportType());
196 stlBuilder.setKey(tlKey).setTunnelInterfaceName(name).setOperState(tunOpStatus).setTunnelState(state)
197 .setDstInfo(dstInfoBuilder.build()).setSrcInfo(srcInfoBuilder.build());
198 return stlBuilder.build();
201 private Class<? extends TepTypeBase> getDeviceType(String device) {
202 if (device.startsWith("hwvtep")) {
203 return TepTypeHwvtep.class;
204 } else if (device.contains("IpAddress")) {
205 return TepTypeExternal.class;
207 return TepTypeInternal.class;
211 private InstanceIdentifier<StateTunnelList> buildStateTunnelListId(StateTunnelListKey tlKey) {
212 return InstanceIdentifier.builder(TunnelsState.class)
213 .child(StateTunnelList.class, tlKey).build();