IPv6 NS RS tests and fixes 10/4610/3
authorNeale Ranns <nranns@cisco.com>
Mon, 9 Jan 2017 09:00:45 +0000 (01:00 -0800)
committerOle Trøan <otroan@employees.org>
Tue, 10 Jan 2017 14:09:55 +0000 (14:09 +0000)
includes Fix for VPP-584 with API change to remove prefix length from LL programming

Change-Id: If860751c35e60255fb977f73bc33e8c2649e728e
Signed-off-by: Neale Ranns <nranns@cisco.com>
15 files changed:
src/vat/api_format.c
src/vnet/interface_funcs.h
src/vnet/ip/icmp6.h
src/vnet/ip/ip.api
src/vnet/ip/ip6.h
src/vnet/ip/ip6_forward.c
src/vnet/ip/ip6_neighbor.c
src/vnet/ip/ip_api.c
src/vnet/rewrite.c
src/vpp/api/custom_dump.c
src/vpp/api/test_client.c
test/test_ip6.py
test/vpp_interface.py
test/vpp_papi_provider.py
test/vpp_pg_interface.py

index c00104d..7514820 100644 (file)
@@ -7671,7 +7671,6 @@ api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
   f64 timeout;
   u32 sw_if_index;
   u8 sw_if_index_set = 0;
-  u32 address_length = 0;
   u8 v6_address_set = 0;
   ip6_address_t v6address;
 
@@ -7682,8 +7681,7 @@ api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
        sw_if_index_set = 1;
       else if (unformat (i, "sw_if_index %d", &sw_if_index))
        sw_if_index_set = 1;
-      else if (unformat (i, "%U/%d",
-                        unformat_ip6_address, &v6address, &address_length))
+      else if (unformat (i, "%U", unformat_ip6_address, &v6address))
        v6_address_set = 1;
       else
        break;
@@ -7706,7 +7704,6 @@ api_sw_interface_ip6_set_link_local_address (vat_main_t * vam)
 
   mp->sw_if_index = ntohl (sw_if_index);
   clib_memcpy (mp->address, &v6address, sizeof (v6address));
-  mp->address_length = address_length;
 
   /* send it... */
   S;
index b84d151..ab808df 100644 (file)
@@ -52,6 +52,14 @@ vnet_get_sw_interface (vnet_main_t * vnm, u32 sw_if_index)
   return pool_elt_at_index (vnm->interface_main.sw_interfaces, sw_if_index);
 }
 
+always_inline vnet_sw_interface_t *
+vnet_get_sw_interface_safe (vnet_main_t * vnm, u32 sw_if_index)
+{
+  if (!pool_is_free_index (vnm->interface_main.sw_interfaces, sw_if_index))
+    return pool_elt_at_index (vnm->interface_main.sw_interfaces, sw_if_index);
+  return (NULL);
+}
+
 always_inline vnet_sw_interface_t *
 vnet_get_hw_sw_interface (vnet_main_t * vnm, u32 hw_if_index)
 {
index a426512..9a3487b 100644 (file)
      "neighbor discovery unsupported  interface")                       \
   _ (ROUTER_SOLICITATION_RADV_NOT_CONFIG,                               \
      "neighbor discovery not configured")                               \
-  _ (ROUTER_SOLICITATION_DEST_UNKNOWN,                                  \
-     "router solicitations for unknown destination")                    \
-  _ (ROUTER_SOLICITATION_SOURCE_UNKNOWN,                                \
-     "router solicitations for unknown source")                         \
   _ (ROUTER_ADVERTISEMENT_SOURCE_NOT_LINK_LOCAL,                        \
      "router advertisement source not link local")                      \
   _ (ROUTER_ADVERTISEMENTS_TX, "router advertisements sent")            \
index c811e46..f244480 100644 (file)
@@ -311,7 +311,6 @@ define sw_interface_ip6_enable_disable_reply
     @param context - sender context, to match reply w/ request
     @param sw_if_index - interface to set link local on
     @param address[] - the new link local address
