This patch implements the following.
1. We do Service binding for a port only when a v6 address is
configured on the port. IPv6Address could be part of the port
when its initially created or later (i.e, port updated) after
the VM is spawned. Both cases are handled and the port is
unbinded when the v6Address-is-removed/port-deleted. Once
Service Binding is done, packets would hit the IPV6_TABLE(45)
for further processing.
2. Optimizes the IPv6 punt flows by matching on the elanTag.
Previous patch implements punt flows based on the VM macaddress,
this is not optimal as we have to add VM specific punt flows when
a new VM is added. In this patch, we take into account the elanTag
(i.e., network-id) and configure punt flows for
- icmpv6 Router solicitation requests
- icmpv6 Neighbor solicitation requests for router interface
3. Multiple IPv6 subnets can be added/deleted (even when existing VMs
are present) on the network and those edge cases are handled in
this patchset. IPv6Service maintains a cache of (dpnIds <--> List[ports])
per network. We use this info, while programing flows when IPv6 subnets
are added/deleted to handle the edge cases.
Change-Id: I84c98979e9f6f71feb934a96df68613dd6defc42
Signed-off-by: Sridhar Gaddam <sgaddam@redhat.com>
<artifactId>slf4j-simple</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.netvirt</groupId>
+ <artifactId>elanmanager-api</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netvirt</groupId>
+ <artifactId>elanmanager-impl</artifactId>
+ <version>0.3.0-SNAPSHOT</version>
+ </dependency>
</dependencies>
<build>
<plugins>
import com.google.common.net.InetAddresses;
import io.netty.util.Timeout;
+import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
-import org.apache.commons.lang3.tuple.ImmutablePair;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants.Ipv6RtrAdvertType;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
import org.opendaylight.yangtools.yang.common.RpcResult;
static final Logger LOG = LoggerFactory.getLogger(IfMgr.class);
private HashMap<Uuid, VirtualRouter> vrouters;
+ private HashMap<Uuid, VirtualNetwork> vnetworks;
private HashMap<Uuid, VirtualSubnet> vsubnets;
private HashMap<Uuid, VirtualPort> vintfs;
private HashMap<Uuid, VirtualPort> vrouterv6IntfMap;
private HashMap<Uuid, List<VirtualPort>> unprocessedRouterIntfs;
private HashMap<Uuid, List<VirtualPort>> unprocessedSubnetIntfs;
- private HashMap<String, ImmutablePair<String, VirtualPort>> ifaceFlowCache;
private OdlInterfaceRpcService interfaceManagerRpc;
+ private IElanService elanProvider;
+ private IMdsalApiManager mdsalUtil;
+ private Ipv6ServiceUtils ipv6ServiceUtils;
+ private DataBroker dataBroker;
+
private static IfMgr ifMgr;
private Ipv6ServiceUtils ipv6Utils = Ipv6ServiceUtils.getInstance();
void init() {
this.vrouters = new HashMap<>();
+ this.vnetworks = new HashMap<>();
this.vsubnets = new HashMap<>();
this.vintfs = new HashMap<>();
this.vrouterv6IntfMap = new HashMap<>();
this.unprocessedRouterIntfs = new HashMap<>();
this.unprocessedSubnetIntfs = new HashMap<>();
- this.ifaceFlowCache = new HashMap<>();
+ this.ipv6ServiceUtils = new Ipv6ServiceUtils();
LOG.info("IfMgr is enabled");
}
IfMgr.ifMgr = ifMgr;
}
+ public void setElanProvider(IElanService elanProvider) {
+ this.elanProvider = elanProvider;
+ }
+
+ public void setDataBroker(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ }
+
+ public void setMdsalUtilManager(IMdsalApiManager mdsalUtil) {
+ this.mdsalUtil = mdsalUtil;
+ }
+
public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
LOG.trace("Registered interfaceManager successfully");
this.interfaceManagerRpc = interfaceManagerRpc;
transmitUnsolicitedRA(intf);
MacAddress ifaceMac = MacAddress.getDefaultInstance(macAddress);
Ipv6Address llAddr = ipv6Utils.getIpv6LinkLocalAddressFromMac(ifaceMac);
- programNSFlowForAddress(intf, llAddr, true);
+ /* A new router interface is created. This is basically triggered when an
+ IPv6 subnet is associated to the router. Check if network is already hosting
+ any VMs. If so, on all the hosts that have VMs on the network, program the
+ icmpv6 punt flows in IPV6_TABLE(45).
+ */
+ programIcmpv6RSPuntFlows(intf, Ipv6Constants.ADD_FLOW);
+ programIcmpv6NSPuntFlowForAddress(intf, llAddr, Ipv6Constants.ADD_FLOW);
} else {
intf.setSubnetInfo(snetId, fixedIp);
}
}
vrouterv6IntfMap.put(networkId, intf);
- programNSFlowForAddress(intf, fixedIp.getIpv6Address(), true);
+ programIcmpv6NSPuntFlowForAddress(intf, fixedIp.getIpv6Address(), Ipv6Constants.ADD_FLOW);
return;
}
return;
}
+ List<Ipv6Address> existingIPv6AddressList = intf.getIpv6AddressesWithoutLLA();
+ List<Ipv6Address> newlyAddedIpv6AddressList = new ArrayList<>();
intf.clearSubnetInfo();
for (FixedIps fip : fixedIpsList) {
IpAddress fixedIp = fip.getIpAddress();
addUnprocessed(unprocessedSubnetIntfs, fip.getSubnetId(), intf);
}
vrouterv6IntfMap.put(intf.getNetworkID(), intf);
+
+ if (existingIPv6AddressList.contains(fixedIp.getIpv6Address())) {
+ existingIPv6AddressList.remove(fixedIp.getIpv6Address());
+ } else {
+ newlyAddedIpv6AddressList.add(fixedIp.getIpv6Address());
+ }
+ }
+
+ /* This is a port update event for routerPort. Check if any IPv6 subnet is added
+ or removed from the router port. Depending on subnet added/removed, we add/remove
+ the corresponding flows from IPV6_TABLE(45).
+ */
+ for (Ipv6Address ipv6Address: newlyAddedIpv6AddressList) {
+ // Some v6 subnets are associated to the routerPort add the corresponding NS Flows.
+ programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.ADD_FLOW);
+ }
+
+ for (Ipv6Address ipv6Address: existingIPv6AddressList) {
+ // Some v6 subnets are disassociated from the routerPort, remove the corresponding NS Flows.
+ programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.DEL_FLOW);
}
return;
}
.setMacAddress(macAddress)
.setRouterIntfFlag(false)
.setDeviceOwner(deviceOwner);
+ Long elanTag = getNetworkElanTag(networkId);
+ // Do service binding for the port and set the serviceBindingStatus to true.
+ ipv6ServiceUtils.bindIpv6Service(dataBroker, portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
+ intf.setServiceBindingStatus(Boolean.TRUE);
} else {
intf.setSubnetInfo(snetId, fixedIp);
}
public void updateHostIntf(Uuid portId, List<FixedIps> fixedIpsList) {
LOG.debug("updateHostIntf portId {}, fixedIpsList {} ", portId, fixedIpsList);
+ Boolean portIncludesV6Address = Boolean.FALSE;
VirtualPort intf = vintfs.get(portId);
if (intf == null) {
if (fixedIp.getIpv4Address() != null) {
continue;
}
+ portIncludesV6Address = Boolean.TRUE;
//Save the interface ipv6 address in its fully expanded format
Ipv6Address addr = new Ipv6Address(InetAddresses
.forString(fixedIp.getIpv6Address().getValue()).getHostAddress());
addUnprocessed(unprocessedSubnetIntfs, fip.getSubnetId(), intf);
}
}
+
+ /* If the VMPort initially included an IPv6 address (along with IPv4 address) and IPv6 address
+ was removed, we will have to unbind the service on the VM port. Similarly we do a ServiceBind
+ if required.
+ */
+ if (portIncludesV6Address) {
+ if (intf.getServiceBindingStatus() == Boolean.FALSE) {
+ Long elanTag = getNetworkElanTag(intf.getNetworkID());
+ ipv6ServiceUtils.bindIpv6Service(dataBroker, portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
+ intf.setServiceBindingStatus(Boolean.TRUE);
+ }
+ } else {
+ ipv6ServiceUtils.unbindIpv6Service(dataBroker, portId.getValue());
+ intf.setServiceBindingStatus(Boolean.FALSE);
+ }
return;
}
- public void updateInterface(Uuid portId, String dpId, Long ofPort) {
+ public void updateInterface(Uuid portId, BigInteger dpId, Long ofPort) {
LOG.debug("in updateInterface portId {}, dpId {}, ofPort {}",
portId, dpId, ofPort);
VirtualPort intf = vintfs.get(portId);
}
if (intf != null) {
- intf.setDpId(dpId)
+ intf.setDpId(dpId.toString())
.setOfPort(ofPort);
}
+
+ // Update the network <--> List[dpnIds, List<ports>] cache.
+ VirtualNetwork vnet = vnetworks.get(intf.getNetworkID());
+ if (null != vnet) {
+ vnet.updateDpnPortInfo(dpId, portId, Ipv6Constants.ADD_ENTRY);
+ }
+
return;
}
MacAddress ifaceMac = MacAddress.getDefaultInstance(intf.getMacAddress());
Ipv6Address llAddr = ipv6Utils.getIpv6LinkLocalAddressFromMac(ifaceMac);
vrouterv6IntfMap.remove(intf.getNetworkID(), intf);
- programNSFlowForAddress(intf, llAddr, false);
+ /* Router port is deleted. Remove the corresponding icmpv6 punt flows on all
+ the dpnIds which were hosting the VMs on the network.
+ */
+ programIcmpv6RSPuntFlows(intf, Ipv6Constants.DEL_FLOW);
+ for (Ipv6Address ipv6Address: intf.getIpv6Addresses()) {
+ programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.DEL_FLOW);
+ }
transmitRouterAdvertisement(intf, Ipv6RtrAdvertType.CEASE_ADVERTISEMENT);
Ipv6TimerWheel timer = Ipv6TimerWheel.getInstance();
timer.cancelPeriodicTransmissionTimeout(intf.getPeriodicTimeout());
intf.resetPeriodicTimeout();
LOG.debug("Reset the periodic RA Timer for intf {}", intf.getIntfUUID());
- }
- for (IpAddress ipAddr : intf.getIpAddresses()) {
- if (ipAddr.getIpv6Address() != null) {
- if (intf.getDeviceOwner().equalsIgnoreCase(Ipv6Constants.NETWORK_ROUTER_INTERFACE)) {
- programNSFlowForAddress(intf, ipAddr.getIpv6Address(), false);
- }
+ } else {
+ // Remove the serviceBinding entry for the port.
+ ipv6ServiceUtils.unbindIpv6Service(dataBroker, portId.getValue());
+ // Remove the portId from the (network <--> List[dpnIds, List <ports>]) cache.
+ VirtualNetwork vnet = vnetworks.get(intf.getNetworkID());
+ if (null != vnet) {
+ BigInteger dpId = ipv6ServiceUtils.getDataPathId(intf.getDpId());
+ vnet.updateDpnPortInfo(dpId, intf.getIntfUUID(), Ipv6Constants.DEL_ENTRY);
}
}
vintfs.remove(portId);
return null;
}
- private void programNSFlowForAddress(VirtualPort intf, Ipv6Address address, boolean action) {
- //Todo: Will be done in a separate patch.
+ private void programIcmpv6RSPuntFlows(VirtualPort routerPort, int action) {
+ Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
+ int flowStatus;
+ VirtualNetwork vnet = vnetworks.get(routerPort.getNetworkID());
+ if (vnet != null) {
+ List<BigInteger> dpnList = vnet.getDpnsHostingNetwork();
+ for (BigInteger dpId : dpnList) {
+ flowStatus = vnet.getRSPuntFlowStatusOnDpnId(dpId);
+ if (action == Ipv6Constants.ADD_FLOW && flowStatus == Ipv6Constants.FLOWS_NOT_CONFIGURED) {
+ ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
+ mdsalUtil, Ipv6Constants.ADD_FLOW);
+ vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_CONFIGURED);
+ } else if (action == Ipv6Constants.DEL_FLOW && flowStatus == Ipv6Constants.FLOWS_CONFIGURED) {
+ ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
+ mdsalUtil, Ipv6Constants.DEL_FLOW);
+ vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_NOT_CONFIGURED);
+ }
+ }
+ }
+ }
+
+ private void programIcmpv6NSPuntFlowForAddress(VirtualPort routerPort, Ipv6Address ipv6Address, int action) {
+ Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
+ VirtualNetwork vnet = vnetworks.get(routerPort.getNetworkID());
+ if (vnet != null) {
+ Collection<VirtualNetwork.DpnInterfaceInfo> dpnIfaceList = vnet.getDpnIfaceList();
+ for (VirtualNetwork.DpnInterfaceInfo dpnIfaceInfo : dpnIfaceList) {
+ if (action == Ipv6Constants.ADD_FLOW && !dpnIfaceInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
+ ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpnIfaceInfo.getDpId(),
+ elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
+ dpnIfaceInfo.updateNDTargetAddress(ipv6Address, action);
+ } else if (action == Ipv6Constants.DEL_FLOW && dpnIfaceInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
+ ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpnIfaceInfo.getDpId(),
+ elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.DEL_FLOW);
+ dpnIfaceInfo.updateNDTargetAddress(ipv6Address, action);
+ }
+ }
+ }
+ }
+
+ public void programIcmpv6PuntFlowsIfNecessary(Uuid vmPortId, BigInteger dpId, VirtualPort routerPort) {
+ VirtualPort vmPort = vintfs.get(vmPortId);
+ if (null != vmPort) {
+ VirtualNetwork vnet = vnetworks.get(vmPort.getNetworkID());
+ if (null != vnet) {
+ VirtualNetwork.DpnInterfaceInfo dpnInfo = vnet.getDpnIfaceInfo(dpId);
+ if (null != dpnInfo) {
+ Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
+ if (vnet.getRSPuntFlowStatusOnDpnId(dpId) == Ipv6Constants.FLOWS_NOT_CONFIGURED) {
+ ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
+ mdsalUtil, Ipv6Constants.ADD_FLOW);
+ vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_CONFIGURED);
+ }
+
+ for (Ipv6Address ipv6Address: routerPort.getIpv6Addresses()) {
+ if (!dpnInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
+ ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
+ elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
+ dpnInfo.updateNDTargetAddress(ipv6Address, Ipv6Constants.ADD_FLOW);
+ }
+ }
+ }
+ }
+ }
}
public String getInterfaceNameFromTag(long portTag) {
return interfaceName;
}
- public void updateInterfaceCache(String interfaceName, ImmutablePair<String, VirtualPort> pair) {
- ifaceFlowCache.put(interfaceName, pair);
+ public Long updateNetworkElanTag(Uuid networkId) {
+ Long elanTag = null;
+ if (null != this.elanProvider) {
+ ElanInstance elanInstance = this.elanProvider.getElanInstance(networkId.getValue());
+ if (null != elanInstance) {
+ elanTag = elanInstance.getElanTag();
+ VirtualNetwork net = vnetworks.get(networkId);
+ if (null != net) {
+ net.setElanTag(elanTag);
+ }
+ }
+ }
+ return elanTag;
+ }
+
+ public Long getNetworkElanTag(Uuid networkId) {
+ Long elanTag = null;
+ VirtualNetwork net = vnetworks.get(networkId);
+ if (null != net) {
+ elanTag = net.getElanTag();
+ if (null == elanTag) {
+ elanTag = updateNetworkElanTag(networkId);
+ }
+ }
+ return elanTag;
}
- public ImmutablePair<String, VirtualPort> getInterfaceCache(String interfaceName) {
- return ifaceFlowCache.get(interfaceName);
+ public void addNetwork(Uuid networkId) {
+ VirtualNetwork net = vnetworks.get(networkId);
+ if (null == net) {
+ net = new VirtualNetwork();
+ net.setNetworkUuid(networkId);
+ vnetworks.put(networkId, net);
+ updateNetworkElanTag(networkId);
+ }
}
- public void removeInterfaceCache(String interfaceName) {
- ifaceFlowCache.remove(interfaceName);
+ public void removeNetwork(Uuid networkId) {
+ // Delete the network and the corresponding dpnIds<-->List(ports) cache.
+ VirtualNetwork net = vnetworks.get(networkId);
+ if (null == net) {
+ net.removeSelf();
+ vnetworks.remove(networkId);
+ net = null;
+ }
}
private void transmitRouterAdvertisement(VirtualPort intf, Ipv6RtrAdvertType advType) {
*/
package org.opendaylight.netvirt.ipv6service;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
+import org.opendaylight.netvirt.elanmanager.api.IElanService;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6PeriodicTrQueue;
import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
private final PacketProcessingService pktProcessingService;
private final OdlInterfaceRpcService interfaceManagerRpc;
private final IfMgr ifMgr;
+ private final IElanService elanProvider;
+ private final DataBroker dataBroker;
+ private final IMdsalApiManager mdsalUtil;
public Ipv6ServiceImpl(final PacketProcessingService pktProcessingService,
- final OdlInterfaceRpcService interfaceManagerRpc) {
+ final OdlInterfaceRpcService interfaceManagerRpc,
+ final IElanService elanProvider,
+ final DataBroker dataBroker,
+ final IMdsalApiManager mdsalUtil) {
this.pktProcessingService = pktProcessingService;
this.interfaceManagerRpc = interfaceManagerRpc;
+ this.elanProvider = elanProvider;
+ this.dataBroker = dataBroker;
+ this.mdsalUtil = mdsalUtil;
ifMgr = IfMgr.getIfMgrInstance();
}
public void start() {
LOG.info("{} start", getClass().getSimpleName());
ifMgr.setInterfaceManagerRpc(interfaceManagerRpc);
+ ifMgr.setElanProvider(elanProvider);
+ ifMgr.setDataBroker(dataBroker);
+ ifMgr.setMdsalUtilManager(mdsalUtil);
final Ipv6PeriodicRAThread ipv6Thread = Ipv6PeriodicRAThread.getInstance();
Ipv6RouterAdvt.setPacketProcessingService(pktProcessingService);
}
import java.math.BigInteger;
import java.util.List;
-import org.apache.commons.lang3.tuple.ImmutablePair;
import org.opendaylight.controller.md.sal.binding.api.ClusteredDataTreeChangeListener;
import org.opendaylight.controller.md.sal.binding.api.DataBroker;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
import org.opendaylight.genius.datastoreutils.AsyncDataTreeChangeListenerBase;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
-import org.opendaylight.genius.mdsalutil.NwConstants;
-import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev140508.Tunnel;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.InterfacesState;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
implements ClusteredDataTreeChangeListener<Interface>, AutoCloseable {
private static final Logger LOG = LoggerFactory.getLogger(Ipv6ServiceInterfaceEventListener.class);
private final DataBroker dataBroker;
- private final IMdsalApiManager mdsalUtil;
private final IfMgr ifMgr;
- private Ipv6ServiceUtils ipv6ServiceUtils;
/**
* Intialize the member variables.
* @param broker the data broker instance.
*/
- public Ipv6ServiceInterfaceEventListener(DataBroker broker, IMdsalApiManager mdsalUtil) {
+ public Ipv6ServiceInterfaceEventListener(DataBroker broker) {
super(Interface.class, Ipv6ServiceInterfaceEventListener.class);
this.dataBroker = broker;
- this.mdsalUtil = mdsalUtil;
ifMgr = IfMgr.getIfMgrInstance();
- ipv6ServiceUtils = new Ipv6ServiceUtils();
}
public void start() {
@Override
protected void remove(InstanceIdentifier<Interface> key, Interface del) {
LOG.debug("Port removed {}, {}", key, del);
- List<String> ofportIds = del.getLowerLayerIf();
- if (ofportIds == null || ofportIds.isEmpty()) {
- return;
- }
- String interfaceName = del.getName();
- ImmutablePair<String, VirtualPort> pair = ifMgr.getInterfaceCache(interfaceName);
- if (pair != null && pair.getLeft() != null && pair.getRight() != null) {
- NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
- BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
- if (!dpId.equals(Ipv6Constants.INVALID_DPID)) {
- VirtualPort routerPort = pair.getRight();
- ipv6ServiceUtils.unbindIpv6Service(dataBroker, interfaceName);
- ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, pair.getLeft(),
- mdsalUtil, Ipv6Constants.DEL_FLOW);
- for (Ipv6Address ipv6Address : routerPort.getIpv6Addresses()) {
- ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
- pair.getLeft(), ipv6Address.getValue(), mdsalUtil, Ipv6Constants.DEL_FLOW);
- }
- ifMgr.removeInterfaceCache(interfaceName);
- ifMgr.deleteInterface(new Uuid(del.getName()), dpId.toString());
- }
- }
}
@Override
}
Long ofPort = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
- ifMgr.updateInterface(portId, dpId.toString(), ofPort);
+ ifMgr.updateInterface(portId, dpId, ofPort);
VirtualPort routerPort = ifMgr.getRouterV6InterfaceForNetwork(port.getNetworkID());
if (routerPort == null) {
LOG.info("Port {} is not associated to a Router, skipping.", routerPort);
return;
}
-
- ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId,
- port.getMacAddress(), mdsalUtil, Ipv6Constants.ADD_FLOW);
- for (Ipv6Address ipv6Address : routerPort.getIpv6Addresses()) {
- ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
- port.getMacAddress(), ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
- }
- ipv6ServiceUtils.bindIpv6Service(dataBroker, iface.getName(), NwConstants.IPV6_TABLE);
- ifMgr.updateInterfaceCache(iface.getName(), new ImmutablePair<>(port.getMacAddress(), routerPort));
+ // Check and program icmpv6 punt flows on the dpnID if its the first VM on the host.
+ ifMgr.programIcmpv6PuntFlowsIfNecessary(portId, dpId, routerPort);
}
}
}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, Inc. 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.ipv6service;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
+import org.opendaylight.controller.md.sal.common.api.data.AsyncDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.genius.mdsalutil.AbstractDataChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.Networks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.networks.rev150712.networks.attributes.networks.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.rev150712.Neutron;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NeutronNetworkChangeListener extends AbstractDataChangeListener<Network> implements AutoCloseable {
+ private static final Logger LOG = LoggerFactory.getLogger(NeutronRouterChangeListener.class);
+ private ListenerRegistration<DataChangeListener> listenerRegistration;
+ private final DataBroker dataBroker;
+ private final IfMgr ifMgr;
+
+ public NeutronNetworkChangeListener(final DataBroker dataBroker) {
+ super(Network.class);
+ this.dataBroker = dataBroker;
+ this.ifMgr = IfMgr.getIfMgrInstance();
+ }
+
+ public void start() {
+ LOG.info("{} start", getClass().getSimpleName());
+ listenerRegistration = dataBroker.registerDataChangeListener(LogicalDatastoreType.CONFIGURATION,
+ getWildCardPath(), this, AsyncDataBroker.DataChangeScope.SUBTREE);
+ }
+
+ private InstanceIdentifier<Network> getWildCardPath() {
+ return InstanceIdentifier.create(Neutron.class).child(Networks.class).child(Network.class);
+ }
+
+ @Override
+ protected void add(InstanceIdentifier<Network> identifier, Network input) {
+ LOG.debug("Add Network notification handler is invoked {} ", input);
+ ifMgr.addNetwork(input.getUuid());
+ }
+
+ @Override
+ protected void remove(InstanceIdentifier<Network> identifier, Network input) {
+ LOG.debug("Remove Network notification handler is invoked {} ", input);
+ ifMgr.removeNetwork(input.getUuid());
+ }
+
+ @Override
+ protected void update(InstanceIdentifier<Network> identifier, Network original, Network update) {
+ LOG.debug("Update Network notification handler is invoked...");
+ }
+
+ @Override
+ public void close() throws Exception {
+ if (listenerRegistration != null) {
+ listenerRegistration.close();
+ listenerRegistration = null;
+ }
+ LOG.info("{} close", getClass().getSimpleName());
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 Red Hat, Inc. 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.ipv6service;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
+
+public class VirtualNetwork {
+ Long elanTag;
+ private Uuid networkUUID;
+ private HashMap<BigInteger, DpnInterfaceInfo> dpnIfaceList;
+
+ public VirtualNetwork() {
+ dpnIfaceList = new HashMap<BigInteger, DpnInterfaceInfo>();
+ }
+
+ public void setNetworkUuid(Uuid networkUuid) {
+ this.networkUUID = networkUuid;
+ }
+
+ public Uuid getNetworkUuid() {
+ return networkUUID;
+ }
+
+ public void updateDpnPortInfo(BigInteger dpnId, Uuid portId, int addOrRemove) {
+ DpnInterfaceInfo dpnInterface = dpnIfaceList.get(dpnId);
+ if (dpnInterface == null) {
+ dpnInterface = new DpnInterfaceInfo(dpnId);
+ dpnIfaceList.put(dpnId, dpnInterface);
+ }
+
+ if (addOrRemove == Ipv6Constants.ADD_ENTRY) {
+ dpnInterface.updatePort(portId);
+ } else {
+ dpnInterface.removePort(portId);
+ }
+ }
+
+ public Long getElanTag() {
+ return elanTag;
+ }
+
+ public void setElanTag(Long etag) {
+ elanTag = etag;
+ }
+
+ public List<BigInteger> getDpnsHostingNetwork() {
+ List<BigInteger> dpnList = new ArrayList<>();
+ Collection<DpnInterfaceInfo> dpnCollection = dpnIfaceList.values();
+ for (DpnInterfaceInfo dpnInterfaceInfo: dpnCollection) {
+ dpnList.add(dpnInterfaceInfo.getDpId());
+ }
+ return dpnList;
+ }
+
+ public Collection<DpnInterfaceInfo> getDpnIfaceList() {
+ return dpnIfaceList.values();
+ }
+
+ public DpnInterfaceInfo getDpnIfaceInfo(BigInteger dpId) {
+ return dpnIfaceList.get(dpId);
+ }
+
+ public void setRSPuntFlowStatusOnDpnId(BigInteger dpnId, int action) {
+ DpnInterfaceInfo dpnInterface = dpnIfaceList.get(dpnId);
+ if (null != dpnInterface) {
+ dpnInterface.setRsFlowConfiguredStatus(action);
+ }
+ }
+
+ public int getRSPuntFlowStatusOnDpnId(BigInteger dpnId) {
+ DpnInterfaceInfo dpnInterface = dpnIfaceList.get(dpnId);
+ if (null != dpnInterface) {
+ return dpnInterface.getRsFlowConfiguredStatus();
+ }
+ return Ipv6Constants.FLOWS_NOT_CONFIGURED;
+ }
+
+ public void clearDpnInterfaceList() {
+ dpnIfaceList.clear();
+ }
+
+ @Override
+ public String toString() {
+ return "VirtualNetwork [networkUUID=" + networkUUID + " dpnIfaceList=" + dpnIfaceList + "]";
+ }
+
+ public void removeSelf() {
+ Collection<DpnInterfaceInfo> dpns = dpnIfaceList.values();
+ Iterator itr = dpns.iterator();
+ while (itr.hasNext()) {
+ DpnInterfaceInfo dpnInterfaceInfo = (DpnInterfaceInfo) itr.next();
+ if (null != dpnInterfaceInfo) {
+ dpnInterfaceInfo.clearPortInfo();
+ dpnInterfaceInfo.clearNdTargetFlowInfo();
+ }
+ }
+ clearDpnInterfaceList();
+ }
+
+ public class DpnInterfaceInfo {
+ BigInteger dpId;
+ int rsPuntFlowConfigured;
+ List<Uuid> portUUID;
+ List<Ipv6Address> ndTargetFlowsPunted;
+
+ DpnInterfaceInfo(BigInteger dpnId) {
+ dpId = dpnId;
+ portUUID = new ArrayList<>();
+ ndTargetFlowsPunted = new ArrayList<>();
+ rsPuntFlowConfigured = Ipv6Constants.FLOWS_NOT_CONFIGURED;
+ }
+
+ public void setDpId(BigInteger dpId) {
+ this.dpId = dpId;
+ }
+
+ public BigInteger getDpId() {
+ return dpId;
+ }
+
+ public void setRsFlowConfiguredStatus(int status) {
+ this.rsPuntFlowConfigured = status;
+ }
+
+ public int getRsFlowConfiguredStatus() {
+ return rsPuntFlowConfigured;
+ }
+
+ public List<Ipv6Address> getNDTargetFlows() {
+ return ndTargetFlowsPunted;
+ }
+
+ public void updateNDTargetAddress(Ipv6Address ipv6Address, int addOrRemove) {
+ if (addOrRemove == Ipv6Constants.ADD_ENTRY) {
+ this.ndTargetFlowsPunted.add(ipv6Address);
+ } else {
+ this.ndTargetFlowsPunted.remove(ipv6Address);
+ }
+ }
+
+ public void clearNdTargetFlowInfo() {
+ this.ndTargetFlowsPunted.clear();
+ }
+
+ public void updatePort(Uuid portID) {
+ this.portUUID.add(portID);
+ }
+
+ public void removePort(Uuid portID) {
+ this.portUUID.remove(portID);
+ }
+
+ public void clearPortInfo() {
+ this.portUUID.clear();
+ }
+
+ @Override
+ public String toString() {
+ return "DpnInterfaceInfo [dpId=" + dpId + " rsPuntFlowConfigured=" + rsPuntFlowConfigured + " portUUID="
+ + portUUID + "]";
+ }
+ }
+}
private String dpId;
private String deviceOwner;
private Long ofPort;
+ private Boolean serviceBindingStatus;
private HashMap<Uuid, SubnetInfo> snetInfo;
private Ipv6PeriodicTimer periodicTimer;
private Timeout periodicTimeout;
public VirtualPort() {
snetInfo = new HashMap<Uuid, SubnetInfo>();
+ serviceBindingStatus = Boolean.FALSE;
}
public Uuid getIntfUUID() {
return ipv6AddrList;
}
+ public List<Ipv6Address> getIpv6AddressesWithoutLLA() {
+ List<Ipv6Address> ipv6AddrList = new ArrayList<>();
+ for (SubnetInfo subnetInfo : snetInfo.values()) {
+ if (subnetInfo.getIpAddr().getIpv6Address() instanceof Ipv6Address) {
+ ipv6AddrList.add(subnetInfo.getIpAddr().getIpv6Address());
+ }
+ }
+ return ipv6AddrList;
+ }
+
public String getMacAddress() {
return macAddress;
}
return ofPort;
}
+ public void setServiceBindingStatus(Boolean status) {
+ this.serviceBindingStatus = status;
+ }
+
+ public Boolean getServiceBindingStatus() {
+ return serviceBindingStatus;
+ }
+
public void removeSelf() {
if (routerIntfFlag == true) {
if (router != null) {
public static final int ADD_FLOW = 0;
public static final int DEL_FLOW = 1;
+ public static final int ADD_ENTRY = 0;
+ public static final int DEL_ENTRY = 1;
+ public static final int FLOWS_CONFIGURED = 1;
+ public static final int FLOWS_NOT_CONFIGURED = 0;
public static final String OPENFLOW_NODE_PREFIX = "openflow:";
public static final short IPV6_VERSION = 6;
public static final short ICMP6_NHEADER = 58;
import org.opendaylight.genius.mdsalutil.MDSALUtil;
import org.opendaylight.genius.mdsalutil.MatchFieldType;
import org.opendaylight.genius.mdsalutil.MatchInfo;
+import org.opendaylight.genius.mdsalutil.MetaDataUtil;
import org.opendaylight.genius.mdsalutil.NwConstants;
import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
import org.opendaylight.genius.mdsalutil.packet.IPProtocols;
import org.opendaylight.genius.utils.ServiceIndex;
+import org.opendaylight.netvirt.elan.utils.ElanUtils;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.Interfaces;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.InterfaceKey;
return ipv6LLA;
}
- private static List<MatchInfo> getIcmpv6RSMatch(String vmMacAddress) {
+ private static List<MatchInfo> getIcmpv6RSMatch(Long elanTag) {
List<MatchInfo> matches = new ArrayList<>();
- matches.add(new MatchInfo(MatchFieldType.eth_src,
- new String[] { vmMacAddress }));
matches.add(new MatchInfo(MatchFieldType.eth_type,
new long[] { NwConstants.ETHTYPE_IPV6 }));
matches.add(new MatchInfo(MatchFieldType.ip_proto,
new long[] { IPProtocols.IPV6ICMP.intValue() }));
matches.add(new MatchInfo(MatchFieldType.icmp_v6,
new long[] { Ipv6Constants.ICMP_V6_RS_CODE, 0}));
+ matches.add(new MatchInfo(MatchFieldType.metadata,
+ new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE}));
return matches;
}
- private List<MatchInfo> getIcmpv6NSMatch(String vmMacAddress, String ndTarget) {
+ private List<MatchInfo> getIcmpv6NSMatch(Long elanTag, String ndTarget) {
List<MatchInfo> matches = new ArrayList<>();
- matches.add(new MatchInfo(MatchFieldType.eth_src,
- new String[] { vmMacAddress }));
matches.add(new MatchInfo(MatchFieldType.eth_type,
new long[] { NwConstants.ETHTYPE_IPV6 }));
matches.add(new MatchInfo(MatchFieldType.ip_proto,
new long[] { Ipv6Constants.ICMP_V6_NS_CODE, 0}));
matches.add(new MatchInfo(MatchFieldType.ipv6_nd_target,
new String[] { ndTarget }));
+ matches.add(new MatchInfo(MatchFieldType.metadata,
+ new BigInteger[] { ElanUtils.getElanMetadataLabel(elanTag), MetaDataUtil.METADATA_MASK_SERVICE}));
return matches;
}
- private static String getIPv6FlowRef(BigInteger dpId, String vmMacAddress, String flowType) {
+ private static String getIPv6FlowRef(BigInteger dpId, Long elanTag, String flowType) {
return new StringBuffer().append(Ipv6Constants.FLOWID_PREFIX)
.append(dpId).append(Ipv6Constants.FLOWID_SEPARATOR)
- .append(vmMacAddress).append(flowType).toString();
+ .append(elanTag).append(Ipv6Constants.FLOWID_SEPARATOR)
+ .append(flowType).toString();
}
- private static void installRsPuntFlow(String interfaceName, short tableId, BigInteger dpId, String vmMacAddress,
- IMdsalApiManager mdsalUtil, int addOrRemove) {
- List<MatchInfo> routerSolicitationMatch = getIcmpv6RSMatch(vmMacAddress);
+ public void installIcmpv6NsPuntFlow(short tableId, BigInteger dpId, Long elanTag, String ipv6Address,
+ IMdsalApiManager mdsalUtil,int addOrRemove) {
+ List<MatchInfo> neighborSolicitationMatch = getIcmpv6NSMatch(elanTag, ipv6Address);
List<InstructionInfo> instructions = new ArrayList<>();
List<ActionInfo> actionsInfos = new ArrayList<>();
- // Punt to controller
actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
new String[] {}));
instructions.add(new InstructionInfo(InstructionType.write_actions,
actionsInfos));
FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
- getIPv6FlowRef(dpId, vmMacAddress, "IPv6RS"),Ipv6Constants.DEFAULT_FLOW_PRIORITY, "IPv6RS", 0, 0,
- NwConstants.COOKIE_IPV6_TABLE, routerSolicitationMatch, instructions);
- if (addOrRemove == Ipv6Constants.DEL_FLOW) {
- LOG.trace("Removing IPv6 Router Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
- mdsalUtil.removeFlow(rsFlowEntity);
- } else {
- LOG.trace("Installing IPv6 Router Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
- mdsalUtil.installFlow(rsFlowEntity);
- }
- }
-
- public void installIcmpv6NsPuntFlow(short tableId, BigInteger dpId, String vmMacAddress,
- String ipv6Address, IMdsalApiManager mdsalUtil, int addOrRemove) {
- List<MatchInfo> neighborSolicitationMatch = getIcmpv6NSMatch(vmMacAddress, ipv6Address);
- List<InstructionInfo> instructions = new ArrayList<>();
- List<ActionInfo> actionsInfos = new ArrayList<>();
- actionsInfos.add(new ActionInfo(ActionType.punt_to_controller,
- new String[] {}));
- instructions.add(new InstructionInfo(InstructionType.write_actions,
- actionsInfos));
- FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
- getIPv6FlowRef(dpId, vmMacAddress, ipv6Address),Ipv6Constants.DEFAULT_FLOW_PRIORITY, "IPv6NS",
+ getIPv6FlowRef(dpId, elanTag, ipv6Address),Ipv6Constants.DEFAULT_FLOW_PRIORITY, "IPv6NS",
0, 0, NwConstants.COOKIE_IPV6_TABLE, neighborSolicitationMatch, instructions);
if (addOrRemove == Ipv6Constants.DEL_FLOW) {
- LOG.trace("Removing IPv6 Neighbor Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ LOG.trace("Removing IPv6 Neighbor Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
mdsalUtil.removeFlow(rsFlowEntity);
} else {
- LOG.trace("Installing IPv6 Neighbor Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ LOG.trace("Installing IPv6 Neighbor Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
mdsalUtil.installFlow(rsFlowEntity);
}
}
- public void installIcmpv6RsPuntFlow(short tableId, BigInteger dpId, String vmMacAddress,
- IMdsalApiManager mdsalUtil, int addOrRemove) {
+ public void installIcmpv6RsPuntFlow(short tableId, BigInteger dpId, Long elanTag, IMdsalApiManager mdsalUtil,
+ int addOrRemove) {
if (dpId == null || dpId.equals(Ipv6Constants.INVALID_DPID)) {
return;
}
- List<MatchInfo> routerSolicitationMatch = getIcmpv6RSMatch(vmMacAddress);
+ List<MatchInfo> routerSolicitationMatch = getIcmpv6RSMatch(elanTag);
List<InstructionInfo> instructions = new ArrayList<>();
List<ActionInfo> actionsInfos = new ArrayList<>();
// Punt to controller
instructions.add(new InstructionInfo(InstructionType.write_actions,
actionsInfos));
FlowEntity rsFlowEntity = MDSALUtil.buildFlowEntity(dpId, tableId,
- getIPv6FlowRef(dpId, vmMacAddress, "IPv6RS"),Ipv6Constants.DEFAULT_FLOW_PRIORITY, "IPv6RS", 0, 0,
+ getIPv6FlowRef(dpId, elanTag, "IPv6RS"),Ipv6Constants.DEFAULT_FLOW_PRIORITY, "IPv6RS", 0, 0,
NwConstants.COOKIE_IPV6_TABLE, routerSolicitationMatch, instructions);
if (addOrRemove == Ipv6Constants.DEL_FLOW) {
- LOG.trace("Removing IPv6 Router Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ LOG.trace("Removing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
mdsalUtil.removeFlow(rsFlowEntity);
} else {
- LOG.trace("Installing IPv6 Router Solicitation Flow DpId {}, vmMacAddress {}", dpId, vmMacAddress);
+ LOG.trace("Installing IPv6 Router Solicitation Flow DpId {}, elanTag {}", dpId, elanTag);
mdsalUtil.installFlow(rsFlowEntity);
}
}
.child(BoundServices.class, new BoundServicesKey(priority)).build();
}
- public void bindIpv6Service(DataBroker broker, String interfaceName, short tableId) {
+ public void bindIpv6Service(DataBroker broker, String interfaceName, Long elanTag, short tableId) {
int instructionKey = 0;
List<Instruction> instructions = new ArrayList<>();
+ instructions.add(MDSALUtil.buildAndGetWriteMetadaInstruction(ElanUtils.getElanMetadataLabel(elanTag),
+ MetaDataUtil.METADATA_MASK_SERVICE, ++instructionKey));
instructions.add(MDSALUtil.buildAndGetGotoTableInstruction(tableId, ++instructionKey));
short serviceIndex = ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME, NwConstants.IPV6_SERVICE_INDEX);
BoundServices
buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME,
NwConstants.IPV6_SERVICE_INDEX)));
}
+
+ public static BigInteger getDataPathId(String dpId) {
+ long dpid = 0L;
+ if (dpId != null) {
+ dpid = new BigInteger(dpId.replaceAll(":", ""), 16).longValue();
+ }
+ return BigInteger.valueOf(dpid);
+ }
}
<reference id="mdsalUtils"
interface="org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager" />
+ <reference id="elanProvider" interface="org.opendaylight.netvirt.elanmanager.api.IElanService" availability="optional" />
+
<odl:rpc-service id="odlInterfaceRpcService"
interface="org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService" />
<odl:rpc-service id="packetProcessingService"
class="org.opendaylight.netvirt.ipv6service.Ipv6ServiceInterfaceEventListener"
init-method="start" destroy-method="close">
<argument ref="dataBroker" />
- <argument ref="mdsalUtils" />
</bean>
<bean id="neutronPortChangeListener"
<argument ref="dataBroker" />
</bean>
+ <bean id="neutronNetworkChangeListener"
+ class="org.opendaylight.netvirt.ipv6service.NeutronNetworkChangeListener"
+ init-method="start" destroy-method="close">
+ <argument ref="dataBroker" />
+ </bean>
+
<bean id="neutronSubnetChangeListener"
class="org.opendaylight.netvirt.ipv6service.NeutronSubnetChangeListener"
init-method="start" destroy-method="close">
init-method="start" destroy-method="close">
<argument ref="packetProcessingService" />
<argument ref="odlInterfaceRpcService" />
+ <argument ref="elanProvider" />
+ <argument ref="dataBroker" />
+ <argument ref="mdsalUtils" />
</bean>
</blueprint>