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 com.google.common.util.concurrent.ListenableFuture;
11 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
12 import java.util.Collections;
13 import java.util.List;
15 import java.util.Optional;
16 import java.util.concurrent.Callable;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
20 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
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.api.WriteTransaction;
31 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
32 import org.opendaylight.serviceutils.tools.listener.AbstractClusteredSyncDataTreeChangeListener;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.TunnelOperStatus;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelList;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListBuilder;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.tunnels_state.StateTunnelListKey;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.OvsdbTerminationPointAugmentation;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatus;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.InterfaceBfdStatusKey;
41 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
42 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
43 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
44 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
45 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
49 public class TerminationPointStateListener
50 extends AbstractClusteredSyncDataTreeChangeListener<OvsdbTerminationPointAugmentation> {
52 private static final Logger LOG = LoggerFactory.getLogger(TerminationPointStateListener.class);
53 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
55 private final ManagedNewTransactionRunner txRunner;
56 private final EntityOwnershipUtils entityOwnershipUtils;
57 private final JobCoordinator coordinator;
58 private final BfdStateCache bfdStateCache;
59 private final DpnTepStateCache dpnTepStateCache;
60 private final TunnelStateCache tunnelStateCache;
62 public TerminationPointStateListener(final DataBroker dataBroker, final EntityOwnershipUtils entityOwnershipUtils,
63 final JobCoordinator coordinator, final BfdStateCache bfdStateCache,
64 final DpnTepStateCache dpnTepStateCache,
65 final TunnelStateCache tunnelStateCache) {
66 super(dataBroker, LogicalDatastoreType.OPERATIONAL,
67 InstanceIdentifier.create(NetworkTopology.class).child(Topology.class).child(Node.class)
68 .child(TerminationPoint.class).augmentation(OvsdbTerminationPointAugmentation.class));
69 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
70 this.entityOwnershipUtils = entityOwnershipUtils;
71 this.coordinator = coordinator;
72 this.bfdStateCache = bfdStateCache;
73 this.dpnTepStateCache = dpnTepStateCache;
74 this.tunnelStateCache = tunnelStateCache;
79 public void remove(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
80 @NonNull OvsdbTerminationPointAugmentation tpOld) {
81 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpOld.getName())
82 && dpnTepStateCache.isInternal(tpOld.getName())) {
83 LOG.debug("Received remove DataChange Notification for ovsdb termination point {}", tpOld.getName());
84 if (tpOld.getInterfaceBfdStatus() != null) {
85 LOG.debug("Received termination point removed notification with bfd status values {}", tpOld.getName());
86 RendererTunnelStateRemoveWorker rendererStateRemoveWorker = new RendererTunnelStateRemoveWorker(tpOld);
87 coordinator.enqueueJob(tpOld.getName(), rendererStateRemoveWorker);
93 public void update(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
94 @NonNull OvsdbTerminationPointAugmentation tpOld,
95 @NonNull OvsdbTerminationPointAugmentation tpNew) {
96 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpNew.getName())
97 && dpnTepStateCache.isInternal(tpNew.getName())) {
98 LOG.debug("Received Update DataChange Notification for ovsdb termination point {}", tpNew.getName());
99 if (DirectTunnelUtils.changeInBfdMonitoringDetected(tpOld, tpNew)
100 || DirectTunnelUtils.ifBfdStatusNotEqual(tpOld, tpNew)) {
101 EVENT_LOGGER.debug("ITM-TerminationPointState,UPDATE {}", tpNew.getName());
102 LOG.info("Bfd Status changed for ovsdb termination point identifier: {}, old: {}, new: {}",
103 identifier, tpOld, tpNew);
104 RendererTunnelStateUpdateWorker rendererStateAddWorker = new RendererTunnelStateUpdateWorker(tpNew);
105 coordinator.enqueueJob(tpNew.getName(), rendererStateAddWorker, ITMConstants.JOB_MAX_RETRIES);
111 public void add(@NonNull InstanceIdentifier<OvsdbTerminationPointAugmentation> identifier,
112 @NonNull OvsdbTerminationPointAugmentation tpNew) {
113 if (DirectTunnelUtils.TUNNEL_PORT_PREDICATE.test(tpNew.getName())
114 && dpnTepStateCache.isInternal(tpNew.getName())) {
115 LOG.debug("Received add DataChange Notification for ovsdb termination point {}", tpNew.getName());
116 if (tpNew.getInterfaceBfdStatus() != null && !tpNew.getInterfaceBfdStatus().isEmpty()) {
117 EVENT_LOGGER.debug("ITM-TerminationPointState,ADD {}", tpNew.getName());
118 LOG.debug("Received termination point added notification with bfd status values {}", tpNew.getName());
119 RendererTunnelStateUpdateWorker rendererStateUpdateWorker = new RendererTunnelStateUpdateWorker(tpNew);
120 coordinator.enqueueJob(tpNew.getName(), rendererStateUpdateWorker, ITMConstants.JOB_MAX_RETRIES);
125 @SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
126 justification = "https://github.com/spotbugs/spotbugs/issues/811")
127 private List<ListenableFuture<Void>> updateTunnelState(OvsdbTerminationPointAugmentation terminationPointNew) {
128 final String interfaceName = terminationPointNew.getName();
129 final Interface.OperStatus interfaceBfdStatus = getTunnelOpState(terminationPointNew);
130 TunnelOperStatus tunnelState = DirectTunnelUtils.convertInterfaceToTunnelOperState(interfaceBfdStatus);
131 bfdStateCache.add(interfaceName, interfaceBfdStatus);
132 if (!entityOwnershipUtils.isEntityOwner(ITMConstants.ITM_CONFIG_ENTITY, ITMConstants.ITM_CONFIG_ENTITY)) {
133 return Collections.emptyList();
136 coordinator.enqueueJob(interfaceName, () -> {
137 // update opstate of interface if TEP has gone down/up as a result of BFD monitoring
138 Optional<StateTunnelList> stateTnl = tunnelStateCache.get(tunnelStateCache
139 .getStateTunnelListIdentifier(interfaceName));
140 if (stateTnl.isPresent() && stateTnl.get().getOperState() != TunnelOperStatus.Unknown
141 && stateTnl.get().getOperState() != tunnelState) {
142 LOG.debug("updating tunnel state for interface {} as {}", interfaceName,
143 stateTnl.get().getOperState());
144 return Collections.singletonList(txRunner.callWithNewWriteOnlyTransactionAndSubmit(
145 tx -> updateOpState(tx, interfaceName, tunnelState)));
147 return Collections.emptyList();
149 return Collections.emptyList();
152 private Interface.OperStatus getTunnelOpState(OvsdbTerminationPointAugmentation terminationPoint) {
153 if (!DirectTunnelUtils.bfdMonitoringEnabled(terminationPoint.getInterfaceBfd())) {
154 return Interface.OperStatus.Up;
156 @Nullable Map<InterfaceBfdStatusKey, InterfaceBfdStatus> tunnelBfdStatus =
157 terminationPoint.getInterfaceBfdStatus();
158 if (tunnelBfdStatus != null && !tunnelBfdStatus.isEmpty()) {
159 for (InterfaceBfdStatus bfdState : tunnelBfdStatus.values()) {
160 if (DirectTunnelUtils.BFD_OP_STATE.equalsIgnoreCase(bfdState.getBfdStatusKey())) {
161 String bfdOpState = bfdState.getBfdStatusValue();
162 return DirectTunnelUtils.BFD_STATE_UP.equalsIgnoreCase(bfdOpState)
163 ? Interface.OperStatus.Up : Interface.OperStatus.Down;
167 return Interface.OperStatus.Down;
171 * update operational state of interface based on events like tunnel
174 private static void updateOpState(WriteTransaction transaction, String interfaceName, TunnelOperStatus operStatus) {
175 StateTunnelListKey stateTnlKey = new StateTunnelListKey(interfaceName);
176 InstanceIdentifier<StateTunnelList> stateTnlII = ItmUtils.buildStateTunnelListId(stateTnlKey);
177 LOG.debug("updating tep interface state as {} for {}", operStatus.name(), interfaceName);
178 StateTunnelListBuilder stateTnlBuilder = new StateTunnelListBuilder().withKey(stateTnlKey);
179 stateTnlBuilder.setOperState(operStatus);
180 transaction.mergeParentStructureMerge(LogicalDatastoreType.OPERATIONAL, stateTnlII, stateTnlBuilder.build());
183 private class RendererTunnelStateUpdateWorker implements Callable<List<? extends ListenableFuture<?>>> {
184 private final OvsdbTerminationPointAugmentation terminationPointNew;
186 RendererTunnelStateUpdateWorker(OvsdbTerminationPointAugmentation tpNew) {
187 this.terminationPointNew = tpNew;
191 public List<ListenableFuture<Void>> call() throws Exception {
192 // If another renderer(for eg : OVS) needs to be supported, check can be performed here
193 // to call the respective helpers.
194 return updateTunnelState(terminationPointNew);
198 private class RendererTunnelStateRemoveWorker implements Callable<List<? extends ListenableFuture<?>>> {
199 private final OvsdbTerminationPointAugmentation terminationPointOld;
201 RendererTunnelStateRemoveWorker(OvsdbTerminationPointAugmentation tpNew) {
202 this.terminationPointOld = tpNew;
206 public List<ListenableFuture<Void>> call() throws Exception {
207 LOG.debug("Removing bfd state from cache, if any, for {}", terminationPointOld.getName());
208 bfdStateCache.remove(terminationPointOld.getName());
209 return Collections.emptyList();