-    @param address_length - link local address length
 */
 define sw_interface_ip6_set_link_local_address
 {
@@ -319,7 +318,6 @@ define sw_interface_ip6_set_link_local_address
   u32 context;
   u32 sw_if_index;
   u8 address[16];
-  u8 address_length;
 };
 
 /** \brief IPv6 set link local address on interface response
index 586b7c1..f493db0 100644 (file)
@@ -376,8 +376,7 @@ int ip6_interface_enabled (vlib_main_t * vm, u32 sw_if_index);
 
 clib_error_t *set_ip6_link_local_address (vlib_main_t * vm,
                                          u32 sw_if_index,
-                                         ip6_address_t * address,
-                                         u8 address_length);
+                                         ip6_address_t * address);
 
 void vnet_register_ip6_neighbor_resolution_event (vnet_main_t * vnm,
                                                  void *address_arg,
index b5c7955..866a44e 100644 (file)
@@ -404,8 +404,10 @@ ip6_sw_interface_enable_disable (u32 sw_if_index, u32 is_enable)
     }
   else
     {
-      ASSERT (im->ip_enabled_by_sw_if_index[sw_if_index] > 0);
-      if (0 != --im->ip_enabled_by_sw_if_index[sw_if_index])
+      /* The ref count is 0 when an address is removed from an interface that has
+       * no address - this is not a ciritical error */
+      if (0 == im->ip_enabled_by_sw_if_index[sw_if_index] ||
+         0 != --im->ip_enabled_by_sw_if_index[sw_if_index])
        return;
     }
 
index 5a1c9e8..46c0e31 100644 (file)
@@ -155,8 +155,6 @@ typedef struct
 
   /* Link local address to use (defaults to underlying physical for logical interfaces */
   ip6_address_t link_local_address;
-  u8 link_local_prefix_len;
-
 } ip6_radv_t;
 
 typedef struct
