16 #ifndef __CNAT_NODE_H__ 17 #define __CNAT_NODE_H__ 35 case ICMP4_destination_unreachable:
36 case ICMP4_time_exceeded:
37 case ICMP4_parameter_problem:
38 case ICMP4_source_quench:
40 case ICMP4_alternate_host_address:
51 case ICMP4_echo_request:
52 case ICMP4_echo_reply:
63 case ICMP6_echo_request:
64 case ICMP6_echo_reply:
75 case ICMP6_destination_unreachable:
76 case ICMP6_time_exceeded:
77 case ICMP6_parameter_problem:
86 return ((a1->as_u64[0] == a2->as_u64[0])
87 && (a1->as_u64[1] == a2->as_u64[1]));
97 return ((0 != a->as_u64[0]) || (0 != a->as_u64[1]));
104 u16 new_port[VLIB_N_DIR])
131 *sum =
ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX],
144 *sum =
ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX],
200 u16 new_port[VLIB_N_DIR])
210 sum = icmp->checksum;
220 icmp46_header_t *
icmp,
222 u16 outer_new_port[VLIB_N_DIR],
229 ip_csum_t sum, old_ip_sum, inner_l4_sum, inner_l4_old_sum;
246 sum = icmp->checksum;
254 if (ip4->
protocol == IP_PROTOCOL_TCP)
256 inner_l4_old_sum = inner_l4_sum = tcp->checksum;
260 else if (ip4->
protocol == IP_PROTOCOL_UDP)
262 inner_l4_old_sum = inner_l4_sum = udp->
checksum;
291 if (new_addr[VLIB_TX].as_u32)
293 ip_csum_update (sum, old_addr[VLIB_TX].as_u32, new_addr[VLIB_TX].as_u32,
296 if (new_addr[VLIB_RX].as_u32)
298 ip_csum_update (sum, old_addr[VLIB_RX].as_u32, new_addr[VLIB_RX].as_u32,
317 if (ip4->
protocol == IP_PROTOCOL_TCP)
325 else if (ip4->
protocol == IP_PROTOCOL_UDP)
332 else if (ip4->
protocol == IP_PROTOCOL_ICMP)
334 icmp46_header_t *
icmp = (icmp46_header_t *) udp;
362 u16 new_port[VLIB_N_DIR])
388 if (new_port[VLIB_TX])
391 *sum =
ip_csum_update (*sum, old_port[VLIB_TX], new_port[VLIB_TX],
403 if (new_port[VLIB_RX])
406 *sum =
ip_csum_update (*sum, old_port[VLIB_RX], new_port[VLIB_RX],
415 u16 new_port[VLIB_N_DIR])
425 sum = icmp->checksum;
454 icmp46_header_t *
icmp,
456 u16 outer_new_port[VLIB_N_DIR],
464 ip_csum_t sum, inner_l4_sum, inner_l4_old_sum;
484 sum = icmp->checksum;
508 if (ip6->
protocol == IP_PROTOCOL_TCP)
510 inner_l4_old_sum = inner_l4_sum = tcp->checksum;
514 else if (ip6->
protocol == IP_PROTOCOL_UDP)
516 inner_l4_old_sum = inner_l4_sum = udp->
checksum;
529 if (old_port[VLIB_TX] && new_port[VLIB_TX])
534 if (old_port[VLIB_RX] && new_port[VLIB_RX])
574 if (ip6->
protocol == IP_PROTOCOL_TCP)
582 else if (ip6->
protocol == IP_PROTOCOL_UDP)
589 else if (ip6->
protocol == IP_PROTOCOL_ICMP6)
591 icmp46_header_t *
icmp = (icmp46_header_t *) udp;
613 session->
key.__cs_pad[0] = 0;
614 session->
key.__cs_pad[1] = 0;
621 icmp46_header_t *
icmp = (icmp46_header_t *) (ip4 + 1);
668 icmp46_header_t *
icmp = (icmp46_header_t *) (ip6 + 1);
758 (
u8 *) & l,
sizeof (l));
781 &session->value.cs_ip[
VLIB_TX]);
783 &session->value.cs_ip[
VLIB_RX]);
784 rsession->key.cs_proto = session->key.cs_proto;
785 rsession->key.__cs_pad[0] = 0;
786 rsession->key.__cs_pad[1] = 0;
787 rsession->key.cs_af =
ctx->af;
792 rv = clib_bihash_search_inline_2_40_48 (&
cnat_session_db, &rkey, &rvalue);
805 rsession->value.cs_ts_index = session->value.cs_ts_index;
807 rsession->value.flags = rsession_flags;
821 u32 n_left, *from, thread_index;
871 next[3] = cnat_sub (vm, node, b[3], &ctx, rv[3], session[3]);
878 next[2] = cnat_sub (vm, node, b[2], &ctx, rv[2], session[2]);
885 next[1] = cnat_sub (vm, node, b[1], &ctx, rv[1], session[1]);
892 next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
923 &bkey[0], &bvalue[0]);
926 next[0] = cnat_sub (vm, node, b[0], &ctx, rv[0], session[0]);
static_always_inline void cnat_translation_icmp6_echo(ip6_header_t *ip6, icmp46_header_t *icmp, ip6_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
static_always_inline void clib_spinlock_unlock(clib_spinlock_t *p)
static_always_inline void clib_spinlock_lock(clib_spinlock_t *p)
ip_address_t ** throttle_pool
static_always_inline u8 cmp_ip6_address(const ip6_address_t *a1, const ip6_address_t *a2)
struct cnat_session_t_::@632 key
this key sits in the same memory location a 'key' in the bihash kvp
static f64 vlib_time_now(vlib_main_t *vm)
uword(* cnat_node_sub_t)(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, cnat_node_ctx_t *ctx, int rv, cnat_session_t *session)
u16 cs_port[VLIB_N_DIR]
ports in rx/tx
static u64 clib_bihash_hash_40_48(const clib_bihash_kv_40_48_t *v)
static_always_inline void cnat_translation_icmp4_error(ip4_header_t *outer_ip4, icmp46_header_t *icmp, ip4_address_t outer_new_addr[VLIB_N_DIR], u16 outer_new_port[VLIB_N_DIR], u8 snat_outer_ip)
static u32 cnat_timestamp_new(f64 t)
static_always_inline void ip46_address_set_ip6(ip46_address_t *dst, const ip6_address_t *src)
static_always_inline void cnat_tcp_update_session_lifetime(tcp_header_t *tcp, u32 index)
void cnat_session_free(cnat_session_t *session)
Free a session & update refcounts.
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
struct _tcp_header tcp_header_t
clib_bihash_40_48_t cnat_session_db
The DB of sessions.
static_always_inline void cnat_ip6_translate_l4(ip6_header_t *ip6, udp_header_t *udp, ip_csum_t *sum, ip6_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
static_always_inline u8 icmp_type_is_error_message(u8 icmp_type)
static void cnat_timestamp_set_lifetime(u32 index, u16 lifetime)
A session represents the memory of a translation.
u8 cs_af
The address family describing the IP addresses.
#define static_always_inline
#define vlib_prefetch_buffer_header(b, type)
Prefetch buffer metadata.
void vl_api_rpc_call_main_thread(void *fp, u8 *data, u32 data_length)
static_always_inline void cnat_ip4_translate_l4(ip4_header_t *ip4, udp_header_t *udp, ip_csum_t *sum, ip4_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
ip46_address_t cs_ip[VLIB_N_DIR]
IP 4/6 address in the rx/tx direction.
u32 cs_ts_index
Timestamp index this session was last used.
static_always_inline u32 cnat_client_cnt_session(cnat_client_t *cc)
Add a session refcnt to this client.
static_always_inline void ip46_address_copy(ip46_address_t *dst, const ip46_address_t *src)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
static u64 throttle_seed(throttle_t *t, u32 thread_index, f64 time_now)
static_always_inline cnat_client_t * cnat_client_ip4_find(const ip4_address_t *ip)
Find a client from an IP4 address.
vl_api_address_union_t src_address
static_always_inline void cnat_translation_ip6(const cnat_session_t *session, ip6_header_t *ip6, udp_header_t *udp)
static_always_inline u8 icmp6_type_is_error_message(u8 icmp_type)
static_always_inline u8 icmp6_type_is_echo(u8 icmp_type)
static_always_inline void cnat_session_make_key(vlib_buffer_t *b, ip_address_family_t af, clib_bihash_kv_40_48_t *bkey)
static_always_inline void cnat_ip6_translate_l3(ip6_header_t *ip6, ip6_address_t new_addr[VLIB_N_DIR])
clib_spinlock_t * throttle_pool_lock
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
static_always_inline void cnat_ip4_translate_l3(ip4_header_t *ip4, ip4_address_t new_addr[VLIB_N_DIR])
vlib_main_t vlib_node_runtime_t * node
static_always_inline void cnat_translation_ip4(const cnat_session_t *session, ip4_header_t *ip4, udp_header_t *udp)
void cnat_client_learn(const cnat_learn_arg_t *l)
Called in the main thread by RPC from the workers to learn a new client.
#define CNAT_DEFAULT_TCP_RST_TIMEOUT
static ip_csum_t ip_csum_sub_even(ip_csum_t c, ip_csum_t x)
ip_address_family_t version
static_always_inline u8 icmp_type_is_echo(u8 icmp_type)
static_always_inline cnat_client_t * cnat_client_ip6_find(const ip6_address_t *ip)
Find a client from an IP6 address.
enum ip_address_family_t_ ip_address_family_t
static_always_inline void cnat_translation_icmp6_error(ip6_header_t *outer_ip6, icmp46_header_t *icmp, ip6_address_t outer_new_addr[VLIB_N_DIR], u16 outer_new_port[VLIB_N_DIR], u8 snat_outer_ip)
static_always_inline void cnat_translation_icmp4_echo(ip4_header_t *ip4, icmp46_header_t *icmp, ip4_address_t new_addr[VLIB_N_DIR], u16 new_port[VLIB_N_DIR])
ip_protocol_t cs_proto
The IP protocol TCP or UDP only supported.
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
VLIB buffer representation.
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
#define ip_csum_update(sum, old, new, type, field)
static void ip6_address_copy(ip6_address_t *dst, const ip6_address_t *src)
cnat_client_db_t cnat_client_db
static_always_inline void cnat_session_create(cnat_session_t *session, cnat_node_ctx_t *ctx, u8 rsession_flags)
Create NAT sessions.
static_always_inline void vlib_get_buffers(vlib_main_t *vm, u32 *bi, vlib_buffer_t **b, int count)
Translate array of buffer indices into buffer pointers.
static u16 ip_csum_fold(ip_csum_t c)
static void ip46_address_set_ip4(ip46_address_t *ip46, const ip4_address_t *ip)
static uword cnat_node_inline(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, cnat_node_sub_t cnat_sub, ip_address_family_t af, u8 do_trace)
static ip_csum_t ip_csum_add_even(ip_csum_t c, ip_csum_t x)
struct cnat_session_t_::@633 value
this value sits in the same memory location a 'value' in the bihash kvp
A client is a representation of an IP address behind the NAT.
static_always_inline u8 has_ip6_address(ip6_address_t *a)
Inline translation functions.
static int throttle_check(throttle_t *t, u32 thread_index, u64 hash, u64 seed)