return error;
}
+static clib_error_t *
+flowprobe_clear_state_if_index (u32 sw_if_index)
+{
+ flowprobe_main_t *fm = &flowprobe_main;
+ clib_error_t *error = 0;
+ u32 worker_i;
+ u32 entry_i;
+
+ if (fm->active_timer > 0)
+ {
+ vec_foreach_index (worker_i, fm->pool_per_worker)
+ {
+ pool_foreach_index (entry_i, fm->pool_per_worker[worker_i])
+ {
+ flowprobe_entry_t *e =
+ pool_elt_at_index (fm->pool_per_worker[worker_i], entry_i);
+ if (e->key.rx_sw_if_index == sw_if_index ||
+ e->key.tx_sw_if_index == sw_if_index)
+ {
+ if (fm->passive_timer > 0)
+ {
+ tw_timer_stop_2t_1w_2048sl (
+ fm->timers_per_worker[worker_i],
+ e->passive_timer_handle);
+ }
+ flowprobe_delete_by_index (worker_i, entry_i);
+ }
+ }
+ }
+ }
+
+ return error;
+}
+
static int
validate_feature_on_interface (flowprobe_main_t * fm, u32 sw_if_index,
u8 which)
{
if (which == FLOW_VARIANT_L2)
{
+ if (!is_add)
+ {
+ flowprobe_flush_callback_l2 ();
+ }
if (fm->record & FLOW_RECORD_L2)
{
rv = flowprobe_template_add_del (1, UDP_DST_PORT_ipfix, flags,
}
else if (which == FLOW_VARIANT_IP4)
{
+ if (!is_add)
+ {
+ flowprobe_flush_callback_ip4 ();
+ }
rv = flowprobe_template_add_del (
1, UDP_DST_PORT_ipfix, flags, flowprobe_data_callback_ip4,
flowprobe_template_rewrite_ip4, is_add, &template_id);
}
else if (which == FLOW_VARIANT_IP6)
{
+ if (!is_add)
+ {
+ flowprobe_flush_callback_ip6 ();
+ }
rv = flowprobe_template_add_del (
1, UDP_DST_PORT_ipfix, flags, flowprobe_data_callback_ip6,
flowprobe_template_rewrite_ip6, is_add, &template_id);
vlib_process_signal_event (vm, flowprobe_timer_node.index, 1, 0);
}
+ if (!is_add && fm->initialized)
+ {
+ flowprobe_clear_state_if_index (sw_if_index);
+ }
+
return 0;
}
ipfix.remove_vpp_config()
self.logger.info("FFP_TEST_FINISH_0001")
+ def test_no_leftover_flows_after_disabling(self):
+ """disable flowprobe feature and expect no leftover flows"""
+ self.pg_enable_capture(self.pg_interfaces)
+ self.pkts = []
+
+ # enable ip4 datapath for an interface
+ # set active and passive timers
+ ipfix = VppCFLOW(
+ test=self,
+ active=3,
+ passive=4,
+ intf="pg3",
+ layer="l3",
+ datapath="ip4",
+ direction="rx",
+ mtu=100,
+ )
+ ipfix.add_vpp_config()
+
+ # template packet should arrive immediately
+ ipfix.verify_templates(count=1)
+
+ # send some ip4 packets
+ self.create_stream(src_if=self.pg3, dst_if=self.pg4, packets=5)
+ self.send_packets(src_if=self.pg3, dst_if=self.pg4)
+
+ # disable feature for the interface
+ # currently stored ip4 flows should be removed
+ ipfix.disable_flowprobe_feature()
+
+ # no leftover ip4 flows are expected
+ self.pg_enable_capture([self.collector])
+ self.sleep(12, "wait for leftover ip4 flows during three passive intervals")
+ self.collector.assert_nothing_captured()
+
+ # cleanup
+ ipfix.disable_exporter()
+
@unittest.skipUnless(config.extended, "part of extended tests")
class ReenableFP(MethodHolder):