import java.util.Collection;
import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.inject.Singleton;
import org.apache.aries.blueprint.annotation.service.Service;
import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayCache;
import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
/**
* Implementation of L2GatewayCache.
@Service(classes = L2GatewayCache.class)
public class L2GatewayCacheImpl implements L2GatewayCache {
private final ConcurrentMap<String, L2GatewayDevice> cache = new ConcurrentHashMap<>();
+ private final ConcurrentMap<String, L2GatewayDevice> cacheByNodeId = new ConcurrentHashMap<>();
@Override
public L2GatewayDevice addOrGet(String deviceName) {
return cache.computeIfAbsent(deviceName, key -> new L2GatewayDevice(deviceName));
}
+ @Override
+ public void add(String deviceName, L2GatewayDevice l2GatewayDevice) {
+ cache.put(deviceName, l2GatewayDevice);
+ }
+
@Override
public L2GatewayDevice remove(String deviceName) {
- return deviceName != null ? cache.remove(deviceName) : null;
+ L2GatewayDevice l2GatewayDevice = deviceName != null ? cache.remove(deviceName) : null;
+ if (l2GatewayDevice != null && l2GatewayDevice.getHwvtepNodeId() != null) {
+ cacheByNodeId.remove(l2GatewayDevice.getHwvtepNodeId());
+ }
+ return l2GatewayDevice;
}
@Override
return deviceName != null ? cache.get(deviceName) : null;
}
+ @Override
+ public L2GatewayDevice getByNodeId(String nodeId) {
+ return nodeId != null ? (L2GatewayDevice) cacheByNodeId.get(nodeId) : null;
+ }
+
@Override
public Collection<L2GatewayDevice> getAll() {
return Collections.unmodifiableCollection(cache.values());
}
-}
+
+ @Override
+ public L2GatewayDevice updateL2GatewayCache(String deviceName, Uuid l2gwUuid) {
+ L2GatewayDevice l2GwDevice = get(deviceName);
+ if (l2GwDevice == null) {
+ l2GwDevice = new L2GatewayDevice(deviceName);
+ l2GwDevice.addL2GatewayId(l2gwUuid);
+ } else {
+ l2GwDevice.addL2GatewayId(l2gwUuid);
+ }
+
+ add(deviceName, l2GwDevice);
+ return l2GwDevice;
+ }
+
+ @Override
+ public L2GatewayDevice updateL2GatewayCache(String deviceName, String hwvtepNodeId, List<TunnelIps> tunnelIps) {
+ L2GatewayDevice l2GwDevice = get(deviceName);
+ if (l2GwDevice == null) {
+ l2GwDevice = new L2GatewayDevice(deviceName);
+ }
+
+ l2GwDevice.setConnected(true);
+ l2GwDevice.setHwvtepNodeId(hwvtepNodeId);
+ if (tunnelIps != null && !tunnelIps.isEmpty()) {
+ Iterator var4 = tunnelIps.iterator();
+
+ while (var4.hasNext()) {
+ TunnelIps tunnelIp = (TunnelIps)var4.next();
+ IpAddress tunnelIpAddr = tunnelIp.getTunnelIpsKey();
+ l2GwDevice.addTunnelIp(tunnelIpAddr);
+ }
+ }
+
+ add(deviceName, l2GwDevice);
+ cacheByNodeId.put(hwvtepNodeId, l2GwDevice);
+ return l2GwDevice;
+ }
+
+ @Override
+ public ConcurrentMap<String, L2GatewayDevice> getCache() {
+ return cache;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.elan.internal;
+
+import com.google.common.base.Optional;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.netvirt.elan.utils.Scheduler;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class ElanGroupCache extends AsyncClusteredDataTreeChangeListenerBase<Group, ElanGroupCache> {
+ private static final Logger LOG = LoggerFactory.getLogger(ElanGroupCache.class);
+ private final DataBroker dataBroker;
+ private final Scheduler scheduler;
+ private final Map<InstanceIdentifier<Group>, Group> groupsById = new ConcurrentHashMap<>();
+ private final Map<InstanceIdentifier<Group>, Collection<Runnable>> waitingJobs = new ConcurrentHashMap<>();
+ private volatile boolean initialized = false;
+
+ @Inject
+ public ElanGroupCache(final DataBroker dataBroker, final Scheduler scheduler) {
+ super(Group.class, ElanGroupCache.class);
+ this.dataBroker = dataBroker;
+ this.scheduler = scheduler;
+ }
+
+ public synchronized void init() {
+ if (!initialized) {
+ initialized = true;
+ this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ }
+ }
+
+ @Override
+ protected InstanceIdentifier<Group> getWildCardPath() {
+ return InstanceIdentifier.builder(Nodes.class)
+ .child(Node.class).augmentation(FlowCapableNode.class)
+ .child(Group.class).build();
+ }
+
+ public synchronized void addJobToWaitList(InstanceIdentifier<Group> key,
+ Runnable job) {
+ if (groupsById.containsKey(key)) {
+ job.run();
+ } else {
+ waitingJobs.putIfAbsent(key, new ArrayList<>());
+ waitingJobs.get(key).add(job);
+ }
+ }
+
+ @Override
+ protected ElanGroupCache getDataTreeChangeListener() {
+ return ElanGroupCache.this;
+ }
+
+ @Override
+ protected synchronized void remove(InstanceIdentifier<Group> key, Group deleted) {
+ groupsById.remove(key);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Group> key, Group old, Group updated) {
+ add(key, updated);
+ }
+
+ @Override
+ protected synchronized void add(InstanceIdentifier<Group> key, Group added) {
+ if (groupsById.containsKey(key)) {
+ groupsById.put(key, added);
+ return;
+ }
+ scheduler.getScheduledExecutorService().schedule(() -> {
+ groupsById.put(key, added);
+ Collection<Runnable> jobs = waitingJobs.remove(key);
+ if (jobs == null) {
+ return;
+ }
+ for (Runnable job : jobs) {
+ job.run();
+ }
+ }, ElanInterfaceManager.WAIT_TIME_FOR_SYNC_INSTALL, TimeUnit.MILLISECONDS);
+ }
+
+ public Optional<Group> getGroup(InstanceIdentifier<Group> key) throws ReadFailedException {
+ if (groupsById.containsKey(key)) {
+ return Optional.of(groupsById.get(key));
+ }
+ ReadOnlyTransaction transaction = dataBroker.newReadOnlyTransaction();
+ Optional<Group> optional = transaction.read(LogicalDatastoreType.CONFIGURATION, key).checkedGet();
+ transaction.close();
+ return optional;
+ }
+}
public class ElanInterfaceManager extends AsyncDataTreeChangeListenerBase<ElanInterface, ElanInterfaceManager>
implements RecoverableListener {
private static final Logger LOG = LoggerFactory.getLogger(ElanInterfaceManager.class);
- private static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
+ public static final long WAIT_TIME_FOR_SYNC_INSTALL = Long.getLong("wait.time.sync.install", 300L);
private static final boolean SH_FLAG_SET = true;
private static final boolean SH_FLAG_UNSET = false;
--- /dev/null
+/*
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+
+package org.opendaylight.netvirt.elan.l2gw.listeners;
+
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.ElanForwardingTables;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.forwarding.tables.MacTable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class ElanMacTableCache extends AsyncClusteredDataTreeChangeListenerBase<MacTable, ElanMacTableCache> {
+ private static final Logger LOG = LoggerFactory.getLogger(ElanMacTableCache.class);
+ private final DataBroker dataBroker;
+ private final ConcurrentHashMap<String, MacTable> macsByElan = new ConcurrentHashMap<>();
+
+ @Inject
+ public ElanMacTableCache(final DataBroker dataBroker) {
+ super(MacTable.class, ElanMacTableCache.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+ }
+
+ @Override
+ protected InstanceIdentifier<MacTable> getWildCardPath() {
+ return InstanceIdentifier.builder(ElanForwardingTables.class).child(MacTable.class).build();
+ }
+
+ @Override
+ protected ElanMacTableCache getDataTreeChangeListener() {
+ return ElanMacTableCache.this;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<MacTable> key, MacTable mac) {
+ macsByElan.remove(mac.getElanInstanceName());
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<MacTable> key, MacTable old, MacTable mac) {
+ macsByElan.put(mac.getElanInstanceName(), mac);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<MacTable> key, MacTable mac) {
+ macsByElan.put(mac.getElanInstanceName(), mac);
+ }
+
+ public MacTable getByElanName(String name) {
+ return macsByElan.get(name);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2019 Ericsson India Global Services Pvt Ltd. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.netvirt.elan.l2gw.listeners;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.annotation.PostConstruct;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.datastoreutils.AsyncClusteredDataTreeChangeListenerBase;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+@Singleton
+public class HwvtepConfigNodeCache extends AsyncClusteredDataTreeChangeListenerBase<Node, HwvtepConfigNodeCache> {
+ private final DataBroker dataBroker;
+ private final Map<InstanceIdentifier<Node>, Node> cache = new ConcurrentHashMap<>();
+ private final Map<InstanceIdentifier<Node>, List<Runnable>> waitList = new ConcurrentHashMap<>();
+
+ @Inject
+ public HwvtepConfigNodeCache(final DataBroker dataBroker) {
+ super(Node.class, HwvtepConfigNodeCache.class);
+ this.dataBroker = dataBroker;
+ }
+
+ @PostConstruct
+ public void init() {
+ this.registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ }
+
+ @Override
+ protected InstanceIdentifier<Node> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+ .child(Node.class);
+ }
+
+ @Override
+ protected HwvtepConfigNodeCache getDataTreeChangeListener() {
+ return HwvtepConfigNodeCache.this;
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Node> key, Node deleted) {
+ cache.remove(key);
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Node> key, Node old, Node added) {
+ cache.put(key, added);
+ }
+
+ @Override
+ protected synchronized void add(InstanceIdentifier<Node> key, Node added) {
+ cache.put(key, added);
+ if (waitList.containsKey(key)) {
+ waitList.remove(key).stream().forEach(runnable -> runnable.run());
+ }
+ }
+
+ public Node getConfigNode(InstanceIdentifier<Node> key) {
+ return cache.get(key);
+ }
+
+ public synchronized void runAfterNodeAvailable(InstanceIdentifier<Node> key, Runnable runnable) {
+ if (cache.containsKey(key)) {
+ runnable.run();
+ } else {
+ waitList.putIfAbsent(key, new ArrayList<>());
+ waitList.get(key).add(runnable);
+ }
+ }
+}
\ No newline at end of file
package org.opendaylight.netvirt.neutronvpn.api.l2gw;
import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
+
+
public interface L2GatewayCache {
@NonNull
L2GatewayDevice addOrGet(@NonNull String deviceName);
+ void add(@NonNull String deviceName, L2GatewayDevice l2GatewayDevice);
+
@Nullable
L2GatewayDevice remove(String deviceName);
@Nullable
L2GatewayDevice get(String deviceName);
+ @Nullable
+ L2GatewayDevice getByNodeId(String nodeId);
+
@NonNull
Collection<L2GatewayDevice> getAll();
+
+ @Nullable
+ L2GatewayDevice updateL2GatewayCache(String psName, Uuid l2gwUuid);
+
+ @Nullable
+ L2GatewayDevice updateL2GatewayCache(String psName, String hwvtepNodeId, List<TunnelIps> tunnelIps);
+
+ @NonNull
+ ConcurrentMap<String, L2GatewayDevice> getCache();
}