policer: API policer selection by index

Policer API calls were only by policer name. It is now possible to
select a policer by its index.
Some functionalities are also added to allow updating a policer
configuration and to refill its token buckets.
Some dead codes are being removed, and small fixes made.

Type: improvement

Signed-off-by: Maxime Peim <mpeim@cisco.com>
Change-Id: I4cc8fda0fc7c635a4110da3e757356b150f9b606
This commit is contained in:
Maxime Peim 2023-01-06 11:57:38 +00:00 committed by Neale Ranns
parent 3220d9f16b
commit 2d1a62bfdd
10 changed files with 923 additions and 285 deletions

View File

@ -73,8 +73,6 @@ typedef enum
typedef struct
{
CLIB_CACHE_LINE_ALIGN_MARK (cacheline0);
u32 lock; // for exclusive access to the struct
u32 single_rate; // 1 = single rate policer, 0 = two rate policer
u32 color_aware; // for hierarchical policing
u32 scale; // power-of-2 shift amount for lower rates
@ -93,11 +91,9 @@ typedef struct
u32 current_bucket; // MOD
u32 extended_limit;
u32 extended_bucket; // MOD
u64 last_update_time; // MOD
u32 thread_index; // Tie policer to a thread, rather than lock
u32 pad32;
u64 last_update_time; // MOD
u8 *name;
} policer_t;
STATIC_ASSERT_SIZEOF (policer_t, CLIB_CACHE_LINE_BYTES);

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
option version = "2.0.0";
option version = "3.0.0";
import "vnet/interface_types.api";
import "vnet/policer/policer_types.api";
@ -35,6 +35,16 @@ autoreply define policer_bind
bool bind_enable;
};
autoreply define policer_bind_v2
{
u32 client_index;
u32 context;
u32 policer_index;
u32 worker_index;
bool bind_enable;
};
/** \brief policer input: Apply policer as an input feature.
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@ -52,6 +62,16 @@ autoreply define policer_input
bool apply;
};
autoreply define policer_input_v2
{
u32 client_index;
u32 context;
u32 policer_index;
vl_api_interface_index_t sw_if_index;
bool apply;
};
/** \brief policer output: Apply policer as an output feature.
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@ -69,6 +89,16 @@ autoreply define policer_output
bool apply;
};
autoreply define policer_output_v2
{
u32 client_index;
u32 context;
u32 policer_index;
vl_api_interface_index_t sw_if_index;
bool apply;
};
/** \brief Add/del policer
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@ -106,6 +136,40 @@ define policer_add_del
vl_api_sse2_qos_action_t violate_action;
};
define policer_add
{
u32 client_index;
u32 context;
string name[64];
vl_api_policer_config_t infos;
};
autoreply define policer_del
{
u32 client_index;
u32 context;
u32 policer_index;
};
autoreply define policer_update
{
u32 client_index;
u32 context;
u32 policer_index;
vl_api_policer_config_t infos;
};
autoreply define policer_reset
{
u32 client_index;
u32 context;
u32 policer_index;
};
/** \brief Add/del policer response
@param context - sender context, to match reply w/ request
@param retval - return value for request
@ -118,6 +182,13 @@ define policer_add_del_reply
u32 policer_index;
};
define policer_add_reply
{
u32 context;
i32 retval;
u32 policer_index;
};
/** \brief Get list of policers
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@ -133,6 +204,23 @@ define policer_dump
string match_name[64];
};
/** \brief Get list of policers
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
@param policer_index - index of policer in the pool, ~0 to request all
*/
define policer_dump_v2
{
u32 client_index;
u32 context;
u32 policer_index;
};
service {
rpc policer_dump_v2 returns stream policer_details;
};
/** \brief Policer operational state response.
@param context - sender context, to match reply w/ request
@param name - policer name

File diff suppressed because it is too large Load Diff

View File

@ -32,7 +32,7 @@ typedef struct
qos_pol_cfg_params_st *configs;
policer_t *policer_templates;
/* Config by name hash */
/* Config by policer name hash */
uword *policer_config_by_name;
/* Policer by name hash */
@ -68,11 +68,16 @@ typedef enum
} vnet_policer_next_t;
u8 *format_policer_instance (u8 * s, va_list * va);
clib_error_t *policer_add_del (vlib_main_t *vm, u8 *name,
qos_pol_cfg_params_st *cfg, u32 *policer_index,
u8 is_add);
int policer_bind_worker (u8 *name, u32 worker, bool bind);
int policer_input (u8 *name, u32 sw_if_index, vlib_dir_t dir, bool apply);
int policer_add (vlib_main_t *vm, const u8 *name,
const qos_pol_cfg_params_st *cfg, u32 *policer_index);
int policer_update (vlib_main_t *vm, u32 policer_index,
const qos_pol_cfg_params_st *cfg);
int policer_del (vlib_main_t *vm, u32 policer_index);
int policer_reset (vlib_main_t *vm, u32 policer_index);
int policer_bind_worker (u32 policer_index, u32 worker, bool bind);
int policer_input (u32 policer_index, u32 sw_if_index, vlib_dir_t dir,
bool apply);
#endif /* __included_policer_h__ */

