From bd8e43dfa045b4aec4ecf4ad3e5503924b5c9c38 Mon Sep 17 00:00:00 2001 From: Neale Ranns Date: Mon, 15 Mar 2021 14:42:30 +0000 Subject: gre: Multipoint GRE fixes Type: fix - the CLI was broken when a nh-table-id was present, since it overwrote the next-hop address - bouncing interface state stacked the adjacencies on the tunnel's destination (which is all zeros) - don't crash in the switch path if the interface has no hw-address Signed-off-by: Neale Ranns Change-Id: I1ba9fdc9b2185899b753a2d40f23afa847a3ef4f --- src/vnet/gre/interface.c | 54 ++++++++++++++++++++++++++++++++++++- src/vnet/gre/test/test_gre.py | 28 +++++++++++++++++-- src/vnet/ip-neighbor/ip4_neighbor.h | 7 +++-- src/vnet/teib/teib_cli.c | 4 +-- 4 files changed, 86 insertions(+), 7 deletions(-) diff --git a/src/vnet/gre/interface.c b/src/vnet/gre/interface.c index 30c8dc479c2..30dfa3057b1 100644 --- a/src/vnet/gre/interface.c +++ b/src/vnet/gre/interface.c @@ -155,6 +155,45 @@ gre_tunnel_stack (adj_index_t ai) } } +/** + * mgre_tunnel_stack + * + * 'stack' (resolve the recursion for) the tunnel's midchain adjacency + */ +static void +mgre_tunnel_stack (adj_index_t ai) +{ + gre_main_t *gm = &gre_main; + const ip_adjacency_t *adj; + const gre_tunnel_t *gt; + u32 sw_if_index; + + adj = adj_get (ai); + sw_if_index = adj->rewrite_header.sw_if_index; + + if ((vec_len (gm->tunnel_index_by_sw_if_index) <= sw_if_index) || + (~0 == gm->tunnel_index_by_sw_if_index[sw_if_index])) + return; + + gt = pool_elt_at_index (gm->tunnels, + gm->tunnel_index_by_sw_if_index[sw_if_index]); + + if ((vnet_hw_interface_get_flags (vnet_get_main (), gt->hw_if_index) & + VNET_HW_INTERFACE_FLAG_LINK_UP) == 0) + { + adj_midchain_delegate_unstack (ai); + } + else + { + const teib_entry_t *ne; + + ne = teib_entry_find_46 (sw_if_index, adj->ia_nh_proto, + &adj->sub_type.nbr.next_hop); + if (NULL != ne) + teib_entry_adj_stack (ne, ai); + } +} + /** * @brief Call back when restacking all adjacencies on a GRE interface */ @@ -165,6 +204,13 @@ gre_adj_walk_cb (adj_index_t ai, void *ctx) return (ADJ_WALK_RC_CONTINUE); } +static adj_walk_rc_t +mgre_adj_walk_cb (adj_index_t ai, void *ctx) +{ + mgre_tunnel_stack (ai); + + return (ADJ_WALK_RC_CONTINUE); +} static void gre_tunnel_restack (gre_tunnel_t * gt) @@ -176,7 +222,13 @@ gre_tunnel_restack (gre_tunnel_t * gt) */ FOR_EACH_FIB_IP_PROTOCOL (proto) { - adj_nbr_walk (gt->sw_if_index, proto, gre_adj_walk_cb, NULL); + switch (gt->mode) + { + case TUNNEL_MODE_P2P: + return (adj_nbr_walk (gt->sw_if_index, proto, gre_adj_walk_cb, NULL)); + case TUNNEL_MODE_MP: + return (adj_nbr_walk (gt->sw_if_index, proto, mgre_adj_walk_cb, NULL)); + } } } diff --git a/src/vnet/gre/test/test_gre.py b/src/vnet/gre/test/test_gre.py index 828fb731006..3192fee0e8a 100644 --- a/src/vnet/gre/test/test_gre.py +++ b/src/vnet/gre/test/test_gre.py @@ -1121,6 +1121,7 @@ class TestGRE(VppTestCase): # for ii in range(1, 4): route_addr = "4.4.4.%d" % ii + tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr) # # route traffic via the peer @@ -1131,6 +1132,15 @@ class TestGRE(VppTestCase): gre_if.sw_if_index)]) route_via_tun.add_vpp_config() + # all packets dropped at this point + self.logger.error(self.vapi.cli("sh adj 19")) + rx = self.send_and_assert_no_replies(self.pg0, tx_e) + + gre_if.admin_down() + gre_if.admin_up() + self.logger.error(self.vapi.cli("sh adj 19")) + rx = self.send_and_assert_no_replies(self.pg0, tx_e) + # # Add a TEIB entry resolves the peer # @@ -1143,8 +1153,10 @@ class TestGRE(VppTestCase): # Send a packet stream that is routed into the tunnel # - packets are GRE encapped # - tx_e = self.create_stream_ip4(self.pg0, "5.5.5.5", route_addr) - rx = self.send_and_expect(self.pg0, tx_e, itf) + try: + rx = self.send_and_expect(self.pg0, tx_e, itf) + finally: + self.logger.error(self.vapi.cli("sh adj 19")) self.verify_tunneled_4o4(self.pg0, rx, tx_e, itf.local_ip4, itf._remote_hosts[ii].ip4) @@ -1172,6 +1184,18 @@ class TestGRE(VppTestCase): rx = self.send_and_expect(self.pg0, tx_i, self.pg0) self.verify_decapped_4o4(self.pg0, rx, tx_i) + # + # bounce the interface state and try packets again + # + gre_if.admin_down() + gre_if.admin_up() + rx = self.send_and_expect(self.pg0, tx_e, itf) + self.verify_tunneled_4o4(self.pg0, rx, tx_e, + itf.local_ip4, + itf._remote_hosts[ii].ip4) + rx = self.send_and_expect(self.pg0, tx_i, self.pg0) + self.verify_decapped_4o4(self.pg0, rx, tx_i) + gre_if.admin_down() gre_if.unconfig_ip4() diff --git a/src/vnet/ip-neighbor/ip4_neighbor.h b/src/vnet/ip-neighbor/ip4_neighbor.h index 8805beadf23..11309af82d5 100644 --- a/src/vnet/ip-neighbor/ip4_neighbor.h +++ b/src/vnet/ip-neighbor/ip4_neighbor.h @@ -37,6 +37,11 @@ ip4_neighbor_probe (vlib_main_t * vm, vlib_buffer_t *b0; u32 bi0; + hw_if0 = vnet_get_sup_hw_interface (vnm, adj0->rewrite_header.sw_if_index); + + /* if (NULL == hw_if0->hw_address) */ + /* return (NULL); */ + /* Send ARP request. */ h0 = vlib_packet_template_get_packet (vm, &ip4_main.ip4_arp_request_packet_template, @@ -50,8 +55,6 @@ ip4_neighbor_probe (vlib_main_t * vm, /* Add rewrite/encap string for ARP packet. */ vnet_rewrite_one_header (adj0[0], h0, sizeof (ethernet_header_t)); - hw_if0 = vnet_get_sup_hw_interface (vnm, adj0->rewrite_header.sw_if_index); - /* Src ethernet address in ARP header. */ mac_address_from_bytes (&h0->ip4_over_ethernet[0].mac, hw_if0->hw_address); diff --git a/src/vnet/teib/teib_cli.c b/src/vnet/teib/teib_cli.c index fd9e55ed742..a23902e0f60 100644 --- a/src/vnet/teib/teib_cli.c +++ b/src/vnet/teib/teib_cli.c @@ -40,10 +40,10 @@ teib_add (vlib_main_t * vm, ; else if (unformat (line_input, "peer %U", unformat_ip_address, &peer)) ; - else if (unformat (line_input, "nh %U", unformat_ip_address, &nh)) - ; else if (unformat (line_input, "nh-table-id %d", &nh_table_id)) ; + else if (unformat (line_input, "nh %U", unformat_ip_address, &nh)) + ; else { error = clib_error_return (0, "unknown input `%U'", -- cgit 1.2.3-korg