@@ -1316,7 +1314,8 @@ icmp6_router_solicitation (vlib_main_t * vm,
                      /* for solicited adverts - need to rate limit */
                      if (is_solicitation)
                        {
-                         if ((now - radv_info->last_radv_time) <
+                         if (0 != radv_info->last_radv_time &&
+                             (now - radv_info->last_radv_time) <
                              MIN_DELAY_BETWEEN_RAS)
                            is_dropped = 1;
                          else
@@ -1523,16 +1522,6 @@ icmp6_router_solicitation (vlib_main_t * vm,
                            error0 = ICMP6_ERROR_DST_LOOKUP_MISS;
                          else
                            {
-                             ip_adjacency_t *adj0 =
-                               ip_get_adjacency (&im->lookup_main,
-                                                 adj_index0);
-                             error0 =
-                               ((adj0->rewrite_header.sw_if_index !=
-                                 sw_if_index0
-                                 || adj0->lookup_next_index !=
-                                 IP_LOOKUP_NEXT_REWRITE) ?
-                                ICMP6_ERROR_ROUTER_SOLICITATION_DEST_UNKNOWN
-                                : error0);
                              next0 =
                                is_dropped ? next0 :
                                ICMP6_ROUTER_SOLICITATION_NEXT_REPLY_RW;
@@ -2022,7 +2011,6 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm,
          /* fill in default link-local address  (this may be overridden) */
          ip6_link_local_address_from_ethernet_address
            (&a->link_local_address, eth_if0->address);
-         a->link_local_prefix_len = 64;
 
          mhash_init (&a->address_to_prefix_index, sizeof (uword),
                      sizeof (ip6_address_t));
@@ -3266,9 +3254,7 @@ disable_ip6_interface (vlib_main_t * vm, u32 sw_if_index)
          /* essentially "disables" ipv6 on this interface */
          error = ip6_add_del_interface_address (vm, sw_if_index,
                                                 &radv_info->
-                                                link_local_address,
-                                                radv_info->
-                                                link_local_prefix_len,
+                                                link_local_address, 128,
                                                 1 /* is_del */ );
 
          ip6_neighbor_sw_interface_add_del (vnm, sw_if_index,
@@ -3372,7 +3358,6 @@ enable_ip6_interface (vlib_main_t * vm, u32 sw_if_index)
                  else
                    {
                      radv_info->link_local_address = link_local_address;
-                     radv_info->link_local_prefix_len = 64;
                    }
                }
            }
@@ -3585,8 +3570,7 @@ VLIB_CLI_COMMAND (ip6_nd_command, static) =
 
 clib_error_t *
 set_ip6_link_local_address (vlib_main_t * vm,
-                           u32 sw_if_index,
-                           ip6_address_t * address, u8 address_length)
+                           u32 sw_if_index, ip6_address_t * address)
 {
   clib_error_t *error = 0;
   ip6_neighbor_main_t *nm = &ip6_neighbor_main;
@@ -3615,22 +3599,18 @@ set_ip6_link_local_address (vlib_main_t * vm,
       /* delete the old one */
       error = ip6_add_del_interface_address (vm, sw_if_index,
                                             &radv_info->link_local_address,
-                                            radv_info->link_local_prefix_len
-                                            /* address width */ ,
-                                            1 /* is_del */ );
+                                            128, 1 /* is_del */ );
 
       if (!error)
        {
          /* add the new one */
          error = ip6_add_del_interface_address (vm, sw_if_index,
-                                                address, address_length
-                                                /* address width */ ,
+                                                address, 128,
                                                 0 /* is_del */ );
 
          if (!error)
            {
              radv_info->link_local_address = *address;
-             radv_info->link_local_prefix_len = address_length;
            }
        }
     }
@@ -3652,21 +3632,19 @@ set_ip6_link_local_address_cmd (vlib_main_t * vm,
   clib_error_t *error = 0;
   u32 sw_if_index;
   ip6_address_t ip6_addr;
-  u32 addr_len = 0;
 
   if (unformat_user (input, unformat_vnet_sw_interface, vnm, &sw_if_index))
     {
       /* get the rest of the command */
       while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
        {
-         if (unformat (input, "%U/%d",
-                       unformat_ip6_address, &ip6_addr, &addr_len))
+         if (unformat (input, "%U", unformat_ip6_address, &ip6_addr))
            break;
          else
            return (unformat_parse_error (input));
        }
     }
-  error = set_ip6_link_local_address (vm, sw_if_index, &ip6_addr, addr_len);
+  error = set_ip6_link_local_address (vm, sw_if_index, &ip6_addr);
   return error;
 }
 
@@ -3678,13 +3656,13 @@ set_ip6_link_local_address_cmd (vlib_main_t * vm,
  *
  * @cliexpar
  * Example of how to assign an IPv6 Link-local address to an interface:
- * @cliexcmd{set ip6 link-local address GigabitEthernet2/0/0 FE80::AB8/64}
+ * @cliexcmd{set ip6 link-local address GigabitEthernet2/0/0 FE80::AB8}
 ?*/
 /* *INDENT-OFF* */
 VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) =
 {
   .path = "set ip6 link-local address",
-  .short_help = "set ip6 link-local address <interface> <ip6-address>/<width>",
+  .short_help = "set ip6 link-local address <interface> <ip6-address>",
   .function = set_ip6_link_local_address_cmd,
 };
 /* *INDENT-ON* */
index cd9b739..aafde46 100644 (file)
@@ -1132,8 +1132,7 @@ static void
 
   error = set_ip6_link_local_address (vm,
                                      ntohl (mp->sw_if_index),
-                                     (ip6_address_t *) mp->address,
-                                     mp->address_length);
+                                     (ip6_address_t *) mp->address);
   if (error)
     {
       clib_error_report (error);
index 53d548b..8925ad6 100644 (file)
@@ -79,8 +79,11 @@ format_vnet_rewrite (u8 * s, va_list * args)
   if (rw->sw_if_index != ~0)
     {
       vnet_sw_interface_t *si;
-      si = vnet_get_sw_interface (vnm, rw->sw_if_index);
-      s = format (s, "%U: ", format_vnet_sw_interface_name, vnm, si);
+      si = vnet_get_sw_interface_safe (vnm, rw->sw_if_index);
+      if (NULL != si)
+       s = format (s, "%U: ", format_vnet_sw_interface_name, vnm, si);
+      else
+       s = format (s, "DELETED");
     }
   else
     s = format (s, "%v: ", next->name);
index c2cd3d1..f14a031 100644 (file)
@@ -911,8 +911,7 @@ static void *vl_api_sw_interface_ip6_set_link_local_address_t_print
 
   s = format (s, "sw_if_index %d ", ntohl (mp->sw_if_index));
 
-  s = format (s, "%U/%d ", format_ip6_address, mp->address,
-             mp->address_length);
+  s = format (s, "%U ", format_ip6_address, mp->address);
 
   FINISH;
 }
index 5c56895..ceafc35 100644 (file)
@@ -1196,8 +1196,6 @@ ip6_set_link_local_address (test_main_t * tm)
   clib_memcpy (mp->address, &tmp[0], 8);
   clib_memcpy (&mp->address[8], &tmp[1], 8);
 
-  mp->address_length = 64;
-
   mp->_vl_msg_id = ntohs (VL_API_SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS);
 
   vl_msg_api_send_shmem (tm->vl_input_queue, (u8 *) & mp);
index e8b12f6..cd9c4b9 100644 (file)
@@ -8,8 +8,18 @@ from vpp_sub_interface import VppSubInterface, VppDot1QSubint
 
 from scapy.packet import Raw
 from scapy.layers.l2 import Ether, Dot1Q
-from scapy.layers.inet6 import IPv6, UDP
+from scapy.layers.inet6 import IPv6, UDP, ICMPv6ND_NS, ICMPv6ND_RS, ICMPv6ND_RA, \
+    ICMPv6NDOptSrcLLAddr, getmacbyip6, ICMPv6MRD_Solicitation
 from util import ppp
+from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \
+    in6_mactoifaceid
+from scapy.utils import inet_pton, inet_ntop
+
+
+def mk_ll_addr(mac):
+    euid = in6_mactoifaceid(mac)
+    addr = "fe80::" + euid
+    return addr
 
 
 class TestIPv6(VppTestCase):
@@ -76,6 +86,12 @@ class TestIPv6(VppTestCase):
 
     def tearDown(self):
         """Run standard test teardown and log ``show ip6 neighbors``."""
+        for i in self.sub_interfaces:
+            i.unconfig_ip6()
+            i.ip6_disable()
+            i.admin_down()
+            i.remove_vpp_config()
+
         super(TestIPv6, self).tearDown()
         if not self.vpp_dead:
             self.logger.info(self.vapi.cli("show ip6 neighbors"))
@@ -206,6 +222,225 @@ class TestIPv6(VppTestCase):
             pkts = i.parent.get_capture()
             self.verify_capture(i, pkts)
 
+    def send_and_assert_no_replies(self, intf, pkts, remark):
+        intf.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        intf.assert_nothing_captured(remark=remark)
+
+    def test_ns(self):
+        """ IPv6 Neighbour Soliciatation Exceptions
+
+        Test sceanrio:
+           - Send an NS Sourced from an address not covered by the link sub-net
+           - Send an NS to an mcast address the router has not joined
+           - Send NS for a target address the router does not onn.
+        """
+
+        #
+        # An NS from a non link source address
+        #
+        nsma = in6_getnsma(inet_pton(socket.AF_INET6, self.pg0.local_ip6))
+        d = inet_ntop(socket.AF_INET6, nsma)
+
+        p = (Ether(dst=in6_getnsmac(nsma)) /
+             IPv6(dst=d, src="2002::2") /
+             ICMPv6ND_NS(tgt=self.pg0.local_ip6) /
+             ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
+        pkts = [p]
+
+        self.send_and_assert_no_replies(self.pg0, pkts,
+                                        "No response to NS source by address not on sub-net")
+
+        #
+        # An NS for sent to a solicited mcast group the router is not a member of
+        #  FAILS
+        #
+        if 0:
+            nsma = in6_getnsma(inet_pton(socket.AF_INET6, "fd::ffff"))
+            d = inet_ntop(socket.AF_INET6, nsma)
+
+            p = (Ether(dst=in6_getnsmac(nsma)) /
+                 IPv6(dst=d, src=self.pg0.remote_ip6) /
+                 ICMPv6ND_NS(tgt=self.pg0.local_ip6) /
+                 ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
+            pkts = [p]
+
+            self.send_and_assert_no_replies(self.pg0, pkts,
+                                            "No response to NS sent to unjoined mcast address")
+
+        #
+        # An NS whose target address is one the router does not own
+        #
+        nsma = in6_getnsma(inet_pton(socket.AF_INET6, self.pg0.local_ip6))
+        d = inet_ntop(socket.AF_INET6, nsma)
+
+        p = (Ether(dst=in6_getnsmac(nsma)) /
+             IPv6(dst=d, src=self.pg0.remote_ip6) /
+             ICMPv6ND_NS(tgt="fd::ffff") /
+             ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))
+        pkts = [p]
+
+        self.send_and_assert_no_replies(self.pg0, pkts,
+                                        "No response to NS for unknown target")
+
+    def send_and_expect_ra(self, intf, pkts, remark, src_ip=None):
+        if not src_ip:
+            src_ip = intf.remote_ip6
+        intf.add_stream(pkts)
+        self.pg0.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        rx = intf.get_capture(1)
+
+        self.assertEqual(len(rx), 1)
+        rx = rx[0]
+
+        # the rx'd RA should be addressed to the sender's source
+        self.assertTrue(rx.haslayer(ICMPv6ND_RA))
+        self.assertEqual(in6_ptop(rx[IPv6].dst),
+                         in6_ptop(src_ip))
+
+        # and come from the router's link local
+        self.assertTrue(in6_islladdr(rx[IPv6].src))
+        self.assertEqual(in6_ptop(rx[IPv6].src),
+                         in6_ptop(mk_ll_addr(intf.local_mac)))
+
+    def test_rs(self):
+        """ IPv6 Router Soliciatation Exceptions
+
+        Test sceanrio:
+        """
+
+        #
+        # Before we begin change the IPv6 RA responses to use the unicast address
+        # that way we will not confuse them with the periodic Ras which go to the Mcast
+        # address
+        #
+        self.pg0.ip6_ra_config(send_unicast=1)
+
+        #
+        # An RS from a link source address
+        #  - expect an RA in return
+        #
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) /
+             ICMPv6ND_RS())
+        pkts = [p]
+        self.send_and_expect_ra(self.pg0, pkts, "Genuine RS")
+
+        #
+        # For the next RS sent the RA should be rate limited
+        #
+        self.send_and_assert_no_replies(self.pg0, pkts, "RA rate limited")
+
+        #
+        # When we reconfiure the IPv6 RA config, we reset the RA rate limiting,
+        # so we need to do this before each test below so as not to drop packets for
+        # rate limiting reasons. Test this works here.
+        #
+        self.pg0.ip6_ra_config(send_unicast=1)
+        self.send_and_expect_ra(self.pg0, pkts, "Rate limit reset RS")
+
+        #
+        # An RS sent from a non-link local source
+        #
+        self.pg0.ip6_ra_config(send_unicast=1)
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IPv6(dst=self.pg0.local_ip6, src="2002::ffff") /
+             ICMPv6ND_RS())
+        pkts = [p]
+        self.send_and_assert_no_replies(self.pg0, pkts,
+                                        "RS from non-link source")
+
+        #
+        # Source an RS from a link local address
+        #
+        self.pg0.ip6_ra_config(send_unicast=1)
+        ll = mk_ll_addr(self.pg0.remote_mac)
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IPv6(dst=self.pg0.local_ip6, src=ll) /
+             ICMPv6ND_RS())
+        pkts = [p]
+        self.send_and_expect_ra(
+            self.pg0, pkts, "RS sourced from link-local", src_ip=ll)
+
+        #
+        # Source from the unspecified address ::. This happens when the RS is sent before
+        # the host has a configured address/sub-net, i.e. auto-config.
+        # Since the sender has no IP address, the reply comes back mcast - so the
+        # capture needs to not filter this.
+        # If we happen to pick up the periodic RA at this point then so be it, it's not
+        # an error.
+        #
+        self.pg0.ip6_ra_config(send_unicast=1)
+        p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
+             IPv6(dst=self.pg0.local_ip6, src="::") /
+             ICMPv6ND_RS())
+        pkts = [p]
+
+        self.pg0.add_stream(pkts)
+        self.pg0.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        capture = self.pg0.get_capture(1, filter_out_fn=None)
+        found = 0
+        for rx in capture:
+            if (rx.haslayer(ICMPv6ND_RA)):
+                # and come from the router's link local
+                self.assertTrue(in6_islladdr(rx[IPv6].src))
+                self.assertEqual(in6_ptop(rx[IPv6].src),
+                                 in6_ptop(mk_ll_addr(self.pg0.local_mac)))
+                # sent to the all hosts mcast
+                self.assertEqual(in6_ptop(rx[IPv6].dst), "ff02::1")
+
+                found = 1
+        self.assertTrue(found)
+
+    @unittest.skip("Unsupported")
+    def test_mrs(self):
+        """ IPv6 Multicast Router Soliciatation Exceptions
+
+        Test sceanrio:
+        """
+
+        #
+        # An RS from a link source address
+        #  - expect an RA in return
+        #
+        nsma = in6_getnsma(inet_pton(socket.AF_INET6, self.pg0.local_ip6))
+        d = inet_ntop(socket.AF_INET6, nsma)
+
+        p = (Ether(dst=getmacbyip6("ff02::2")) /
+             IPv6(dst=d, src=self.pg0.remote_ip6) /
+             ICMPv6MRD_Solicitation())
+        pkts = [p]
+
+        self.pg0.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.pg0.assert_nothing_captured(
+            remark="No response to NS source by address not on sub-net")
+
+        #
+        # An RS from a non link source address
+        #
+        nsma = in6_getnsma(inet_pton(socket.AF_INET6, self.pg0.local_ip6))
+        d = inet_ntop(socket.AF_INET6, nsma)
+
+        p = (Ether(dst=getmacbyip6("ff02::2")) /
+             IPv6(dst=d, src="2002::2") /
+             ICMPv6MRD_Solicitation())
+        pkts = [p]
+
+        self.send_and_assert_no_replies(self.pg0, pkts,
+                                        "RA rate limited")
+        self.pg0.add_stream(pkts)
+        self.pg_enable_capture(self.pg_interfaces)
+        self.pg_start()
+        self.pg0.assert_nothing_captured(
+            remark="No response to NS source by address not on sub-net")
+
 
 if __name__ == '__main__':
     unittest.main(testRunner=VppTestRunner)
