cnat: Add sctp support 59/37259/6
authorNathan Skrzypczak <nathan.skrzypczak@gmail.com>
Wed, 2 Feb 2022 18:31:58 +0000 (19:31 +0100)
committerBeno�t Ganne <bganne@cisco.com>
Mon, 17 Oct 2022 16:25:01 +0000 (16:25 +0000)
This patch adds SCTP support in the CNat translation primitives.
It also exposes a clib_crc32c_with_init function allowing to set
the init value to start the crc32 with instead of 0.

Type: feature

Change-Id: I86add4cfcac08f2a5a34d1e1841122fafd349fe7
Signed-off-by: Nathan Skrzypczak <nathan.skrzypczak@gmail.com>
src/plugins/cnat/cnat_node.h
src/plugins/cnat/cnat_types.h
src/vppinfra/crc32.h

index 80d803c..c304c5c 100644 (file)
@@ -225,6 +225,29 @@ cnat_ip4_translate_l4 (ip4_header_t * ip4, udp_header_t * udp,
     }
 }
 
+static_always_inline void
+cnat_ip4_translate_sctp (ip4_header_t *ip4, sctp_header_t *sctp,
+                        u16 new_port[VLIB_N_DIR])
+{
+  /* Fastpath no checksum */
+  if (PREDICT_TRUE (0 == sctp->checksum))
+    {
+      sctp->dst_port = new_port[VLIB_TX];
+      sctp->src_port = new_port[VLIB_RX];
+      return;
+    }
+
+  if (new_port[VLIB_TX])
+    sctp->dst_port = new_port[VLIB_TX];
+  if (new_port[VLIB_RX])
+    sctp->src_port = new_port[VLIB_RX];
+
+  sctp->checksum = 0;
+  sctp->checksum = clib_host_to_little_u32 (~clib_crc32c_with_init (
+    (u8 *) sctp, ntohs (ip4->length) - sizeof (ip4_header_t),
+    ~0 /* init value */));
+}
+
 static_always_inline void
 cnat_ip4_translate_l3 (ip4_header_t * ip4, ip4_address_t new_addr[VLIB_N_DIR])
 {
@@ -407,6 +430,12 @@ cnat_translation_ip4 (const cnat_session_t * session,
       udp->checksum = ip_csum_fold (sum);
       cnat_ip4_translate_l3 (ip4, new_addr);
     }
+  else if (ip4->protocol == IP_PROTOCOL_SCTP)
+    {
+      sctp_header_t *sctp = (sctp_header_t *) udp;
+      cnat_ip4_translate_sctp (ip4, sctp, new_port);
+      cnat_ip4_translate_l3 (ip4, new_addr);
+    }
   else if (ip4->protocol == IP_PROTOCOL_ICMP)
     {
       icmp46_header_t *icmp = (icmp46_header_t *) udp;
@@ -743,6 +772,18 @@ cnat_session_make_key (vlib_buffer_t *b, ip_address_family_t af,
          session->key.cs_port[VLIB_RX] = udp->src_port;
          session->key.cs_port[VLIB_TX] = udp->dst_port;
        }
+      else if (ip4->protocol == IP_PROTOCOL_SCTP)
+       {
+         sctp_header_t *sctp;
+         sctp = (sctp_header_t *) (ip4 + 1);
+         ip46_address_set_ip4 (&session->key.cs_ip[VLIB_TX],
+                               &ip4->dst_address);
+         ip46_address_set_ip4 (&session->key.cs_ip[VLIB_RX],
+                               &ip4->src_address);
+         session->key.cs_proto = ip4->protocol;
+         session->key.cs_port[VLIB_RX] = sctp->src_port;
+         session->key.cs_port[VLIB_TX] = sctp->dst_port;
+       }
       else
        goto error;
     }
index 7b779a6..bf2726f 100644 (file)
 
 #define MIN_SRC_PORT ((u16) 0xC000)
 
+typedef struct
+{
+  /* Source and destination port. */
+  u16 src_port, dst_port;
+
+  /* Random value to distinguish connections. */
+  u32 verification_tag;
+
+  u32 checksum;
+} sctp_header_t;
+
 typedef enum cnat_trk_flag_t_
 {
   /* Endpoint is active (static or dhcp resolved) */
index 3b81daf..2b20fef 100644 (file)
@@ -76,23 +76,27 @@ clib_crc32c_u64 (u32 last, u64 data)
 
 #ifdef clib_crc32c_uses_intrinsics
 static_always_inline u32
-clib_crc32c (u8 * s, int len)
+clib_crc32c_with_init (u8 *s, int len, u32 last)
 {
-  u32 v = 0;
-
   for (; len >= 8; len -= 8, s += 8)
-    v = clib_crc32c_u64 (v, *((u64u *) s));
+    last = clib_crc32c_u64 (last, *((u64u *) s));
 
   for (; len >= 4; len -= 4, s += 4)
-    v = clib_crc32c_u32 (v, *((u32u *) s));
+    last = clib_crc32c_u32 (last, *((u32u *) s));
 
   for (; len >= 2; len -= 2, s += 2)
-    v = clib_crc32c_u16 (v, *((u16u *) s));
+    last = clib_crc32c_u16 (last, *((u16u *) s));
 
   for (; len >= 1; len -= 1, s += 1)
-    v = clib_crc32c_u8 (v, *((u8 *) s));
+    last = clib_crc32c_u8 (last, *((u8 *) s));
+
+  return last;
+}
 
-  return v;
+static_always_inline u32
+clib_crc32c (u8 *s, int len)
+{
+  return clib_crc32c_with_init (s, len, 0);
 }
 #endif