2 * Copyright (c) 2016, 2017 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.ovsdb.hwvtepsouthbound;
11 import com.google.common.collect.Sets;
12 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
13 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependentJob;
14 import org.opendaylight.ovsdb.hwvtepsouthbound.transact.TransactCommand;
15 import org.opendaylight.ovsdb.lib.notation.UUID;
16 import org.opendaylight.ovsdb.schema.hardwarevtep.LogicalSwitch;
17 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalLocator;
18 import org.opendaylight.ovsdb.schema.hardwarevtep.PhysicalSwitch;
19 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionHistory;
20 import org.opendaylight.ovsdb.utils.mdsal.utils.TransactionType;
21 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
22 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
23 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteUcastMacs;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
25 import org.opendaylight.yangtools.yang.binding.Identifiable;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
30 import java.util.HashMap;
31 import java.util.Iterator;
34 import java.util.concurrent.ConcurrentHashMap;
37 * HwvtepDeviceInfo is used to store some of the table entries received
38 * in updates from a Hwvtep device. There will be one instance of this per
39 * Hwvtep device connected. Table entries are stored in a map keyed by
40 * uuids of respective rows.
42 * Purpose of this class is to provide data present in tables which
43 * were updated in a previous transaction and are not available in
44 * current updatedRows. This allows us to handle updates for Tables
45 * which reference other tables and need information in those tables
46 * to add data to Operational data store.
48 * e.g. Mac-entries in data store use logical-switch-ref as one of the
49 * keys. Mac-entry updates from switch rarely contain Logical_Switch
50 * table entries. To add mac-entries we need table entries from
51 * Logical_Switch table which were created in an earlier update.
54 public class HwvtepDeviceInfo {
56 private static final Logger LOG = LoggerFactory.getLogger(HwvtepDeviceInfo.class);
58 public enum DeviceDataStatus {
64 public static class DeviceData {
65 private final InstanceIdentifier key;
66 private final UUID uuid;
67 private final Object data;
68 private final DeviceDataStatus status;
69 private long intransitTimeStamp;
71 DeviceData(InstanceIdentifier key, UUID uuid, Object data, DeviceDataStatus status) {
76 if (status == DeviceDataStatus.IN_TRANSIT) {
77 intransitTimeStamp = System.currentTimeMillis();
81 public Object getData() {
85 public DeviceDataStatus getStatus() {
89 public UUID getUuid() {
93 public InstanceIdentifier getKey() {
97 public boolean isIntransitTimeExpired() {
98 return System.currentTimeMillis()
99 > intransitTimeStamp + HwvtepSouthboundConstants.IN_TRANSIT_STATE_EXPIRY_TIME_MILLIS;
102 public boolean isInTransitState() {
103 return status == DeviceDataStatus.IN_TRANSIT;
107 private Map<InstanceIdentifier, Set<InstanceIdentifier>> tepIdReferences;
108 private Map<InstanceIdentifier<LogicalSwitches>, Map<InstanceIdentifier<RemoteUcastMacs>, RemoteUcastMacs>> logicalSwitchVsUcasts;
109 private Map<InstanceIdentifier<LogicalSwitches>, Map<InstanceIdentifier<RemoteMcastMacs>, RemoteMcastMacs>> logicalSwitchVsMcasts;
110 private Map<UUID, LogicalSwitch> logicalSwitches = null;
111 private Map<UUID, PhysicalSwitch> physicalSwitches = null;
112 private Map<UUID, PhysicalLocator> physicalLocators = null;
113 private Map<UUID, UUID> mapTunnelToPhysicalSwitch = null;
115 private HwvtepConnectionInstance connectionInstance;
117 private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData = new ConcurrentHashMap<>();
118 private Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> opKeyVsData = new ConcurrentHashMap<>();
119 private Map<Class<? extends Identifiable>, Map<UUID, Object>> uuidVsData = new ConcurrentHashMap<>();
120 private DependencyQueue dependencyQueue;
121 private TransactionHistory controllerTxHistory;
122 private TransactionHistory deviceUpdateHistory;
125 public HwvtepDeviceInfo(HwvtepConnectionInstance hwvtepConnectionInstance) {
126 this.connectionInstance = hwvtepConnectionInstance;
127 this.logicalSwitches = new ConcurrentHashMap<>();
128 this.physicalSwitches = new ConcurrentHashMap<>();
129 this.physicalLocators = new ConcurrentHashMap<>();
130 this.mapTunnelToPhysicalSwitch = new ConcurrentHashMap<>();
131 this.tepIdReferences = new ConcurrentHashMap<>();
132 this.logicalSwitchVsUcasts = new ConcurrentHashMap<>();
133 this.logicalSwitchVsMcasts = new ConcurrentHashMap<>();
134 this.dependencyQueue = new DependencyQueue(this);
137 public LogicalSwitch getLogicalSwitch(UUID uuid) {
138 return (LogicalSwitch) getDeviceOperData(LogicalSwitches.class, uuid);
141 public Map<UUID, LogicalSwitch> getLogicalSwitches() {
142 Map<UUID, Object> switches = uuidVsData.get(LogicalSwitches.class);
143 Map<UUID, LogicalSwitch> result = new HashMap<>();
144 if (switches != null) {
145 for (Map.Entry<UUID, Object> entry : switches.entrySet()) {
146 result.put(entry.getKey(), (LogicalSwitch) entry.getValue());
152 public void putPhysicalSwitch(UUID uuid, PhysicalSwitch pSwitch) {
153 physicalSwitches.put(uuid, pSwitch);
156 public PhysicalSwitch getPhysicalSwitch(UUID uuid) {
157 return physicalSwitches.get(uuid);
160 public PhysicalSwitch removePhysicalSwitch(UUID uuid) {
161 return physicalSwitches.remove(uuid);
164 public Map<UUID, PhysicalSwitch> getPhysicalSwitches() {
165 return physicalSwitches;
168 public PhysicalLocator getPhysicalLocator(UUID uuid) {
169 return (PhysicalLocator) getDeviceOperData(TerminationPoint.class, uuid);
172 public Map<UUID, PhysicalLocator> getPhysicalLocators() {
173 Map<UUID, Object> locators = uuidVsData.get(TerminationPoint.class);
174 Map<UUID, PhysicalLocator> result = new HashMap<>();
175 if (locators != null) {
176 for (Map.Entry<UUID, Object> entry : locators.entrySet()) {
177 result.put(entry.getKey(), (PhysicalLocator) entry.getValue());
183 public void putPhysicalSwitchForTunnel(UUID uuid, UUID psUUID) {
184 mapTunnelToPhysicalSwitch.put(uuid, psUUID);
187 public PhysicalSwitch getPhysicalSwitchForTunnel(UUID uuid) {
188 return physicalSwitches.get(mapTunnelToPhysicalSwitch.get(uuid));
191 public void removePhysicalSwitchForTunnel(UUID uuid) {
192 mapTunnelToPhysicalSwitch.remove(uuid);
195 public Map<UUID, UUID> getPhysicalSwitchesForTunnels() {
196 return mapTunnelToPhysicalSwitch;
199 public boolean isKeyInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
200 DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
201 return deviceData != null && DeviceDataStatus.IN_TRANSIT == deviceData.status;
204 public boolean isConfigDataAvailable(Class<? extends Identifiable> cls, InstanceIdentifier key) {
205 return HwvtepSouthboundUtil.getData(configKeyVsData, cls, key) != null;
208 public void updateConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key, Object data) {
209 HwvtepSouthboundUtil.updateData(configKeyVsData, cls, key,
210 new DeviceData(key, null, data, DeviceDataStatus.AVAILABLE));
213 public Object getConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
214 DeviceData deviceData = HwvtepSouthboundUtil.getData(configKeyVsData, cls, key);
215 if (deviceData != null) {
216 return deviceData.getData();
221 public void clearConfigData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
222 HwvtepSouthboundUtil.clearData(configKeyVsData, cls, key);
225 public void markKeyAsInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
226 LOG.debug("Marking device data as intransit {}", key);
227 DeviceData deviceData = getDeviceOperData(cls, key);
230 if (deviceData != null) {
231 uuid = deviceData.getUuid();
232 data = deviceData.getData();
234 HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
235 new DeviceData(key, uuid, data, DeviceDataStatus.IN_TRANSIT));
238 public void updateDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key, UUID uuid, Object data) {
239 LOG.debug("Updating device data {}", key);
240 HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
241 new DeviceData(key, uuid, data, DeviceDataStatus.AVAILABLE));
242 HwvtepSouthboundUtil.updateData(uuidVsData, cls, uuid, data);
245 public void clearDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
246 DeviceData deviceData = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
247 if (deviceData != null && deviceData.uuid != null) {
248 HwvtepSouthboundUtil.clearData(uuidVsData, cls, deviceData.uuid);
250 HwvtepSouthboundUtil.clearData(opKeyVsData, cls, key);
253 public Object getDeviceOperData(Class<? extends Identifiable> cls, UUID uuid) {
254 return HwvtepSouthboundUtil.getData(uuidVsData, cls, uuid);
257 public DeviceData getDeviceOperData(Class<? extends Identifiable> cls, InstanceIdentifier key) {
258 return HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
261 public UUID getUUID(Class<? extends Identifiable> cls, InstanceIdentifier key) {
262 DeviceData data = HwvtepSouthboundUtil.getData(opKeyVsData, cls, key);
269 public <T extends Identifiable> void addJobToQueue(DependentJob<T> job) {
270 dependencyQueue.addToQueue(job);
273 public void onConfigDataAvailable() {
274 dependencyQueue.processReadyJobsFromConfigQueue(connectionInstance);
277 public synchronized void onOperDataAvailable() {
278 dependencyQueue.processReadyJobsFromOpQueue(connectionInstance);
281 public void scheduleTransaction(final TransactCommand transactCommand) {
282 dependencyQueue.submit(() -> connectionInstance.transact(transactCommand));
285 public void clearDeviceOperData(Class<? extends Identifiable> cls) {
286 Map<InstanceIdentifier, DeviceData> iids = opKeyVsData.get(cls);
287 if (iids != null && !iids.isEmpty()) {
288 Iterator<Map.Entry<InstanceIdentifier, DeviceData>> it = iids.entrySet().iterator();
289 while (it.hasNext()) {
290 Map.Entry<InstanceIdentifier, DeviceData> entry = it.next();
291 DeviceData deviceData = entry.getValue();
292 if (deviceData != null && deviceData.getStatus() != DeviceDataStatus.IN_TRANSIT) {
299 public void clearInTransit(Class<? extends Identifiable> cls, InstanceIdentifier key) {
300 DeviceData deviceData = getDeviceOperData(cls, key);
301 if (deviceData != null && deviceData.isInTransitState()) {
302 if (deviceData.getData() != null) {
303 HwvtepSouthboundUtil.updateData(opKeyVsData, cls, key,
304 new DeviceData(key, deviceData.getUuid(), deviceData.getData(), DeviceDataStatus.AVAILABLE));
306 clearDeviceOperData(cls, key);
311 public Map<InstanceIdentifier, DeviceData> getDeviceOperData(Class<? extends Identifiable> cls) {
312 return opKeyVsData.get(cls);
315 public void incRefCount(InstanceIdentifier reference, InstanceIdentifier tep) {
316 if (reference == null || tep == null) {
319 tepIdReferences.computeIfAbsent(tep, (tepId) -> Sets.newConcurrentHashSet());
320 tepIdReferences.get(tep).add(reference);
323 public int getRefCount(InstanceIdentifier tep) {
324 return tepIdReferences.containsKey(tep) ? tepIdReferences.get(tep).size() : 0;
327 public Set<InstanceIdentifier> getRefCounts(InstanceIdentifier tep) {
328 return tepIdReferences.get(tep);
331 public void decRefCount(InstanceIdentifier reference, InstanceIdentifier tep) {
332 if (reference == null || tep == null || !tepIdReferences.containsKey(tep)) {
335 //synchronize to make sure that no two parallel deletes puts the key in transit state twice
336 synchronized (this) {
337 boolean removed = tepIdReferences.get(tep).remove(reference);
338 if (removed && tepIdReferences.get(tep).isEmpty()) {
339 LOG.debug("Marking the termination point as in transit ref count zero {} ", tep);
340 markKeyAsInTransit(TerminationPoint.class, tep);
345 public void clearLogicalSwitchRefs(InstanceIdentifier<LogicalSwitches> logicalSwitchKey) {
346 Map<InstanceIdentifier<RemoteMcastMacs>, RemoteMcastMacs> mcasts = logicalSwitchVsMcasts.get(logicalSwitchKey);
347 if (mcasts != null ) {
348 mcasts.entrySet().forEach( (entry) -> removeRemoteMcast(logicalSwitchKey, entry.getKey()));
350 Map<InstanceIdentifier<RemoteUcastMacs>, RemoteUcastMacs> ucasts = logicalSwitchVsUcasts.get(logicalSwitchKey);
351 if (ucasts != null ) {
352 ucasts.entrySet().forEach( (entry) -> removeRemoteUcast(logicalSwitchKey, entry.getKey()));
354 markKeyAsInTransit(LogicalSwitches.class, logicalSwitchKey);
357 public void updateRemoteMcast(InstanceIdentifier<LogicalSwitches> lsIid,
358 InstanceIdentifier<RemoteMcastMacs> mcastIid,
359 RemoteMcastMacs mac) {
360 logicalSwitchVsMcasts.computeIfAbsent(lsIid, (lsKey) -> new ConcurrentHashMap<>());
361 logicalSwitchVsMcasts.get(lsIid).put(mcastIid, mac);
362 if (mac.getLocatorSet() != null) {
363 mac.getLocatorSet().forEach( (iid) -> incRefCount(mcastIid, iid.getLocatorRef().getValue()));
367 public void updateRemoteUcast(InstanceIdentifier<LogicalSwitches> lsIid,
368 InstanceIdentifier<RemoteUcastMacs> ucastIid,
369 RemoteUcastMacs mac) {
370 logicalSwitchVsUcasts.computeIfAbsent(lsIid, (lsKey) -> new ConcurrentHashMap<>());
371 logicalSwitchVsUcasts.get(lsIid).put(ucastIid, mac);
372 incRefCount(ucastIid, mac.getLocatorRef().getValue());
375 public void removeRemoteMcast(InstanceIdentifier<LogicalSwitches> lsIid, InstanceIdentifier<RemoteMcastMacs> mcastIid) {
376 if (!logicalSwitchVsMcasts.containsKey(lsIid)) {
379 RemoteMcastMacs mac = logicalSwitchVsMcasts.get(lsIid).remove(mcastIid);
380 if (mac != null && mac.getLocatorSet() != null) {
381 mac.getLocatorSet().forEach((iid) -> decRefCount(mcastIid, iid.getLocatorRef().getValue()));
383 markKeyAsInTransit(RemoteMcastMacs.class, mcastIid);
386 public void removeRemoteUcast(InstanceIdentifier<LogicalSwitches> lsIid,
387 InstanceIdentifier<RemoteUcastMacs> ucastIid) {
388 if (!logicalSwitchVsUcasts.containsKey(lsIid)) {
391 RemoteUcastMacs mac = logicalSwitchVsUcasts.get(lsIid).remove(ucastIid);
393 decRefCount(ucastIid, mac.getLocatorRef().getValue());
395 markKeyAsInTransit(RemoteUcastMacs.class, ucastIid);
398 public HwvtepConnectionInstance getConnectionInstance() {
399 return connectionInstance;
402 public void setConfigKeyVsData(Map<Class<? extends Identifiable>, Map<InstanceIdentifier, DeviceData>> configKeyVsData) {
403 this.configKeyVsData = configKeyVsData;
406 public void setControllerTxHistory(TransactionHistory controllerTxHistory) {
407 this.controllerTxHistory = controllerTxHistory;
410 public void setDeviceUpdateHistory(TransactionHistory deviceUpdateHistory) {
411 this.deviceUpdateHistory = deviceUpdateHistory;
414 public void addToControllerTx(TransactionType transactionType, Object object) {
415 controllerTxHistory.addToHistory(transactionType, object);
418 public void addToDeviceUpdate(TransactionType transactionType, Object object) {
419 deviceUpdateHistory.addToHistory(transactionType, object);