A Protocol Independent Hierarchical FIB (VPP-352)
[vpp.git] / vnet / vnet / ip / udp.h
index 151f2a8..1845fa7 100644 (file)
@@ -51,6 +51,7 @@ _ (547, dhcpv6_to_server)                       \
 _ (546, dhcpv6_to_client)                      \
 _ (4341, lisp_gpe6)                             \
 _ (4342, lisp_cp6)                             \
+_ (4790, vxlan6_gpe)      \
 _ (6633, vpath6_3)
 
 typedef enum {
@@ -114,14 +115,13 @@ void udp_register_dst_port (vlib_main_t * vm,
                             u32 node_index, u8 is_ip4);
 
 always_inline void
-ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
+ip_udp_fixup_one (vlib_main_t * vm,
+                  vlib_buffer_t * b0,
                   u8 is_ip4)
 {
   u16 new_l0;
   udp_header_t * udp0;
 
-  vlib_buffer_advance (b0, - ec_len);
-
   if (is_ip4)
     {
       ip4_header_t * ip0;
@@ -130,9 +130,6 @@ ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
 
       ip0 = vlib_buffer_get_current(b0);
 
-      /* Apply the encap string. */
-      clib_memcpy(ip0, ec0, ec_len);
-
       /* fix the <bleep>ing outer-IP checksum */
       sum0 = ip0->checksum;
       /* old_l0 always 0, see the rewrite setup */
@@ -152,10 +149,9 @@ ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
   else
     {
       ip6_header_t * ip0;
-      ip0 = vlib_buffer_get_current(b0);
+      int bogus0;
 
-      /* Apply the encap string. */
-      clib_memcpy(ip0, ec0, ec_len);
+      ip0 = vlib_buffer_get_current(b0);
 
       new_l0 = clib_host_to_net_u16 (vlib_buffer_length_in_chain (vm, b0)
                                      - sizeof (*ip0));
@@ -164,6 +160,39 @@ ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
       /* Fix UDP length */
       udp0 = (udp_header_t *)(ip0+1);
       udp0->length = new_l0;
+
+      udp0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
+      ASSERT(bogus0 == 0);
+
+      if (udp0->checksum == 0)
+          udp0->checksum = 0xffff;
+    }
+}
+always_inline void
+ip_udp_encap_one (vlib_main_t * vm, vlib_buffer_t * b0, u8 * ec0, word ec_len,
+                  u8 is_ip4)
+{
+  vlib_buffer_advance (b0, - ec_len);
+
+  if (is_ip4)
+    {
+      ip4_header_t * ip0;
+
+      ip0 = vlib_buffer_get_current(b0);
+
+      /* Apply the encap string. */
+      clib_memcpy(ip0, ec0, ec_len);
+      ip_udp_fixup_one(vm, b0, 1);
+    }
+  else
+    {
+      ip6_header_t * ip0;
+
+      ip0 = vlib_buffer_get_current(b0);
+
+      /* Apply the encap string. */
+      clib_memcpy(ip0, ec0, ec_len);
+      ip_udp_fixup_one(vm, b0, 0);
     }
 }
 
@@ -225,6 +254,8 @@ ip_udp_encap_two (vlib_main_t * vm, vlib_buffer_t * b0, vlib_buffer_t * b1,
   else
     {
       ip6_header_t * ip0, * ip1;
+      int bogus0, bogus1;
+
       ip0 = vlib_buffer_get_current(b0);
       ip1 = vlib_buffer_get_current(b1);
 
@@ -245,6 +276,16 @@ ip_udp_encap_two (vlib_main_t * vm, vlib_buffer_t * b0, vlib_buffer_t * b1,
 
       udp0->length = new_l0;
       udp1->length = new_l1;
+
+      udp0->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0, &bogus0);
+      udp1->checksum = ip6_tcp_udp_icmp_compute_checksum (vm, b1, ip1, &bogus1);
+      ASSERT(bogus0 == 0);
+      ASSERT(bogus1 == 0);
+
+      if (udp0->checksum == 0)
+          udp0->checksum = 0xffff;
+      if (udp1->checksum == 0)
+          udp1->checksum = 0xffff;
     }
 }