2 * Copyright (c) 2018 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.genius.itm.itmdirecttunnels.listeners;
10 import static org.opendaylight.mdsal.binding.util.Datastore.OPERATIONAL;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
14 import java.util.Collections;
15 import java.util.List;
17 import java.util.Optional;
18 import java.util.concurrent.Callable;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.opendaylight.genius.itm.cache.BfdStateCache;
22 import org.opendaylight.genius.itm.cache.DpnTepStateCache;
23 import org.opendaylight.genius.itm.cache.TunnelStateCache;
24 import org.opendaylight.genius.itm.globals.ITMConstants;
25 import org.opendaylight.genius.itm.impl.ItmUtils;
26 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
27 import org.opendaylight.genius.utils.clustering.EntityOwnershipUtils;
28 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
29 import org.opendaylight.mdsal.binding.api.DataBroker;
30 import org.opendaylight.mdsal.binding.util.Datastore.Operational;
31 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
32 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
33 import org.opendaylight.mdsal.binding.util.TypedWriteTransaction;
34 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
35 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatusKey;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
45 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
46 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
47 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
48 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
49 import org.slf4j.Logger;
50 import org.slf4j.LoggerFactory;
52 public class TerminationPointStateListener
53 extends AbstractClusteredSyncDataTreeChangeListener<OvsdbTerminationPointAugmentation> {
55 private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
56 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
58 private final ManagedNewTransactionRunner txRunner;
59 private final EntityOwnershipUtils entityOwnershipUtils;
60 private final JobCoordinator coordinator;
61 private final BfdStateCache bfdStateCache;
62 private final DpnTepStateCache dpnTepStateCache;
63 private final TunnelStateCache tunnelStateCache;
65 public TerminationPointStateListener(final DataBroker dataBroker, final EntityOwnershipUtils entityOwnershipUtils,
66 final JobCoordinator coordinator, final BfdStateCache bfdStateCache,
67 final DpnTepStateCache dpnTepStateCache,
68 final TunnelStateCache tunnelStateCache) {
69 super(dataBroker, LogicalDatastoreType.OPERATIONAL,
70 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
71 .child(TerminationPoint.class).augmentation(OvsdbTerminationPointAugmentation.class));
72 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
73 this.entityOwnershipUtils = entityOwnershipUtils;
74 this.coordinator = coordinator;
75 this.bfdStateCache = bfdStateCache;
76 this.dpnTepStateCache = dpnTepStateCache;
77 this.tunnelStateCache = tunnelStateCache;
82 public void remove(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
83 @NonNull OvsdbTerminationPointAugmentation tpOld) {
84 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpOld.getName())
85 && dpnTepStateCache.isInternal(tpOld.getName())) {
86 LOG.debug("Received remove DataChange Notification for ovsdb termination point {}", tpOld.getName());
87 if (tpOld.getInterfaceBfdStatus() != null) {
88 LOG.debug("Received termination point removed notification with bfd status values {}", tpOld.getName());
89 RendererTunnelStateRemoveWorker rendererStateRemoveWorker = new RendererTunnelStateRemoveWorker(tpOld);
90 coordinator.enqueueJob(tpOld.getName(), rendererStateRemoveWorker);
96 public void update(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
97 @NonNull OvsdbTerminationPointAugmentation tpOld,
98 @NonNull OvsdbTerminationPointAugmentation tpNew) {
99 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpNew.getName())
100 && dpnTepStateCache.isInternal(tpNew.getName())) {
101 LOG.debug("Received Update DataChange Notification for ovsdb termination point {}", tpNew.getName());
102 if (DirectTunnelUtils.changeInBfdMonitoringDetected(tpOld, tpNew)
103 || DirectTunnelUtils.ifBfdStatusNotEqual(tpOld, tpNew)) {
104 EVENT_LOGGER.debug("ITM-TerminationPointState,UPDATE {}", tpNew.getName());
105 LOG.info("Bfd Status changed for ovsdb termination point identifier: {}, old: {}, new: {}",
106 identifier, tpOld, tpNew);
107 RendererTunnelStateUpdateWorker rendererStateAddWorker = new RendererTunnelStateUpdateWorker(tpNew);
108 coordinator.enqueueJob(tpNew.getName(), rendererStateAddWorker, ITMConstants.JOB_MAX_RETRIES);
114 public void add(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
115 @NonNull OvsdbTerminationPointAugmentation tpNew) {
116 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpNew.getName())
117 && dpnTepStateCache.isInternal(tpNew.getName())) {
118 LOG.debug("Received add DataChange Notification for ovsdb termination point {}", tpNew.getName());
119 if (tpNew.getInterfaceBfdStatus() != null && !tpNew.getInterfaceBfdStatus().isEmpty()) {
120 EVENT_LOGGER.debug("ITM-TerminationPointState,ADD {}", tpNew.getName());
121 LOG.debug("Received termination point added notification with bfd status values {}", tpNew.getName());
122 RendererTunnelStateUpdateWorker rendererStateUpdateWorker = new RendererTunnelStateUpdateWorker(tpNew);
123 coordinator.enqueueJob(tpNew.getName(), rendererStateUpdateWorker, ITMConstants.JOB_MAX_RETRIES);
128 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
129 justification = "https://github.com/spotbugs/spotbugs/issues/811")
130 private List<ListenableFuture<Void>> updateTunnelState(OvsdbTerminationPointAugmentation terminationPointNew) {
131 final String interfaceName = terminationPointNew.getName();
132 final Interface.OperStatus interfaceBfdStatus = getTunnelOpState(terminationPointNew);
133 TunnelOperStatus tunnelState = DirectTunnelUtils.convertInterfaceToTunnelOperState(interfaceBfdStatus);
134 bfdStateCache.add(interfaceName, interfaceBfdStatus);
135 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
136 return Collections.emptyList();
139 coordinator.enqueueJob(interfaceName, () -> {
140 // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
141 Optional<StateTunnelList> stateTnl = tunnelStateCache.get(tunnelStateCache
142 .getStateTunnelListIdentifier(interfaceName));
143 if (stateTnl.isPresent() && stateTnl.get().getOperState() != TunnelOperStatus.Unknown
144 && stateTnl.get().getOperState() != tunnelState) {
145 LOG.debug("updating tunnel state for interface {} as {}", interfaceName,
146 stateTnl.get().getOperState());
147 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(OPERATIONAL,
148 tx -> updateOpState(tx, interfaceName, tunnelState)));
150 return Collections.emptyList();
152 return Collections.emptyList();
155 private Interface.OperStatus getTunnelOpState(OvsdbTerminationPointAugmentation terminationPoint) {
156 if (!DirectTunnelUtils.bfdMonitoringEnabled(terminationPoint.getInterfaceBfd())) {
157 return Interface.OperStatus.Up;
159 @Nullable Map<InterfaceBfdStatusKey, InterfaceBfdStatus> tunnelBfdStatus =
160 terminationPoint.getInterfaceBfdStatus();
161 if (tunnelBfdStatus != null && !tunnelBfdStatus.isEmpty()) {
162 for (InterfaceBfdStatus bfdState : tunnelBfdStatus.values()) {
163 if (DirectTunnelUtils.BFD_OP_STATE.equalsIgnoreCase(bfdState.getBfdStatusKey())) {
164 String bfdOpState = bfdState.getBfdStatusValue();
165 return DirectTunnelUtils.BFD_STATE_UP.equalsIgnoreCase(bfdOpState)
166 ? Interface.OperStatus.Up : Interface.OperStatus.Down;
170 return Interface.OperStatus.Down;
174 * update operational state of interface based on events like tunnel
177 private static void updateOpState(TypedWriteTransaction<@NonNull Operational> tx, String interfaceName,
178 TunnelOperStatus operStatus) {
179 StateTunnelListKey stateTnlKey = new StateTunnelListKey(interfaceName);
180 InstanceIdentifier<StateTunnelList> stateTnlII = ItmUtils.buildStateTunnelListId(stateTnlKey);
181 LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
182 StateTunnelListBuilder stateTnlBuilder = new StateTunnelListBuilder().withKey(stateTnlKey);
183 stateTnlBuilder.setOperState(operStatus);
184 tx.mergeParentStructureMerge(stateTnlII, stateTnlBuilder.build());
187 private class RendererTunnelStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
188 private final OvsdbTerminationPointAugmentation terminationPointNew;
190 RendererTunnelStateUpdateWorker(OvsdbTerminationPointAugmentation tpNew) {
191 this.terminationPointNew = tpNew;
195 public List<ListenableFuture<Void>> call() throws Exception {
196 // If another renderer(for eg : OVS) needs to be supported, check can be performed here
197 // to call the respective helpers.
198 return updateTunnelState(terminationPointNew);
202 private class RendererTunnelStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
203 private final OvsdbTerminationPointAugmentation terminationPointOld;
205 RendererTunnelStateRemoveWorker(OvsdbTerminationPointAugmentation tpNew) {
206 this.terminationPointOld = tpNew;
210 public List<ListenableFuture<Void>> call() throws Exception {
211 LOG.debug("Removing bfd state from cache, if any, for {}", terminationPointOld.getName());
212 bfdStateCache.remove(terminationPointOld.getName());
213 return Collections.emptyList();