diff options
author | Neale Ranns <nranns@cisco.com> | 2019-05-15 02:13:37 -0700 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2019-05-28 13:30:44 +0000 |
commit | 50f0ac0f097e5495da1f2b1816106e3d420ff34b (patch) | |
tree | d10ae0385fc10b7da97b2a24f8dea3882f6d702d /src/vnet/ip/punt_api.c | |
parent | 9080096f7c548415fc4d5354c7e582a3eda1a5ed (diff) |
Punt: socket register for exception dispatched/punted packets based on reason
- add to the Punt API to allow different descriptions of the desired packets: UDP or exceptions
- move the punt nodes into punt_node.c
- improve tests (test that the correct packets are punted to the registered socket)
Change-Id: I1a133dec88106874993cba1f5a439cd26b2fef72
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'src/vnet/ip/punt_api.c')
-rw-r--r-- | src/vnet/ip/punt_api.c | 274 |
1 files changed, 218 insertions, 56 deletions
diff --git a/src/vnet/ip/punt_api.c b/src/vnet/ip/punt_api.c index ecb461bcdda..95fff714b46 100644 --- a/src/vnet/ip/punt_api.c +++ b/src/vnet/ip/punt_api.c @@ -20,6 +20,7 @@ #include <vnet/vnet.h> #include <vlibmemory/api.h> #include <vnet/ip/punt.h> +#include <vnet/ip/ip_types_api.h> #include <vnet/vnet_msg_enum.h> @@ -43,107 +44,226 @@ _(SET_PUNT, set_punt) \ _(PUNT_SOCKET_REGISTER, punt_socket_register) \ _(PUNT_SOCKET_DEREGISTER, punt_socket_deregister) \ -_(PUNT_DUMP, punt_dump) \ -_(PUNT_SOCKET_DUMP, punt_socket_dump) +_(PUNT_SOCKET_DUMP, punt_socket_dump) \ +_(PUNT_REASON_DUMP, punt_reason_dump) + +static int +vl_api_punt_type_decode (vl_api_punt_type_t in, punt_type_t * out) +{ + in = clib_net_to_host_u32 (in); + + switch (in) + { +#define _(v, s) \ + case PUNT_API_TYPE_##v: \ + *out = PUNT_TYPE_##v; \ + return (0); + foreach_punt_type +#undef _ + } + + return (-1); +} + +static vl_api_punt_type_t +vl_api_punt_type_encode (punt_type_t in) +{ + vl_api_punt_type_t pt = PUNT_API_TYPE_L4; + + switch (in) + { +#define _(v, s) \ + case PUNT_TYPE_##v: \ + pt = PUNT_API_TYPE_##v; \ + break; + foreach_punt_type +#undef _ + } + + return (clib_host_to_net_u32 (pt)); +} + +static int +vl_api_punt_l4_decode (const vl_api_punt_l4_t * in, punt_l4_t * out) +{ + int rv; + + rv = ip_address_family_decode (in->af, &out->af); + rv += ip_proto_decode (in->protocol, &out->protocol); + out->port = clib_net_to_host_u16 (in->port); + + return (rv); +} + +static int +vl_api_punt_exception_decode (const vl_api_punt_exception_t * in, + punt_exception_t * out) +{ + int rv; + + out->reason = clib_net_to_host_u32 (in->id); + rv = vlib_punt_reason_validate (out->reason); + + return (rv); +} + +static int +vl_api_punt_decode (const vl_api_punt_t * in, punt_reg_t * out) +{ + int rv; + + rv = vl_api_punt_type_decode (in->type, &out->type); + + if (rv) + return (rv); + + switch (out->type) + { + case PUNT_TYPE_L4: + return (vl_api_punt_l4_decode (&in->punt.l4, &out->punt.l4)); + case PUNT_TYPE_EXCEPTION: + return (vl_api_punt_exception_decode (&in->punt.exception, + &out->punt.exception)); + } + + return (-1); +} + +static void +vl_api_punt_l4_encode (const punt_l4_t * in, vl_api_punt_l4_t * out) +{ + out->af = ip_address_family_encode (in->af); + out->protocol = ip_proto_encode (in->protocol); + out->port = clib_net_to_host_u16 (in->port); +} + +static void +vl_api_punt_exception_encode (const punt_exception_t * in, + vl_api_punt_exception_t * out) +{ + out->id = clib_host_to_net_u32 (in->reason); +} + +static void +vl_api_punt_encode (const punt_reg_t * in, vl_api_punt_t * out) +{ + out->type = vl_api_punt_type_encode (in->type); + + switch (in->type) + { + case PUNT_TYPE_L4: + vl_api_punt_l4_encode (&in->punt.l4, &out->punt.l4); + break; + case PUNT_TYPE_EXCEPTION: + vl_api_punt_exception_encode (&in->punt.exception, + &out->punt.exception); + break; + } +} static void vl_api_set_punt_t_handler (vl_api_set_punt_t * mp) { vl_api_set_punt_reply_t *rmp; vlib_main_t *vm = vlib_get_main (); - int rv = 0; clib_error_t *error; + punt_reg_t pr; + int rv; + + rv = vl_api_punt_decode (&mp->punt, &pr); - error = vnet_punt_add_del (vm, mp->punt.ipv, mp->punt.l4_protocol, - ntohs (mp->punt.l4_port), mp->is_add); + if (rv) + goto out; + + error = vnet_punt_add_del (vm, &pr, mp->is_add); if (error) { rv = -1; clib_error_report (error); } +out: REPLY_MACRO (VL_API_SET_PUNT_REPLY); } static void -vl_api_punt_dump_t_handler (vl_api_punt_dump_t * mp) -{ - -} - -static void vl_api_punt_socket_register_t_handler (vl_api_punt_socket_register_t * mp) { vl_api_punt_socket_register_reply_t *rmp; vlib_main_t *vm = vlib_get_main (); - int rv = 0; clib_error_t *error; - vl_api_registration_t *reg; + punt_reg_t pr; + int rv; + + rv = vl_api_punt_decode (&mp->punt, &pr); + + if (rv) + return; error = vnet_punt_socket_add (vm, ntohl (mp->header_version), - mp->punt.ipv, mp->punt.l4_protocol, - ntohs (mp->punt.l4_port), - (char *) mp->pathname); + &pr, (char *) mp->pathname); if (error) { rv = -1; clib_error_report (error); } - reg = vl_api_client_index_to_registration (mp->client_index); - if (!reg) - return; - - rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = htons (VL_API_PUNT_SOCKET_REGISTER_REPLY); - rmp->context = mp->context; - rmp->retval = htonl (rv); char *p = vnet_punt_get_server_pathname (); - /* Abstract pathnames start with \0 */ - memcpy ((char *) rmp->pathname, p, sizeof (rmp->pathname)); - vl_api_send_msg (reg, (u8 *) rmp); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_PUNT_SOCKET_REGISTER_REPLY, + ({ + memcpy ((char *) rmp->pathname, p, sizeof (rmp->pathname)); + })); + /* *INDENT-ON* */ } -void -send_punt_socket_details (vl_api_registration_t * reg, - u32 context, punt_socket_detail_t * p) +typedef struct punt_socket_send_ctx_t_ +{ + vl_api_registration_t *reg; + u32 context; +} punt_socket_send_ctx_t; + +static walk_rc_t +vl_api_punt_socket_send_details (const punt_client_t * pc, void *args) { + punt_socket_send_ctx_t *ctx = args; vl_api_punt_socket_details_t *mp; mp = vl_msg_api_alloc (sizeof (*mp)); if (!mp) - return; + return (WALK_STOP); clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_PUNT_SOCKET_DETAILS); - mp->context = context; - mp->punt.ipv = p->ipv; - mp->punt.l4_protocol = p->l4_protocol; - mp->punt.l4_port = htons (p->l4_port); - memcpy (mp->pathname, p->pathname, sizeof (p->pathname)); + mp->context = ctx->context; + vl_api_punt_encode (&pc->reg, &mp->punt); + memcpy (mp->pathname, pc->caddr.sun_path, sizeof (pc->caddr.sun_path)); + + vl_api_send_msg (ctx->reg, (u8 *) mp); - vl_api_send_msg (reg, (u8 *) mp); + return (WALK_CONTINUE); } static void vl_api_punt_socket_dump_t_handler (vl_api_punt_socket_dump_t * mp) { vl_api_registration_t *reg; - punt_socket_detail_t *p, *ps; - int rv __attribute__ ((unused)) = 0; + punt_type_t pt; + + if (0 != vl_api_punt_type_decode (mp->type, &pt)) + return; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; - ps = punt_socket_entries (mp->is_ipv6); - /* *INDENT-OFF* */ - vec_foreach (p, ps) - { - send_punt_socket_details (reg, mp->context, p); - } - /* *INDENT-ON* */ - vec_free (ps); + punt_socket_send_ctx_t ctx = { + .reg = reg, + .context = mp->context, + }; + + punt_client_walk (pt, vl_api_punt_socket_send_details, &ctx); } static void @@ -151,27 +271,69 @@ vl_api_punt_socket_deregister_t_handler (vl_api_punt_socket_deregister_t * mp) { vl_api_punt_socket_deregister_reply_t *rmp; vlib_main_t *vm = vlib_get_main (); - int rv = 0; clib_error_t *error; - vl_api_registration_t *reg; + punt_reg_t pr; + int rv; + + rv = vl_api_punt_decode (&mp->punt, &pr); - error = vnet_punt_socket_del (vm, mp->punt.ipv, mp->punt.l4_protocol, - ntohs (mp->punt.l4_port)); + if (rv) + goto out; + + error = vnet_punt_socket_del (vm, &pr); if (error) { rv = -1; clib_error_report (error); } +out: + REPLY_MACRO (VL_API_PUNT_SOCKET_DEREGISTER_REPLY); +} + +typedef struct punt_reason_dump_walk_ctx_t_ +{ + vl_api_registration_t *reg; + u32 context; +} punt_reason_dump_walk_ctx_t; + +static int +punt_reason_dump_walk_cb (vlib_punt_reason_t id, const u8 * name, void *args) +{ + punt_reason_dump_walk_ctx_t *ctx = args; + vl_api_punt_reason_details_t *mp; + + mp = vl_msg_api_alloc (sizeof (*mp) + vec_len (name)); + if (!mp) + return (0); + + clib_memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_PUNT_REASON_DETAILS); + + mp->context = ctx->context; + mp->reason.id = clib_host_to_net_u32 (id); + vl_api_to_api_string (vec_len (name), (char *) name, &mp->reason.name); + + vl_api_send_msg (ctx->reg, (u8 *) mp); + + return (1); +} + +static void +vl_api_punt_reason_dump_t_handler (vl_api_punt_reason_dump_t * mp) +{ + vl_api_registration_t *reg; + reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; - rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = htons (VL_API_PUNT_SOCKET_DEREGISTER_REPLY); - rmp->context = mp->context; - rmp->retval = htonl (rv); - vl_api_send_msg (reg, (u8 *) rmp); + punt_reason_dump_walk_ctx_t ctx = { + .reg = reg, + .context = mp->context, + }; + + punt_reason_walk (punt_reason_dump_walk_cb, &ctx); } #define vl_msg_name_crc_list |