lb: Loadbalancer plugin, correctly rewrite checksum in L3DSR, non-TCP cases 73/28673/6
authorHiroki Narukawa <nhirokinet@nhiroki.net>
Fri, 4 Sep 2020 06:41:40 +0000 (15:41 +0900)
committerDamjan Marion <dmarion@me.com>
Sat, 24 Oct 2020 09:00:56 +0000 (09:00 +0000)
Current loadbalancer seems to rewrite the 17th and 18th octet of L4 header regardless of which kind of L4 protocol is used in case of L3DSR.

In case UDP, it rewrites 9th and 10th octet of payload (because UDP header is 8 octets long). If UDP payload is less than 8 octets, UDP checksum becomes invalid.

In other protocols similar problems is likely to occue.

This patch checks which L4 protocol is used, and rewrite packet regarding the L4 protocol.

Signed-off-by: Hiroki Narukawa <nhirokinet@nhiroki.net>
Change-Id: I84390ff58a33f05efac0421856beea89014adc72
Type: fix

src/plugins/lb/node.c

index 870201d..b5e9da7 100644 (file)
@@ -435,7 +435,6 @@ lb_node_fn (vlib_main_t * vm,
           else if (encap_type == LB_ENCAP_TYPE_L3DSR) /* encap L3DSR*/
             {
               ip4_header_t *ip40;
-              tcp_header_t *th0;
               ip_csum_t csum;
               u32 old_dst, new_dst;
               u8 old_tos, new_tos;
@@ -459,9 +458,20 @@ lb_node_fn (vlib_main_t * vm,
               ip40->checksum = ip_csum_fold (csum);
 
               /* Recomputing L4 checksum after dst-IP modifying */
-              th0 = ip4_next_header (ip40);
-              th0->checksum = 0;
-              th0->checksum = ip4_tcp_udp_compute_checksum (vm, p0, ip40);
+              if (ip40->protocol == IP_PROTOCOL_TCP)
+                {
+                  tcp_header_t *th0;
+                  th0 = ip4_next_header (ip40);
+                  th0->checksum = 0;
+                  th0->checksum = ip4_tcp_udp_compute_checksum (vm, p0, ip40);
+                }
+              else if (ip40->protocol == IP_PROTOCOL_UDP)
+                {
+                  udp_header_t *uh0;
+                  uh0 = ip4_next_header (ip40);
+                  uh0->checksum = 0;
+                  uh0->checksum = ip4_tcp_udp_compute_checksum (vm, p0, ip40);
+                }
             }
           else if ((encap_type == LB_ENCAP_TYPE_NAT4)
               || (encap_type == LB_ENCAP_TYPE_NAT6))