diff options
author | Andrew Yourtchenko <ayourtch@gmail.com> | 2017-06-21 11:24:25 +0200 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2017-06-21 20:31:44 +0000 |
commit | eb46754ef6b3efd958a11ea2f0b110eb99ce3b27 (patch) | |
tree | 2aae6193381512af33205c323cf56c0299cfdfc6 | |
parent | a2b4ac1c13559b1cdf5088edfad4a68022960b00 (diff) |
acl-plugin: CLI to clear all sessions
It is useful to have the CLI to clear the existing sessions.
There was a work-in-progress CLI but it did not work properly.
Fix it and split into a separate "clear acl-plugin sessions",
and add a unit test into the extended connection-oriented tests.
Change-Id: I55889165ebcee139841fdac88747390903a05394
Signed-off-by: Andrew Yourtchenko <ayourtch@gmail.com>
-rw-r--r-- | src/plugins/acl/acl.c | 23 | ||||
-rw-r--r-- | src/plugins/acl/fa_node.c | 23 | ||||
-rw-r--r-- | test/test_acl_plugin_conns.py | 37 |
3 files changed, 75 insertions, 8 deletions
diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index ae1cbf714c1..d9f22d826d4 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -1828,12 +1828,6 @@ acl_set_aclplugin_fn (vlib_main_t * vm, goto done; } if (unformat (input, "session")) { - if (unformat (input, "clear")) { - acl_main_t *am = &acl_main; - vlib_process_signal_event (am->vlib_main, am->fa_cleaner_node_index, - ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX, ~0); - goto done; - } if (unformat (input, "table")) { /* The commands here are for tuning/testing. No user-serviceable parts inside */ if (unformat (input, "max-entries")) { @@ -2189,6 +2183,17 @@ acl_show_aclplugin_fn (vlib_main_t * vm, return error; } +static clib_error_t * +acl_clear_aclplugin_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + clib_error_t *error = 0; + acl_main_t *am = &acl_main; + vlib_process_signal_event (am->vlib_main, am->fa_cleaner_node_index, + ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX, ~0); + return error; +} /* *INDENT-OFF* */ VLIB_CLI_COMMAND (aclplugin_set_command, static) = { @@ -2202,6 +2207,12 @@ VLIB_CLI_COMMAND (aclplugin_show_command, static) = { .short_help = "show acl-plugin {sessions|acl|interface|tables}", .function = acl_show_aclplugin_fn, }; + +VLIB_CLI_COMMAND (aclplugin_clear_command, static) = { + .path = "clear acl-plugin sessions", + .short_help = "clear acl-plugin sessions", + .function = acl_clear_aclplugin_fn, +}; /* *INDENT-ON* */ diff --git a/src/plugins/acl/fa_node.c b/src/plugins/acl/fa_node.c index e89c47e288e..c0ff1a5e01a 100644 --- a/src/plugins/acl/fa_node.c +++ b/src/plugins/acl/fa_node.c @@ -1465,6 +1465,7 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, { uword *clear_sw_if_index_bitmap = 0; uword *sw_if_index0; + int clear_all = 0; #ifdef FA_NODE_VERBOSE_DEBUG clib_warning("ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX received"); #endif @@ -1476,7 +1477,17 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, ("ACL_FA_NODE_CLEAN: ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX: %d", *sw_if_index0); #endif - clear_sw_if_index_bitmap = clib_bitmap_set(clear_sw_if_index_bitmap, *sw_if_index0, 1); + if (*sw_if_index0 == ~0) + { + clear_all = 1; + } + else + { + if (!pool_is_free_index (am->vnet_main->interface_main.sw_interfaces, *sw_if_index0)) + { + clear_sw_if_index_bitmap = clib_bitmap_set(clear_sw_if_index_bitmap, *sw_if_index0, 1); + } + } } #ifdef FA_NODE_VERBOSE_DEBUG clib_warning("ACL_FA_CLEANER_DELETE_BY_SW_IF_INDEX bitmap: %U", format_bitmap_hex, clear_sw_if_index_bitmap); @@ -1496,7 +1507,15 @@ acl_fa_session_cleaner_process (vlib_main_t * vm, vlib_node_runtime_t * rt, if (pw0->clear_in_process) { clib_warning("ERROR-BUG! Could not initiate cleaning on worker because another cleanup in progress"); } else { - pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(clear_sw_if_index_bitmap); + if (clear_all) + { + /* if we need to clear all, then just clear the interfaces that we are servicing */ + pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(pw0->serviced_sw_if_index_bitmap); + } + else + { + pw0->pending_clear_sw_if_index_bitmap = clib_bitmap_dup(clear_sw_if_index_bitmap); + } pw0->clear_in_process = 1; } } diff --git a/test/test_acl_plugin_conns.py b/test/test_acl_plugin_conns.py index 705ffbc6191..1a9100cb0d7 100644 --- a/test/test_acl_plugin_conns.py +++ b/test/test_acl_plugin_conns.py @@ -279,6 +279,27 @@ class ACLPluginConnTestCase(VppTestCase): # If it didn't - it is a problem self.assert_equal(p2, None, "packet on long-idle conn") + def run_clear_conn_test(self, af, acl_side): + """ Clear the connections via CLI """ + conn1 = Conn(self, self.pg0, self.pg1, af, UDP, 42001, 4242) + conn1.apply_acls(0, acl_side) + conn1.send_through(0) + # the return packets should pass + conn1.send_through(1) + # send some packets on conn1, ensure it doesn't go away + for i in IterateWithSleep(self, 20, "Keep conn active", 0.3): + conn1.send_through(1) + # clear all connections + self.vapi.ppcli("clear acl-plugin sessions") + # now try to send a packet on the reflected side + try: + p2 = conn1.send_through(1).command() + except: + # If we asserted while waiting, it's good. + # the conn should have timed out. + p2 = None + self.assert_equal(p2, None, "packet on supposedly deleted conn") + def test_0000_conn_prepare_test(self): """ Prepare the settings """ self.vapi.ppcli("set acl-plugin session timeout udp idle 1") @@ -291,6 +312,14 @@ class ACLPluginConnTestCase(VppTestCase): """ IPv4: Basic conn timeout test reflect on egress """ self.run_basic_conn_test(AF_INET, 1) + def test_0005_clear_conn_test(self): + """ IPv4: reflect egress, clear conn """ + self.run_clear_conn_test(AF_INET, 1) + + def test_0006_clear_conn_test(self): + """ IPv4: reflect ingress, clear conn """ + self.run_clear_conn_test(AF_INET, 0) + def test_0011_active_conn_test(self): """ IPv4: Idle conn behind active conn, reflect on ingress """ self.run_active_conn_test(AF_INET, 0) @@ -307,6 +336,14 @@ class ACLPluginConnTestCase(VppTestCase): """ IPv6: Basic conn timeout test reflect on egress """ self.run_basic_conn_test(AF_INET6, 1) + def test_1005_clear_conn_test(self): + """ IPv6: reflect egress, clear conn """ + self.run_clear_conn_test(AF_INET6, 1) + + def test_1006_clear_conn_test(self): + """ IPv6: reflect ingress, clear conn """ + self.run_clear_conn_test(AF_INET6, 0) + def test_1011_active_conn_test(self): """ IPv6: Idle conn behind active conn, reflect on ingress """ self.run_active_conn_test(AF_INET6, 0) |