BFD: improve ip header handling, fix assert 73/4173/4
authorKlement Sekera <ksekera@cisco.com>
Thu, 8 Dec 2016 04:03:32 +0000 (05:03 +0100)
committerDamjan Marion <dmarion.lists@gmail.com>
Thu, 8 Dec 2016 12:16:42 +0000 (12:16 +0000)
Instead of storing a pointer, store an offset within vlib_buffer marking
the start of the ip header (similar to storing start of ethernet
header). Handle negative timeout in the bfd process main loop.

Change-Id: I05a1ff3ac41da5bdc3b2ac6f9e03b3241994688b
Signed-off-by: Klement Sekera <ksekera@cisco.com>
test/framework.py
test/test_bfd.py
vnet/vnet/bfd/bfd_main.c
vnet/vnet/bfd/bfd_udp.c
vnet/vnet/buffer.h
vnet/vnet/ip/ip4_forward.c

index aa4f2fd..e1f3ba5 100644 (file)
@@ -278,6 +278,8 @@ class VppTestCase(unittest.TestCase):
 
     def setUp(self):
         """ Clear trace before running each test"""
+        if self.vpp_dead:
+            raise Exception("VPP is dead when setting up the test")
         self.vapi.cli("clear trace")
         # store the test instance inside the test class - so that objects
         # holding the class can access instance methods (like assertEqual)
index 20d3aea..58f1264 100644 (file)
@@ -128,6 +128,7 @@ class BFDTestCase(VppTestCase):
             raise
 
     def setUp(self):
+        super(BFDTestCase, self).setUp()
         self.vapi.want_bfd_events()
         self.vpp_session = VppBFDUDPSession(self, self.pg0, self.pg0.remote_ip4)
         self.vpp_session.add_vpp_config()
index a72d6fe..26b9fe3 100644 (file)
@@ -570,15 +570,23 @@ bfd_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
        {
          BFD_DBG ("wait for event without timeout");
          (void) vlib_process_wait_for_event (vm);
+         event_type = vlib_process_get_events (vm, &event_data);
        }
       else
        {
          f64 timeout = ((i64) next_expire - (i64) now) / bm->cpu_cps;
          BFD_DBG ("wait for event with timeout %.02f", timeout);
-         ASSERT (timeout > 0);
-         (void) vlib_process_wait_for_event_or_clock (vm, timeout);
+         if (timeout < 0)
+           {
+             BFD_DBG ("negative timeout, already expired, skipping wait");
+             event_type = ~0;
+           }
+         else
+           {
+             (void) vlib_process_wait_for_event_or_clock (vm, timeout);
+             event_type = vlib_process_get_events (vm, &event_data);
+           }
        }
-      event_type = vlib_process_get_events (vm, &event_data);
       now = clib_cpu_time_now ();
       switch (event_type)
        {
index ded3342..44a4a18 100644 (file)
@@ -311,7 +311,23 @@ typedef enum {
 static void bfd_udp4_find_headers (vlib_buffer_t *b, const ip4_header_t **ip4,
                                    const udp_header_t **udp)
 {
-  *ip4 = vnet_buffer (b)->ip.header;
+  /* sanity check first */
+  const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+  if (start < 0 && start < sizeof (b->pre_data))
+    {
+      BFD_ERR ("Start of ip header is before pre_data, ignoring");
+      *ip4 = NULL;
+      *udp = NULL;
+      return;
+    }
+  *ip4 = (ip4_header_t *)(b->data + start);
+  if ((u8 *)*ip4 > (u8 *)vlib_buffer_get_current (b))
+    {
+      BFD_ERR ("Start of ip header is beyond current data, ignoring");
+      *ip4 = NULL;
+      *udp = NULL;
+      return;
+    }
   *udp = (udp_header_t *)((*ip4) + 1);
 }
 
@@ -493,14 +509,14 @@ static uword bfd_udp_input (vlib_main_t *vm, vlib_node_runtime_t *rt,
       next0 = BFD_UDP_INPUT_NEXT_NORMAL;
       if (BFD_UDP_ERROR_NONE == error0)
         {
-         /* if everything went fine, check for poll bit, if present, re-use
-            the buffer and based on (now update) session parameters, send the
-            final packet back */
+          /* if everything went fine, check for poll bit, if present, re-use
+             the buffer and based on (now update) session parameters, send the
+             final packet back */
           const bfd_pkt_t *pkt = vlib_buffer_get_current (b0);
           if (bfd_pkt_get_poll (pkt))
             {
               bfd_send_final (vm, b0, bs);
-             next0 = BFD_UDP_INPUT_NEXT_REPLY;
+              next0 = BFD_UDP_INPUT_NEXT_REPLY;
             }
         }
       vlib_set_next_frame_buffer (vm, rt, next0, bi0);
index 82806bb..7935027 100644 (file)
@@ -144,8 +144,8 @@ typedef struct
          u32 data;
        } icmp;
 
-       /* IP header - saved by ip*_local nodes */
-       void *header;
+       /* IP header offset from vlib_buffer.data - saved by ip*_local nodes */
+       i32 start_of_ip_header;
       };
 
     } ip;
index 38729c8..43a8940 100644 (file)
@@ -1472,8 +1472,8 @@ ip4_local (vlib_main_t * vm,
          ip0 = vlib_buffer_get_current (p0);
          ip1 = vlib_buffer_get_current (p1);
 
-          vnet_buffer (p0)->ip.header = ip0;
-          vnet_buffer (p1)->ip.header = ip1;
+          vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
+          vnet_buffer (p1)->ip.start_of_ip_header = p1->current_data;
 
           fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
                                 vnet_buffer (p0)->sw_if_index[VLIB_RX]);
@@ -1682,7 +1682,7 @@ ip4_local (vlib_main_t * vm,
 
          ip0 = vlib_buffer_get_current (p0);
 
-          vnet_buffer (p0)->ip.header = ip0;
+          vnet_buffer (p0)->ip.start_of_ip_header = p0->current_data;
 
          fib_index0 = vec_elt (im->fib_index_by_sw_if_index,
                                 vnet_buffer(p0)->sw_if_index[VLIB_RX]);