2 * Copyright (c) 2015 Dell Inc. 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.netvirt.ipv6service;
11 import com.google.common.net.InetAddresses;
12 import io.netty.util.Timeout;
13 import java.math.BigInteger;
14 import java.util.ArrayList;
15 import java.util.Collection;
16 import java.util.HashMap;
17 import java.util.List;
19 import java.util.concurrent.ExecutionException;
20 import java.util.concurrent.Future;
21 import java.util.concurrent.TimeUnit;
22 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
23 import org.opendaylight.genius.mdsalutil.MDSALUtil;
24 import org.opendaylight.genius.mdsalutil.NwConstants;
25 import org.opendaylight.genius.mdsalutil.interfaces.IMdsalApiManager;
26 import org.opendaylight.netvirt.elanmanager.api.IElanService;
27 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
28 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants.Ipv6RtrAdvertType;
29 import org.opendaylight.netvirt.ipv6service.utils.Ipv6ServiceUtils;
30 import org.opendaylight.netvirt.ipv6service.utils.Ipv6TimerWheel;
31 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
32 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
34 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev140508.interfaces.state.Interface;
35 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
36 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.Uuid;
37 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
38 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
39 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
40 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
41 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
42 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
43 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
44 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
45 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
46 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
47 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
48 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
49 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.elan.rev150602.elan.instances.ElanInstance;
50 import org.opendaylight.yang.gen.v1.urn.opendaylight.neutron.ports.rev150712.port.attributes.FixedIps;
51 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
52 import org.opendaylight.yangtools.yang.common.RpcResult;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
57 static final Logger LOG = LoggerFactory.getLogger(IfMgr.class);
59 private final Map<Uuid, VirtualRouter> vrouters = new HashMap<>();
60 private final Map<Uuid, VirtualNetwork> vnetworks = new HashMap<>();
61 private final Map<Uuid, VirtualSubnet> vsubnets = new HashMap<>();
62 private final Map<Uuid, VirtualPort> vintfs = new HashMap<>();
63 private final Map<Uuid, VirtualPort> vrouterv6IntfMap = new HashMap<>();
64 private final Map<Uuid, List<VirtualPort>> unprocessedRouterIntfs = new HashMap<>();
65 private final Map<Uuid, List<VirtualPort>> unprocessedSubnetIntfs = new HashMap<>();
66 private OdlInterfaceRpcService interfaceManagerRpc;
67 private IElanService elanProvider;
68 private IMdsalApiManager mdsalUtil;
69 private final Ipv6ServiceUtils ipv6ServiceUtils = new Ipv6ServiceUtils();
70 private DataBroker dataBroker;
72 private static IfMgr ifMgr;
73 private Ipv6ServiceUtils ipv6Utils = Ipv6ServiceUtils.getInstance();
76 LOG.info("IfMgr is enabled");
79 public static IfMgr getIfMgrInstance() {
86 public static void setIfMgrInstance(IfMgr ifMgr) {
90 public void setElanProvider(IElanService elanProvider) {
91 this.elanProvider = elanProvider;
94 public void setDataBroker(DataBroker dataBroker) {
95 this.dataBroker = dataBroker;
98 public void setMdsalUtilManager(IMdsalApiManager mdsalUtil) {
99 this.mdsalUtil = mdsalUtil;
102 public void setInterfaceManagerRpc(OdlInterfaceRpcService interfaceManagerRpc) {
103 LOG.trace("Registered interfaceManager successfully");
104 this.interfaceManagerRpc = interfaceManagerRpc;
110 * @param rtrUuid router uuid
111 * @param rtrName router name
112 * @param tenantId tenant id
114 public void addRouter(Uuid rtrUuid, String rtrName, Uuid tenantId) {
116 VirtualRouter rtr = new VirtualRouter();
118 rtr.setTenantID(tenantId)
119 .setRouterUUID(rtrUuid)
121 vrouters.put(rtrUuid, rtr);
123 List<VirtualPort> intfList = unprocessedRouterIntfs.get(rtrUuid);
125 if (intfList == null) {
126 LOG.info("No unprocessed interfaces for the router {}", rtrUuid);
130 for (VirtualPort intf : intfList) {
133 rtr.addInterface(intf);
135 for (VirtualSubnet snet : intf.getSubnets()) {
141 removeUnprocessed(unprocessedRouterIntfs, rtrUuid);
147 * @param rtrUuid router uuid
149 public void removeRouter(Uuid rtrUuid) {
151 VirtualRouter rtr = vrouters.get(rtrUuid);
154 vrouters.remove(rtrUuid);
155 removeUnprocessed(unprocessedRouterIntfs, rtrUuid);
157 LOG.error("Delete router failed for :{}", rtrUuid);
164 * @param snetId subnet id
165 * @param name subnet name
166 * @param tenantId tenant id
167 * @param gatewayIp gateway ip address
168 * @param ipVersion IP Version "IPv4 or IPv6"
169 * @param subnetCidr subnet CIDR
170 * @param ipV6AddressMode Address Mode of IPv6 Subnet
171 * @param ipV6RaMode RA Mode of IPv6 Subnet.
173 public void addSubnet(Uuid snetId, String name, Uuid tenantId,
174 IpAddress gatewayIp, String ipVersion, IpPrefix subnetCidr,
175 String ipV6AddressMode, String ipV6RaMode) {
177 // Save the gateway ipv6 address in its fully expanded format. We always store the v6Addresses
178 // in expanded form and are used during Neighbor Discovery Support.
179 if (gatewayIp != null) {
180 Ipv6Address addr = new Ipv6Address(InetAddresses
181 .forString(gatewayIp.getIpv6Address().getValue()).getHostAddress());
182 gatewayIp = new IpAddress(addr);
185 VirtualSubnet snet = new VirtualSubnet();
186 snet.setTenantID(tenantId)
187 .setSubnetUUID(snetId)
189 .setGatewayIp(gatewayIp)
190 .setIPVersion(ipVersion)
191 .setSubnetCidr(subnetCidr)
192 .setIpv6AddressMode(ipV6AddressMode)
193 .setIpv6RAMode(ipV6RaMode);
195 vsubnets.put(snetId, snet);
197 List<VirtualPort> intfList = unprocessedSubnetIntfs.get(snetId);
198 if (intfList == null) {
199 LOG.info("No unprocessed interfaces for the subnet {}", snetId);
202 for (VirtualPort intf : intfList) {
204 intf.setSubnet(snetId, snet);
205 snet.addInterface(intf);
207 VirtualRouter rtr = intf.getRouter();
214 removeUnprocessed(unprocessedSubnetIntfs, snetId);
220 * @param snetId subnet id
222 public void removeSubnet(Uuid snetId) {
223 VirtualSubnet snet = vsubnets.get(snetId);
225 LOG.info("removeSubnet is invoked for {}", snetId);
227 vsubnets.remove(snetId);
228 removeUnprocessed(unprocessedSubnetIntfs, snetId);
232 public void addRouterIntf(Uuid portId, Uuid rtrId, Uuid snetId,
233 Uuid networkId, IpAddress fixedIp, String macAddress,
234 String deviceOwner) {
235 LOG.debug("addRouterIntf portId {}, rtrId {}, snetId {}, networkId {}, ip {}, mac {}",
236 portId, rtrId, snetId, networkId, fixedIp, macAddress);
237 //Save the interface ipv6 address in its fully expanded format
238 Ipv6Address addr = new Ipv6Address(InetAddresses
239 .forString(fixedIp.getIpv6Address().getValue()).getHostAddress());
240 fixedIp = new IpAddress(addr);
242 VirtualPort intf = vintfs.get(portId);
243 boolean newIntf = false;
245 intf = new VirtualPort();
246 vintfs.put(portId, intf);
247 intf.setIntfUUID(portId)
248 .setSubnetInfo(snetId, fixedIp)
249 .setNetworkID(networkId)
250 .setMacAddress(macAddress)
251 .setRouterIntfFlag(true)
252 .setDeviceOwner(deviceOwner);
253 intf.setPeriodicTimer();
255 MacAddress ifaceMac = MacAddress.getDefaultInstance(macAddress);
256 Ipv6Address llAddr = ipv6Utils.getIpv6LinkLocalAddressFromMac(ifaceMac);
257 /* A new router interface is created. This is basically triggered when an
258 IPv6 subnet is associated to the router. Check if network is already hosting
259 any VMs. If so, on all the hosts that have VMs on the network, program the
260 icmpv6 punt flows in IPV6_TABLE(45).
262 programIcmpv6RSPuntFlows(intf, Ipv6Constants.ADD_FLOW);
263 programIcmpv6NSPuntFlowForAddress(intf, llAddr, Ipv6Constants.ADD_FLOW);
265 intf.setSubnetInfo(snetId, fixedIp);
268 VirtualRouter rtr = vrouters.get(rtrId);
269 VirtualSubnet snet = vsubnets.get(snetId);
271 if (rtr != null && snet != null) {
273 intf.setSubnet(snetId, snet);
275 } else if (snet != null) {
276 intf.setSubnet(snetId, snet);
277 addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
279 addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
280 addUnprocessed(unprocessedSubnetIntfs, snetId, intf);
283 vrouterv6IntfMap.put(networkId, intf);
284 programIcmpv6NSPuntFlowForAddress(intf, fixedIp.getIpv6Address(), Ipv6Constants.ADD_FLOW);
287 LOG.debug("start the periodic RA Timer for routerIntf {}", portId);
288 transmitUnsolicitedRA(intf);
292 public void updateRouterIntf(Uuid portId, Uuid rtrId, List<FixedIps> fixedIpsList) {
293 LOG.info("updateRouterIntf portId {}, fixedIpsList {} ", portId, fixedIpsList);
294 VirtualPort intf = vintfs.get(portId);
296 LOG.info("Skip Router interface update for non-ipv6 port {}", portId);
300 List<Ipv6Address> existingIPv6AddressList = intf.getIpv6AddressesWithoutLLA();
301 List<Ipv6Address> newlyAddedIpv6AddressList = new ArrayList<>();
302 intf.clearSubnetInfo();
303 for (FixedIps fip : fixedIpsList) {
304 IpAddress fixedIp = fip.getIpAddress();
306 if (fixedIp.getIpv4Address() != null) {
310 //Save the interface ipv6 address in its fully expanded format
311 Ipv6Address addr = new Ipv6Address(InetAddresses
312 .forString(fixedIp.getIpv6Address().getValue()).getHostAddress());
313 fixedIp = new IpAddress(addr);
314 intf.setSubnetInfo(fip.getSubnetId(), fixedIp);
316 VirtualRouter rtr = vrouters.get(rtrId);
317 VirtualSubnet snet = vsubnets.get(fip.getSubnetId());
319 if (rtr != null && snet != null) {
321 intf.setSubnet(fip.getSubnetId(), snet);
323 } else if (snet != null) {
324 intf.setSubnet(fip.getSubnetId(), snet);
325 addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
327 addUnprocessed(unprocessedRouterIntfs, rtrId, intf);
328 addUnprocessed(unprocessedSubnetIntfs, fip.getSubnetId(), intf);
330 vrouterv6IntfMap.put(intf.getNetworkID(), intf);
332 if (existingIPv6AddressList.contains(fixedIp.getIpv6Address())) {
333 existingIPv6AddressList.remove(fixedIp.getIpv6Address());
335 newlyAddedIpv6AddressList.add(fixedIp.getIpv6Address());
339 /* This is a port update event for routerPort. Check if any IPv6 subnet is added
340 or removed from the router port. Depending on subnet added/removed, we add/remove
341 the corresponding flows from IPV6_TABLE(45).
343 for (Ipv6Address ipv6Address: newlyAddedIpv6AddressList) {
344 // Some v6 subnets are associated to the routerPort add the corresponding NS Flows.
345 programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.ADD_FLOW);
348 for (Ipv6Address ipv6Address: existingIPv6AddressList) {
349 // Some v6 subnets are disassociated from the routerPort, remove the corresponding NS Flows.
350 programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.DEL_FLOW);
354 public void addHostIntf(Uuid portId, Uuid snetId, Uuid networkId,
355 IpAddress fixedIp, String macAddress, String deviceOwner) {
356 LOG.debug("addHostIntf portId {}, snetId {}, networkId {}, ip {}, mac {}",
357 portId, snetId, networkId, fixedIp, macAddress);
359 //Save the interface ipv6 address in its fully expanded format
360 Ipv6Address addr = new Ipv6Address(InetAddresses
361 .forString(fixedIp.getIpv6Address().getValue()).getHostAddress());
362 fixedIp = new IpAddress(addr);
363 VirtualPort intf = vintfs.get(portId);
365 intf = new VirtualPort();
366 vintfs.put(portId, intf);
367 intf.setIntfUUID(portId)
368 .setSubnetInfo(snetId, fixedIp)
369 .setNetworkID(networkId)
370 .setMacAddress(macAddress)
371 .setRouterIntfFlag(false)
372 .setDeviceOwner(deviceOwner);
373 Long elanTag = getNetworkElanTag(networkId);
374 // Do service binding for the port and set the serviceBindingStatus to true.
375 ipv6ServiceUtils.bindIpv6Service(dataBroker, portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
376 intf.setServiceBindingStatus(Boolean.TRUE);
378 /* Update the intf dpnId/ofPort from the Operational Store */
379 updateInterfaceDpidOfPortInfo(portId);
382 intf.setSubnetInfo(snetId, fixedIp);
385 VirtualSubnet snet = vsubnets.get(snetId);
388 intf.setSubnet(snetId, snet);
390 addUnprocessed(unprocessedSubnetIntfs, snetId, intf);
394 public void clearAnyExistingSubnetInfo(Uuid portId) {
395 VirtualPort intf = vintfs.get(portId);
397 intf.clearSubnetInfo();
401 public void updateHostIntf(Uuid portId, Boolean portIncludesV6Address) {
402 VirtualPort intf = vintfs.get(portId);
404 LOG.debug("Update Host interface failed. Could not get Host interface details {}", portId);
408 /* If the VMPort initially included an IPv6 address (along with IPv4 address) and IPv6 address
409 was removed, we will have to unbind the service on the VM port. Similarly we do a ServiceBind
412 if (portIncludesV6Address) {
413 if (intf.getServiceBindingStatus() == Boolean.FALSE) {
414 Long elanTag = getNetworkElanTag(intf.getNetworkID());
415 LOG.info("In updateHostIntf, service binding for portId {}", portId);
416 ipv6ServiceUtils.bindIpv6Service(dataBroker, portId.getValue(), elanTag, NwConstants.IPV6_TABLE);
417 intf.setServiceBindingStatus(Boolean.TRUE);
420 LOG.info("In updateHostIntf, removing service binding for portId {}", portId);
421 ipv6ServiceUtils.unbindIpv6Service(dataBroker, portId.getValue());
422 intf.setServiceBindingStatus(Boolean.FALSE);
426 public void updateDpnInfo(Uuid portId, BigInteger dpId, Long ofPort) {
427 LOG.info("In updateDpnInfo portId {}, dpId {}, ofPort {}",
428 portId, dpId, ofPort);
429 VirtualPort intf = vintfs.get(portId);
431 intf.setDpId(dpId.toString())
434 // Update the network <--> List[dpnIds, List<ports>] cache.
435 VirtualNetwork vnet = vnetworks.get(intf.getNetworkID());
437 vnet.updateDpnPortInfo(dpId, ofPort, Ipv6Constants.ADD_ENTRY);
442 public void updateInterfaceDpidOfPortInfo(Uuid portId) {
443 LOG.debug("In updateInterfaceDpidOfPortInfo portId {}", portId);
444 Interface interfaceState = Ipv6ServiceUtils.getInterfaceStateFromOperDS(dataBroker, portId.getValue());
445 if (interfaceState == null) {
446 LOG.warn("In updateInterfaceDpidOfPortInfo, port info not found in Operational Store {}.", portId);
450 List<String> ofportIds = interfaceState.getLowerLayerIf();
451 NodeConnectorId nodeConnectorId = new NodeConnectorId(ofportIds.get(0));
452 BigInteger dpId = BigInteger.valueOf(MDSALUtil.getDpnIdFromPortName(nodeConnectorId));
453 if (!dpId.equals(Ipv6Constants.INVALID_DPID)) {
454 Long ofPort = MDSALUtil.getOfPortNumberFromPortName(nodeConnectorId);
455 updateDpnInfo(portId, dpId, ofPort);
460 public void removePort(Uuid portId) {
461 VirtualPort intf = vintfs.get(portId);
464 if (intf.getDeviceOwner().equalsIgnoreCase(Ipv6Constants.NETWORK_ROUTER_INTERFACE)) {
465 LOG.info("In removePort for router interface, portId {}", portId);
466 MacAddress ifaceMac = MacAddress.getDefaultInstance(intf.getMacAddress());
467 vrouterv6IntfMap.remove(intf.getNetworkID(), intf);
468 /* Router port is deleted. Remove the corresponding icmpv6 punt flows on all
469 the dpnIds which were hosting the VMs on the network.
471 programIcmpv6RSPuntFlows(intf, Ipv6Constants.DEL_FLOW);
472 for (Ipv6Address ipv6Address: intf.getIpv6Addresses()) {
473 programIcmpv6NSPuntFlowForAddress(intf, ipv6Address, Ipv6Constants.DEL_FLOW);
475 transmitRouterAdvertisement(intf, Ipv6RtrAdvertType.CEASE_ADVERTISEMENT);
476 Ipv6TimerWheel timer = Ipv6TimerWheel.getInstance();
477 timer.cancelPeriodicTransmissionTimeout(intf.getPeriodicTimeout());
478 intf.resetPeriodicTimeout();
479 LOG.debug("Reset the periodic RA Timer for intf {}", intf.getIntfUUID());
481 LOG.info("In removePort for host interface, portId {}", portId);
482 // Remove the serviceBinding entry for the port.
483 ipv6ServiceUtils.unbindIpv6Service(dataBroker, portId.getValue());
484 // Remove the portId from the (network <--> List[dpnIds, List <ports>]) cache.
485 VirtualNetwork vnet = vnetworks.get(intf.getNetworkID());
487 BigInteger dpId = Ipv6ServiceUtils.getDataPathId(intf.getDpId());
488 vnet.updateDpnPortInfo(dpId, intf.getOfPort(), Ipv6Constants.DEL_ENTRY);
491 vintfs.remove(portId);
495 public void deleteInterface(Uuid interfaceUuid, String dpId) {
496 // Nothing to do for now
499 public void addUnprocessed(Map<Uuid, List<VirtualPort>> unprocessed, Uuid id, VirtualPort intf) {
500 unprocessed.computeIfAbsent(id, key -> new ArrayList<>()).add(intf);
503 public void removeUnprocessed(Map<Uuid, List<VirtualPort>> unprocessed, Uuid id) {
504 unprocessed.remove(id);
507 public VirtualPort getRouterV6InterfaceForNetwork(Uuid networkId) {
508 LOG.debug("obtaining the virtual interface for {}", networkId);
509 return (vrouterv6IntfMap.get(networkId));
512 public VirtualPort obtainV6Interface(Uuid id) {
513 VirtualPort intf = vintfs.get(id);
517 for (VirtualSubnet snet : intf.getSubnets()) {
518 if (snet.getIpVersion().equals(Ipv6Constants.IP_VERSION_V6)) {
525 private void programIcmpv6RSPuntFlows(VirtualPort routerPort, int action) {
526 Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
528 VirtualNetwork vnet = vnetworks.get(routerPort.getNetworkID());
530 List<BigInteger> dpnList = vnet.getDpnsHostingNetwork();
531 for (BigInteger dpId : dpnList) {
532 flowStatus = vnet.getRSPuntFlowStatusOnDpnId(dpId);
533 if (action == Ipv6Constants.ADD_FLOW && flowStatus == Ipv6Constants.FLOWS_NOT_CONFIGURED) {
534 ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
535 mdsalUtil, Ipv6Constants.ADD_FLOW);
536 vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_CONFIGURED);
537 } else if (action == Ipv6Constants.DEL_FLOW && flowStatus == Ipv6Constants.FLOWS_CONFIGURED) {
538 ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
539 mdsalUtil, Ipv6Constants.DEL_FLOW);
540 vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_NOT_CONFIGURED);
546 private void programIcmpv6NSPuntFlowForAddress(VirtualPort routerPort, Ipv6Address ipv6Address, int action) {
547 Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
548 VirtualNetwork vnet = vnetworks.get(routerPort.getNetworkID());
550 Collection<VirtualNetwork.DpnInterfaceInfo> dpnIfaceList = vnet.getDpnIfaceList();
551 for (VirtualNetwork.DpnInterfaceInfo dpnIfaceInfo : dpnIfaceList) {
552 if (action == Ipv6Constants.ADD_FLOW && !dpnIfaceInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
553 ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpnIfaceInfo.getDpId(),
554 elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
555 dpnIfaceInfo.updateNDTargetAddress(ipv6Address, action);
556 } else if (action == Ipv6Constants.DEL_FLOW && dpnIfaceInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
557 ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpnIfaceInfo.getDpId(),
558 elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.DEL_FLOW);
559 dpnIfaceInfo.updateNDTargetAddress(ipv6Address, action);
565 public void programIcmpv6PuntFlowsIfNecessary(Uuid vmPortId, BigInteger dpId, VirtualPort routerPort) {
566 VirtualPort vmPort = vintfs.get(vmPortId);
567 if (null != vmPort) {
568 VirtualNetwork vnet = vnetworks.get(vmPort.getNetworkID());
570 VirtualNetwork.DpnInterfaceInfo dpnInfo = vnet.getDpnIfaceInfo(dpId);
571 if (null != dpnInfo) {
572 Long elanTag = getNetworkElanTag(routerPort.getNetworkID());
573 if (vnet.getRSPuntFlowStatusOnDpnId(dpId) == Ipv6Constants.FLOWS_NOT_CONFIGURED) {
574 ipv6ServiceUtils.installIcmpv6RsPuntFlow(NwConstants.IPV6_TABLE, dpId, elanTag,
575 mdsalUtil, Ipv6Constants.ADD_FLOW);
576 vnet.setRSPuntFlowStatusOnDpnId(dpId, Ipv6Constants.FLOWS_CONFIGURED);
579 for (Ipv6Address ipv6Address: routerPort.getIpv6Addresses()) {
580 if (!dpnInfo.ndTargetFlowsPunted.contains(ipv6Address)) {
581 ipv6ServiceUtils.installIcmpv6NsPuntFlow(NwConstants.IPV6_TABLE, dpId,
582 elanTag, ipv6Address.getValue(), mdsalUtil, Ipv6Constants.ADD_FLOW);
583 dpnInfo.updateNDTargetAddress(ipv6Address, Ipv6Constants.ADD_FLOW);
591 public String getInterfaceNameFromTag(long portTag) {
592 String interfaceName = null;
593 GetInterfaceFromIfIndexInput input = new GetInterfaceFromIfIndexInputBuilder()
594 .setIfIndex((int) portTag).build();
595 Future<RpcResult<GetInterfaceFromIfIndexOutput>> futureOutput =
596 interfaceManagerRpc.getInterfaceFromIfIndex(input);
598 GetInterfaceFromIfIndexOutput output = futureOutput.get().getResult();
599 interfaceName = output.getInterfaceName();
600 } catch (InterruptedException | ExecutionException e) {
601 LOG.error("Error while retrieving the interfaceName from tag using getInterfaceFromIfIndex RPC");
603 LOG.trace("Returning interfaceName {} for tag {} form getInterfaceNameFromTag", interfaceName, portTag);
604 return interfaceName;
607 public Long updateNetworkElanTag(Uuid networkId) {
609 if (null != this.elanProvider) {
610 ElanInstance elanInstance = this.elanProvider.getElanInstance(networkId.getValue());
611 if (null != elanInstance) {
612 elanTag = elanInstance.getElanTag();
613 VirtualNetwork net = vnetworks.get(networkId);
615 net.setElanTag(elanTag);
622 public Long getNetworkElanTag(Uuid networkId) {
624 VirtualNetwork net = vnetworks.get(networkId);
626 elanTag = net.getElanTag();
627 if (null == elanTag) {
628 elanTag = updateNetworkElanTag(networkId);
634 public void addNetwork(Uuid networkId) {
635 VirtualNetwork net = vnetworks.get(networkId);
637 net = new VirtualNetwork();
638 net.setNetworkUuid(networkId);
639 vnetworks.put(networkId, net);
640 updateNetworkElanTag(networkId);
644 public void removeNetwork(Uuid networkId) {
645 // Delete the network and the corresponding dpnIds<-->List(ports) cache.
646 VirtualNetwork net = vnetworks.get(networkId);
649 vnetworks.remove(networkId);
653 private void transmitRouterAdvertisement(VirtualPort intf, Ipv6RtrAdvertType advType) {
654 Ipv6RouterAdvt ipv6RouterAdvert = new Ipv6RouterAdvt();
656 LOG.debug("in transmitRouterAdvertisement for {}", advType);
657 VirtualNetwork vnet = vnetworks.get(intf.getNetworkID());
661 Collection<VirtualNetwork.DpnInterfaceInfo> dpnIfaceList = vnet.getDpnIfaceList();
662 for (VirtualNetwork.DpnInterfaceInfo dpnIfaceInfo : dpnIfaceList) {
663 nodeName = Ipv6Constants.OPENFLOW_NODE_PREFIX + dpnIfaceInfo.getDpId();
664 List<NodeConnectorRef> ncRefList = new ArrayList<>();
665 for (Long ofPort: dpnIfaceInfo.ofPortList) {
666 outPort = nodeName + ":" + ofPort;
667 LOG.debug("Transmitting RA {} for node {}, port {}", advType, nodeName, outPort);
668 InstanceIdentifier<NodeConnector> outPortId = InstanceIdentifier.builder(Nodes.class)
669 .child(Node.class, new NodeKey(new NodeId(nodeName)))
670 .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(outPort)))
672 ncRefList.add(new NodeConnectorRef(outPortId));
674 if (!ncRefList.isEmpty()) {
675 ipv6RouterAdvert.transmitRtrAdvertisement(advType, intf, ncRefList, null);
681 public void transmitUnsolicitedRA(Uuid portId) {
682 VirtualPort port = vintfs.get(portId);
683 LOG.debug("in transmitUnsolicitedRA for {}, port", portId, port);
685 transmitUnsolicitedRA(port);
689 public void transmitUnsolicitedRA(VirtualPort port) {
690 transmitRouterAdvertisement(port, Ipv6RtrAdvertType.UNSOLICITED_ADVERTISEMENT);
691 Ipv6TimerWheel timer = Ipv6TimerWheel.getInstance();
692 Timeout portTimeout = timer.setPeriodicTransmissionTimeout(port.getPeriodicTimer(),
693 Ipv6Constants.PERIODIC_RA_INTERVAL,
695 port.setPeriodicTimeout(portTimeout);
696 LOG.debug("re-started periodic RA Timer for routerIntf {}, int {}s", port.getIntfUUID(),
697 Ipv6Constants.PERIODIC_RA_INTERVAL);