File diff suppressed because it is too large Load Diff

View File

@ -56,6 +56,34 @@ typedef sse2_qos_action
u8 dscp;
};
/** \brief Policer configuration
@param cir - CIR
@param eir - EIR
@param cb - Committed Burst
@param eb - Excess or Peak Burst
@param rate_type - rate type
@param round_type - rounding type
@param type - policer algorithm
@param color_aware - 0=color-blind, 1=color-aware
@param conform_action - conform action
@param exceed_action - exceed action type
@param violate_action - violate action type
*/
typedef policer_config
{
u32 cir;
u32 eir;
u64 cb;
u64 eb;
vl_api_sse2_qos_rate_type_t rate_type;
vl_api_sse2_qos_round_type_t round_type;
vl_api_sse2_qos_policer_type_t type;
bool color_aware;
vl_api_sse2_qos_action_t conform_action;
vl_api_sse2_qos_action_t exceed_action;
vl_api_sse2_qos_action_t violate_action;
};
/*
* Local Variables:
* eval: (c-set-style "gnu")

View File

@ -1058,7 +1058,7 @@ x86_pol_compute_hw_params (qos_pol_cfg_params_st *cfg, policer_t *hw)
* Return: Status, success or failure code.
*/
int
pol_logical_2_physical (qos_pol_cfg_params_st *cfg, policer_t *phys)
pol_logical_2_physical (const qos_pol_cfg_params_st *cfg, policer_t *phys)
{
int rc;
qos_pol_cfg_params_st kbps_cfg;

View File

@ -158,7 +158,7 @@ typedef struct qos_pol_hw_params_st_
u32 extd_bkt;
} qos_pol_hw_params_st;
int pol_logical_2_physical (qos_pol_cfg_params_st *cfg, policer_t *phys);
int pol_logical_2_physical (const qos_pol_cfg_params_st *cfg, policer_t *phys);
#endif /* __included_xlate_h__ */

View File

@ -92,6 +92,85 @@ class TestPolicerInput(VppTestCase):
"""Output Policing"""
self.policer_interface_test(Dir.TX)
def test_policer_reset(self):
"""Policer reset bucket"""
pkts = self.pkt * NUM_PKTS
action_tx = PolicerAction(
VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
)
policer = VppPolicer(
self,
"pol1",
1,
0,
10000,
0,
conform_action=action_tx,
exceed_action=action_tx,
violate_action=action_tx,
)
policer.add_vpp_config()
# Start policing on pg0
policer.apply_vpp_config(self.pg0.sw_if_index, Dir.RX, True)
self.send_and_expect(self.pg0, pkts, self.pg1, worker=0)
details = policer.get_details()
self.assertGreater(details.current_limit, details.current_bucket)
self.send_and_expect(self.pg0, pkts, self.pg1, worker=0)
self.vapi.policer_reset(policer_index=policer.policer_index)
details = policer.get_details()
self.assertEqual(details.current_limit, details.current_bucket)
policer.apply_vpp_config(self.pg0.sw_if_index, Dir.RX, False)
policer.remove_vpp_config()
def test_policer_update(self):
"""Policer update"""
pkts = self.pkt * NUM_PKTS
action_tx = PolicerAction(
VppEnum.vl_api_sse2_qos_action_type_t.SSE2_QOS_ACTION_API_TRANSMIT, 0
)
policer = VppPolicer(
self,
"pol1",
1,
0,
10000,
0,
conform_action=action_tx,
exceed_action=action_tx,
violate_action=action_tx,
)
policer.add_vpp_config()
# Start policing on pg0
policer.apply_vpp_config(self.pg0.sw_if_index, Dir.RX, True)
self.send_and_expect(self.pg0, pkts, self.pg1, worker=0)
details_before = policer.get_details()
self.assertGreater(details_before.current_limit, details_before.current_bucket)
policer.cir = 8000
policer.commited_burst = 100000
policer.update()
details_after = policer.get_details()
self.assertGreater(details_after.cir, details_before.cir)
self.assertGreater(details_after.cb, details_before.cb)
policer.apply_vpp_config(self.pg0.sw_if_index, Dir.RX, False)
policer.remove_vpp_config()
def policer_handoff_test(self, dir: Dir):
pkts = self.pkt * NUM_PKTS

