summaryrefslogtreecommitdiffstats
path: root/src/plugins/acl/fa_node.c
diff options
context:
space:
mode:
authorAndrew Yourtchenko <ayourtch@gmail.com>2018-03-28 14:33:48 +0200
committerDamjan Marion <dmarion.lists@gmail.com>2018-03-30 20:48:01 +0000
commit17ddc0fee1bc20d0da84dd70bb579c8844a48ef4 (patch)
tree1b7444cfc8a6ff4fad13a5fed69d8503ae8cf7af /src/plugins/acl/fa_node.c
parent6091d230e3786c635eea3513d73af45081a5770c (diff)
acl-plugin: implement an optional session reclassification when ACL is (re-)applied
There were several discussions in which users would expect the sessions to be deleted if the new policy after the change does not permit them. There is no right or wrong answer to this question - it is a policy decision. This patch implements an idea to approach this. It uses a per-interface-per-direction counter to designate a "policy epoch" - a period of unchanging rulesets. The moment one removes or adds an ACL applied to an interface, this counter increments. The newly created connections inherit the current policy epoch in a given direction. Likewise, this counter increments if anyone updates an ACL applied to an interface. There is also a new (so far hidden) CLI "set acl-plugin reclassify-sessions [0|1]" (with default being 0) which allows to enable the checking of the existing sessions against the current policy epoch in a given direction. The session is not verified unless there is traffic hitting that session *in the direction of the policy creation* - if the epoch has changed, the session is deleted and within the same processing cycle is evaluated against the ACL rule base and recreated - thus, it should allow traffic-driven session state refresh without affecting the connectivity for the existing sessions. If the packet is coming in the direction opposite to which the session was initially created, the state adjustment is never done, because doing so generically is not really possible without diving too deep into the special cases, which may or may not work. Change-Id: I9e90426492d4bd474b5e89ea8dfb75a7c9de2646 Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
Diffstat (limited to 'src/plugins/acl/fa_node.c')
-rw-r--r--src/plugins/acl/fa_node.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/plugins/acl/fa_node.c b/src/plugins/acl/fa_node.c
index d29576a4bce..833b0fa1523 100644
--- a/src/plugins/acl/fa_node.c
+++ b/src/plugins/acl/fa_node.c
@@ -589,7 +589,7 @@ acl_fa_try_recycle_session (acl_main_t * am, int is_input, u16 thread_index, u32
static fa_session_t *
acl_fa_add_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now,
- fa_5tuple_t * p5tuple)
+ fa_5tuple_t * p5tuple, u16 current_policy_epoch)
{
clib_bihash_kv_40_8_t *pkv = &p5tuple->kv;
clib_bihash_kv_40_8_t kv;
@@ -603,6 +603,7 @@ acl_fa_add_session (acl_main_t * am, int is_input, u32 sw_if_index, u64 now,
pool_get_aligned (pw->fa_sessions_pool, sess, CLIB_CACHE_LINE_BYTES);
f_sess_id.session_index = sess - pw->fa_sessions_pool;
+ f_sess_id.intf_policy_epoch = current_policy_epoch;
kv.key[0] = pkv->key[0];
kv.key[1] = pkv->key[1];
@@ -662,6 +663,7 @@ acl_fa_node_fn (vlib_main_t * vm,
vlib_node_runtime_t *error_node;
u64 now = clib_cpu_time_now ();
uword thread_index = os_get_thread_index ();
+ acl_fa_per_worker_data_t *pw = &am->per_worker_data[thread_index];
from = vlib_frame_vector_args (frame);
n_left_from = frame->n_vectors;
@@ -709,6 +711,10 @@ acl_fa_node_fn (vlib_main_t * vm,
lc_index0 = am->input_lc_index_by_sw_if_index[sw_if_index0];
else
lc_index0 = am->output_lc_index_by_sw_if_index[sw_if_index0];
+
+ u32 **p_epoch_vec = is_input ? &am->input_policy_epoch_by_sw_if_index
+ : &am->output_policy_epoch_by_sw_if_index;
+ u16 current_policy_epoch = sw_if_index0 < vec_len(*p_epoch_vec) ? vec_elt(*p_epoch_vec, sw_if_index0) : (is_input * FA_POLICY_EPOCH_IS_INPUT);
/*
* Extract the L3/L4 matching info into a 5-tuple structure,
* then create a session key whose layout is independent on forward or reverse
@@ -782,6 +788,21 @@ acl_fa_node_fn (vlib_main_t * vm,
acl_check_needed = 0;
action = 0;
}
+ if (PREDICT_FALSE(am->reclassify_sessions)) {
+ /* if the MSB of policy epoch matches but not the LSB means it is a stale session */
+ if ( (0 == ((current_policy_epoch ^ f_sess_id.intf_policy_epoch) & FA_POLICY_EPOCH_IS_INPUT))
+ && (current_policy_epoch != f_sess_id.intf_policy_epoch) ) {
+ /* delete session and increment the counter */
+ vec_validate (pw->fa_session_epoch_change_by_sw_if_index, sw_if_index0);
+ vec_elt (pw->fa_session_epoch_change_by_sw_if_index, sw_if_index0)++;
+ if(acl_fa_conn_list_delete_session(am, f_sess_id)) {
+ /* delete the session only if we were able to unlink it */
+ acl_fa_delete_session (am, sw_if_index0, f_sess_id);
+ }
+ acl_check_needed = 1;
+ trace_bitmap |= 0x40000000;
+ }
+ }
}
}
@@ -804,7 +825,7 @@ acl_fa_node_fn (vlib_main_t * vm,
if (PREDICT_TRUE (valid_new_sess)) {
fa_session_t *sess = acl_fa_add_session (am, is_input,
sw_if_index0,
- now, &kv_sess);
+ now, &kv_sess, current_policy_epoch);
acl_fa_track_session (am, is_input, sw_if_index0, now,
sess, &fa_5tuple);
pkts_new_session += 1;