#ifndef __CNAT_TYPES_H__
#define __CNAT_TYPES_H__
+#include <vppinfra/bihash_24_8.h>
#include <vnet/fib/fib_node.h>
#include <vnet/fib/fib_source.h>
#include <vnet/ip/ip_types.h>
#include <vnet/ip/ip.h>
+#include <vnet/util/throttle.h>
/* only in the default table for v4 and v6 */
#define CNAT_FIB_TABLE 0
#define CNAT_DEFAULT_SESSION_BUCKETS 1024
#define CNAT_DEFAULT_TRANSLATION_BUCKETS 1024
#define CNAT_DEFAULT_SNAT_BUCKETS 1024
+#define CNAT_DEFAULT_SNAT_IF_MAP_LEN 4096
#define CNAT_DEFAULT_SESSION_MEMORY (1 << 20)
#define CNAT_DEFAULT_TRANSLATION_MEMORY (256 << 10)
#define CNAT_DEFAULT_SNAT_MEMORY (64 << 20)
+/* Should be prime >~ 100 * numBackends */
+#define CNAT_DEFAULT_MAGLEV_LEN 1009
+
/* This should be strictly lower than FIB_SOURCE_INTERFACE
* from fib_source.h */
#define CNAT_FIB_SOURCE_PRIORITY 0x02
-/* Initial refcnt for timestamps (2 : session & rsession) */
-#define CNAT_TIMESTAMP_INIT_REFCNT 2
+/* Initial number of timestamps for a session
+ * this will be incremented when adding the reverse
+ * session in cnat_rsession_create */
+#define CNAT_TIMESTAMP_INIT_REFCNT 1
#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) */
+ CNAT_TRK_ACTIVE = (1 << 0),
+ /* Don't translate this endpoint, but still
+ * forward. Used by maglev for DSR */
+ CNAT_TRK_FLAG_NO_NAT = (1 << 1),
+ /* */
+ CNAT_TRK_FLAG_TEST_DISABLED = (1 << 7),
+} cnat_trk_flag_t;
+
+typedef enum
+{
+ /* Endpoint addr has been resolved */
+ CNAT_EP_FLAG_RESOLVED = (1 << 0),
+} cnat_ep_flag_t;
+
typedef struct cnat_endpoint_t_
{
ip_address_t ce_ip;
+ u32 ce_sw_if_index;
u16 ce_port;
+ u8 ce_flags;
} cnat_endpoint_t;
typedef struct cnat_endpoint_tuple_t_
{
cnat_endpoint_t dst_ep;
cnat_endpoint_t src_ep;
+ u8 ep_flags; /* cnat_trk_flag_t */
} cnat_endpoint_tuple_t;
-
-
typedef struct
{
- u32 dst_address_length_refcounts[129];
- u16 *prefix_lengths_in_search_order;
- uword *non_empty_dst_address_length_bitmap;
-} cnat_snat_pfx_table_meta_t;
-
-typedef struct
-{
- /* Stores (ip family, prefix & mask) */
- clib_bihash_24_8_t ip_hash;
- /* family dependant cache */
- cnat_snat_pfx_table_meta_t meta[2];
- /* Precomputed ip masks (ip4 & ip6) */
- ip6_address_t ip_masks[129];
-} cnat_snat_pfx_table_t;
+ u16 identifier;
+ u16 sequence;
+} cnat_echo_header_t;
typedef struct cnat_main_
{
/* Number of buckets of the source NAT prefix bihash */
u32 snat_hash_buckets;
+ /* Bit map for include / exclude sw_if_index
+ * so max number of expected interfaces */
+ u32 snat_if_map_length;
+
/* Timeout after which to clear sessions (in seconds) */
u32 session_max_age;
/* 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;
-
- /* Ip4 Address to use for source NATing */
- ip4_address_t snat_ip4;
-
- /* Ip6 Address to use for source NATing */
- ip6_address_t snat_ip6;
-
- /* Longest prefix Match table for source NATing */
- cnat_snat_pfx_table_t snat_pfx_table;
-
/* Index of the scanner process node */
uword scanner_node_index;
/* Enable or Disable the scanner on startup */
u8 default_scanner_state;
+
+ /* Number of buckets for maglev, should be a
+ * prime >= 100 * max num bakends */
+ u32 maglev_len;
} cnat_main_t;
typedef struct cnat_timestamp_t_
u16 refcnt;
} cnat_timestamp_t;
-typedef struct cnat_node_ctx_t_
+typedef struct cnat_node_ctx_
{
f64 now;
- u64 seed;
u32 thread_index;
ip_address_family_t af;
u8 do_trace;
} cnat_node_ctx_t;
+cnat_main_t *cnat_get_main ();
extern u8 *format_cnat_endpoint (u8 * s, va_list * args);
extern uword unformat_cnat_ep_tuple (unformat_input_t * input,
va_list * args);
extern cnat_timestamp_t *cnat_timestamps;
extern fib_source_t cnat_fib_source;
extern cnat_main_t cnat_main;
-extern throttle_t cnat_throttle;
extern char *cnat_error_strings[];
*/
extern void cnat_enable_disable_scanner (cnat_scanner_cmd_t event_type);
-/*
- Dataplane functions
-*/
+/**
+ * Resolve endpoint address
+ */
+extern u8 cnat_resolve_ep (cnat_endpoint_t * ep);
+extern u8 cnat_resolve_addr (u32 sw_if_index, ip_address_family_t af,
+ ip_address_t * addr);
-always_inline u32
-cnat_timestamp_new (f64 t)
-{
- u32 index;
- cnat_timestamp_t *ts;
- clib_rwlock_writer_lock (&cnat_main.ts_lock);
- pool_get (cnat_timestamps, ts);
- ts->last_seen = t;
- ts->lifetime = cnat_main.session_max_age;
- ts->refcnt = CNAT_TIMESTAMP_INIT_REFCNT;
- index = ts - cnat_timestamps;
- clib_rwlock_writer_unlock (&cnat_main.ts_lock);
- return index;
-}
-
-always_inline void
-cnat_timestamp_inc_refcnt (u32 index)
-{
- clib_rwlock_reader_lock (&cnat_main.ts_lock);
- cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
- ts->refcnt++;
- clib_rwlock_reader_unlock (&cnat_main.ts_lock);
-}
-
-always_inline void
-cnat_timestamp_update (u32 index, f64 t)
-{
- clib_rwlock_reader_lock (&cnat_main.ts_lock);
- cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
- ts->last_seen = t;
- clib_rwlock_reader_unlock (&cnat_main.ts_lock);
-}
-
-always_inline void
-cnat_timestamp_set_lifetime (u32 index, u16 lifetime)
-{
- clib_rwlock_reader_lock (&cnat_main.ts_lock);
- cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
- ts->lifetime = lifetime;
- clib_rwlock_reader_unlock (&cnat_main.ts_lock);
-}
-
-always_inline f64
-cnat_timestamp_exp (u32 index)
-{
- f64 t;
- if (INDEX_INVALID == index)
- return -1;
- clib_rwlock_reader_lock (&cnat_main.ts_lock);
- cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
- t = ts->last_seen + (f64) ts->lifetime;
- clib_rwlock_reader_unlock (&cnat_main.ts_lock);
- return t;
-}
-
-always_inline void
-cnat_timestamp_free (u32 index)
-{
- if (INDEX_INVALID == index)
- return;
- clib_rwlock_writer_lock (&cnat_main.ts_lock);
- cnat_timestamp_t *ts = pool_elt_at_index (cnat_timestamps, index);
- ts->refcnt--;
- if (0 == ts->refcnt)
- pool_put (cnat_timestamps, ts);
- clib_rwlock_writer_unlock (&cnat_main.ts_lock);
-}
-
-always_inline void
-cnat_free_port (u16 port)
-{
- 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);
-}
-
-always_inline int
-cnat_allocate_port (cnat_main_t * cm, u16 * port)
-{
- *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))
- {
- *port = clib_bitmap_next_clear (cm->src_ports, *port);
- if (PREDICT_FALSE (*port >= UINT16_MAX))
- *port = clib_bitmap_next_clear (cm->src_ports, MIN_SRC_PORT);
- if (PREDICT_FALSE (*port >= UINT16_MAX))
- return -1;
- }
- clib_bitmap_set_no_check (cm->src_ports, *port, 1);
- *port = clib_host_to_net_u16 (*port);
- clib_spinlock_unlock (&cm->src_ports_lock);
- return 0;
-}
/*
* fd.io coding-style-patch-verification: ON