summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatus Fabian <matfabia@cisco.com>2016-05-13 05:44:48 -0700
committerDave Barach <openvpp@barachs.net>2016-05-16 13:30:40 +0000
commit65fcd4d7372718d353143c4deec65fe8b8e36577 (patch)
tree0358a6ac42188b39c14e567154e29bc967bbc95e
parent6b70c213ee0b53ab9cbd4a9a3768b2d64f63109d (diff)
Add configure policer API
JIRA: VPP-67 Change-Id: I04560d78e2eb131cd6cc31472b70b3d3e8fdd79a Signed-off-by: Matus Fabian <matfabia@cisco.com>
-rw-r--r--vnet/Makefile.am2
-rw-r--r--vnet/vnet/policer/policer.c95
-rw-r--r--vnet/vnet/policer/policer.h3
-rw-r--r--vpp-api-test/vat/api_format.c129
-rw-r--r--vpp/api/api.c34
-rw-r--r--vpp/api/vpe.api37
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;
+};