From 87df12d5de67600414ae80b891e8a0f89e89ce5c Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Sat, 18 Feb 2017 08:16:41 -0800 Subject: [PATCH] IPv6 RA improvements 1) tests for RA options 2) memleaks deleteing a ip6_radv_info_t 3) MLD prefix code refactoring Change-Id: I34db103994bd8fbdbbec50b202d72770dd145681 Signed-off-by: Neale Ranns --- src/vnet/ip/ip.api | 36 +++++-- src/vnet/ip/ip6_neighbor.c | 244 ++++++++++++++++++--------------------------- src/vppinfra/pool.h | 26 +++++ test/test_ip6.py | 219 +++++++++++++++++++++++++++++++++++++++- test/vpp_interface.py | 11 ++ test/vpp_neighbor.py | 2 +- test/vpp_papi_provider.py | 25 +++++ 7 files changed, 400 insertions(+), 163 deletions(-) diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index 326c825b39f..ff16e781c05 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -241,17 +241,31 @@ define sw_interface_ip6nd_ra_config_reply /** \brief IPv6 router advertisement prefix config request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request - @param sw_if_index - - @param address[] - - @param address_length - - @param use_default - - @param no_advertise - - @param off_link - - @param no_autoconfig - - @param no_onlink - - @param is_no - - @param val_lifetime - - @param pref_lifetime - + @param sw_if_index - The interface the RA prefix information is for + @param address[] - The prefix to advertise + @param address_length - the prefix length + @param use_default - Revert to default settings + @param no_advertise - Do not advertise this prefix + @param off_link - The prefix is off link (it is not configured on the interface) + Configures the L-flag, When set, indicates that this + prefix can be used for on-link determination. + @param no_autoconfig - Setting for the A-flag. When + set indicates that this prefix can be used for + stateless address configuration. + @param no_onlink - The prefix is not on link. Make sure this is consistent + with the off_link parameter else YMMV + @param is_no - add/delete + @param val_lifetime - The length of time in + seconds (relative to the time the packet is sent) + that the prefix is valid for the purpose of on-link + determination. A value of all one bits + (0xffffffff) represents infinity + @param pref_lifetime - The length of time in + seconds (relative to the time the packet is sent) + that addresses generated from the prefix via + stateless address autoconfiguration remain + preferred [ADDRCONF]. A value of all one bits + (0xffffffff) represents infinity. */ define sw_interface_ip6nd_ra_prefix { diff --git a/src/vnet/ip/ip6_neighbor.c b/src/vnet/ip/ip6_neighbor.c index 91ff224c68e..43d68cd18bb 100644 --- a/src/vnet/ip/ip6_neighbor.c +++ b/src/vnet/ip/ip6_neighbor.c @@ -107,7 +107,6 @@ typedef struct /* local information */ u32 sw_if_index; - u32 fib_index; int send_radv; /* radv on/off on this interface - set by config */ int cease_radv; /* we are ceasing to send - set byf config */ int send_unicast; @@ -1924,7 +1923,79 @@ icmp6_router_advertisement (vlib_main_t * vm, return frame->n_vectors; } -/* create and initialize router advertisement parameters with default values for this intfc */ +/** + * @brief Add a multicast Address to the advertised MLD set + */ +static void +ip6_neighbor_add_mld_prefix (ip6_radv_t * radv_info, ip6_address_t * addr) +{ + ip6_mldp_group_t *mcast_group_info; + uword *p; + + /* lookup mldp info for this interface */ + p = mhash_get (&radv_info->address_to_mldp_index, &addr); + mcast_group_info = + p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; + + /* add address */ + if (!mcast_group_info) + { + /* add */ + u32 mi; + pool_get (radv_info->mldp_group_pool, mcast_group_info); + + mi = mcast_group_info - radv_info->mldp_group_pool; + mhash_set (&radv_info->address_to_mldp_index, &addr, mi, /* old_value */ + 0); + + mcast_group_info->type = 4; + mcast_group_info->mcast_source_address_pool = 0; + mcast_group_info->num_sources = 0; + clib_memcpy (&mcast_group_info->mcast_address, &addr, + sizeof (ip6_address_t)); + } +} + +/** + * @brief Delete a multicast Address from the advertised MLD set + */ +static void +ip6_neighbor_del_mld_prefix (ip6_radv_t * radv_info, ip6_address_t * addr) +{ + ip6_mldp_group_t *mcast_group_info; + uword *p; + + p = mhash_get (&radv_info->address_to_mldp_index, &addr); + mcast_group_info = + p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; + + if (mcast_group_info) + { + mhash_unset (&radv_info->address_to_mldp_index, &addr, + /* old_value */ 0); + pool_put (radv_info->mldp_group_pool, mcast_group_info); + } +} + +/** + * @brief Add a multicast Address to the advertised MLD set + */ +static void +ip6_neighbor_add_mld_grp (ip6_radv_t * a, + ip6_multicast_address_scope_t scope, + ip6_multicast_link_local_group_id_t group) +{ + ip6_address_t addr; + + ip6_set_reserved_multicast_address (&addr, scope, group); + + ip6_neighbor_add_mld_prefix (a, &addr); +} + +/** + * @brief create and initialize router advertisement parameters with default + * values for this intfc + */ static u32 ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, u32 sw_if_index, u32 is_add) @@ -1953,47 +2024,29 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, if (!is_add) { - u32 i, *to_delete = 0; ip6_radv_prefix_t *p; ip6_mldp_group_t *m; /* release the lock on the interface's mcast adj */ adj_unlock (a->mcast_adj_index); - /* clean up prefix_pool */ + /* clean up prefix and MDP pools */ /* *INDENT-OFF* */ - pool_foreach (p, a->adv_prefixes_pool, + pool_flush(p, a->adv_prefixes_pool, ({ - vec_add1 (to_delete, p - a->adv_prefixes_pool); - })); - /* *INDENT-ON* */ - - for (i = 0; i < vec_len (to_delete); i++) - { - p = pool_elt_at_index (a->adv_prefixes_pool, to_delete[i]); mhash_unset (&a->address_to_prefix_index, &p->prefix, 0); - pool_put (a->adv_prefixes_pool, p); - } - - vec_free (to_delete); - to_delete = 0; - - /* clean up mldp group pool */ - /* *INDENT-OFF* */ - pool_foreach (m, a->mldp_group_pool, + })); + pool_flush (m, a->mldp_group_pool, ({ - vec_add1 (to_delete, m - a->mldp_group_pool); + mhash_unset (&a->address_to_mldp_index, &m->mcast_address, 0); })); /* *INDENT-ON* */ - for (i = 0; i < vec_len (to_delete); i++) - { - m = pool_elt_at_index (a->mldp_group_pool, to_delete[i]); - mhash_unset (&a->address_to_mldp_index, &m->mcast_address, 0); - pool_put (a->mldp_group_pool, m); - } + pool_free (a->mldp_group_pool); + pool_free (a->adv_prefixes_pool); - vec_free (to_delete); + mhash_free (&a->address_to_prefix_index); + mhash_free (&a->address_to_mldp_index); pool_put (nm->if_radv_pool, a); nm->if_radv_pool_index_by_sw_if_index[sw_if_index] = ~0; @@ -2017,13 +2070,13 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, memset (a, 0, sizeof (a[0])); a->sw_if_index = sw_if_index; - a->fib_index = ~0; a->max_radv_interval = DEF_MAX_RADV_INTERVAL; a->min_radv_interval = DEF_MIN_RADV_INTERVAL; a->curr_hop_limit = DEF_CURR_HOP_LIMIT; a->adv_router_lifetime_in_sec = DEF_DEF_RTR_LIFETIME; - a->adv_link_layer_address = 1; /* send ll address source address option */ + /* send ll address source address option */ + a->adv_link_layer_address = 1; a->min_delay_between_radv = MIN_DELAY_BETWEEN_RAS; a->max_delay_between_radv = MAX_DELAY_BETWEEN_RAS; @@ -2059,86 +2112,15 @@ ip6_neighbor_sw_interface_add_del (vnet_main_t * vnm, sw_if_index); /* add multicast groups we will always be reporting */ - ip6_address_t addr; - ip6_mldp_group_t *mcast_group_info; - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_hosts); - - /* lookup mldp info for this interface */ - - uword *p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = - p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - /* add address */ - if (!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ - 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy (&mcast_group_info->mcast_address, &addr, - sizeof (ip6_address_t)); - } - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_all_routers); - - p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = - p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - if (!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ - 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy (&mcast_group_info->mcast_address, &addr, - sizeof (ip6_address_t)); - } - - ip6_set_reserved_multicast_address (&addr, - IP6_MULTICAST_SCOPE_link_local, - IP6_MULTICAST_GROUP_ID_mldv2_routers); - - p = mhash_get (&a->address_to_mldp_index, &addr); - mcast_group_info = - p ? pool_elt_at_index (a->mldp_group_pool, p[0]) : 0; - - if (!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (a->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - a->mldp_group_pool; - mhash_set (&a->address_to_mldp_index, &addr, mi, /* old_value */ - 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy (&mcast_group_info->mcast_address, &addr, - sizeof (ip6_address_t)); - } + ip6_neighbor_add_mld_grp (a, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_hosts); + ip6_neighbor_add_mld_grp (a, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_all_routers); + ip6_neighbor_add_mld_grp (a, + IP6_MULTICAST_SCOPE_link_local, + IP6_MULTICAST_GROUP_ID_mldv2_routers); } } return ri; @@ -3695,7 +3677,9 @@ VLIB_CLI_COMMAND (set_ip6_link_local_address_command, static) = }; /* *INDENT-ON* */ -/* callback when an interface address is added or deleted */ +/** + * @brief callback when an interface address is added or deleted + */ static void ip6_neighbor_add_del_interface_address (ip6_main_t * im, uword opaque, @@ -3710,7 +3694,6 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, vlib_main_t *vm = vnm->vlib_main; ip6_radv_t *radv_info; ip6_address_t a; - ip6_mldp_group_t *mcast_group_info; /* create solicited node multicast address for this interface adddress */ ip6_set_solicited_node_multicast_address (&a, 0); @@ -3737,28 +3720,7 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, if (!ip6_address_is_link_local_unicast (address)) radv_info->ref_count++; - /* lookup prefix info for this address on this interface */ - uword *p = mhash_get (&radv_info->address_to_mldp_index, &a); - mcast_group_info = - p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; - - /* add -solicted node multicast address */ - if (!mcast_group_info) - { - /* add */ - u32 mi; - pool_get (radv_info->mldp_group_pool, mcast_group_info); - - mi = mcast_group_info - radv_info->mldp_group_pool; - mhash_set (&radv_info->address_to_mldp_index, &a, mi, - /* old_value */ 0); - - mcast_group_info->type = 4; - mcast_group_info->mcast_source_address_pool = 0; - mcast_group_info->num_sources = 0; - clib_memcpy (&mcast_group_info->mcast_address, &a, - sizeof (ip6_address_t)); - } + ip6_neighbor_add_mld_prefix (radv_info, &a); } } else @@ -3775,17 +3737,7 @@ ip6_neighbor_add_del_interface_address (ip6_main_t * im, /* get radv_info */ radv_info = pool_elt_at_index (nm->if_radv_pool, ri); - /* lookup prefix info for this address on this interface */ - uword *p = mhash_get (&radv_info->address_to_mldp_index, &a); - mcast_group_info = - p ? pool_elt_at_index (radv_info->mldp_group_pool, p[0]) : 0; - - if (mcast_group_info) - { - mhash_unset (&radv_info->address_to_mldp_index, &a, - /* old_value */ 0); - pool_put (radv_info->mldp_group_pool, mcast_group_info); - } + ip6_neighbor_del_mld_prefix (radv_info, &a); /* if interface up send MLDP "report" */ radv_info->all_routers_mcast = 0; diff --git a/src/vppinfra/pool.h b/src/vppinfra/pool.h index 586d13e73a9..57838e1c609 100644 --- a/src/vppinfra/pool.h +++ b/src/vppinfra/pool.h @@ -350,6 +350,7 @@ do { \ It is a bad idea to allocate or free pool element from within @c pool_foreach. Build a vector of indices and dispose of them later. + Or call pool_flush. @par Example @@ -421,6 +422,31 @@ do { \ do { body; } while (0); \ } +/** + * @brief Remove all elemenets from a pool in a safe way + * + * @param VAR each element in the pool + * @param POOL The pool to flush + * @param BODY The actions to perform on each element before it is returned to + * the pool. i.e. before it is 'freed' + */ +#define pool_flush(VAR, POOL, BODY) \ +{ \ + uword *_pool_var(ii), *_pool_var(dv) = NULL; \ + \ + pool_foreach((VAR), (POOL), \ + ({ \ + vec_add1(_pool_var(dv), (VAR) - (POOL)); \ + })); \ + vec_foreach(_pool_var(ii), _pool_var(dv)) \ + { \ + (VAR) = pool_elt_at_index((POOL), *_pool_var(ii)); \ + do { BODY; } while (0); \ + pool_put((POOL), (VAR)); \ + } \ + vec_free(_pool_var(dv)); \ +} + #endif /* included_pool_h */ /* diff --git a/test/test_ip6.py b/test/test_ip6.py index fb5383cfc0c..b8278329ba9 100644 --- a/test/test_ip6.py +++ b/test/test_ip6.py @@ -10,7 +10,8 @@ from vpp_pg_interface import is_ipv6_misc from scapy.packet import Raw from scapy.layers.l2 import Ether, Dot1Q from scapy.layers.inet6 import IPv6, UDP, ICMPv6ND_NS, ICMPv6ND_RS, \ - ICMPv6ND_RA, ICMPv6NDOptSrcLLAddr, getmacbyip6, ICMPv6MRD_Solicitation + ICMPv6ND_RA, ICMPv6NDOptSrcLLAddr, getmacbyip6, ICMPv6MRD_Solicitation, \ + ICMPv6NDOptMTU, ICMPv6NDOptSrcLLAddr, ICMPv6NDOptPrefixInfo from util import ppp from scapy.utils6 import in6_getnsma, in6_getnsmac, in6_ptop, in6_islladdr, \ in6_mactoifaceid, in6_ismaddr @@ -288,7 +289,7 @@ class TestIPv6(VppTestCase): self.send_and_assert_no_replies(self.pg0, pkts, "No response to NS for unknown target") - def validate_ra(self, intf, rx, dst_ip=None): + def validate_ra(self, intf, rx, dst_ip=None, mtu=9000, pi_opt=None): if not dst_ip: dst_ip = intf.remote_ip6 @@ -308,17 +309,47 @@ class TestIPv6(VppTestCase): self.assertEqual(in6_ptop(rx[IPv6].src), in6_ptop(mk_ll_addr(intf.local_mac))) + # it should contain the links MTU + ra = rx[ICMPv6ND_RA] + self.assertEqual(ra[ICMPv6NDOptMTU].mtu, mtu) + + # it should contain the source's link layer address option + sll = ra[ICMPv6NDOptSrcLLAddr] + self.assertEqual(sll.lladdr, intf.local_mac) + + if not pi_opt: + # the RA should not contain prefix information + self.assertFalse(ra.haslayer(ICMPv6NDOptPrefixInfo)) + else: + raos = rx.getlayer(ICMPv6NDOptPrefixInfo, 1) + + # the options are nested in the scapy packet in way that i cannot + # decipher how to decode. this 1st layer of option always returns + # nested classes, so a direct obj1=obj2 comparison always fails. + # however, the getlayer(.., 2) does give one instnace. + # so we cheat here and construct a new opt instnace for comparison + rd = ICMPv6NDOptPrefixInfo(prefixlen=raos.prefixlen, + prefix=raos.prefix, + L=raos.L, + A=raos.A) + if type(pi_opt) is list: + for ii in range(len(pi_opt)): + self.assertEqual(pi_opt[ii], rd) + rd = rx.getlayer(ICMPv6NDOptPrefixInfo, ii+2) + else: + self.assertEqual(pi_opt, raos) + def send_and_expect_ra(self, intf, pkts, remark, dst_ip=None, - filter_out_fn=is_ipv6_misc): + filter_out_fn=is_ipv6_misc, + opt=None): intf.add_stream(pkts) - self.pg0.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = intf.get_capture(1, filter_out_fn=filter_out_fn) self.assertEqual(len(rx), 1) rx = rx[0] - self.validate_ra(intf, rx, dst_ip) + self.validate_ra(intf, rx, dst_ip, pi_opt=opt) def test_rs(self): """ IPv6 Router Solicitation Exceptions @@ -415,6 +446,184 @@ class TestIPv6(VppTestCase): dst_ip="ff02::1", filter_out_fn=None) + # + # Configure The RA to announce the links prefix + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len) + + # + # RAs should now contain the prefix information option + # + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=1, + A=1) + + 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()) + self.send_and_expect_ra(self.pg0, p, + "RA with prefix-info", + dst_ip=ll, + opt=opt) + + # + # Change the prefix info to not off-link + # L-flag is clear + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len, + off_link=1) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=0, + A=1) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix info with L-flag=0", + dst_ip=ll, + opt=opt) + + # + # Change the prefix info to not off-link, no-autoconfig + # L and A flag are clear in the advert + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len, + off_link=1, + no_autoconfig=1) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=0, + A=0) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix info with A & L-flag=0", + dst_ip=ll, + opt=opt) + + # + # Change the flag settings back to the defaults + # L and A flag are set in the advert + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=1, + A=1) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix info", + dst_ip=ll, + opt=opt) + + # + # Change the prefix info to not off-link, no-autoconfig + # L and A flag are clear in the advert + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len, + off_link=1, + no_autoconfig=1) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=0, + A=0) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix info with A & L-flag=0", + dst_ip=ll, + opt=opt) + + # + # Use the reset to defults option to revert to defaults + # L and A flag are clear in the advert + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len, + use_default=1) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=1, + A=1) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix reverted to defaults", + dst_ip=ll, + opt=opt) + + # + # Advertise Another prefix. With no L-flag/A-flag + # + self.pg0.ip6_ra_prefix(self.pg1.local_ip6n, + self.pg1.local_ip6_prefix_len, + off_link=1, + no_autoconfig=1) + + opt = [ICMPv6NDOptPrefixInfo(prefixlen=self.pg0.local_ip6_prefix_len, + prefix=self.pg0.local_ip6, + L=1, + A=1), + ICMPv6NDOptPrefixInfo(prefixlen=self.pg1.local_ip6_prefix_len, + prefix=self.pg1.local_ip6, + L=0, + A=0)] + + 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()) + self.send_and_expect_ra(self.pg0, p, + "RA with multiple Prefix infos", + dst_ip=ll, + opt=opt) + + # + # Remove the first refix-info - expect the second is still in the + # advert + # + self.pg0.ip6_ra_prefix(self.pg0.local_ip6n, + self.pg0.local_ip6_prefix_len, + is_no=1) + + opt = ICMPv6NDOptPrefixInfo(prefixlen=self.pg1.local_ip6_prefix_len, + prefix=self.pg1.local_ip6, + L=0, + A=0) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix reverted to defaults", + dst_ip=ll, + opt=opt) + + # + # Remove the second prefix-info - expect no prefix-info i nthe adverts + # + self.pg0.ip6_ra_prefix(self.pg1.local_ip6n, + self.pg1.local_ip6_prefix_len, + is_no=1) + + self.pg0.ip6_ra_config(send_unicast=1) + self.send_and_expect_ra(self.pg0, p, + "RA with Prefix reverted to defaults", + dst_ip=ll) + # # Reset the periodic advertisements back to default values # diff --git a/test/vpp_interface.py b/test/vpp_interface.py index 4588943dd8a..53a0ae8de98 100644 --- a/test/vpp_interface.py +++ b/test/vpp_interface.py @@ -272,6 +272,17 @@ class VppInterface(object): suppress, send_unicast) + def ip6_ra_prefix(self, address, address_length, is_no=0, + off_link=0, no_autoconfig=0, use_default=0): + """Configure IPv6 RA suppress on the VPP interface.""" + self.test.vapi.ip6_sw_interface_ra_prefix(self.sw_if_index, + address, + address_length, + is_no=is_no, + off_link=off_link, + no_autoconfig=no_autoconfig, + use_default=use_default) + def admin_up(self): """Put interface ADMIN-UP.""" self.test.vapi.sw_interface_set_flags(self.sw_if_index, diff --git a/test/vpp_neighbor.py b/test/vpp_neighbor.py index fbd41eb5352..5c2e34794ec 100644 --- a/test/vpp_neighbor.py +++ b/test/vpp_neighbor.py @@ -31,7 +31,7 @@ class VppNeighbor(VppObject): """ def __init__(self, test, sw_if_index, mac_addr, nbr_addr, - af=AF_INET, is_static=0): + af=AF_INET, is_static=False): self._test = test self.sw_if_index = sw_if_index self.mac_addr = mactobinary(mac_addr) diff --git a/test/vpp_papi_provider.py b/test/vpp_papi_provider.py index 5d4d6b7ef0c..fe152de3969 100644 --- a/test/vpp_papi_provider.py +++ b/test/vpp_papi_provider.py @@ -286,6 +286,31 @@ class VppPapiProvider(object): 'suppress': suppress, 'send_unicast': send_unicast}) + def ip6_sw_interface_ra_prefix(self, + sw_if_index, + address, + address_length, + use_default=0, + no_advertise=0, + off_link=0, + no_autoconfig=0, + no_onlink=0, + is_no=0, + val_lifetime=0xffffffff, + pref_lifetime=0xffffffff): + return self.api(self.papi.sw_interface_ip6nd_ra_prefix, + {'sw_if_index': sw_if_index, + 'address': address, + 'address_length': address_length, + 'use_default': use_default, + 'no_advertise': no_advertise, + 'off_link': off_link, + 'no_autoconfig': no_autoconfig, + 'no_onlink': no_onlink, + 'is_no': is_no, + 'val_lifetime': val_lifetime, + 'pref_lifetime': pref_lifetime}) + def ip6_sw_interface_enable_disable(self, sw_if_index, enable): """ Enable/Disable An interface for IPv6 -- 2.16.6