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:
parent
3220d9f16b
commit
2d1a62bfdd
@ -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);
|
||||
|
@ -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
@ -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
@ -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")
|
||||
|
@ -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;
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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")
|
||||
|
Loading…
x
Reference in New Issue
Block a user