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.infra.ManagedNewTransactionRunner;
21 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
22 import org.opendaylight.genius.itm.globals.ITMConstants;
23 import org.opendaylight.genius.itm.impl.ItmUtils;
24 import org.opendaylight.genius.itm.itmdirecttunnels.renderer.ovs.utilities.DirectTunnelUtils;
25 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorker;
26 import org.opendaylight.genius.itm.itmdirecttunnels.workers.TunnelStateAddWorkerForNodeConnector;
27 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfo;
28 import org.opendaylight.genius.itm.utils.DpnTepInterfaceInfoBuilder;
29 import org.opendaylight.genius.itm.utils.TunnelEndPointInfo;
30 import org.opendaylight.genius.itm.utils.TunnelEndPointInfoBuilder;
31 import org.opendaylight.genius.itm.utils.TunnelStateInfo;
32 import org.opendaylight.genius.itm.utils.TunnelStateInfoBuilder;
33 import org.opendaylight.genius.mdsalutil.cache.DataObjectCache;
34 import org.opendaylight.infrautils.caches.CacheProvider;
35 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
36 import org.opendaylight.infrautils.utils.concurrent.NamedSimpleReentrantLock.Acquired;
37 import org.opendaylight.mdsal.binding.api.DataBroker;
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().toString(),
104 remoteDpns.getDestinationDpnId().toString());
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().toString(),
123 remoteDpns.getDestinationDpnId().toString());
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().getSrcEndPointInfo();
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().getDstEndPointInfo();
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 private DpnTepInterfaceInfo getDpnTepInterface(String srcDpnId, String dstDpnId) {
175 return getDpnTepInterface(Uint64.valueOf(srcDpnId), Uint64.valueOf(dstDpnId));
178 public DpnTepInterfaceInfo getDpnTepInterface(Uint64 srcDpnId, Uint64 dstDpnId) {
179 DpnTepInterfaceInfo dpnTepInterfaceInfo = dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
180 if (dpnTepInterfaceInfo == null) {
182 Optional<DpnsTeps> dpnsTeps = super.get(srcDpnId);
183 if (dpnsTeps.isPresent()) {
184 DpnsTeps teps = dpnsTeps.get();
185 teps.nonnullRemoteDpns().values().forEach(remoteDpns -> {
186 DpnTepInterfaceInfo value = new DpnTepInterfaceInfoBuilder()
187 .setTunnelName(remoteDpns.getTunnelName())
188 .setIsMonitoringEnabled(remoteDpns.isMonitoringEnabled())
189 .setIsInternal(remoteDpns.isInternal())
190 .setTunnelType(teps.getTunnelType())
191 .setRemoteDPN(remoteDpns.getDestinationDpnId()).build();
192 dpnTepInterfaceMap.putIfAbsent(getDpnId(srcDpnId, remoteDpns.getDestinationDpnId()), value);
193 addTunnelEndPointInfoToCache(remoteDpns.getTunnelName(),
194 teps.getSourceDpnId().toString(), remoteDpns.getDestinationDpnId().toString());
198 } catch (ReadFailedException e) {
199 LOG.error("cache read for dpnID {} in DpnTepStateCache failed ", srcDpnId, e);
202 return dpnTepInterfaceMap.get(getDpnId(srcDpnId, dstDpnId));
205 public void removeTepFromDpnTepInterfaceConfigDS(Uint64 srcDpnId) throws TransactionCommitFailedException {
206 Collection<DpnsTeps> dpnsTeps = this.getAllPresent();
207 for (DpnsTeps dpnTep : dpnsTeps) {
208 if (!Objects.equals(dpnTep.getSourceDpnId(), srcDpnId)) {
209 for (RemoteDpns remoteDpns : dpnTep.nonnullRemoteDpns().values()) {
210 if (Objects.equals(remoteDpns.getDestinationDpnId(), srcDpnId)) {
211 // Remote the SrcDpnId from the remote List. Remove it from COnfig DS. 4
212 // This will be reflected in cache by the ClusteredDTCN. Not removing it here !
213 //Caution :- Batching Delete !!
214 InstanceIdentifier<RemoteDpns> remoteDpnII =
215 buildRemoteDpnsInstanceIdentifier(dpnTep.getSourceDpnId(),
216 remoteDpns.getDestinationDpnId());
217 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION,
223 // The source DPn id is the one to be removed
224 InstanceIdentifier<DpnsTeps> dpnsTepsII
225 = buildDpnsTepsInstanceIdentifier(dpnTep.getSourceDpnId());
226 SingleTransactionDataBroker.syncDelete(dataBroker, LogicalDatastoreType.CONFIGURATION, dpnsTepsII);
231 private static InstanceIdentifier<DpnsTeps> buildDpnsTepsInstanceIdentifier(Uint64 srcDpnId) {
232 return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, new DpnsTepsKey(srcDpnId)).build();
235 private static InstanceIdentifier<RemoteDpns> buildRemoteDpnsInstanceIdentifier(Uint64 srcDpnId, Uint64 dstDpnId) {
236 DpnsTepsKey dpnsTepsKey = new DpnsTepsKey(srcDpnId);
237 RemoteDpnsKey remoteDpnsKey = new RemoteDpnsKey(dstDpnId);
238 return InstanceIdentifier.builder(DpnTepsState.class).child(DpnsTeps.class, dpnsTepsKey)
239 .child(RemoteDpns.class, remoteDpnsKey).build();
242 // Given the tunnel name find out if its internal or external
243 public boolean isInternal(String tunnelName) {
244 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
245 if (endPointInfo != null) {
246 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getSrcEndPointInfo(),
247 endPointInfo.getDstEndPointInfo());
248 return dpnTepInfo != null && dpnTepInfo.isInternal();
253 public boolean isConfigAvailable(String tunnelName) {
254 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
255 if (endPointInfo != null) {
256 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(endPointInfo.getSrcEndPointInfo(),
257 endPointInfo.getDstEndPointInfo());
258 return dpnTepInfo != null;
263 public DpnTepInterfaceInfo getTunnelFromCache(String tunnelName) {
264 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
265 return getDpnTepInterface(endPointInfo.getSrcEndPointInfo(), endPointInfo.getDstEndPointInfo());
268 // FIXME: this seems to be a cache key -- it should use a composite structure rather than string concat
269 private String getDpnId(Uint64 src, Uint64 dst) {
270 return src + ":" + dst;
273 public Interface getInterfaceFromCache(String tunnelName) {
274 TunnelEndPointInfo endPointInfo = getTunnelEndPointInfoFromCache(tunnelName);
275 Uint64 srcDpnId = Uint64.valueOf(endPointInfo.getSrcEndPointInfo());
276 Uint64 dstDpnId = Uint64.valueOf(endPointInfo.getDstEndPointInfo());
277 Interface iface = null ;
278 int monitoringInt = 1000;
279 DpnTepInterfaceInfo dpnTepInfo = getDpnTepInterface(srcDpnId, dstDpnId);
280 if (dpnTepInfo != null) {
281 List<DPNTEPsInfo> srcDpnTEPsInfo = dpnTepsInfoCache
282 .getDPNTepListFromDPNId(Collections.singletonList(srcDpnId));
283 List<DPNTEPsInfo> dstDpnTEPsInfo = dpnTepsInfoCache
284 .getDPNTepListFromDPNId(Collections.singletonList(dstDpnId));
285 iface = ItmUtils.buildTunnelInterface(srcDpnId, tunnelName,
286 String.format("%s %s", ItmUtils.convertTunnelTypetoString(dpnTepInfo.getTunnelType()),
287 "Trunk Interface"), true, dpnTepInfo.getTunnelType(),
288 srcDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),
289 dstDpnTEPsInfo.get(0).getTunnelEndPoints().get(0).getIpAddress(),true,
290 dpnTepInfo.isMonitoringEnabled(), TunnelMonitoringTypeBfd.class,
291 monitoringInt, true, null);
296 //Start: TunnelEndPoint Cache accessors
297 private void addTunnelEndPointInfoToCache(String tunnelName, String srcEndPtInfo, String dstEndPtInfo) {
298 tunnelEndpointMap.put(tunnelName, getTunnelEndPointInfo(srcEndPtInfo,dstEndPtInfo));
301 private TunnelEndPointInfo getTunnelEndPointInfo(String srcEndPtInfo, String dstEndPtInfo) {
303 new TunnelEndPointInfoBuilder().setSrcEndPointInfo(srcEndPtInfo).setDstEndPointInfo(dstEndPtInfo).build();
306 public TunnelEndPointInfo getTunnelEndPointInfoFromCache(String tunnelName) {
307 return tunnelEndpointMap.get(tunnelName);
310 public void removeFromTunnelEndPointMap(String tunnelName) {
311 tunnelEndpointMap.remove(tunnelName);