View File

@ -57,46 +57,54 @@ class VppPolicer(VppObject):
def policer_index(self):
return self._policer_index
@property
def config(self):
return {
"cir": self.cir,
"eir": self.eir,
"cb": self.commited_burst,
"eb": self.excess_burst,
"rate_type": self.rate_type,
"round_type": self.round_type,
"type": self.type,
"color_aware": self.color_aware,
"conform_action": self.conform_action.encode(),
"exceed_action": self.exceed_action.encode(),
"violate_action": self.violate_action.encode(),
}
def add_vpp_config(self):
r = self._test.vapi.policer_add_del(
name=self.name,
cir=self.cir,
eir=self.eir,
cb=self.commited_burst,
eb=self.excess_burst,
rate_type=self.rate_type,
round_type=self.round_type,
type=self.type,
color_aware=self.color_aware,
conform_action=self.conform_action.encode(),
exceed_action=self.exceed_action.encode(),
violate_action=self.violate_action.encode(),
)
r = self._test.vapi.policer_add(name=self.name, infos=self.config)
self._test.registry.register(self, self._test.logger)
self._policer_index = r.policer_index
return self
def update(self):
self._test.vapi.policer_update(
policer_index=self._policer_index, infos=self.config
)
def remove_vpp_config(self):
self._test.vapi.policer_add_del(is_add=False, name=self.name)
self._test.vapi.policer_del(policer_index=self._policer_index)
self._policer_index = INVALID_INDEX
def bind_vpp_config(self, worker, bind):
self._test.vapi.policer_bind(
name=self.name, worker_index=worker, bind_enable=bind
self._test.vapi.policer_bind_v2(
policer_index=self._policer_index, worker_index=worker, bind_enable=bind
)
def apply_vpp_config(self, if_index, dir: Dir, apply):
if dir == Dir.RX:
self._test.vapi.policer_input(
name=self.name, sw_if_index=if_index, apply=apply
self._test.vapi.policer_input_v2(
policer_index=self._policer_index, sw_if_index=if_index, apply=apply
)
else:
self._test.vapi.policer_output(
name=self.name, sw_if_index=if_index, apply=apply
self._test.vapi.policer_output_v2(
policer_index=self._policer_index, sw_if_index=if_index, apply=apply
)
def query_vpp_config(self):
dump = self._test.vapi.policer_dump(match_name_valid=True, match_name=self.name)
dump = self._test.vapi.policer_dump_v2(policer_index=self._policer_index)
for policer in dump:
if policer.name == self.name:
return True
@ -105,6 +113,13 @@ class VppPolicer(VppObject):
def object_id(self):
return "policer-%s" % (self.name)
def get_details(self):
dump = self._test.vapi.policer_dump_v2(policer_index=self._policer_index)
for policer in dump:
if policer.name == self.name:
return policer
raise self._test.vapi.VPPValueError("Missing policer")
def get_stats(self, worker=None):
conform = self._test.statistics.get_counter("/net/policer/conform")
exceed = self._test.statistics.get_counter("/net/policer/exceed")