22 #define NAT_HA_RETRIES 3 24 #define foreach_nat_ha_counter \ 25 _(RECV_ADD, "add-event-recv", 0) \ 26 _(RECV_DEL, "del-event-recv", 1) \ 27 _(RECV_REFRESH, "refresh-event-recv", 2) \ 28 _(SEND_ADD, "add-event-send", 3) \ 29 _(SEND_DEL, "del-event-send", 4) \ 30 _(SEND_REFRESH, "refresh-event-send", 5) \ 31 _(RECV_ACK, "ack-recv", 6) \ 32 _(SEND_ACK, "ack-send", 7) \ 33 _(RETRY_COUNT, "retry-count", 8) \ 34 _(MISSED_COUNT, "missed-count", 9) 37 #define NAT_HA_VERSION 0x01 40 #define NAT_HA_FLAG_ACK 0x01 88 #define _(N, s, v) NAT_HA_COUNTER_##N = v, 235 clib_net_to_host_u32 (seq));
247 u32 i, *del, *to_delete = 0;
272 [NAT_HA_COUNTER_MISSED_COUNT],
290 b->
flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
291 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
346 #define _(N, s, v) ha->counters[v].name = s; \ 347 ha->counters[v].stat_segment_name = "/nat44/ha/" s; \ 348 vlib_validate_simple_counter(&ha->counters[v], 0); \ 349 vlib_zero_simple_counter(&ha->counters[v], 0); 375 nat_ha_handoff_node.index, 1);
434 in_addr.
as_u32 =
event->in_addr;
435 out_addr.
as_u32 =
event->out_addr;
436 eh_addr.
as_u32 =
event->eh_addr;
437 ehn_addr.
as_u32 =
event->ehn_addr;
438 fib_index = clib_net_to_host_u32 (event->
fib_index);
439 flags = clib_net_to_host_u16 (event->
flags);
443 fib_index, flags, thread_index);
456 out_addr.
as_u32 =
event->out_addr;
457 eh_addr.
as_u32 =
event->eh_addr;
458 fib_index = clib_net_to_host_u32 (event->
fib_index);
461 event->
protocol, fib_index, thread_index);
469 u32 fib_index, total_pkts;
475 out_addr.
as_u32 =
event->out_addr;
476 eh_addr.
as_u32 =
event->eh_addr;
477 fib_index = clib_net_to_host_u32 (event->
fib_index);
478 total_pkts = clib_net_to_host_u32 (event->
total_pkts);
479 total_bytes = clib_net_to_host_u64 (event->
total_bytes);
482 event->
protocol, fib_index, total_pkts, total_bytes,
519 b->
flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
520 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
575 is_resync, thread_index);
633 offset +=
sizeof (*event);
641 [NAT_HA_COUNTER_SEND_ADD],
646 [NAT_HA_COUNTER_SEND_DEL],
651 [NAT_HA_COUNTER_SEND_REFRESH],
677 #define skip_if_disabled() \ 679 nat_ha_main_t *ha = &nat_ha_main; \ 680 if (PREDICT_TRUE (!ha->dst_port)) \ 703 event.flags = clib_host_to_net_u16 (flags);
704 event.in_addr = in_addr->
as_u32;
705 event.in_port = in_port;
706 event.out_addr = out_addr->
as_u32;
707 event.out_port = out_port;
708 event.eh_addr = eh_addr->
as_u32;
709 event.eh_port = eh_port;
710 event.ehn_addr = ehn_addr->
as_u32;
711 event.ehn_port = ehn_port;
712 event.fib_index = clib_host_to_net_u32 (fib_index);
713 event.protocol =
proto;
727 event.out_addr = out_addr->
as_u32;
728 event.out_port = out_port;
729 event.eh_addr = eh_addr->
as_u32;
730 event.eh_port = eh_port;
731 event.fib_index = clib_host_to_net_u32 (fib_index);
732 event.protocol =
proto;
739 u64 total_bytes,
u32 thread_index,
f64 * last_refreshed,
f64 now)
749 *last_refreshed = now;
752 event.out_addr = out_addr->
as_u32;
753 event.out_port = out_port;
754 event.eh_addr = eh_addr->
as_u32;
755 event.eh_port = eh_port;
756 event.fib_index = clib_host_to_net_u32 (fib_index);
757 event.protocol =
proto;
758 event.total_pkts = clib_host_to_net_u32 (total_pkts);
759 event.total_bytes = clib_host_to_net_u64 (total_bytes);
791 .state = VLIB_NODE_STATE_INTERRUPT,
792 .name =
"nat-ha-worker",
802 uword *event_data = 0;
808 nat_elog_info (
"nat-ha-process: bogus kickoff event received");
822 nat_ha_worker_node.index);
833 .name =
"nat-ha-process",
873 #define foreach_nat_ha_error \ 874 _(PROCESSED, "pkts-processed") \ 875 _(BAD_VERSION, "bad-version") 879 #define _(sym, str) NAT_HA_ERROR_##sym, 885 static char *nat_ha_error_strings[] = {
886 #define _(sym, str) str, 896 u32 n_left_from, *from, next_index, *to_next;
899 u32 pkts_processed = 0;
908 while (n_left_from > 0)
914 while (n_left_from > 0 && n_left_to_next > 0)
916 u32 bi0, next0, src_addr0, dst_addr0;;
920 u16 event_count0, src_port0, dst_port0, old_len0;
943 b0->
error = node->
errors[NAT_HA_ERROR_BAD_VERSION];
947 event_count0 = clib_net_to_host_u16 (h0->
count);
970 b0->
current_length =
sizeof (*ip0) +
sizeof (*udp0) +
sizeof (*h0);
982 ip0->
ttl = host_config_ttl;
999 [NAT_HA_COUNTER_SEND_ACK],
1000 thread_index, 0, 1);
1004 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1014 to_next, n_left_to_next,
1022 NAT_HA_ERROR_PROCESSED, pkts_processed);
1031 .vector_size =
sizeof (
u32),
1034 .n_errors =
ARRAY_LEN (nat_ha_error_strings),
1050 #define foreach_nat_ha_handoff_error \ 1051 _(CONGESTION_DROP, "congestion drop") \ 1052 _(SAME_WORKER, "same worker") \ 1053 _(DO_HANDOFF, "do handoff") 1057 #define _(sym,str) NAT_HA_HANDOFF_ERROR_##sym, 1063 static char *nat_ha_handoff_error_strings[] = {
1064 #define _(sym,string) string, 1089 u32 n_enq, n_left_from, *from;
1092 u32 do_handoff = 0, same_worker = 0;
1099 ti = thread_indices;
1101 while (n_left_from > 0)
1108 if (ti[0] != thread_index)
1114 && (b[0]->
flags & VLIB_BUFFER_IS_TRACED)))
1130 if (n_enq < frame->n_vectors)
1132 NAT_HA_HANDOFF_ERROR_CONGESTION_DROP,
1135 NAT_HA_HANDOFF_ERROR_SAME_WORKER, same_worker);
1137 NAT_HA_HANDOFF_ERROR_DO_HANDOFF, do_handoff);
1151 .name =
"nat-ha-handoff",
1152 .vector_size =
sizeof (
u32),
1155 .n_errors =
ARRAY_LEN(nat_ha_handoff_error_strings),
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
void nat_ha_disable()
Disable NAT HA.
#define vec_foreach_index(var, v)
Iterate over vector indices.
static char * nat_ha_handoff_error_strings[]
struct nat_ha_main_s nat_ha_main_t
vlib_node_registration_t nat_ha_handoff_node
(constructor) VLIB_REGISTER_NODE (nat_ha_handoff_node)
static f64 vlib_process_wait_for_event_or_clock(vlib_main_t *vm, f64 dt)
Suspend a cooperative multi-tasking thread Waits for an event, or for the indicated number of seconds...
vl_api_wireguard_peer_flags_t flags
static uword * vlib_process_wait_for_event(vlib_main_t *vm)
#define nat_elog_info(nat_elog_str)
static uword nat_ha_handoff_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
#define skip_if_disabled()
i16 current_data
signed offset in data[], pre_data[] that we are currently processing.
static void vlib_node_set_interrupt_pending(vlib_main_t *vm, u32 node_index)
#define clib_memcpy_fast(a, b, c)
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
static f64 vlib_time_now(vlib_main_t *vm)
u32 vlib_frame_queue_main_init(u32 node_index, u32 frame_queue_nelts)
u16 current_length
Nbytes between current data and the end of this buffer.
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
#define foreach_nat_ha_handoff_error
#define clib_atomic_fetch_sub(a, b)
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
void nat_ha_init(vlib_main_t *vm, u32 num_workers, u32 num_threads)
Initialize NAT HA.
void(* nat_ha_sref_cb_t)(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 total_pkts, u64 total_bytes, u32 thread_index)
#define nat_elog_warn(nat_elog_str)
void nat_ha_sadd(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index, u8 is_resync)
Create session add HA event.
static void vlib_increment_simple_counter(vlib_simple_counter_main_t *cm, u32 thread_index, u32 index, u64 increment)
Increment a simple counter.
static void nat_ha_header_create(vlib_buffer_t *b, u32 *offset, u32 thread_index)
vlib_error_t * errors
Vector of errors for this node.
static_always_inline void nat_ha_recv_add(nat_ha_event_t *event, f64 now, u32 thread_index)
void nat_ha_get_resync_status(u8 *in_resync, u32 *resync_ack_missed)
Get resync status.
vlib_main_t ** vlib_mains
static_always_inline u8 plugin_enabled()
static u8 * format_nat_ha_trace(u8 *s, va_list *args)
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
static_always_inline void nat_ha_recv_refresh(nat_ha_event_t *event, f64 now, u32 thread_index)
vlib_node_registration_t ip4_lookup_node
(constructor) VLIB_REGISTER_NODE (ip4_lookup_node)
void nat_ha_sref(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 total_pkts, u64 total_bytes, u32 thread_index, f64 *last_refreshed, f64 now)
Create session refresh HA event.
#define clib_memcpy(d, s, n)
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
static char * nat_ha_error_strings[]
nat_ha_main_t nat_ha_main
ip4_address_t dst_ip_address
#define static_always_inline
static uword vlib_process_get_events(vlib_main_t *vm, uword **data_vector)
Return the first event type which has occurred and a vector of per-event data of that type...
description fragment has unexpected format
vlib_frame_t * vlib_get_frame_to_node(vlib_main_t *vm, u32 to_node_index)
static void * ip4_next_header(ip4_header_t *i)
#define foreach_nat_ha_error
#define nat_elog_debug_X1(nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
A collection of simple counters.
static u8 * format_nat_ha_handoff_trace(u8 *s, va_list *args)
static u32 vlib_get_buffer_index(vlib_main_t *vm, void *p)
Translate buffer pointer into buffer index.
static uword nat_ha_process(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
vl_api_fib_path_type_t type
vlib_error_t error
Error code for buffers to be enqueued to error handler.
static void vlib_process_signal_event(vlib_main_t *vm, uword node_index, uword type_opaque, uword data)
static_always_inline void nat_ha_event_process(nat_ha_event_t *event, f64 now, u32 thread_index)
static __clib_warn_unused_result u32 vlib_buffer_alloc(vlib_main_t *vm, u32 *buffers, u32 n_buffers)
Allocate buffers into supplied array.
vlib_node_registration_t nat_ha_node
(constructor) VLIB_REGISTER_NODE (nat_ha_node)
static_always_inline void nat_ha_recv_del(nat_ha_event_t *event, u32 thread_index)
void vlib_put_frame_to_node(vlib_main_t *vm, u32 to_node_index, vlib_frame_t *f)
static void * vlib_buffer_get_current(vlib_buffer_t *b)
Get pointer to current data to process.
void nat_ha_get_listener(ip4_address_t *addr, u16 *port, u32 *path_mtu)
Get HA listener/local configuration.
void nat_ha_flush(u8 is_resync)
Flush the current HA data (for testing)
#define vec_del1(v, i)
Delete the element at index I.
static int nat_ha_resend_queue_add(u32 seq, u8 *data, u8 data_len, u8 is_resync, u32 thread_index)
struct ip4_main_t::@380 host_config
Template information for VPP generated packets.
u32 node_index
Node index.
#define vlib_validate_buffer_enqueue_x1(vm, node, next_index, to_next, n_left_to_next, bi0, next0)
Finish enqueueing one buffer forward in the graph.
#define vlib_get_next_frame(vm, node, next_index, vectors, n_vectors_left)
Get pointer to next frame vector data by (vlib_node_runtime_t, next_index).
nat_ha_per_thread_data_t * per_thread_data
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
#define VLIB_REGISTER_NODE(x,...)
vlib_node_registration_t nat_ha_worker_node
(constructor) VLIB_REGISTER_NODE (nat_ha_worker_node)
sll srl srl sll sra u16x4 i
#define vec_free(V)
Free vector's memory (no header).
#define nat_elog_notice_X1(nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
nat_ha_resend_entry_t * resend_queue
void vlib_put_next_frame(vlib_main_t *vm, vlib_node_runtime_t *r, u32 next_index, u32 n_vectors_left)
Release pointer to next frame vector data.
void(* nat_ha_resync_event_cb_t)(u32 client_index, u32 pid, u32 missed_count)
static uword nat_ha_worker_fn(vlib_main_t *vm, vlib_node_runtime_t *rt, vlib_frame_t *f)
int nat_ha_set_listener(ip4_address_t *addr, u16 port, u32 path_mtu)
Set HA listener (local settings)
vlib_main_t vlib_node_runtime_t * node
vlib_frame_t * state_sync_frame
u16 cached_next_index
Next frame index that vector arguments were last enqueued to last time this node ran.
int nat_ha_set_failover(ip4_address_t *addr, u16 port, u32 session_refresh_interval)
Set HA failover (remote settings)
vlib_simple_counter_main_t counters[NAT_HA_N_COUNTERS]
static void vlib_buffer_advance(vlib_buffer_t *b, word l)
Advance current data pointer by the supplied (signed!) amount.
vlib_node_registration_t nat_ha_process_node
(constructor) VLIB_REGISTER_NODE (nat_ha_process_node)
void nat_ha_sdel(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
Create session delete HA event.
#define clib_atomic_fetch_add(a, b)
struct _vlib_node_registration vlib_node_registration_t
template key/value backing page structure
static_always_inline void nat_ha_event_add(nat_ha_event_t *event, u8 do_flush, u32 thread_index, u8 is_resync)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
vlib_buffer_t * state_sync_buffer
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
#define VLIB_BUFFER_TRACE_TRAJECTORY_INIT(b)
static void nat_ha_resync_fin(void)
VLIB buffer representation.
static_always_inline void nat_ha_ack_recv(u32 seq, u32 thread_index)
static uword nat_ha_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame)
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)
void nat_ha_get_failover(ip4_address_t *addr, u16 *port, u32 *session_refresh_interval)
Get HA failover/remote settings.
static_always_inline u32 vlib_buffer_enqueue_to_thread(vlib_main_t *vm, u32 frame_queue_index, u32 *buffer_indices, u16 *thread_indices, u32 n_packets, int drop_on_congestion)
struct clib_bihash_value offset
template key/value backing page structure
ip4_main_t ip4_main
Global ip4 main structure.
void(* nat_ha_sadd_cb_t)(ip4_address_t *in_addr, u16 in_port, ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, ip4_address_t *ehn_addr, u16 ehn_port, u8 proto, u32 fib_index, u16 flags, u32 thread_index)
static void nat_ha_send(vlib_frame_t *f, vlib_buffer_t *b, u8 is_resync, u32 thread_index)
int nat_ha_resync(u32 client_index, u32 pid, nat_ha_resync_event_cb_t event_callback)
Resync HA (resend existing sessions to new failover)
#define vec_foreach(var, vec)
Vector iterator.
#define IP4_HEADER_FLAG_DONT_FRAGMENT
u16 flags
Copy of main node flags.
void * vlib_add_trace(vlib_main_t *vm, vlib_node_runtime_t *r, vlib_buffer_t *b, u32 n_data_bytes)
u32 session_refresh_interval
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.
#define VLIB_NODE_FLAG_TRACE
static void nat_ha_resend_scan(f64 now, u32 thread_index)
#define foreach_nat_ha_counter
nat_ha_resync_event_cb_t event_callback
u8 ttl
TTL to use for host generated packets.
#define nat_elog_info_X1(nat_elog_fmt_str, nat_elog_fmt_arg, nat_elog_val1)
void(* nat_ha_sdel_cb_t)(ip4_address_t *out_addr, u16 out_port, ip4_address_t *eh_addr, u16 eh_port, u8 proto, u32 fib_index, u32 thread_index)
static vlib_buffer_t * vlib_get_buffer(vlib_main_t *vm, u32 buffer_index)
Translate buffer index into buffer pointer.
static u16 ip4_header_checksum(ip4_header_t *i)
static u16 ip_csum_fold(ip_csum_t c)
u32 state_sync_next_event_offset
ip4_address_t src_ip_address
void nat_ha_enable(nat_ha_sadd_cb_t sadd_cb, nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb)
Enable NAT HA, set callbacks.