diff options
-rw-r--r-- | vnet/Makefile.am | 2 | ||||
-rw-r--r-- | vnet/vnet/policer/policer.c | 95 | ||||
-rw-r--r-- | vnet/vnet/policer/policer.h | 3 | ||||
-rw-r--r-- | vpp-api-test/vat/api_format.c | 129 | ||||
-rw-r--r-- | vpp/api/api.c | 34 | ||||
-rw-r--r-- | vpp/api/vpe.api | 37 |
6 files changed, 253 insertions, 47 deletions
diff --git a/vnet/Makefile.am b/vnet/Makefile.am index 8a9f214ca70..dddcdbfed63 100644 --- a/vnet/Makefile.am +++ b/vnet/Makefile.am @@ -58,6 +58,8 @@ libvnet_la_SOURCES += \ nobase_include_HEADERS += \ vnet/policer/police.h \ + vnet/policer/policer.h \ + vnet/policer/fix_types.h \ vnet/policer/xlate.h ######################################## diff --git a/vnet/vnet/policer/policer.c b/vnet/vnet/policer/policer.c index 2dbd02b3d0a..9e98de17cc8 100644 --- a/vnet/vnet/policer/policer.c +++ b/vnet/vnet/policer/policer.c @@ -15,6 +15,56 @@ #include <stdint.h> #include <vnet/policer/policer.h> +clib_error_t * +policer_add_del (vlib_main_t *vm, + u8 * name, sse2_qos_pol_cfg_params_st * cfg, + u8 is_add) +{ + vnet_policer_main_t *pm = &vnet_policer_main; + policer_read_response_type_st test_policer; + uword * p; + int rv; + + if (is_add == 0) + { + p = hash_get_mem (pm->policer_config_by_name, name); + if (p == 0) + { + vec_free(name); + return clib_error_return (0, "No such policer configuration"); + } + hash_unset_mem (pm->policer_config_by_name, name); + vec_free(name); + return 0; + } + + /* Vet the configuration before adding it to the table */ + rv = sse2_pol_logical_2_physical (cfg, &test_policer); + + if (rv == 0) + { + policer_read_response_type_st *pp; + sse2_qos_pol_cfg_params_st *cp; + + pool_get (pm->configs, cp); + pool_get (pm->policer_templates, pp); + + ASSERT (cp - pm->configs == pp - pm->policer_templates); + + clib_memcpy (cp, cfg, sizeof (*cp)); + clib_memcpy (pp, &test_policer, sizeof (*pp)); + + hash_set_mem (pm->policer_config_by_name, name, cp - pm->configs); + } + else + { + vec_free (name); + return clib_error_return (0, "Config failed sanity check"); + } + + return 0; +} + u8 * format_policer_instance (u8 * s, va_list * va) { policer_read_response_type_st * i @@ -228,14 +278,10 @@ configure_policer_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) { - vnet_policer_main_t *pm = &vnet_policer_main; sse2_qos_pol_cfg_params_st c; - policer_read_response_type_st test_policer; unformat_input_t _line_input, * line_input = &_line_input; - int is_add = 1; - int rv; + u8 is_add = 1; u8 * name = 0; - uword * p; /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -261,44 +307,7 @@ configure_policer_command_fn (vlib_main_t * vm, unformat_free (line_input); - if (is_add == 0) - { - p = hash_get_mem (pm->policer_config_by_name, name); - if (p == 0) - { - vec_free(name); - return clib_error_return (0, "No such policer configuration"); - } - hash_unset_mem (pm->policer_config_by_name, name); - vec_free(name); - return 0; - } - - /* Vet the configuration before adding it to the table */ - rv = sse2_pol_logical_2_physical (&c, &test_policer); - - if (rv == 0) - { - policer_read_response_type_st *pp; - sse2_qos_pol_cfg_params_st *cp; - - pool_get (pm->configs, cp); - pool_get (pm->policer_templates, pp); - - ASSERT (cp - pm->configs == pp - pm->policer_templates); - - clib_memcpy (cp, &c, sizeof (*cp)); - clib_memcpy (pp, &test_policer, sizeof (*pp)); - - hash_set_mem (pm->policer_config_by_name, name, cp - pm->configs); - } - else - { - vec_free (name); - return clib_error_return (0, "Config failed sanity check"); - } - - return 0; + return policer_add_del(vm, name, &c, is_add); } VLIB_CLI_COMMAND (configure_policer_command, static) = { diff --git a/vnet/vnet/policer/policer.h b/vnet/vnet/policer/policer.h index f91521e2268..02c2d228edd 100644 --- a/vnet/vnet/policer/policer.h +++ b/vnet/vnet/policer/policer.h @@ -56,5 +56,8 @@ 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, sse2_qos_pol_cfg_params_st * cfg, + u8 is_add); #endif /* __included_policer_h__ */ diff --git a/vpp-api-test/vat/api_format.c b/vpp-api-test/vat/api_format.c index bf1a3931b0b..4776e2adca1 100644 --- a/vpp-api-test/vat/api_format.c +++ b/vpp-api-test/vat/api_format.c @@ -43,6 +43,7 @@ #include <vnet/map/map.h> #include <vnet/cop/cop.h> #include <vnet/ip/ip6_hop_by_hop.h> +#include <vnet/policer/xlate.h> #include "vat/json_format.h" @@ -364,6 +365,56 @@ unformat_ikev2_id_type (unformat_input_t * input, va_list * args) #endif } +uword +unformat_policer_rate_type (unformat_input_t * input, va_list * args) +{ + u8 * r = va_arg (*args, u8 *); + + if (unformat (input, "kbps")) + *r = SSE2_QOS_RATE_KBPS; + else if (unformat(input, "pps")) + *r = SSE2_QOS_RATE_PPS; + else + return 0; + return 1; +} + +uword +unformat_policer_round_type (unformat_input_t * input, va_list * args) +{ + u8 * r = va_arg (*args, u8 *); + + if (unformat(input, "closest")) + *r = SSE2_QOS_ROUND_TO_CLOSEST; + else if (unformat (input, "up")) + *r = SSE2_QOS_ROUND_TO_UP; + else if (unformat (input, "down")) + *r = SSE2_QOS_ROUND_TO_DOWN; + else + return 0; + return 1; +} + +uword +unformat_policer_type (unformat_input_t * input, va_list * args) +{ + u8 * r = va_arg (*args, u8 *); + + if (unformat (input, "1r2c")) + *r = SSE2_QOS_POLICER_TYPE_1R2C; + else if (unformat (input, "1r3c")) + *r = SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697; + else if (unformat (input, "2r3c-2698")) + *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698; + else if (unformat (input, "2r3c-4115")) + *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115; + else if (unformat (input, "2r3c-mef5cf1")) + *r = SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1; + else + return 0; + return 1; +} + u8 * format_ip4_address (u8 * s, va_list * args) { u8 * a = va_arg (*args, u8 *); @@ -2179,7 +2230,8 @@ _(lisp_gpe_add_del_iface_reply) \ _(lisp_enable_disable_reply) \ _(vxlan_gpe_add_del_tunnel_reply) \ _(af_packet_create_reply) \ -_(af_packet_delete_reply) +_(af_packet_delete_reply) \ +_(policer_add_del_reply) #define _(n) \ static void vl_api_##n##_t_handler \ @@ -2359,7 +2411,8 @@ _(LISP_MAP_RESOLVER_DETAILS, lisp_map_resolver_details) \ _(LISP_ENABLE_DISABLE_STATUS_DETAILS, \ lisp_enable_disable_status_details) \ _(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \ -_(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) +_(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \ +_(POLICER_ADD_DEL_REPLY, policer_add_del_reply) /* M: construct, but don't yet send a message */ @@ -10206,6 +10259,75 @@ api_af_packet_delete (vat_main_t * vam) return 0; } +static int +api_policer_add_del (vat_main_t * vam) +{ + unformat_input_t * i = vam->input; + vl_api_policer_add_del_t * mp; + f64 timeout; + u8 is_add = 1; + u8 * name = 0; + u32 cir = 0; + u32 eir = 0; + u64 cb = 0; + u64 eb = 0; + u8 rate_type = 0; + u8 round_type = 0; + u8 type = 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "name %s", &name)) + vec_add1 (name, 0); + else if (unformat (i, "cir %u", &cir)) + ; + else if (unformat (i, "eir %u", &eir)) + ; + else if (unformat (i, "cb %u", &cb)) + ; + else if (unformat (i, "eb %u", &eb)) + ; + else if (unformat (i, "rate_type %U", unformat_policer_rate_type, + &rate_type)) + ; + else if (unformat (i, "round_type %U", unformat_policer_round_type, + &round_type)) + ; + else if (unformat (i, "type %U", unformat_policer_type, &type)) + ; + else + break; + } + + if (!vec_len (name)) { + errmsg ("policer name must be specified"); + return -99; + } + + if (vec_len (name) > 64) { + errmsg ("policer name too long"); + return -99; + } + + M(POLICER_ADD_DEL, policer_add_del); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + mp->is_add = is_add; + mp->cir = cir; + mp->eir = eir; + mp->cb = cb; + mp->eb = eb; + mp->rate_type = rate_type; + mp->round_type = round_type; + mp->type = type; + + S; W; + /* NOTREACHED */ + return 0; +} + static int q_or_quit (vat_main_t * vam) { longjmp (vam->jump_buf, 1); @@ -10691,7 +10813,8 @@ _(lisp_gpe_tunnel_dump, "") \ _(lisp_map_resolver_dump, "") \ _(lisp_enable_disable_status_dump, "") \ _(af_packet_create, "name <host interface name> [hw_addr <mac>]") \ -_(af_packet_delete, "name <host interface name>") +_(af_packet_delete, "name <host interface name>") \ +_(policer_add_del, "name <policer name> <params> [del]") /* List of command functions, CLI names map directly to functions */ #define foreach_cli_function \ diff --git a/vpp/api/api.c b/vpp/api/api.c index 0d5f224118e..f81b9c98af3 100644 --- a/vpp/api/api.c +++ b/vpp/api/api.c @@ -74,6 +74,7 @@ #include <vnet/cop/cop.h> #include <vnet/ip/ip6_hop_by_hop.h> #include <vnet/devices/af_packet/af_packet.h> +#include <vnet/policer/policer.h> #undef BIHASH_TYPE #undef __included_bihash_template_h__ @@ -335,7 +336,8 @@ _(LISP_ENABLE_DISABLE_STATUS_DUMP, \ lisp_enable_disable_status_dump) \ _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del) \ _(AF_PACKET_CREATE, af_packet_create) \ -_(AF_PACKET_DELETE, af_packet_delete) +_(AF_PACKET_DELETE, af_packet_delete) \ +_(POLICER_ADD_DEL, policer_add_del) #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) @@ -5932,6 +5934,36 @@ vl_api_af_packet_delete_t_handler REPLY_MACRO(VL_API_AF_PACKET_DELETE_REPLY); } +static void +vl_api_policer_add_del_t_handler +(vl_api_policer_add_del_t *mp) +{ + vlib_main_t * vm = vlib_get_main(); + vl_api_policer_add_del_reply_t *rmp; + int rv = 0; + u8 *name = NULL; + sse2_qos_pol_cfg_params_st cfg; + clib_error_t * error; + + name = format(0, "%s", mp->name); + + memset (&cfg, 0, sizeof (cfg)); + cfg.rfc = mp->type; + cfg.rnd_type = mp->round_type; + cfg.rate_type = mp->rate_type; + cfg.rb.kbps.cir_kbps = mp->cir; + cfg.rb.kbps.eir_kbps = mp->eir; + cfg.rb.kbps.cb_bytes = mp->cb; + cfg.rb.kbps.eb_bytes = mp->eb; + + error = policer_add_del(vm, name, &cfg, mp->is_add); + + if (error) + rv = VNET_API_ERROR_UNSPECIFIED; + + REPLY_MACRO(VL_API_POLICER_ADD_DEL_REPLY); +} + #define BOUNCE_HANDLER(nn) \ static void vl_api_##nn##_t_handler ( \ vl_api_##nn##_t *mp) \ diff --git a/vpp/api/vpe.api b/vpp/api/vpe.api index df3b2af0e3c..a61c26011f6 100644 --- a/vpp/api/vpe.api +++ b/vpp/api/vpe.api @@ -3475,3 +3475,40 @@ define af_packet_delete_reply { u32 context; i32 retval; }; + +/** \brief Add/del policer + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_add - add policer if non-zero, else delete + @param name - policer name + @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 +*/ +define policer_add_del { + u32 client_index; + u32 context; + + u8 is_add; + u8 name[64]; + u32 cir; + u32 eir; + u64 cb; + u64 eb; + u8 rate_type; + u8 round_type; + u8 type; +}; + +/** \brief Add/del policer response + @param context - sender context, to match reply w/ request + @param retval - return value for request +*/ +define policer_add_del_reply { + u32 context; + i32 retval; +}; |