Dynamic IPv6 assignment for sub-port is not working 25/71825/17
authorKarthikeyan Krishnan <karthikeyangceb007@gmail.com>
Mon, 7 May 2018 10:32:47 +0000 (16:02 +0530)
committerSridhar Gaddam <sgaddam@redhat.com>
Thu, 7 Jun 2018 13:57:32 +0000 (13:57 +0000)
Issue:
========
Dynamic IPv6 assignment is not working as expected for sub-ports(VLANs).
It was working for only trunk port.

Solution:
=========
IPv6 Unsolicited Periodic message is sendt out every minute from ODL
controller (Leader/Master Node for Cluster Setup) to all IPv6 VMs OF ports.
This will not work for Sub-port.Since RA packet is not checking for VLAN IDs.
As part of this fix, sending both Solicited RA and Unsolicited RA packets
to remote ELAN Group to reach all the VMs in the ELAN group. This way we
can achieve optimal way to sending perodically URA to all the IPv6 service
enabled VMs.

ACL Service Changes:
--------------------
Added code changes for allow ICMPv6 Router Advertisement packets from ODL
controller for unsolicited RA packets in EGRESS_ACL_ANTI_SPOOFING_TABLE(table 240).

For Solicited RA packets are sending out from ODL controller to VM port
directly instead of re-submitting back to Egress pipeline.

This changes will address the both RA packets from external router as well
as internal neutron router (ODL Controller) for each VM matching with
lport_tag, ICMPv6_Type=134 and IPv6_Src=fe80::/10 to allow in table 240.

Issue: NETVIRT-1245

Change-Id: Ifb75fcadd971e406674b6108ab0a9b3dc0b1f698
Signed-off-by: Karthikeyan Krishnan <karthikeyangceb007@gmail.com>
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/IngressAclServiceImpl.java
aclservice/impl/src/main/java/org/opendaylight/netvirt/aclservice/utils/AclServiceUtils.java
ipv6service/impl/src/main/java/org/opendaylight/netvirt/ipv6service/IfMgr.java
ipv6service/impl/src/main/java/org/opendaylight/netvirt/ipv6service/Ipv6PktHandler.java
ipv6service/impl/src/main/java/org/opendaylight/netvirt/ipv6service/Ipv6RouterAdvt.java
ipv6service/impl/src/main/java/org/opendaylight/netvirt/ipv6service/utils/Ipv6Constants.java
ipv6service/impl/src/main/java/org/opendaylight/netvirt/ipv6service/utils/Ipv6ServiceUtils.java
ipv6service/impl/src/test/java/org/opendaylight/netvirt/ipv6service/Ipv6PktHandlerTest.java

