From c2aad53aa5430137ac5a76a8746f11604277835a Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Tue, 30 May 2017 09:53:52 -0700 Subject: IP Mcast - recalculate on interface up/dowm Change-Id: Ie5b88fd7187ed62218a2e4e0e493c33e3e9ecc2f Signed-off-by: Neale Ranns --- src/vnet/adj/adj_mcast.c | 8 +-- src/vnet/mfib/mfib_entry.c | 133 ++++++++++++++++++++++++++------------------- src/vnet/mfib/mfib_entry.h | 10 ++++ test/test_ip_mcast.py | 42 ++++++++------ 4 files changed, 115 insertions(+), 78 deletions(-) diff --git a/src/vnet/adj/adj_mcast.c b/src/vnet/adj/adj_mcast.c index 755abfd4..da06cd00 100644 --- a/src/vnet/adj/adj_mcast.c +++ b/src/vnet/adj/adj_mcast.c @@ -230,9 +230,9 @@ VNET_SW_INTERFACE_ADMIN_UP_DOWN_FUNCTION(adj_mcast_interface_state_change); * HW interface state changes */ static void -adj_nbr_hw_sw_interface_state_change (vnet_main_t * vnm, - u32 sw_if_index, - void *arg) +adj_mcast_hw_sw_interface_state_change (vnet_main_t * vnm, + u32 sw_if_index, + void *arg) { adj_mcast_interface_state_change(vnm, sw_if_index, (uword) arg); } @@ -255,7 +255,7 @@ adj_mcast_hw_interface_state_change (vnet_main_t * vnm, 0); vnet_hw_interface_walk_sw(vnm, hw_if_index, - adj_nbr_hw_sw_interface_state_change, + adj_mcast_hw_sw_interface_state_change, (void*) sw_flags); return (NULL); diff --git a/src/vnet/mfib/mfib_entry.c b/src/vnet/mfib/mfib_entry.c index 49792f02..cf25b67a 100644 --- a/src/vnet/mfib/mfib_entry.c +++ b/src/vnet/mfib/mfib_entry.c @@ -366,62 +366,6 @@ mfib_entry_src_remove (mfib_entry_t *mfib_entry, } } -static void -mfib_entry_last_lock_gone (fib_node_t *node) -{ - mfib_entry_t *mfib_entry; - mfib_entry_src_t *msrc; - - mfib_entry = mfib_entry_from_fib_node(node); - - dpo_reset(&mfib_entry->mfe_rep); - - MFIB_ENTRY_DBG(mfib_entry, "last-lock"); - - vec_foreach(msrc, mfib_entry->mfe_srcs) - { - mfib_entry_src_flush(msrc); - } - - vec_free(mfib_entry->mfe_srcs); - - fib_node_deinit(&mfib_entry->mfe_node); - pool_put(mfib_entry_pool, mfib_entry); -} - -/* - * mfib_entry_back_walk_notify - * - * A back walk has reach this entry. - */ -static fib_node_back_walk_rc_t -mfib_entry_back_walk_notify (fib_node_t *node, - fib_node_back_walk_ctx_t *ctx) -{ - // FIXME - re-evalute - - return (FIB_NODE_BACK_WALK_CONTINUE); -} - -static void -mfib_entry_show_memory (void) -{ - fib_show_memory_usage("multicast-Entry", - pool_elts(mfib_entry_pool), - pool_len(mfib_entry_pool), - sizeof(mfib_entry_t)); -} - -/* - * The MFIB entry's graph node virtual function table - */ -static const fib_node_vft_t mfib_entry_vft = { - .fnv_get = mfib_entry_get_node, - .fnv_last_lock = mfib_entry_last_lock_gone, - .fnv_back_walk = mfib_entry_back_walk_notify, - .fnv_mem_show = mfib_entry_show_memory, -}; - u32 mfib_entry_child_add (fib_node_index_t mfib_entry_index, fib_node_type_t child_type, @@ -464,6 +408,7 @@ mfib_entry_alloc (u32 fib_index, mfib_entry->mfe_srcs = NULL; mfib_entry->mfe_itfs = NULL; mfib_entry->mfe_rpf_id = MFIB_RPF_ID_NONE; + mfib_entry->mfe_pl = FIB_NODE_INDEX_INVALID; dpo_reset(&mfib_entry->mfe_rep); @@ -594,6 +539,15 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, dp = fib_proto_to_dpo(mfib_entry_get_proto(mfib_entry)); + /* + * unlink the enty from the previous path list. + */ + if (FIB_NODE_INDEX_INVALID != mfib_entry->mfe_pl) + { + fib_path_list_child_remove(mfib_entry->mfe_pl, + mfib_entry->mfe_sibling); + } + if (NULL != msrc && FIB_NODE_INDEX_INVALID != msrc->mfes_pl) { @@ -658,6 +612,17 @@ mfib_entry_stack (mfib_entry_t *mfib_entry, dpo_reset(&ctx.next_hops[0].path_dpo); vec_free(ctx.next_hops); } + + /* + * link the entry to the path-list. + * The entry needs to be a child so that we receive the back-walk + * updates to recalculate forwarding. + */ + mfib_entry->mfe_pl = msrc->mfes_pl; + mfib_entry->mfe_sibling = + fib_path_list_child_add(mfib_entry->mfe_pl, + FIB_NODE_TYPE_MFIB_ENTRY, + mfib_entry_get_index(mfib_entry)); } else { @@ -1098,6 +1063,62 @@ mfib_entry_cmp_for_sort (void *i1, void *i2) *mfib_entry_index2)); } +static void +mfib_entry_last_lock_gone (fib_node_t *node) +{ + mfib_entry_t *mfib_entry; + mfib_entry_src_t *msrc; + + mfib_entry = mfib_entry_from_fib_node(node); + + dpo_reset(&mfib_entry->mfe_rep); + + MFIB_ENTRY_DBG(mfib_entry, "last-lock"); + + vec_foreach(msrc, mfib_entry->mfe_srcs) + { + mfib_entry_src_flush(msrc); + } + + vec_free(mfib_entry->mfe_srcs); + + fib_node_deinit(&mfib_entry->mfe_node); + pool_put(mfib_entry_pool, mfib_entry); +} + +/* + * mfib_entry_back_walk_notify + * + * A back walk has reach this entry. + */ +static fib_node_back_walk_rc_t +mfib_entry_back_walk_notify (fib_node_t *node, + fib_node_back_walk_ctx_t *ctx) +{ + mfib_entry_recalculate_forwarding(mfib_entry_from_fib_node(node)); + + return (FIB_NODE_BACK_WALK_CONTINUE); +} + +static void +mfib_entry_show_memory (void) +{ + fib_show_memory_usage("multicast-Entry", + pool_elts(mfib_entry_pool), + pool_len(mfib_entry_pool), + sizeof(mfib_entry_t)); +} + +/* + * The MFIB entry's graph node virtual function table + */ +static const fib_node_vft_t mfib_entry_vft = { + .fnv_get = mfib_entry_get_node, + .fnv_last_lock = mfib_entry_last_lock_gone, + .fnv_back_walk = mfib_entry_back_walk_notify, + .fnv_mem_show = mfib_entry_show_memory, +}; + void mfib_entry_lock (fib_node_index_t mfib_entry_index) { diff --git a/src/vnet/mfib/mfib_entry.h b/src/vnet/mfib/mfib_entry.h index 4f62b18e..d4377878 100644 --- a/src/vnet/mfib/mfib_entry.h +++ b/src/vnet/mfib/mfib_entry.h @@ -48,6 +48,16 @@ typedef struct mfib_entry_t_ { */ struct mfib_entry_src_t_ *mfe_srcs; + /** + * The path-list of which this entry is a child + */ + fib_node_index_t mfe_pl; + + /** + * The sibling index on the path-list + */ + u32 mfe_sibling; + /** * 2nd cache line has the members used in the data plane */ diff --git a/test/test_ip_mcast.py b/test/test_ip_mcast.py index c1397d70..276555d6 100644 --- a/test/test_ip_mcast.py +++ b/test/test_ip_mcast.py @@ -89,8 +89,8 @@ class TestIPMcast(VppTestCase): capture.remove(p) return capture - def verify_capture_ip4(self, src_if, sent): - rxd = self.pg1.get_capture(N_PKTS_IN_STREAM) + def verify_capture_ip4(self, rx_if, sent): + rxd = rx_if.get_capture(len(sent)) try: capture = self.verify_filter(rxd, sent) @@ -118,8 +118,8 @@ class TestIPMcast(VppTestCase): except: raise - def verify_capture_ip6(self, src_if, sent): - capture = self.pg1.get_capture(N_PKTS_IN_STREAM) + def verify_capture_ip6(self, rx_if, sent): + capture = rx_if.get_capture(len(sent)) self.assertEqual(len(capture), len(sent)) @@ -232,11 +232,6 @@ class TestIPMcast(VppTestCase): # We expect replications on Pg1->7 self.verify_capture_ip4(self.pg1, tx) self.verify_capture_ip4(self.pg2, tx) - self.verify_capture_ip4(self.pg3, tx) - self.verify_capture_ip4(self.pg4, tx) - self.verify_capture_ip4(self.pg5, tx) - self.verify_capture_ip4(self.pg6, tx) - self.verify_capture_ip4(self.pg7, tx) # no replications on Pg0 self.pg0.assert_nothing_captured( @@ -259,11 +254,6 @@ class TestIPMcast(VppTestCase): # We expect replications on Pg1->7 self.verify_capture_ip4(self.pg1, tx) self.verify_capture_ip4(self.pg2, tx) - self.verify_capture_ip4(self.pg3, tx) - self.verify_capture_ip4(self.pg4, tx) - self.verify_capture_ip4(self.pg5, tx) - self.verify_capture_ip4(self.pg6, tx) - self.verify_capture_ip4(self.pg7, tx) # no replications on Pg0 self.pg0.assert_nothing_captured( @@ -308,10 +298,10 @@ class TestIPMcast(VppTestCase): self.verify_capture_ip4(self.pg1, tx) self.verify_capture_ip4(self.pg2, tx) self.verify_capture_ip4(self.pg3, tx) - - # no replications on Pg0 - self.pg0.assert_nothing_captured( - remark="IP multicast packets forwarded on PG0") + self.verify_capture_ip4(self.pg4, tx) + self.verify_capture_ip4(self.pg5, tx) + self.verify_capture_ip4(self.pg6, tx) + self.verify_capture_ip4(self.pg7, tx) route_232_1_1_1.remove_vpp_config() route_1_1_1_1_232_1_1_1.remove_vpp_config() @@ -408,6 +398,22 @@ class TestIPMcast(VppTestCase): self.pg3.assert_nothing_captured( remark="IP multicast packets forwarded on PG3") + # + # Bounce the interface and it should still work + # + self.pg1.admin_down() + self.pg0.add_stream(tx) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.pg1.assert_nothing_captured( + remark="IP multicast packets forwarded on down PG1") + + self.pg1.admin_up() + self.pg0.add_stream(tx) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + self.verify_capture_ip6(self.pg1, tx) + # # a stream that matches the route for (*,ff01::1) # -- cgit 1.2.3-korg