cnat: Add sctp support

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>
This commit is contained in:
Nathan Skrzypczak
2022-02-02 19:31:58 +01:00
committed by Beno�t Ganne
parent 2a6f35f24c
commit f284c14c7b
3 changed files with 64 additions and 8 deletions
+41
View 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;
}
+11
View File
@@ -55,6 +55,17 @@
#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) */
+12 -8
View 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 v;
return last;
}
static_always_inline u32
clib_crc32c (u8 *s, int len)
{
return clib_crc32c_with_init (s, len, 0);
}
#endif