16 #include <netinet/in.h> 48 #define foreach_acl_fa_error \ 49 _(ACL_DROP, "ACL deny packets") \ 50 _(ACL_PERMIT, "ACL permit packets") \ 51 _(ACL_NEW_SESSION, "new sessions added") \ 52 _(ACL_EXIST_SESSION, "existing session packets") \ 53 _(ACL_CHECK, "checked packets") \ 54 _(ACL_RESTART_SESSION_TIMER, "restart session timer") \ 55 _(ACL_TOO_MANY_SESSIONS, "too many sessions to add new") \ 60 #define _(sym,str) ACL_FA_ERROR_##sym, 74 u16 current_policy_epoch =
78 return current_policy_epoch;
84 u16 next0,
int match_acl_in_index,
int match_rule_index,
112 u16 current_policy_epoch =
117 ((current_policy_epoch ^
142 u32 * out_sw_if_index)
145 for (ii = 0; ii < vector_sz; ii++)
158 for (ii = 0; ii < vector_sz; ii++)
160 is_input, is_l2_path, &out_fa_5tuple[ii]);
169 for (ii = 0; ii < vector_sz; ii++)
184 u32 counter_node_index,
int is_input,
u64 now,
187 u32 pkt_len,
int node_trace_on,
197 sess, &fa_5tuple[0], pkt_len);
204 ACL_FA_ERROR_ACL_RESTART_SESSION_TIMER, 1);
207 0x00010000 + ((0xff & old_timeout_type) << 8) +
208 (0xff & new_timeout_type);
222 (
"BUG: session LSB16(sw_if_index)=%d and 5-tuple=%d collision!",
230 #define ACL_PLUGIN_VECTOR_SIZE 4 231 #define ACL_PLUGIN_PREFETCH_GAP 3 237 int is_l2_path,
int with_stateful_datapath)
288 &sw_if_index[0], &fa_5tuple[0]);
289 if (with_stateful_datapath)
291 &fa_5tuple[0], &hash[0]);
297 sw_if_index += vec_sz;
303 const int vec_sz = 1;
307 &sw_if_index[0], &fa_5tuple[0]);
308 if (with_stateful_datapath)
310 &fa_5tuple[0], &hash[0]);
316 sw_if_index += vec_sz;
325 int is_ip6,
int is_input,
int is_l2_path,
326 int with_stateful_datapath,
int node_trace_on,
327 int reclassify_sessions)
330 u32 pkts_exist_session = 0;
331 u32 pkts_new_session = 0;
332 u32 pkts_acl_permit = 0;
333 u32 trace_bitmap = 0;
347 u32 saved_matched_acl_index = 0;
348 u32 saved_matched_ace_index = 0;
349 u32 saved_packet_count = 0;
350 u32 saved_byte_count = 0;
353 no_error_existing_session =
354 error_node->
errors[ACL_FA_ERROR_ACL_EXIST_SESSION];
374 if (with_stateful_datapath)
376 &fa_5tuple[0], &f_sess_id_next.
as_u64);
383 int acl_check_needed = 1;
384 u32 match_acl_in_index = ~0;
385 u32 match_acl_pos = ~0;
386 u32 match_rule_index = ~0;
392 if (with_stateful_datapath)
407 hash[1], &fa_5tuple[1],
409 if (f_sess_id_next.
as_u64 != ~0ULL)
415 if (f_sess_id.
as_u64 != ~0ULL)
419 trace_bitmap |= 0x80000000;
422 b[0]->
error = no_error_existing_session;
423 acl_check_needed = 0;
424 pkts_exist_session += 1;
427 is_input, now, f_sess_id,
440 if (reclassify_sessions)
444 (am, is_input, pw, now, sw_if_index[0],
447 acl_check_needed = 1;
450 trace_bitmap |= 0x40000000;
457 if ((f_sess_id_next.
as_u64 != ~0ULL)
458 && 0 == memcmp (&fa_5tuple[1], &fa_5tuple[0],
459 sizeof (fa_5tuple[1])))
460 f_sess_id_next.
as_u64 = ~0ULL;
466 if (acl_check_needed)
487 saved_matched_acl_index,
489 saved_matched_ace_index,
492 saved_matched_acl_index = match_acl_in_index;
493 saved_matched_ace_index = match_rule_index;
494 saved_packet_count = 1;
495 saved_byte_count = buf_len;
498 saved_matched_acl_index,
500 saved_matched_ace_index);
513 sw_if_index[0], now);
517 u16 current_policy_epoch =
524 current_policy_epoch);
541 if ((f_sess_id_next.
as_u64 == ~0ULL)
542 && 0 == memcmp (&fa_5tuple[1], &fa_5tuple[0],
543 sizeof (fa_5tuple[1])))
544 f_sess_id_next = f_sess_id;
551 [ACL_FA_ERROR_ACL_TOO_MANY_SESSIONS];
561 next[0] = action ? next[0] : 0;
567 next[0], match_acl_in_index,
568 match_rule_index, &fa_5tuple[0], action,
586 saved_matched_acl_index,
588 saved_matched_ace_index,
589 saved_packet_count, saved_byte_count);
592 ACL_FA_ERROR_ACL_CHECK, frame->
n_vectors);
594 ACL_FA_ERROR_ACL_EXIST_SESSION,
597 ACL_FA_ERROR_ACL_NEW_SESSION,
600 ACL_FA_ERROR_ACL_PERMIT, pkts_acl_permit);
607 int is_ip6,
int is_input,
int is_l2_path,
608 int do_stateful_datapath)
613 is_l2_path, do_stateful_datapath);
619 is_l2_path, do_stateful_datapath,
624 is_l2_path, do_stateful_datapath, 0,
631 is_l2_path, do_stateful_datapath,
636 is_l2_path, do_stateful_datapath, 0, 0);
643 int is_input,
int is_l2_path)
669 void *format_address_func;
692 format (s,
"%U -> %U ", format_address_func, paddr0, format_address_func,
695 s =
format (s,
"tcp flags (%s) %02x rsvd %x",
701 #ifndef CLIB_MARCH_VARIANT 719 "acl-plugin: lc_index: %d, sw_if_index %d, next index %d, action: %d, match: acl %d rule %d trace_bits %08x\n" 720 " pkt info %016llx %016llx %016llx %016llx %016llx %016llx",
734 #define _(sym,string) string, 799 .name =
"acl-plugin-in-ip6-l2",
800 .vector_size =
sizeof (
u32),
814 .arc_name =
"l2-input-ip6",
815 .node_name =
"acl-plugin-in-ip6-l2",
821 .name =
"acl-plugin-in-ip4-l2",
822 .vector_size =
sizeof (
u32),
836 .arc_name =
"l2-input-ip4",
837 .node_name =
"acl-plugin-in-ip4-l2",
844 .name =
"acl-plugin-out-ip6-l2",
845 .vector_size =
sizeof (
u32),
859 .arc_name =
"l2-output-ip6",
860 .node_name =
"acl-plugin-out-ip6-l2",
867 .name =
"acl-plugin-out-ip4-l2",
868 .vector_size =
sizeof (
u32),
882 .arc_name =
"l2-output-ip4",
883 .node_name =
"acl-plugin-out-ip4-l2",
890 .name =
"acl-plugin-in-ip6-fa",
891 .vector_size =
sizeof (
u32),
905 .arc_name =
"ip6-unicast",
906 .node_name =
"acl-plugin-in-ip6-fa",
912 .name =
"acl-plugin-in-ip4-fa",
913 .vector_size =
sizeof (
u32),
927 .arc_name =
"ip4-unicast",
928 .node_name =
"acl-plugin-in-ip4-fa",
935 .name =
"acl-plugin-out-ip6-fa",
936 .vector_size =
sizeof (
u32),
950 .arc_name =
"ip6-output",
951 .node_name =
"acl-plugin-out-ip6-fa",
957 .name =
"acl-plugin-out-ip4-fa",
958 .vector_size =
sizeof (
u32),
973 .arc_name =
"ip4-output",
974 .node_name =
"acl-plugin-out-ip4-fa",
vlib_node_registration_t acl_in_l2_ip4_node
(constructor) VLIB_REGISTER_NODE (acl_in_l2_ip4_node)
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
u32 * input_policy_epoch_by_sw_if_index
u32 flags
buffer flags: VLIB_BUFFER_FREE_LIST_INDEX_MASK: bits used to store free list index, VLIB_BUFFER_IS_TRACED: trace this buffer.
static void acl_fill_5tuple(acl_main_t *am, u32 sw_if_index0, vlib_buffer_t *b0, int is_ip6, int is_input, int is_l2_path, fa_5tuple_t *p5tuple_pkt)
vlib_combined_counter_main_t * combined_acl_counters
static void maybe_trace_buffer(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_buffer_t *b, u32 sw_if_index0, u32 lc_index0, u16 next0, int match_acl_in_index, int match_rule_index, fa_5tuple_t *fa_5tuple, u8 action, u32 trace_bitmap)
static int acl_fa_conn_list_delete_session(acl_main_t *am, fa_full_session_id_t sess_id, u64 now)
vlib_node_registration_t acl_out_fa_ip4_node
(constructor) VLIB_REGISTER_NODE (acl_out_fa_ip4_node)
static void vlib_increment_combined_counter(vlib_combined_counter_main_t *cm, u32 thread_index, u32 index, u64 n_packets, u64 n_bytes)
Increment a combined counter.
vlib_node_registration_t acl_out_l2_ip6_node
(constructor) VLIB_REGISTER_NODE (acl_out_l2_ip6_node)
vlib_node_registration_t acl_in_fa_ip4_node
(constructor) VLIB_REGISTER_NODE (acl_in_fa_ip4_node)
static void make_session_hash_xN(int vector_sz, acl_main_t *am, int is_ip6, u32 *sw_if_index, fa_5tuple_t *fa_5tuple, u64 *out_hash)
u16 current_length
Nbytes between current data and the end of this buffer.
static u64 clib_cpu_time_now(void)
static int acl_fa_two_stage_delete_session(acl_main_t *am, u32 sw_if_index, fa_full_session_id_t sess_id, u64 now)
u32 * output_policy_epoch_by_sw_if_index
#define VLIB_NODE_FN(node)
vlib_error_t * errors
Vector of errors for this node.
static uword vlib_buffer_length_in_chain(vlib_main_t *vm, vlib_buffer_t *b)
Get length in bytes of the buffer chain.
u32 sw_if_indices[VLIB_FRAME_SIZE]
vlib_main_t ** vlib_mains
static void acl_fa_node_common_prepare_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6, int is_input, int is_l2_path, int with_stateful_datapath)
vlib_node_registration_t acl_in_fa_ip6_node
(constructor) VLIB_REGISTER_NODE (acl_in_fa_ip6_node)
static_always_inline void vnet_feature_next_u16(u16 *next0, vlib_buffer_t *b0)
vlib_node_registration_t acl_out_fa_ip6_node
(constructor) VLIB_REGISTER_NODE (acl_out_fa_ip6_node)
fa_5tuple_t fa_5tuples[VLIB_FRAME_SIZE]
description fragment has unexpected format
static void get_sw_if_index_xN(int vector_sz, int is_input, vlib_buffer_t **b, u32 *out_sw_if_index)
static char * acl_fa_error_strings[]
static u8 acl_fa_track_session(acl_main_t *am, int is_input, u32 sw_if_index, u64 now, fa_session_t *sess, fa_5tuple_t *pkt_5tuple, u32 pkt_len)
vl_api_fib_path_type_t type
static u64 acl_fa_make_session_hash(acl_main_t *am, int is_ip6, u32 sw_if_index0, fa_5tuple_t *p5tuple)
vlib_error_t error
Error code for buffers to be enqueued to error handler.
#define ACL_PLUGIN_VECTOR_SIZE
static uword acl_fa_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6, int is_input, int is_l2_path)
static void acl_fa_try_recycle_session(acl_main_t *am, int is_input, u16 thread_index, u32 sw_if_index, u64 now)
u64 * fa_session_epoch_change_by_sw_if_index
u32 * output_lc_index_by_sw_if_index
static int acl_fa_find_session_with_hash(acl_main_t *am, int is_ip6, u32 sw_if_index0, u64 hash, fa_5tuple_t *p5tuple, u64 *pvalue_sess)
static void vlib_prefetch_combined_counter(const vlib_combined_counter_main_t *cm, u32 thread_index, u32 index)
Pre-fetch a per-thread combined counter for the given object index.
u32 node_index
Node index.
static u16 get_current_policy_epoch(acl_main_t *am, int is_input, u32 sw_if_index0)
u64 hashes[VLIB_FRAME_SIZE]
u32 interface_acl_counters_enabled
static uword acl_fa_inner_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6, int is_input, int is_l2_path, int with_stateful_datapath, int node_trace_on, int reclassify_sessions)
#define FA_POLICY_EPOCH_IS_INPUT
static void vlib_node_increment_counter(vlib_main_t *vm, u32 node_index, u32 counter_index, u64 increment)
#define foreach_acl_fa_error
#define VLIB_REGISTER_NODE(x,...)
#define CLIB_PREFETCH(addr, size, type)
static_always_inline void vlib_buffer_enqueue_to_next(vlib_main_t *vm, vlib_node_runtime_t *node, u32 *buffers, u16 *nexts, uword count)
clib_bihash_kv_40_8_t kv_40_8
static fa_full_session_id_t acl_fa_add_session(acl_main_t *am, int is_input, int is_ip6, u32 sw_if_index, u64 now, fa_5tuple_t *p5tuple, u16 current_policy_epoch)
#define clib_warning(format, args...)
static vlib_node_runtime_t * vlib_node_get_runtime(vlib_main_t *vm, u32 node_index)
Get node runtime by node index.
VNET_FEATURE_INIT(acl_in_l2_ip6_fa_feature, static)
static int acl_fa_restart_timer_for_session(acl_main_t *am, u64 now, fa_full_session_id_t sess_id)
vlib_main_t vlib_node_runtime_t * node
static_always_inline u8 * format_fa_session_l4_key(u8 *s, va_list *args)
u16 nexts[VLIB_FRAME_SIZE]
static int fa_session_get_timeout_type(acl_main_t *am, fa_session_t *sess)
static int acl_plugin_match_5tuple_inline(void *p_acl_main, u32 lc_index, fa_5tuple_opaque_t *pkt_5tuple, int is_ip6, u8 *r_action, u32 *r_acl_pos_p, u32 *r_acl_match_p, u32 *r_rule_match_p, u32 *trace_bitmap)
static int stale_session_deleted(acl_main_t *am, int is_input, acl_fa_per_worker_data_t *pw, u64 now, u32 sw_if_index0, fa_full_session_id_t f_sess_id)
static uword acl_fa_outer_node_fn(vlib_main_t *vm, vlib_node_runtime_t *node, vlib_frame_t *frame, int is_ip6, int is_input, int is_l2_path, int do_stateful_datapath)
static void acl_fa_prefetch_session_bucket_for_hash(acl_main_t *am, int is_ip6, u64 hash)
static int acl_fa_can_add_session(acl_main_t *am, int is_input, u32 sw_if_index)
#define VNET_FEATURES(...)
#define vec_elt(v, i)
Get vector value at index i.
static void prefetch_session_entry(acl_main_t *am, fa_full_session_id_t f_sess_id)
vlib_node_registration_t acl_out_l2_ip4_node
(constructor) VLIB_REGISTER_NODE (acl_out_l2_ip4_node)
static fa_session_t * get_session_ptr_no_check(acl_main_t *am, u16 thread_index, u32 session_index)
vl_api_mac_event_action_t action
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static void fill_5tuple_xN(int vector_sz, acl_main_t *am, int is_ip6, int is_input, int is_l2_path, vlib_buffer_t **b, u32 *sw_if_index, fa_5tuple_t *out_fa_5tuple)
vlib_main_t vlib_node_runtime_t vlib_frame_t * frame
VLIB buffer representation.
acl_fa_per_worker_data_t * per_worker_data
static void * vlib_frame_vector_args(vlib_frame_t *f)
Get pointer to frame vector data.
static_always_inline uword os_get_thread_index(void)
static u8 process_established_session(vlib_main_t *vm, acl_main_t *am, u32 counter_node_index, int is_input, u64 now, fa_full_session_id_t f_sess_id, u32 *sw_if_index, fa_5tuple_t *fa_5tuple, u32 pkt_len, int node_trace_on, u32 *trace_bitmap)
#define ACL_PLUGIN_PREFETCH_GAP
static u8 * format_fa_5tuple(u8 *s, va_list *args)
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)
ip4_address_t ip4_addr[2]
u8 * format_acl_plugin_5tuple(u8 *s, va_list *args)
u32 * input_lc_index_by_sw_if_index
vlib_buffer_t * bufs[VLIB_FRAME_SIZE]
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
#define CLIB_CACHE_LINE_BYTES
static u8 * format_acl_plugin_trace(u8 *s, va_list *args)
static void acl_fa_prefetch_session_data_for_hash(acl_main_t *am, int is_ip6, u64 hash)
int fa_sessions_hash_is_initialized
vl_api_interface_index_t sw_if_index
vlib_node_registration_t acl_in_l2_ip6_node
(constructor) VLIB_REGISTER_NODE (acl_in_l2_ip6_node)
ip6_address_t ip6_addr[2]