index 86939ebf02356bc2a35171210465beca717600e1..3f6267d9245bfb82476794b3f3352fd47ceaaed8 100644 (file)
@@ -272,23 +272,24 @@ public class IngressAclServiceImpl extends AbstractAclServiceImpl {
 
     @Override
     protected void programIcmpv6RARule(AclInterface port, List<SubnetInfo> subnets, int addOrRemove) {
-        // Allow ICMPv6 Router Advertisement packets from external routers only if ipv6_ra_mode is not
-        // specified for an IPv6 subnet.
-        if (!AclServiceUtils.isIpv6RaAllowedFromExternalRouters(subnets)) {
-            return;
+        if (AclServiceUtils.isIpv6Subnet(subnets)) {
+            /* Allow ICMPv6 Router Advertisement packets from external routers as well as internal routers
+             * if subnet is configured with IPv6 version
+             * Allow ICMPv6 Router Advertisement packets if originating from any LinkLocal Address.
+             */
+            List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
+            List<MatchInfoBase> matches =
+                    AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_RA, 0,
+                            port.getLPortTag(), serviceMode);
+            matches.addAll(AclServiceUtils.buildIpMatches(
+                    new IpPrefixOrAddress(new IpPrefix(AclConstants.IPV6_LINK_LOCAL_PREFIX.toCharArray())),
+                    AclServiceManager.MatchCriteria.MATCH_SOURCE));
+            String flowName = "Ingress_ICMPv6" + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
+                    + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
+            syncFlow(port.getDpId(), getAclAntiSpoofingTable(), flowName,
+                    AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, "ACL", 0,
+                    0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
         }
-        List<InstructionInfo> instructions = getDispatcherTableResubmitInstructions();
-        List<MatchInfoBase> matches =
-                AclServiceUtils.buildIcmpV6Matches(AclConstants.ICMPV6_TYPE_RA, 0, port.getLPortTag(), serviceMode);
-        // Allow ICMPv6 Router Advertisement packets if originating from any LinkLocal Address.
-        matches.addAll(AclServiceUtils.buildIpMatches(
-                new IpPrefixOrAddress(new IpPrefix(AclConstants.IPV6_LINK_LOCAL_PREFIX.toCharArray())),
-                AclServiceManager.MatchCriteria.MATCH_SOURCE));
-
-        String flowName = "Ingress_ICMPv6" + "_" + port.getDpId() + "_" + port.getLPortTag() + "_"
-                + AclConstants.ICMPV6_TYPE_RA + "_LinkLocal_Permit_";
-        syncFlow(port.getDpId(), getAclAntiSpoofingTable(), flowName, AclConstants.PROTO_IPV6_ALLOWED_PRIORITY, "ACL",
-                0, 0, AclConstants.COOKIE_ACL_BASE, matches, instructions, addOrRemove);
     }
 
     /**
index b90dcecf00b76c97b17109cb96a34d185ee061e6..936e008710360d4606ebf07c895e441d03585c0b 100644 (file)
@@ -32,6 +32,7 @@ import java.util.concurrent.Future;
 import javax.annotation.Nullable;
 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.binding.api.WriteTransaction;
@@ -1515,11 +1516,10 @@ public final class AclServiceUtils {
         return inetAddress;
     }
 
-    public static Boolean isIpv6RaAllowedFromExternalRouters(List<SubnetInfo> subnetInfoList) {
+    public static Boolean isIpv6Subnet(List<SubnetInfo> subnetInfoList) {
         if (subnetInfoList != null && !subnetInfoList.isEmpty()) {
             for (SubnetInfo subnetInfo : subnetInfoList) {
-                if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())
-                        && subnetInfo.getIpv6RaMode() == null) {
+                if (subnetInfo != null && IpVersionV6.class.equals(subnetInfo.getIpVersion())) {
                     return true;
                 }
             }
index 0243bcd49cdccc0bdd395aa0213850fc043fbfc3..2e17204d9146f87d56d364b71a4eb638f153baeb 100644 (file)
@@ -44,22 +44,17 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.MacAddress;
 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.action.types.rev131112.action.list.Action;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetEgressActionsForInterfaceOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.GetInterfaceFromIfIndexOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.interfacemanager.rpcs.rev160406.OdlInterfaceRpcService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
-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.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -680,28 +675,18 @@ public class IfMgr implements ElementCache, AutoCloseable {
     }
 
     private void transmitRouterAdvertisement(VirtualPort intf, Ipv6RtrAdvertType advType) {
-        Ipv6RouterAdvt ipv6RouterAdvert = new Ipv6RouterAdvt(packetService);
+        Ipv6RouterAdvt ipv6RouterAdvert = new Ipv6RouterAdvt(packetService, this);
 
-        LOG.debug("in transmitRouterAdvertisement for {}", advType);
         VirtualNetwork vnet = getNetwork(intf.getNetworkID());
         if (vnet != null) {
-            String nodeName;
-            String outPort;
+            long elanTag = vnet.getElanTag();
             Collection<VirtualNetwork.DpnInterfaceInfo> dpnIfaceList = vnet.getDpnIfaceList();
             for (VirtualNetwork.DpnInterfaceInfo dpnIfaceInfo : dpnIfaceList) {
-                nodeName = Ipv6Constants.OPENFLOW_NODE_PREFIX + dpnIfaceInfo.getDpId();
-                List<NodeConnectorRef> ncRefList = new ArrayList<>();
-                for (Long ofPort: dpnIfaceInfo.ofPortList) {
-                    outPort = nodeName + ":" + ofPort;
-                    LOG.debug("Transmitting RA {} for node {}, port {}", advType, nodeName, outPort);
-                    InstanceIdentifier<NodeConnector> outPortId = InstanceIdentifier.builder(Nodes.class)
-                            .child(Node.class, new NodeKey(new NodeId(nodeName)))
-                            .child(NodeConnector.class, new NodeConnectorKey(new NodeConnectorId(outPort)))
-                            .build();
-                    ncRefList.add(new NodeConnectorRef(outPortId));
-                }
-                if (!ncRefList.isEmpty()) {
-                    ipv6RouterAdvert.transmitRtrAdvertisement(advType, intf, ncRefList, null);
+                LOG.debug("transmitRouterAdvertisement: Transmitting RA {} for ELAN Tag {}",
+                        advType, elanTag);
+                if (dpnIfaceInfo.getDpId() != null) {
+                    ipv6RouterAdvert.transmitRtrAdvertisement(advType, intf, elanTag, null,
+                            dpnIfaceInfo.getDpId(), intf.getIntfUUID());
                 }
             }
         }
@@ -765,4 +750,24 @@ public class IfMgr implements ElementCache, AutoCloseable {
         }
         return virtualRouter;
     }
+
+    public List<Action> getEgressAction(String interfaceName) {
+        List<Action> actions = null;
+        try {
+            GetEgressActionsForInterfaceInputBuilder egressAction =
+                    new GetEgressActionsForInterfaceInputBuilder().setIntfName(interfaceName);
+            Future<RpcResult<GetEgressActionsForInterfaceOutput>> result =
+                    interfaceManagerRpc.getEgressActionsForInterface(egressAction.build());
+            RpcResult<GetEgressActionsForInterfaceOutput> rpcResult = result.get();
+            if (!rpcResult.isSuccessful()) {
+                LOG.warn("RPC Call to Get egress actions for interface {} returned with Errors {}",
+                        interfaceName, rpcResult.getErrors());
+            } else {
+                actions = rpcResult.getResult().getAction();
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when egress actions for interface {}", interfaceName, e);
+        }
+        return actions;
+    }
 }
index e5d11c79c07ce2f6373886d798f968a08ea3c8fe..58e2e77d90b2b8d9131905df29fbfc1c95d1837d 100644 (file)
@@ -11,9 +11,7 @@ import java.math.BigInteger;
 import java.net.InetAddress;
 import java.net.UnknownHostException;
 import java.nio.ByteBuffer;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicLong;
@@ -30,7 +28,6 @@ import org.opendaylight.openflowplugin.libraries.liblldp.BufferException;
 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.MacAddress;
 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.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.Ipv6Header;
@@ -306,7 +303,8 @@ public class Ipv6PktHandler implements AutoCloseable, PacketProcessingListener {
             BigInteger metadata = packet.getMatch().getMetadata().getMetadata();
             long portTag = MetaDataUtil.getLportFromMetadata(metadata).intValue();
             String interfaceName = ifMgr.getInterfaceNameFromTag(portTag);
-            VirtualPort port = ifMgr.obtainV6Interface(new Uuid(interfaceName));
+            Uuid portId = new Uuid(interfaceName);
+            VirtualPort port = ifMgr.obtainV6Interface(portId);
             if (port == null) {
                 pktProccessedCounter.incrementAndGet();
                 LOG.info("Port {} not found, skipping.", interfaceName);
@@ -319,11 +317,11 @@ public class Ipv6PktHandler implements AutoCloseable, PacketProcessingListener {
                 LOG.warn("Port for networkId {} is not associated to a Router, skipping.", port.getNetworkID());
                 return;
             }
-            Ipv6RouterAdvt ipv6RouterAdvert = new Ipv6RouterAdvt(pktService);
-            List<NodeConnectorRef> ncRefList = new ArrayList<>();
-            ncRefList.add(packet.getIngress());
+            Ipv6RouterAdvt ipv6RouterAdvert = new Ipv6RouterAdvt(pktService, ifMgr);
+            LOG.debug("Sending Solicited Router Advertisement for the port {} belongs to the network {}", port,
+                    port.getNetworkID());
             ipv6RouterAdvert.transmitRtrAdvertisement(Ipv6RtrAdvertType.SOLICITED_ADVERTISEMENT,
-                                                      routerPort, ncRefList, rsPdu);
+                    routerPort, 0, rsPdu, port.getDpId(), port.getIntfUUID());
             pktProccessedCounter.incrementAndGet();
         }
 
index 371dffe2696e6d551200e59dec2feadd34b80c91..37aee2c1b2a0e0d05ba606391cca42363cc9ccf6 100644 (file)
@@ -8,10 +8,15 @@
 
 package org.opendaylight.netvirt.ipv6service;
 
+import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+
+import org.opendaylight.genius.mdsalutil.ActionInfo;
+import org.opendaylight.genius.mdsalutil.MDSALUtil;
+import org.opendaylight.genius.mdsalutil.actions.ActionGroup;
 import org.opendaylight.infrautils.utils.concurrent.JdkFutures;
 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants;
 import org.opendaylight.netvirt.ipv6service.utils.Ipv6Constants.Ipv6RtrAdvertType;
@@ -20,9 +25,8 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.inet.types.rev130715.Ipv6Prefix;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+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.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterAdvertisementPacket;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterAdvertisementPacketBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.RouterSolicitationPacket;
@@ -30,33 +34,49 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.pack
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netvirt.ipv6service.nd.packet.rev160620.router.advertisement.packet.PrefixListBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.PacketProcessingService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+
 public class Ipv6RouterAdvt {
     private static final Logger LOG = LoggerFactory.getLogger(Ipv6RouterAdvt.class);
     private final PacketProcessingService packetService;
+    private final IfMgr ifMgr;
 
-    public Ipv6RouterAdvt(PacketProcessingService packetService) {
+    public Ipv6RouterAdvt(PacketProcessingService packetService, IfMgr ifMgr) {
         this.packetService = packetService;
+        this.ifMgr = ifMgr;
     }
 
     public boolean transmitRtrAdvertisement(Ipv6RtrAdvertType raType, VirtualPort routerPort,
-                                            List<NodeConnectorRef> outportList, RouterSolicitationPacket rsPdu) {
+                                            long elanTag, RouterSolicitationPacket rsPdu,
+                                            BigInteger dpnId, Uuid port) {
         RouterAdvertisementPacketBuilder raPacket = new RouterAdvertisementPacketBuilder();
         updateRAResponse(raType, rsPdu, raPacket, routerPort);
         // Serialize the response packet
         byte[] txPayload = fillRouterAdvertisementPacket(raPacket.build());
-        for (NodeConnectorRef outport: outportList) {
-            InstanceIdentifier<Node> outNode = outport.getValue().firstIdentifierOf(Node.class);
-            TransmitPacketInput input = new TransmitPacketInputBuilder().setPayload(txPayload)
-                    .setNode(new NodeRef(outNode))
-                    .setEgress(outport).build();
-            LOG.debug("Transmitting the Router Advt packet out {}", outport);
-            JdkFutures.addErrorLogging(packetService.transmitPacket(input), LOG, "transmitPacket");
+        TransmitPacketInput input = null;
+        /* Send solicited router advertisement to requested VM port only.
+         * Send periodic unsolicited router advertisement to ELAN broadcast group.
+         */
+        if (raType == Ipv6RtrAdvertType.SOLICITED_ADVERTISEMENT) {
+            List<Action> actions = ifMgr.getEgressAction(port.getValue());
+            if (actions == null || actions.isEmpty()) {
+                LOG.error("Unable to send solicited router advertisement packet out. Since Egress "
+                        + "action is empty for interface {}. ", port.getValue());
+                return false;
+            }
+            input = MDSALUtil.getPacketOut(actions, txPayload, dpnId);
+            LOG.debug("Transmitting the Router Advt packet out to port {}", port.getValue());
+        } else {
+            /* Here we handle UNSOLICITED_ADVERTISEMENT, CEASE_ADVERTISEMENT */
+            long elanGroupId = Ipv6ServiceUtils.getRemoteBCGroup(elanTag);
+            List<ActionInfo> lstActionInfo = new ArrayList<>();
+            lstActionInfo.add(new ActionGroup(elanGroupId));
+            input = MDSALUtil.getPacketOutDefault(lstActionInfo, txPayload, dpnId);
+            LOG.debug("Transmitting the Router Advt packet out to ELAN Group ID {}", elanGroupId);
         }
+        JdkFutures.addErrorLogging(packetService.transmitPacket(input), LOG, "transmitPacket");
         return true;
     }
 
index 15c299c2269a3711b865dc7e7a803f333a6d098f..e1af229760a427bc191a913562ed0f8da8e9570a 100644 (file)
@@ -73,6 +73,7 @@ public interface Ipv6Constants {
     String DEF_MCAST_MAC = "33:33:00:00:00:01";
     //default periodic RA transmission interval. timeunit in sec
     long PERIODIC_RA_INTERVAL = 60;
+    int ELAN_GID_MIN = 200000;
 
     enum Ipv6RtrAdvertType {
         UNSOLICITED_ADVERTISEMENT,
index 277533780690451c9a4f1ff11bf4399ca3c4c888..8dee6b13b76cb19c313131d499a345f04c2a824d 100644 (file)
@@ -475,4 +475,8 @@ public class Ipv6ServiceUtils {
                 buildServiceId(interfaceName, ServiceIndex.getIndex(NwConstants.IPV6_SERVICE_NAME,
                         NwConstants.IPV6_SERVICE_INDEX)));
     }
+
+    public static long getRemoteBCGroup(long elanTag) {
+        return Ipv6Constants.ELAN_GID_MIN + elanTag % Ipv6Constants.ELAN_GID_MIN * 2;
+    }
 }
index 086ff42c598a4692ebebac0ecc2480f7ccef8266..942bd2513ec4c4269a15d79cb93e9fbb2ebdfa08 100644 (file)
@@ -20,6 +20,8 @@ import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
+import org.opendaylight.genius.mdsalutil.NwConstants;
+import org.opendaylight.genius.mdsalutil.actions.ActionNxResubmit;
 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.ietf.inet.types.rev130715.IpAddress;
@@ -27,6 +29,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 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.MacAddress;
 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.action.types.rev131112.action.list.Action;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
@@ -284,8 +287,13 @@ public class Ipv6PktHandlerTest {
     @Test
     public void testonPacketReceivedRouterSolicitationWithSingleSubnet() throws Exception {
         VirtualPort intf = Mockito.mock(VirtualPort.class);
+        when(intf.getDpId()).thenReturn(new BigInteger(String.valueOf(1)));
+        when(intf.getIntfUUID()).thenReturn(Uuid.getDefaultInstance("ddec9dba-d831-4ad7-84b9-00d7f65f052f"));
         when(intf.getMacAddress()).thenReturn("fa:16:3e:4e:18:0c");
         when(ifMgrInstance.getInterfaceNameFromTag(anyLong())).thenReturn("ddec9dba-d831-4ad7-84b9-00d7f65f052f");
+        List<Action> actions = new ArrayList<>();
+        actions.add(new ActionNxResubmit(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE).buildAction());
+        when(ifMgrInstance.getEgressAction(any())).thenReturn(actions);
         when(ifMgrInstance.obtainV6Interface(any())).thenReturn(intf);
         when(ifMgrInstance.getRouterV6InterfaceForNetwork(any())).thenReturn(intf);
 
@@ -364,16 +372,21 @@ public class Ipv6PktHandlerTest {
                 "20 01 0D B8 00 00 00 00 00 00 00 00 00 00 00 00"  // Prefix
         );
         verify(pktProcessService).transmitPacket(new TransmitPacketInputBuilder().setPayload(expectedPayload)
-                .setNode(new NodeRef(ncId)).setEgress(ncRef).build());
+                .setNode(new NodeRef(ncId)).setEgress(ncRef).setIngress(ncRef).setAction(any(List.class)).build());
     }
 
     @Test
     public void testonPacketReceivedRouterSolicitationWithMultipleSubnets() throws Exception {
         VirtualPort intf = Mockito.mock(VirtualPort.class);
+        when(intf.getDpId()).thenReturn(new BigInteger(String.valueOf(1)));
         when(intf.getMacAddress()).thenReturn("50:7B:9D:78:54:F3");
+        when(intf.getIntfUUID()).thenReturn(Uuid.getDefaultInstance("ddec9dba-d831-4ad7-84b9-00d7f65f052f"));
         when(ifMgrInstance.obtainV6Interface(any())).thenReturn(intf);
         when(ifMgrInstance.getInterfaceNameFromTag(anyLong())).thenReturn("ddec9dba-d831-4ad7-84b9-00d7f65f052f");
         when(ifMgrInstance.getRouterV6InterfaceForNetwork(any())).thenReturn(intf);
+        List<Action> actions = new ArrayList<>();
+        actions.add(new ActionNxResubmit(NwConstants.EGRESS_LPORT_DISPATCHER_TABLE).buildAction());
+        when(ifMgrInstance.getEgressAction(any())).thenReturn(actions);
 
         IpAddress gwIpAddress = Mockito.mock(IpAddress.class);
         when(gwIpAddress.getIpv4Address()).thenReturn(null);
@@ -481,7 +494,7 @@ public class Ipv6PktHandlerTest {
 
         verify(pktProcessService).transmitPacket(new TransmitPacketInputBuilder().setPayload(expectedPayload)
                 .setNode(new NodeRef(ncId))
-                .setEgress(ncRef).build());
+                .setEgress(ncRef).setIngress(ncRef).setAction(any(List.class)).build());
     }
 
     private void waitForPacketProcessing() throws InterruptedException {