From 613b2c3c78fbec12cc87a0095ee5488252449698 Mon Sep 17 00:00:00 2001 From: Nathan Skrzypczak Date: Thu, 10 Sep 2020 17:44:41 +0200 Subject: cnat: Add support for SNat ICMP Type: feature snat supports : * echo request/reply by allocating an identifier when translating echo requests * icmp errors in the same manner as dnat Change-Id: I684e983b0181f95c5eace5a984d40084e5625fa4 Signed-off-by: Nathan Skrzypczak --- src/plugins/cnat/cnat_types.h | 81 +++++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 18 deletions(-) (limited to 'src/plugins/cnat/cnat_types.h') diff --git a/src/plugins/cnat/cnat_types.h b/src/plugins/cnat/cnat_types.h index ab59aaf2f37..c9c0b70b8c3 100644 --- a/src/plugins/cnat/cnat_types.h +++ b/src/plugins/cnat/cnat_types.h @@ -49,6 +49,15 @@ #define MIN_SRC_PORT ((u16) 0xC000) +typedef enum +{ + CNAT_SPORT_PROTO_TCP, + CNAT_SPORT_PROTO_UDP, + CNAT_SPORT_PROTO_ICMP, + CNAT_SPORT_PROTO_ICMP6, + CNAT_N_SPORT_PROTO +} cnat_sport_proto_t; + typedef struct cnat_endpoint_t_ { ip_address_t ce_ip; @@ -61,7 +70,11 @@ typedef struct cnat_endpoint_tuple_t_ cnat_endpoint_t src_ep; } cnat_endpoint_tuple_t; - +typedef struct +{ + u16 identifier; + u16 sequence; +} cnat_echo_header_t; typedef struct { @@ -80,6 +93,15 @@ typedef struct ip6_address_t ip_masks[129]; } cnat_snat_pfx_table_t; +typedef struct cnat_src_port_allocator_ +{ + /* Source ports bitmap for snat */ + clib_bitmap_t *bmap; + + /* Lock for src_ports access */ + clib_spinlock_t lock; +} cnat_src_port_allocator_t; + typedef struct cnat_main_ { /* Memory size of the session bihash */ @@ -113,11 +135,8 @@ typedef struct cnat_main_ /* Lock for the timestamp pool */ clib_rwlock_t ts_lock; - /* Source ports bitmap for snat */ - clib_bitmap_t *src_ports; - - /* Lock for src_ports access */ - clib_spinlock_t src_ports_lock; + /* Per proto source ports allocator for snat */ + cnat_src_port_allocator_t *src_ports; /* Ip4 Address to use for source NATing */ ip4_address_t snat_ip4; @@ -265,33 +284,59 @@ cnat_timestamp_free (u32 index) clib_rwlock_writer_unlock (&cnat_main.ts_lock); } -always_inline void -cnat_free_port (u16 port) +always_inline cnat_src_port_allocator_t * +cnat_get_src_port_allocator (ip_protocol_t iproto) { cnat_main_t *cm = &cnat_main; - clib_spinlock_lock (&cm->src_ports_lock); - clib_bitmap_set_no_check (cm->src_ports, port, 0); - clib_spinlock_unlock (&cm->src_ports_lock); + switch (iproto) + { + case IP_PROTOCOL_TCP: + return &cm->src_ports[CNAT_SPORT_PROTO_TCP]; + case IP_PROTOCOL_UDP: + return &cm->src_ports[CNAT_SPORT_PROTO_UDP]; + case IP_PROTOCOL_ICMP: + return &cm->src_ports[CNAT_SPORT_PROTO_ICMP]; + case IP_PROTOCOL_ICMP6: + return &cm->src_ports[CNAT_SPORT_PROTO_ICMP6]; + default: + return 0; + } +} + +always_inline void +cnat_free_port (u16 port, ip_protocol_t iproto) +{ + cnat_src_port_allocator_t *ca; + ca = cnat_get_src_port_allocator (iproto); + if (!ca) + return; + clib_spinlock_lock (&ca->lock); + clib_bitmap_set_no_check (ca->bmap, port, 0); + clib_spinlock_unlock (&ca->lock); } always_inline int -cnat_allocate_port (cnat_main_t * cm, u16 * port) +cnat_allocate_port (u16 * port, ip_protocol_t iproto) { *port = clib_net_to_host_u16 (*port); if (*port == 0) *port = MIN_SRC_PORT; - clib_spinlock_lock (&cm->src_ports_lock); - if (clib_bitmap_get_no_check (cm->src_ports, *port)) + cnat_src_port_allocator_t *ca; + ca = cnat_get_src_port_allocator (iproto); + if (!ca) + return -1; + clib_spinlock_lock (&ca->lock); + if (clib_bitmap_get_no_check (ca->bmap, *port)) { - *port = clib_bitmap_next_clear (cm->src_ports, *port); + *port = clib_bitmap_next_clear (ca->bmap, *port); if (PREDICT_FALSE (*port >= UINT16_MAX)) - *port = clib_bitmap_next_clear (cm->src_ports, MIN_SRC_PORT); + *port = clib_bitmap_next_clear (ca->bmap, MIN_SRC_PORT); if (PREDICT_FALSE (*port >= UINT16_MAX)) return -1; } - clib_bitmap_set_no_check (cm->src_ports, *port, 1); + clib_bitmap_set_no_check (ca->bmap, *port, 1); *port = clib_host_to_net_u16 (*port); - clib_spinlock_unlock (&cm->src_ports_lock); + clib_spinlock_unlock (&ca->lock); return 0; } -- cgit 1.2.3-korg