index 6ccb92b..856a5cc 100644 (file)
@@ -249,6 +249,12 @@ class VppInterface(object):
         """Configure IPv6 RA suppress on the VPP interface."""
         self.test.vapi.sw_interface_ra_suppress(self.sw_if_index)
 
+    def ip6_ra_config(self, suppress=0, send_unicast=0):
+        """Configure IPv6 RA suppress on the VPP interface."""
+        self.test.vapi.ip6_sw_interface_ra_config(self.sw_if_index,
+                                                  suppress,
+                                                  send_unicast)
+
     def admin_up(self):
         """Put interface ADMIN-UP."""
         self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=1)
@@ -257,6 +263,14 @@ class VppInterface(object):
         """Put interface ADMIN-down."""
         self.test.vapi.sw_interface_set_flags(self.sw_if_index, admin_up_down=0)
 
+    def ip6_enable(self):
+        """IPv6 Enable interface"""
+        self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=1)
+
+    def ip6_disable(self):
+        """Put interface ADMIN-DOWN."""
+        self.test.vapi.ip6_sw_interface_enable_disable(self.sw_if_index, enable=0)
+
     def add_sub_if(self, sub_if):
         """Register a sub-interface with this interface.
 
index db530d9..0e4c0cd 100644 (file)
@@ -219,6 +219,22 @@ class VppPapiProvider(object):
         return self.api(self.papi.sw_interface_ip6nd_ra_config,
                         {'sw_if_index': sw_if_index})
 
+    def ip6_sw_interface_ra_config(self, sw_if_index,
+                                   suppress,
+                                   send_unicast,):
+        return self.api(self.papi.sw_interface_ip6nd_ra_config,
+                        {'sw_if_index': sw_if_index,
+                         'suppress' : suppress,
+                         'send_unicast' : send_unicast})
+
+    def ip6_sw_interface_enable_disable(self, sw_if_index, enable):
+        """
+        Enable/Disable An interface for IPv6
+        """
+        return self.api(self.papi.sw_interface_ip6_enable_disable,
+                        {'sw_if_index': sw_if_index,
+                         'enable': enable})
+
     def vxlan_add_del_tunnel(
             self,
             src_addr,
index aef0052..b5929a4 100644 (file)
@@ -10,13 +10,14 @@ from scapy.layers.inet6 import IPv6, ICMPv6ND_NS, ICMPv6ND_NA,\
     ICMPv6NDOptSrcLLAddr, ICMPv6NDOptDstLLAddr, ICMPv6ND_RA, RouterAlert, \
     IPv6ExtHdrHopByHop
 from util import ppp, ppc
-from scapy.utils6 import in6_getnsma, in6_getnsmac
+from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ismaddr
 from scapy.utils import inet_pton, inet_ntop
 
 def is_ipv6_misc(p):
     """ Is packet one of uninteresting IPv6 broadcasts? """
     if p.haslayer(ICMPv6ND_RA):
-        return True
+        if in6_ismaddr(p[IPv6].dst):
+            return True
     if p.haslayer(IPv6ExtHdrHopByHop):
         for o in p[IPv6ExtHdrHopByHop].options:
             if isinstance(o, RouterAlert):