package org.opendaylight.netvirt.dhcpservice;
import com.google.common.base.Optional;
+import com.google.common.collect.Lists;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
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.DataStoreJobCoordinator;
import org.opendaylight.genius.interfacemanager.interfaces.IInterfaceManager;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepLogicalSwitchRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepNodeName;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorAugmentation;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepPhysicalLocatorRef;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacsBuilder;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPoint;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.node.TerminationPointKey;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
import org.slf4j.Logger;
}
public RemoteMcastMacs createRemoteMcastMac(Node dstDevice, String logicalSwitchName, IpAddress internalTunnelIp) {
- List<LocatorSet> locators = new ArrayList<>();
- for (TerminationPoint tp : dstDevice.getTerminationPoint()) {
- HwvtepPhysicalLocatorAugmentation aug = tp.getAugmentation(HwvtepPhysicalLocatorAugmentation.class);
- if (internalTunnelIp.getIpv4Address().equals(aug.getDstIp().getIpv4Address())) {
- HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
- HwvtepSouthboundUtils.createPhysicalLocatorInstanceIdentifier(dstDevice.getNodeId(), aug));
- locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
- }
- }
+ Set<LocatorSet> locators = new HashSet<>();
+ TerminationPointKey terminationPointKey = HwvtepSouthboundUtils.getTerminationPointKey(
+ internalTunnelIp.getIpv4Address().getValue());
+ HwvtepPhysicalLocatorRef phyLocRef = new HwvtepPhysicalLocatorRef(
+ HwvtepSouthboundUtils.createInstanceIdentifier(dstDevice.getNodeId()).child(TerminationPoint.class,
+ terminationPointKey));
+ locators.add(new LocatorSetBuilder().setLocatorRef(phyLocRef).build());
+
HwvtepLogicalSwitchRef lsRef = new HwvtepLogicalSwitchRef(HwvtepSouthboundUtils
.createLogicalSwitchesInstanceIdentifier(dstDevice.getNodeId(), new HwvtepNodeName(logicalSwitchName)));
- RemoteMcastMacs remoteUcastMacs = new RemoteMcastMacsBuilder()
+ RemoteMcastMacs remoteMcastMacs = new RemoteMcastMacsBuilder()
.setMacEntryKey(new MacAddress(UNKNOWN_DMAC))
- .setLogicalSwitchRef(lsRef).setLocatorSet(locators).build();
- return remoteUcastMacs;
+ .setLogicalSwitchRef(lsRef).build();
+ InstanceIdentifier<RemoteMcastMacs> iid = HwvtepSouthboundUtils.createRemoteMcastMacsInstanceIdentifier(
+ dstDevice.getNodeId(), remoteMcastMacs.getKey());
+ ReadOnlyTransaction transaction = broker.newReadOnlyTransaction();
+ try {
+ //TODO do async mdsal read
+ remoteMcastMacs = transaction.read(LogicalDatastoreType.CONFIGURATION, iid).checkedGet().get();
+ locators.addAll(remoteMcastMacs.getLocatorSet());
+ return new RemoteMcastMacsBuilder(remoteMcastMacs).setLocatorSet(new ArrayList<>(locators)).build();
+ } catch (ReadFailedException e) {
+ LOG.error("Failed to read the macs {}", iid);
+ }
+ return null;
}
private WriteTransaction putRemoteMcastMac(WriteTransaction transaction, String elanName,
WriteTransaction transaction = broker.newWriteOnlyTransaction();
putRemoteMcastMac(transaction, elanInstanceName, device, internalTunnelIp);
if (transaction != null) {
- transaction.submit();
+ return Lists.newArrayList(transaction.submit());
}
}
return null;
--- /dev/null
+/*
+ * Copyright (c) 2016 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.dhcpservice;
+
+import com.google.common.base.Optional;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+import java.util.function.Predicate;
+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.mdsalutil.MDSALUtil;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.L2GatewayDevice;
+import org.opendaylight.netvirt.neutronvpn.api.l2gw.utils.L2GatewayCacheUtils;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.PhysicalSwitchAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.Switches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.physical._switch.attributes.TunnelIps;
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class DhcpL2GwUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpL2GwUtil.class);
+
+ private static final Predicate<List> EMPTY_LIST = (list) -> list == null || list.isEmpty();
+
+ private static final Predicate<Optional<Node>> CONTAINS_GLOBAL_AUGMENTATION = (optionalNode) -> {
+ return optionalNode.isPresent() && optionalNode.get().getAugmentation(HwvtepGlobalAugmentation.class) != null;
+ };
+
+ private static final Predicate<Optional<Node>> CONTAINS_SWITCH_AUGMENTATION = (optionalNode) -> {
+ return optionalNode.isPresent() && optionalNode.get().getAugmentation(PhysicalSwitchAugmentation.class) != null;
+ };
+
+ private final DataBroker dataBroker;
+
+ @Inject
+ public DhcpL2GwUtil(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public IpAddress getHwvtepNodeTunnelIp(InstanceIdentifier<Node> nodeIid) {
+ ConcurrentMap<String, L2GatewayDevice> devices = L2GatewayCacheUtils.getCache();
+ String nodeId = nodeIid.firstKeyOf(Node.class).getNodeId().getValue();
+ L2GatewayDevice targetDevice = null;
+ for (L2GatewayDevice device : devices.values()) {
+ if (nodeId.equals(device.getHwvtepNodeId())) {
+ targetDevice = device;
+ break;
+ }
+ }
+ return targetDevice != null ? targetDevice.getTunnelIp() : getTunnelIp(nodeIid);
+ }
+
+
+ private IpAddress getTunnelIp(InstanceIdentifier<Node> nodeIid) {
+ Optional<Node> nodeOptional =
+ MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, nodeIid);
+ if (!CONTAINS_GLOBAL_AUGMENTATION.test(nodeOptional)) {
+ return null;
+ }
+ List<Switches> switchIids = nodeOptional.get().getAugmentation(HwvtepGlobalAugmentation.class).getSwitches();
+ if (EMPTY_LIST.test(switchIids)) {
+ return null;
+ }
+ InstanceIdentifier<Node> psIid = (InstanceIdentifier<Node>) switchIids.get(0).getSwitchRef().getValue();
+ nodeOptional = MDSALUtil.read(dataBroker, LogicalDatastoreType.OPERATIONAL, psIid);
+ if (!CONTAINS_SWITCH_AUGMENTATION.test(nodeOptional)) {
+ return null;
+ }
+ List<TunnelIps> tunnelIps = nodeOptional.get().getAugmentation(PhysicalSwitchAugmentation.class).getTunnelIps();
+ if (EMPTY_LIST.test(tunnelIps)) {
+ return null;
+ }
+ return tunnelIps.get(0).getKey().getTunnelIpsKey();
+ }
+
+}
\ No newline at end of file
@PostConstruct
public void init() {
if (config.isControllerDhcpEnabled()) {
- registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
+ //Taken care by mcast mac listener
+ //registerListener(LogicalDatastoreType.OPERATIONAL, dataBroker);
}
}
@Override
@PreDestroy
public void close() {
- super.close();
+ //super.close();
LOG.info("DhcpLogicalSwitchListener Closed");
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.dhcpservice;
+
+import java.math.BigInteger;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+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.hwvtep.HwvtepAbstractDataTreeChangeListener;
+import org.opendaylight.genius.utils.hwvtep.HwvtepSouthboundConstants;
+import org.opendaylight.netvirt.dhcpservice.api.DhcpMConstants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.dhcpservice.config.rev150710.DhcpserviceConfig;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.HwvtepGlobalAugmentation;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.LogicalSwitches;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.hwvtep.rev150901.hwvtep.global.attributes.RemoteMcastMacs;
+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;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Singleton
+public class DhcpMcastMacListener
+ extends HwvtepAbstractDataTreeChangeListener<RemoteMcastMacs, DhcpMcastMacListener>
+ implements AutoCloseable {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DhcpMcastMacListener.class);
+
+ private final DataBroker dataBroker;
+ private final DhcpExternalTunnelManager externalTunnelManager;
+ private final DhcpL2GwUtil dhcpL2GwUtil;
+ private final DhcpserviceConfig config;
+
+ @Inject
+ public DhcpMcastMacListener(DhcpExternalTunnelManager dhcpManager,
+ DhcpL2GwUtil dhcpL2GwUtil,
+ DataBroker dataBroker,
+ final DhcpserviceConfig config) {
+ super(RemoteMcastMacs.class, DhcpMcastMacListener.class);
+ this.externalTunnelManager = dhcpManager;
+ this.dataBroker = dataBroker;
+ this.dhcpL2GwUtil = dhcpL2GwUtil;
+ this.config = config;
+ }
+
+ @PostConstruct
+ public void init() {
+ if (config.isControllerDhcpEnabled()) {
+ registerListener(LogicalDatastoreType.CONFIGURATION, dataBroker);
+ }
+ }
+
+ @PreDestroy
+ public void close() {
+ if (config.isControllerDhcpEnabled()) {
+ super.close();
+ }
+ }
+
+ @Override
+ protected void updated(InstanceIdentifier<RemoteMcastMacs> identifier,
+ RemoteMcastMacs original, RemoteMcastMacs update) {
+ }
+
+ @Override
+ protected void added(InstanceIdentifier<RemoteMcastMacs> identifier,
+ RemoteMcastMacs add) {
+ String elanInstanceName = getElanName(add);
+ IpAddress tunnelIp = dhcpL2GwUtil.getHwvtepNodeTunnelIp(identifier.firstIdentifierOf(Node.class));
+ if (tunnelIp == null) {
+ LOG.error("Could not find tunnelIp for {}", identifier);
+ return;
+ }
+ List<BigInteger> dpns = DhcpServiceUtils.getListOfDpns(dataBroker);
+ BigInteger designatedDpnId = externalTunnelManager.designateDpnId(tunnelIp, elanInstanceName, dpns);
+ if (designatedDpnId == null || designatedDpnId.equals(DhcpMConstants.INVALID_DPID)) {
+ LOG.error("Unable to designate a DPN for {}", identifier);
+ }
+ }
+
+ @Override
+ protected void removed(InstanceIdentifier<RemoteMcastMacs> identifier,
+ RemoteMcastMacs del) {
+ String elanInstanceName = getElanName(del);
+ IpAddress tunnelIp = dhcpL2GwUtil.getHwvtepNodeTunnelIp(identifier.firstIdentifierOf(Node.class));
+ if (tunnelIp == null) {
+ LOG.error("Could not find tunnelIp for {}", identifier);
+ return;
+ }
+ BigInteger designatedDpnId = externalTunnelManager.readDesignatedSwitchesForExternalTunnel(
+ tunnelIp, elanInstanceName);
+ if (designatedDpnId == null) {
+ LOG.error("Could not find designated DPN ID elanInstanceName {}, tunnelIp {}", elanInstanceName, tunnelIp);
+ return;
+ }
+ externalTunnelManager.removeDesignatedSwitchForExternalTunnel(designatedDpnId, tunnelIp, elanInstanceName);
+ }
+
+ @Override
+ protected InstanceIdentifier<RemoteMcastMacs> getWildCardPath() {
+ return InstanceIdentifier.create(NetworkTopology.class)
+ .child(Topology.class, new TopologyKey(HwvtepSouthboundConstants.HWVTEP_TOPOLOGY_ID))
+ .child(Node.class).augmentation(HwvtepGlobalAugmentation.class)
+ .child(RemoteMcastMacs.class);
+ }
+
+ @Override
+ protected DhcpMcastMacListener getDataTreeChangeListener() {
+ return DhcpMcastMacListener.this;
+ }
+
+ String getElanName(RemoteMcastMacs mac) {
+ InstanceIdentifier<LogicalSwitches> logicalSwitchIid = (InstanceIdentifier<LogicalSwitches>)
+ mac.getLogicalSwitchRef().getValue();
+ return logicalSwitchIid.firstKeyOf(LogicalSwitches.class).getHwvtepNodeName().getValue();
+ }
+}
\ No newline at end of file