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.cache;
10 import java.util.Collection;
11 import java.util.Collections;
12 import java.util.List;
13 import java.util.Objects;
14 import java.util.Optional;
15 import java.util.concurrent.ConcurrentHashMap;
16 import java.util.concurrent.ConcurrentMap;
17 import javax.inject.Inject;
18 import javax.inject.Singleton;
19 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
20 import org.opendaylight.genius.itm.globals.ITMConstants;
21 import org.opendaylight.genius.itm.impl.ItmUtils;
22 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
23 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorker;
24 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorkerForNodeConnector;
25 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
26 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfoBuilder;
27 import org.opendaylight.genius.itm.utils.TunnelEndPointInfo;
28 import org.opendaylight.genius.itm.utils.TunnelEndPointInfoBuilder;
29 import org.opendaylight.genius.itm.utils.TunnelStateInfo;
30 import org.opendaylight.genius.itm.utils.TunnelStateInfoBuilder;
31 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
32 import org.opendaylight.infrautils.caches.CacheProvider;
33 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
34 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
35 import org.opendaylight.mdsal.binding.api.DataBroker;
36 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunner;
37 import org.opendaylight.mdsal.binding.util.ManagedNewTransactionRunnerImpl;
38 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
39 import org.opendaylight.mdsal.common.api.ReadFailedException;
40 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
41 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.Interface;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rev160406.TunnelMonitoringTypeBfd;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.DpnTepsState;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.endpoints.DPNTEPsInfo;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTeps;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.DpnsTepsKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpns;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.itm.op.rev160406.dpn.teps.state.dpns.teps.RemoteDpnsKey;
49 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
50 import org.opendaylight.yangtools.yang.common.Uint64;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
55 public class DpnTepStateCache extends DataObjectCache<Uint64, DpnsTeps> {
57 private static final Logger LOG = LoggerFactory.getLogger(DpnTepStateCache.class);
58 private static final Logger EVENT_LOGGER = LoggerFactory.getLogger("GeniusEventLogger");
60 private final DataBroker dataBroker;
61 private final JobCoordinator coordinator;
62 private final DirectTunnelUtils directTunnelUtils;
63 private final DPNTEPsInfoCache dpnTepsInfoCache;
64 private final UnprocessedNodeConnectorCache unprocessedNCCache;
65 private final UnprocessedNodeConnectorEndPointCache unprocessedNodeConnectorEndPointCache;
66 private final ManagedNewTransactionRunner txRunner;
67 private final ConcurrentMap<String, DpnTepInterfaceInfo> dpnTepInterfaceMap = new ConcurrentHashMap<>();
68 private final ConcurrentMap<String, TunnelEndPointInfo> tunnelEndpointMap = new ConcurrentHashMap<>();
71 public DpnTepStateCache(DataBroker dataBroker, JobCoordinator coordinator,
72 CacheProvider cacheProvider, DirectTunnelUtils directTunnelUtils,
73 DPNTEPsInfoCache dpnTepsInfoCache,
74 UnprocessedNodeConnectorCache unprocessedNCCache,
75 UnprocessedNodeConnectorEndPointCache unprocessedNodeConnectorEndPointCache) {
76 super(DpnsTeps.class, dataBroker, LogicalDatastoreType.CONFIGURATION,
77 InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class).build(), cacheProvider,
78 (iid, dpnsTeps) -> dpnsTeps.getSourceDpnId(),
79 sourceDpnId -> InstanceIdentifier.builder(DpnTepsState.class)
80 .child(DpnsTeps.class, new DpnsTepsKey(sourceDpnId)).build());
81 this.dataBroker = dataBroker;
82 this.coordinator = coordinator;
83 this.directTunnelUtils = directTunnelUtils;
84 this.dpnTepsInfoCache = dpnTepsInfoCache;
85 this.txRunner = new ManagedNewTransactionRunnerImpl(dataBroker);
86 this.unprocessedNCCache = unprocessedNCCache;
87 this.unprocessedNodeConnectorEndPointCache = unprocessedNodeConnectorEndPointCache;
91 protected void added(InstanceIdentifier<DpnsTeps> path, DpnsTeps dpnsTeps) {
92 String srcOfTunnel = dpnsTeps.getOfTunnel();
93 for (RemoteDpns remoteDpns : dpnsTeps.nonnullRemoteDpns().values()) {
94 final String dpn = getDpnId(dpnsTeps.getSourceDpnId(), remoteDpns.getDestinationDpnId());
95 DpnTepInterfaceInfo value = new DpnTepInterfaceInfoBuilder()
96 .setTunnelName(remoteDpns.getTunnelName())
97 .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
98 .setIsInternal(remoteDpns.isInternal())
99 .setTunnelType(dpnsTeps.getTunnelType())
100 .setRemoteDPN(remoteDpns.getDestinationDpnId()).build();
101 dpnTepInterfaceMap.put(dpn, value);
103 addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(), dpnsTeps.getSourceDpnId(),
104 remoteDpns.getDestinationDpnId());
106 //Process the unprocessed NodeConnector for the Tunnel, if present in the UnprocessedNodeConnectorCache
108 TunnelStateInfo tunnelStateInfoNew = null;
110 TunnelStateInfo tunnelStateInfo;
111 try (Acquired lock = directTunnelUtils.lockTunnel(remoteDpns.getTunnelName())) {
112 if (srcOfTunnel != null && unprocessedNCCache.get(dpn) != null) {
113 tunnelStateInfo = unprocessedNCCache.remove(dpn);
115 tunnelStateInfo = unprocessedNCCache.remove(remoteDpns.getTunnelName());
119 if (tunnelStateInfo != null) {
120 LOG.debug("Processing the Unprocessed NodeConnector for Tunnel {}", remoteDpns.getTunnelName());
122 TunnelEndPointInfo tunnelEndPtInfo = getTunnelEndPointInfo(dpnsTeps.getSourceDpnId(),
123 remoteDpns.getDestinationDpnId());
124 TunnelStateInfoBuilder builder = new TunnelStateInfoBuilder()
125 .setNodeConnectorInfo(tunnelStateInfo.getNodeConnectorInfo()).setDpnTepInterfaceInfo(value)
126 .setTunnelEndPointInfo(tunnelEndPtInfo);
128 dpnTepsInfoCache.getDPNTepFromDPNId(dpnsTeps.getSourceDpnId()).ifPresent(builder::setSrcDpnTepsInfo);
129 dpnTepsInfoCache.getDPNTepFromDPNId(remoteDpns.getDestinationDpnId())
130 .ifPresent(builder::setDstDpnTepsInfo);
132 tunnelStateInfoNew = builder.build();
133 if (tunnelStateInfoNew.getSrcDpnTepsInfo() == null) {
134 String srcDpnId = tunnelStateInfoNew.getTunnelEndPointInfo().getSrcEndPointName();
135 try (Acquired lock = directTunnelUtils.lockTunnel(srcDpnId)) {
136 LOG.debug("Source DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
137 remoteDpns.getTunnelName(), srcDpnId);
138 unprocessedNodeConnectorEndPointCache.add(srcDpnId, tunnelStateInfoNew);
142 if (tunnelStateInfoNew.getDstDpnTepsInfo() == null) {
143 String dstDpnId = tunnelStateInfoNew.getTunnelEndPointInfo().getDstEndPointName();
144 try (Acquired lock = directTunnelUtils.lockTunnel(dstDpnId)) {
145 LOG.debug("Destination DPNTepsInfo is null for tunnel {}. Hence Parking with key {}",
146 remoteDpns.getTunnelName(), dstDpnId);
147 unprocessedNodeConnectorEndPointCache.add(dstDpnId, tunnelStateInfoNew);
152 if (tunnelStateInfoNew != null && tunnelStateInfoNew.getSrcDpnTepsInfo() != null
153 && tunnelStateInfoNew.getDstDpnTepsInfo() != null && directTunnelUtils.isEntityOwner()) {
154 TunnelStateAddWorkerForNodeConnector ifStateAddWorker =
155 new TunnelStateAddWorkerForNodeConnector(new TunnelStateAddWorker(directTunnelUtils, txRunner),
157 EVENT_LOGGER.debug("ITM-DpnTepStateCache,ADD {}", remoteDpns.getTunnelName());
158 coordinator.enqueueJob(remoteDpns.getTunnelName(), ifStateAddWorker, ITMConstants.JOB_MAX_RETRIES);
164 protected void removed(InstanceIdentifier<DpnsTeps> path, DpnsTeps dpnsTeps) {
165 for (RemoteDpns remoteDpns : dpnsTeps.nonnullRemoteDpns().values()) {
166 String fwkey = getDpnId(dpnsTeps.getSourceDpnId(), remoteDpns.getDestinationDpnId());
167 dpnTepInterfaceMap.remove(fwkey);
168 tunnelEndpointMap.remove(remoteDpns.getTunnelName());
169 String revkey = getDpnId(remoteDpns.getDestinationDpnId(), dpnsTeps.getSourceDpnId());
170 dpnTepInterfaceMap.remove(revkey);
174 public DpnTepInterfaceInfo getDpnTepInterface(Uint64 srcDpnId, Uint64 dstDpnId) {
175 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
176 if (dpnTepInterfaceInfo == null) {
178 Optional<DpnsTeps> dpnsTeps = super.get(srcDpnId);
179 if (dpnsTeps.isPresent()) {
180 DpnsTeps teps = dpnsTeps.get();
181 teps.nonnullRemoteDpns().values().forEach(remoteDpns -> {
182 DpnTepInterfaceInfo value = new DpnTepInterfaceInfoBuilder()
183 .setTunnelName(remoteDpns.getTunnelName())
184 .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
185 .setIsInternal(remoteDpns.isInternal())
186 .setTunnelType(teps.getTunnelType())
187 .setRemoteDPN(remoteDpns.getDestinationDpnId()).build();
188 dpnTepInterfaceMap.putIfAbsent(getDpnId(srcDpnId, remoteDpns.getDestinationDpnId()), value);
189 addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
190 teps.getSourceDpnId(), remoteDpns.getDestinationDpnId());
194 } catch (ReadFailedException e) {
195 LOG.error("cache read for dpnID {} in DpnTepStateCache failed ", srcDpnId, e);
198 return dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
201 public void removeTepFromDpnTepInterfaceConfigDS(Uint64 srcDpnId) throws TransactionCommitFailedException {
202 Collection<DpnsTeps> dpnsTeps = this.getAllPresent();
203 for (DpnsTeps dpnTep : dpnsTeps) {
204 if (!Objects.equals(dpnTep.getSourceDpnId(), srcDpnId)) {
205 for (RemoteDpns remoteDpns : dpnTep.nonnullRemoteDpns().values()) {
206 if (Objects.equals(remoteDpns.getDestinationDpnId(), srcDpnId)) {
207 // Remote the SrcDpnId from the remote List. Remove it from COnfig DS. 4
208 // This will be reflected in cache by the ClusteredDTCN. Not removing it here !
209 //Caution :- Batching Delete !!
210 InstanceIdentifier<RemoteDpns> remoteDpnII =
211 buildRemoteDpnsInstanceIdentifier(dpnTep.getSourceDpnId(),
212 remoteDpns.getDestinationDpnId());
213 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
219 // The source DPn id is the one to be removed
220 InstanceIdentifier<DpnsTeps> dpnsTepsII
221 = buildDpnsTepsInstanceIdentifier(dpnTep.getSourceDpnId());
222 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, dpnsTepsII);
227 private static InstanceIdentifier<DpnsTeps> buildDpnsTepsInstanceIdentifier(Uint64 srcDpnId) {
228 return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, new DpnsTepsKey(srcDpnId)).build();
231 private static InstanceIdentifier<RemoteDpns> buildRemoteDpnsInstanceIdentifier(Uint64 srcDpnId, Uint64 dstDpnId) {
232 DpnsTepsKey dpnsTepsKey = new DpnsTepsKey(srcDpnId);
233 RemoteDpnsKey remoteDpnsKey = new RemoteDpnsKey(dstDpnId);
234 return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, dpnsTepsKey)
235 .child(RemoteDpns.class, remoteDpnsKey).build();
238 // Given the tunnel name find out if its internal or external
239 public boolean isInternal(String tunnelName) {
240 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
241 if (endPointInfo != null) {
242 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getSrcEndPointInfo(),
243 endPointInfo.getDstEndPointInfo());
244 return dpnTepInfo != null && dpnTepInfo.isInternal();
249 public boolean isConfigAvailable(String tunnelName) {
250 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
251 if (endPointInfo != null) {
252 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getSrcEndPointInfo(),
253 endPointInfo.getDstEndPointInfo());
254 return dpnTepInfo != null;
259 public DpnTepInterfaceInfo getTunnelFromCache(String tunnelName) {
260 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
261 return getDpnTepInterface(endPointInfo.getSrcEndPointInfo(), endPointInfo.getDstEndPointInfo());
264 // FIXME: this seems to be a cache key -- it should use a composite structure rather than string concat
265 private String getDpnId(Uint64 src, Uint64 dst) {
266 return src + ":" + dst;
269 public Interface getInterfaceFromCache(String tunnelName) {
270 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
271 Uint64 srcDpnId = endPointInfo.getSrcEndPointInfo();
272 Uint64 dstDpnId = endPointInfo.getDstEndPointInfo();
273 Interface iface = null ;
274 int monitoringInt = 1000;
275 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(srcDpnId, dstDpnId);
276 if (dpnTepInfo != null) {
277 List<DPNTEPsInfo> srcDpnTEPsInfo = dpnTepsInfoCache
278 .getDPNTepListFromDPNId(Collections.singletonList(srcDpnId));
279 List<DPNTEPsInfo> dstDpnTEPsInfo = dpnTepsInfoCache
280 .getDPNTepListFromDPNId(Collections.singletonList(dstDpnId));
281 iface = ItmUtils.buildTunnelInterface(srcDpnId, tunnelName,
282 String.format("%s %s", ItmUtils.convertTunnelTypetoString(dpnTepInfo.getTunnelType()),
283 "Trunk Interface"), true, dpnTepInfo.getTunnelType(),
284 srcDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),
285 dstDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),true,
286 dpnTepInfo.isMonitoringEnabled(), TunnelMonitoringTypeBfd.class,
287 monitoringInt, true, null);
292 //Start: TunnelEndPoint Cache accessors
293 private void addTunnelEndPointInfoToCache(String tunnelName, Uint64 srcEndPtInfo, Uint64 dstEndPtInfo) {
294 tunnelEndpointMap.put(tunnelName, getTunnelEndPointInfo(srcEndPtInfo,dstEndPtInfo));
297 private static TunnelEndPointInfo getTunnelEndPointInfo(Uint64 srcEndPtInfo, Uint64 dstEndPtInfo) {
298 return new TunnelEndPointInfoBuilder()
299 .setSrcEndPointInfo(srcEndPtInfo)
300 .setDstEndPointInfo(dstEndPtInfo)
304 public TunnelEndPointInfo getTunnelEndPointInfoFromCache(String tunnelName) {
305 return tunnelEndpointMap.get(tunnelName);
308 public void removeFromTunnelEndPointMap(String tunnelName) {
309 tunnelEndpointMap.remove(tunnelName);