gre: Multipoint GRE fixes 43/31643/2
authorNeale Ranns <neale@graphiant.com>
Mon, 15 Mar 2021 14:42:30 +0000 (14:42 +0000)
committerNeale Ranns <neale@graphiant.com>
Sun, 21 Mar 2021 18:55:01 +0000 (18:55 +0000)
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 <neale@graphiant.com>
Change-Id: I1ba9fdc9b2185899b753a2d40f23afa847a3ef4f

src/vnet/gre/interface.c
src/vnet/gre/test/test_gre.py
src/vnet/ip-neighbor/ip4_neighbor.h
src/vnet/teib/teib_cli.c

index 30c8dc4..30dfa30 100644 (file)
@@ -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));
+      }
   }
 }
 
index 828fb73..3192fee 100644 (file)
@@ -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()
 
index 8805bea..11309af 100644 (file)
@@ -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);
 
index fd9e55e..a23902e 100644 (file)
@@ -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'",