+ if (acl_fa_can_add_session (am, is_input, sw_if_index[0]))
+ {
+ u16 current_policy_epoch =
+ get_current_policy_epoch (am, is_input,
+ sw_if_index[0]);
+ fa_full_session_id_t f_sess_id =
+ acl_fa_add_session (am, is_input, is_ip6,
+ sw_if_index[0],
+ now, &fa_5tuple[0],
+ current_policy_epoch);
+
+ /* perform the accounting for the newly added session */
+ process_established_session (vm, am,
+ node->node_index,
+ is_input, now,
+ f_sess_id,
+ &sw_if_index[0],
+ &fa_5tuple[0],
+ b[0]->current_length,
+ node_trace_on,
+ &trace_bitmap);
+ pkts_new_session++;
+ /*
+ * If the next 5tuple is the same and we just added the session,
+ * the f_sess_id_next can not be ~0. Correct it.
+ */
+ if ((f_sess_id_next.as_u64 == ~0ULL)
+ && 0 == memcmp (&fa_5tuple[1], &fa_5tuple[0],
+ sizeof (fa_5tuple[1])))
+ f_sess_id_next = f_sess_id;
+ }
+ else
+ {
+ action = 0;
+ b[0]->error =
+ error_node->errors
+ [ACL_FA_ERROR_ACL_TOO_MANY_SESSIONS];
+ }
+ }
+
+ }
+
+ {
+ u32 next0;
+ /* speculatively get the next0 */
+ vnet_feature_next (&next0, b[0]);
+ /* if the action is not deny - then use that next */
+ next[0] = action ? next0 : 0;
+ }
+
+ if (node_trace_on) // PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
+ {
+ maybe_trace_buffer (vm, node, b[0], sw_if_index[0], lc_index0,
+ next[0], match_acl_in_index,
+ match_rule_index, &fa_5tuple[0], action,
+ trace_bitmap);
+ }
+
+ next++;
+ b++;
+ fa_5tuple++;
+ sw_if_index++;
+ hash++;
+ n_left -= 1;
+ }
+ }
+
+ vlib_buffer_enqueue_to_next (vm, node, from, pw->nexts, frame->n_vectors);
+
+ /*
+ * if we were had an acl match then we have a counter to increment.
+ * else it is all zeroes, so this will be harmless.
+ */
+ vlib_increment_combined_counter (am->combined_acl_counters +
+ saved_matched_acl_index,
+ thread_index,
+ saved_matched_ace_index,
+ saved_packet_count, saved_byte_count);
+
+ vlib_node_increment_counter (vm, node->node_index,
+ ACL_FA_ERROR_ACL_CHECK, frame->n_vectors);
+ vlib_node_increment_counter (vm, node->node_index,
+ ACL_FA_ERROR_ACL_EXIST_SESSION,
+ pkts_exist_session);
+ vlib_node_increment_counter (vm, node->node_index,
+ ACL_FA_ERROR_ACL_NEW_SESSION,
+ pkts_new_session);
+ vlib_node_increment_counter (vm, node->node_index,
+ ACL_FA_ERROR_ACL_PERMIT, pkts_acl_permit);
+ return frame->n_vectors;
+}
+
+always_inline 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)
+{
+ acl_main_t *am = &acl_main;
+
+ acl_fa_node_common_prepare_fn (vm, node, frame, is_ip6, is_input,
+ is_l2_path, do_stateful_datapath);
+
+ if (am->reclassify_sessions)
+ {
+ if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
+ return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
+ is_l2_path, do_stateful_datapath,
+ 1 /* trace */ ,
+ 1 /* reclassify */ );
+ else
+ return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
+ is_l2_path, do_stateful_datapath, 0,
+ 1 /* reclassify */ );
+ }
+ else
+ {
+ if (PREDICT_FALSE (node->flags & VLIB_NODE_FLAG_TRACE))
+ return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
+ is_l2_path, do_stateful_datapath,
+ 1 /* trace */ ,
+ 0);
+ else
+ return acl_fa_inner_node_fn (vm, node, frame, is_ip6, is_input,
+ is_l2_path, do_stateful_datapath, 0, 0);
+ }