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, 234 clib_net_to_host_u32 (seq));
246 u32 i, *del, *to_delete = 0;
271 [NAT_HA_COUNTER_MISSED_COUNT],
289 b->
flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
290 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
343 #define _(N, s, v) ha->counters[v].name = s; \ 344 ha->counters[v].stat_segment_name = "/nat44/ha/" s; \ 345 vlib_validate_simple_counter(&ha->counters[v], 0); \ 346 vlib_zero_simple_counter(&ha->counters[v], 0); 372 nat_ha_handoff_node.index, 1);
431 in_addr.
as_u32 =
event->in_addr;
432 out_addr.
as_u32 =
event->out_addr;
433 eh_addr.
as_u32 =
event->eh_addr;
434 ehn_addr.
as_u32 =
event->ehn_addr;
435 fib_index = clib_net_to_host_u32 (event->
fib_index);
436 flags = clib_net_to_host_u16 (event->
flags);
440 fib_index, flags, thread_index);
453 out_addr.
as_u32 =
event->out_addr;
454 eh_addr.
as_u32 =
event->eh_addr;
455 fib_index = clib_net_to_host_u32 (event->
fib_index);
458 event->
protocol, fib_index, thread_index);
466 u32 fib_index, total_pkts;
472 out_addr.
as_u32 =
event->out_addr;
473 eh_addr.
as_u32 =
event->eh_addr;
474 fib_index = clib_net_to_host_u32 (event->
fib_index);
475 total_pkts = clib_net_to_host_u32 (event->
total_pkts);
476 total_bytes = clib_net_to_host_u64 (event->
total_bytes);
479 event->
protocol, fib_index, total_pkts, total_bytes,
516 b->
flags |= VLIB_BUFFER_TOTAL_LENGTH_VALID;
517 b->
flags |= VNET_BUFFER_F_LOCALLY_ORIGINATED;
572 is_resync, thread_index);
630 offset +=
sizeof (*event);
638 [NAT_HA_COUNTER_SEND_ADD],
643 [NAT_HA_COUNTER_SEND_DEL],
648 [NAT_HA_COUNTER_SEND_REFRESH],
674 #define skip_if_disabled() \ 676 nat_ha_main_t *ha = &nat_ha_main; \ 677 if (PREDICT_TRUE (!ha->dst_port)) \ 700 event.flags = clib_host_to_net_u16 (flags);
701 event.in_addr = in_addr->
as_u32;
702 event.in_port = in_port;
703 event.out_addr = out_addr->
as_u32;
704 event.out_port = out_port;
705 event.eh_addr = eh_addr->
as_u32;
706 event.eh_port = eh_port;
707 event.ehn_addr = ehn_addr->
as_u32;
708 event.ehn_port = ehn_port;
709 event.fib_index = clib_host_to_net_u32 (fib_index);
710 event.protocol =
proto;
724 event.out_addr = out_addr->
as_u32;
725 event.out_port = out_port;
726 event.eh_addr = eh_addr->
as_u32;
727 event.eh_port = eh_port;
728 event.fib_index = clib_host_to_net_u32 (fib_index);
729 event.protocol =
proto;
736 u64 total_bytes,
u32 thread_index,
f64 * last_refreshed,
f64 now)
746 *last_refreshed = now;
749 event.out_addr = out_addr->
as_u32;
750 event.out_port = out_port;
751 event.eh_addr = eh_addr->
as_u32;
752 event.eh_port = eh_port;
753 event.fib_index = clib_host_to_net_u32 (fib_index);
754 event.protocol =
proto;
755 event.total_pkts = clib_host_to_net_u32 (total_pkts);
756 event.total_bytes = clib_host_to_net_u64 (total_bytes);
777 .state = VLIB_NODE_STATE_INTERRUPT,
778 .name =
"nat-ha-worker",
788 uword *event_data = 0;
794 nat_elog_info (
"nat-ha-process: bogus kickoff event received");
808 nat_ha_worker_node.index);
819 .name =
"nat-ha-process",
859 #define foreach_nat_ha_error \ 860 _(PROCESSED, "pkts-processed") \ 861 _(BAD_VERSION, "bad-version") 865 #define _(sym, str) NAT_HA_ERROR_##sym, 871 static char *nat_ha_error_strings[] = {
872 #define _(sym, str) str, 882 u32 n_left_from, *from, next_index, *to_next;
885 u32 pkts_processed = 0;
894 while (n_left_from > 0)
900 while (n_left_from > 0 && n_left_to_next > 0)
902 u32 bi0, next0, src_addr0, dst_addr0;;
906 u16 event_count0, src_port0, dst_port0, old_len0;
929 b0->
error = node->
errors[NAT_HA_ERROR_BAD_VERSION];
933 event_count0 = clib_net_to_host_u16 (h0->
count);
956 b0->
current_length =
sizeof (*ip0) +
sizeof (*udp0) +
sizeof (*h0);
968 ip0->
ttl = host_config_ttl;
985 [NAT_HA_COUNTER_SEND_ACK],
990 && (b0->
flags & VLIB_BUFFER_IS_TRACED)))
1000 to_next, n_left_to_next,
1008 NAT_HA_ERROR_PROCESSED, pkts_processed);
1017 .vector_size =
sizeof (
u32),
1020 .n_errors =
ARRAY_LEN (nat_ha_error_strings),
1036 #define foreach_nat_ha_handoff_error \ 1037 _(CONGESTION_DROP, "congestion drop") \ 1038 _(SAME_WORKER, "same worker") \ 1039 _(DO_HANDOFF, "do handoff") 1043 #define _(sym,str) NAT_HA_HANDOFF_ERROR_##sym, 1049 static char *nat_ha_handoff_error_strings[] = {
1050 #define _(sym,string) string, 1075 u32 n_enq, n_left_from, *from;
1078 u32 do_handoff = 0, same_worker = 0;
1085 ti = thread_indices;
1087 while (n_left_from > 0)
1094 if (ti[0] != thread_index)
1100 && (b[0]->
flags & VLIB_BUFFER_IS_TRACED)))
1116 if (n_enq < frame->n_vectors)
1118 NAT_HA_HANDOFF_ERROR_CONGESTION_DROP,
1121 NAT_HA_HANDOFF_ERROR_SAME_WORKER, same_worker);
1123 NAT_HA_HANDOFF_ERROR_DO_HANDOFF, do_handoff);
1130 .name =
"nat-ha-handoff",
1131 .vector_size =
sizeof (
u32),
1134 .n_errors =
ARRAY_LEN(nat_ha_handoff_error_strings),
#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.
#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(* 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 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...
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)
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).
void udp_unregister_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u8 is_ip4)
#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.
uword * thread_registrations_by_name
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)
#define hash_get_mem(h, key)
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 vlib_thread_main_t * vlib_get_thread_main()
static void nat_ha_send(vlib_frame_t *f, vlib_buffer_t *b, u8 is_resync, u32 thread_index)
#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)
void udp_register_dst_port(vlib_main_t *vm, udp_dst_port_t dst_port, u32 node_index, u8 is_ip4)
u32 session_refresh_interval
struct ip4_main_t::@360 host_config
Template information for VPP generated packets.
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)
void nat_ha_init(vlib_main_t *vm, nat_ha_sadd_cb_t sadd_cb, nat_ha_sdel_cb_t sdel_cb, nat_ha_sref_cb_t sref_cb)
Initialize NAT HA.
u32 state_sync_next_event_offset
ip4_address_t src_ip_address