diff options
author | Alberto Compagno <acompagn+fdio@cisco.com> | 2019-11-17 12:50:48 +0100 |
---|---|---|
committer | Alberto Compagno <acompagn+fdio@cisco.com> | 2019-11-18 11:16:44 +0100 |
commit | fb81ea88640de69820f2b2d24e29e5743e4f301b (patch) | |
tree | 51b929825d7d68b4105ac63ea0cea32dd48ae269 /hicn-plugin | |
parent | 547acf3eed92d3564139cccf205c852178bcc310 (diff) |
[HICN-225] Added generic binary api for handling faces
Supported messages are add, del, get, dump, get.
Each message contains a face id and the expected message has different
fields based on the face type.
The binary api specific for ip faces is still available for compatibility
but deprecated.
Change-Id: I899c6cf31a56abd39ad287ea3128993857997fcb
Signed-off-by: Alberto Compagno <acompagn+fdio@cisco.com>
Diffstat (limited to 'hicn-plugin')
-rw-r--r-- | hicn-plugin/src/error.h | 2 | ||||
-rw-r--r-- | hicn-plugin/src/faces/udp/face_udp.c | 2 | ||||
-rw-r--r-- | hicn-plugin/src/hicn.api | 187 | ||||
-rw-r--r-- | hicn-plugin/src/hicn_api.c | 314 | ||||
-rw-r--r-- | hicn-plugin/src/hicn_api_test.c | 510 |
5 files changed, 865 insertions, 150 deletions
diff --git a/hicn-plugin/src/error.h b/hicn-plugin/src/error.h index 0abcce96c..14cec0a3f 100644 --- a/hicn-plugin/src/error.h +++ b/hicn-plugin/src/error.h @@ -74,7 +74,7 @@ _(APPFACE_FEATURE, -181, "Error while enabling app face feature") \ _(APPFACE_NOT_FOUND, -182, "Application face not found") \ _(APPFACE_PROD_PREFIX_NULL, -183, "Prefix must not be null for producer face") \ - _(STRATEGY_NH_NOT_FOUND, -184, "Next hop not found") \ + _(STRATEGY_NH_NOT_FOUND, -184, "Next hop not found") \ _(MW_STRATEGY_SET, -185, "Error while setting weight for next hop") \ _(STRATEGY_NOT_FOUND, -186, "Strategy not found") diff --git a/hicn-plugin/src/faces/udp/face_udp.c b/hicn-plugin/src/faces/udp/face_udp.c index 751065f82..ec43d9081 100644 --- a/hicn-plugin/src/faces/udp/face_udp.c +++ b/hicn-plugin/src/faces/udp/face_udp.c @@ -366,7 +366,7 @@ format_hicn_face_udp (u8 * s, va_list * args) format_ip6_address, &udp_face->hdrs.ip6.ip.src_address, clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.src_port)); s = - format (s, "remote %U|%u", format_ip6_address, + format (s, "remote %U|%u ", format_ip6_address, &udp_face->hdrs.ip6.ip.dst_address, clib_net_to_host_u16 (udp_face->hdrs.ip6.udp.dst_port)); s = format (s, "%U", format_vnet_link, adj->ia_link); diff --git a/hicn-plugin/src/hicn.api b/hicn-plugin/src/hicn.api index 4f3047b0a..9a194b97f 100644 --- a/hicn-plugin/src/hicn.api +++ b/hicn-plugin/src/hicn.api @@ -16,6 +16,56 @@ option version = "5.1.0"; import "vnet/ip/ip_types.api"; +enum face_type : u8 { + IP_FACE = 0, + UDP_FACE, +}; + +typedef hicn_face_ip { + /* IP local address */ + vl_api_address_t local_addr; + + /* IP remote address */ + vl_api_address_t remote_addr; + + /* IPv4 local port number */ + u32 swif; + + /* Face flags */ + u32 flags; + + /* Name of the interface */ + u8 if_name[30]; +}; + +typedef hicn_face_udp { + /* IP local address */ + vl_api_address_t local_addr; + + /* IP remote address */ + vl_api_address_t remote_addr; + + /* Local port */ + u16 lport; + + /* Remote port */ + u16 rport; + + /* IPv4 local port number */ + u32 swif; + + /* Face flags */ + u32 flags; + + /* Name of the interface */ + u8 if_name[30]; +}; + +typedef hicn_face_union { + vl_api_hicn_face_ip_t ip; + vl_api_hicn_face_udp_t udp; +}; + define hicn_api_node_params_set { /* Client identifier, set from api_main.my_client_index */ @@ -160,13 +210,7 @@ define hicn_api_face_ip_add u32 context; /* IP local address */ - vl_api_address_t local_addr; - - /* IP remote address */ - vl_api_address_t remote_addr; - - /* IPv4 local port number */ - u32 swif; + vl_api_hicn_face_ip_t face; }; define hicn_api_face_ip_add_reply @@ -202,18 +246,6 @@ define hicn_api_face_ip_del_reply i32 retval; }; -define hicn_api_face_ip_params_get -{ - /* Client identifier, set from api_main.my_client_index */ - u32 client_index; - - /* Arbitrary context, so client can match reply to request */ - u32 context; - - /* A Face to be retrieved */ - u32 faceid; -}; - define hicn_api_face_stats_details { /* From the request */ @@ -255,6 +287,18 @@ define hicn_api_face_stats_dump u32 context; }; +define hicn_api_face_ip_params_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face to be retrieved */ + u32 faceid; +}; + define hicn_api_face_ip_params_get_reply { /* From the request */ @@ -279,6 +323,111 @@ define hicn_api_face_ip_params_get_reply u32 flags; }; +define hicn_api_face_add +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* Type of face to add */ + vl_api_face_type_t type; + + /* Face to add */ + vl_api_hicn_face_union_t face; +}; + +define hicn_api_face_add_reply +{ + /* From the request */ + u32 context; + + /* Return value: new Face ID, ~0 means no Face was created */ + u32 faceid; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_face_del +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face ID to be deleted */ + u32 faceid; +}; + +define hicn_api_face_del_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; +}; + +define hicn_api_faces_details +{ +/* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Id of the face */ + u32 faceid; + + /* Type of face to add */ + vl_api_face_type_t type; + + /* Face to add */ + vl_api_hicn_face_union_t face; +}; + +define hicn_api_faces_dump +{ +/* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; +}; + +define hicn_api_face_get +{ + /* Client identifier, set from api_main.my_client_index */ + u32 client_index; + + /* Arbitrary context, so client can match reply to request */ + u32 context; + + /* A Face to be retrieved */ + u32 faceid; +}; + +define hicn_api_face_get_reply +{ + /* From the request */ + u32 context; + + /* Return value, zero means all OK */ + i32 retval; + + /* Id of the face */ + u32 faceid; + + /* Type of face to add */ + vl_api_face_type_t type; + + /* Face to add */ + vl_api_hicn_face_union_t face; +}; + define hicn_api_route_nhops_add { /* Client identifier, set from api_main.my_client_index */ diff --git a/hicn-plugin/src/hicn_api.c b/hicn-plugin/src/hicn_api.c index 5f195b6da..b1e6bccb9 100644 --- a/hicn-plugin/src/hicn_api.c +++ b/hicn-plugin/src/hicn_api.c @@ -26,6 +26,7 @@ #include "hicn.h" #include "faces/ip/face_ip.h" +#include "faces/udp/face_udp.h" #include "infra.h" #include "parser.h" #include "mgmt.h" @@ -70,6 +71,10 @@ _(HICN_API_FACE_IP_ADD, hicn_api_face_ip_add) \ _(HICN_API_FACE_IP_DEL, hicn_api_face_ip_del) \ _(HICN_API_FACE_IP_PARAMS_GET, hicn_api_face_ip_params_get) \ + _(HICN_API_FACE_ADD, hicn_api_face_add) \ + _(HICN_API_FACE_DEL, hicn_api_face_del) \ + _(HICN_API_FACES_DUMP, hicn_api_faces_dump) \ + _(HICN_API_FACE_GET, hicn_api_face_get) \ _(HICN_API_FACE_STATS_DUMP, hicn_api_face_stats_dump) \ _(HICN_API_ROUTE_GET, hicn_api_route_get) \ _(HICN_API_ROUTES_DUMP, hicn_api_routes_dump) \ @@ -175,21 +180,17 @@ vl_api_hicn_api_node_stats_get_t_handler (vl_api_hicn_api_node_stats_get_t * /****** FACE *******/ - -static void -vl_api_hicn_api_face_ip_add_t_handler (vl_api_hicn_api_face_ip_add_t * mp) +static hicn_error_t +hicn_api_face_ip_add (vl_api_hicn_face_ip_t * mp, hicn_face_id_t * face_id) { - vl_api_hicn_api_face_ip_add_reply_t *rmp; hicn_error_t rv = HICN_ERROR_NONE; - hicn_main_t *sm = &hicn_main; vnet_main_t *vnm = vnet_get_main (); - hicn_face_id_t faceid = HICN_FACE_NULL; ip46_address_t local_addr; ip46_address_t remote_addr; - ip_address_decode(&mp->local_addr, &local_addr); - ip_address_decode(&mp->remote_addr, &remote_addr); + ip_address_decode (&mp->local_addr, &local_addr); + ip_address_decode (&mp->remote_addr, &remote_addr); u32 sw_if = clib_net_to_host_u32 (mp->swif); @@ -244,14 +245,25 @@ vl_api_hicn_api_face_ip_add_t_handler (vl_api_hicn_api_face_ip_add_t * mp) } if (rv == HICN_ERROR_NONE) - rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, &faceid, 0); - else - faceid = HICN_FACE_NULL; + rv = hicn_face_ip_add (&local_addr, &remote_addr, sw_if, face_id, 0); + + return rv; +} + +static void +vl_api_hicn_api_face_ip_add_t_handler (vl_api_hicn_api_face_ip_add_t * mp) +{ + vl_api_hicn_api_face_ip_add_reply_t *rmp; + hicn_error_t rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + hicn_face_id_t face_id = HICN_FACE_NULL; + rv = hicn_api_face_ip_add (&(mp->face), &face_id); /* *INDENT-OFF* */ REPLY_MACRO2 (VL_API_HICN_API_FACE_IP_ADD_REPLY /* , rmp, mp, rv */ ,( { - rmp->faceid = clib_host_to_net_u32 ((u32) faceid); + rmp->faceid = clib_host_to_net_u32 ((u32) face_id); rmp->retval = rv; })); /* *INDENT-ON* */ @@ -261,12 +273,15 @@ static void vl_api_hicn_api_face_ip_del_t_handler (vl_api_hicn_api_face_ip_del_t * mp) { vl_api_hicn_api_face_ip_del_reply_t *rmp; - int rv = HICN_ERROR_NONE; + int rv = HICN_ERROR_FACE_NOT_FOUND; hicn_main_t *sm = &hicn_main; hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); - rv = hicn_face_ip_del (faceid); + if (hicn_dpoi_idx_is_valid (faceid)) + { + rv = hicn_face_ip_del (faceid); + } REPLY_MACRO (VL_API_HICN_API_FACE_IP_DEL_REPLY /* , rmp, mp, rv */ ); @@ -292,6 +307,242 @@ static void /* *INDENT-ON* */ } +static hicn_error_t +hicn_api_face_udp_add (vl_api_hicn_face_udp_t * mp, hicn_face_id_t * face_id) +{ + hicn_error_t rv = HICN_ERROR_NONE; + + ip46_address_t local_addr = ip46_address_initializer; + ip46_address_t remote_addr = ip46_address_initializer; + u16 lport; + u16 rport; + u32 sw_if; + ip_address_decode (&mp->local_addr, &local_addr); + ip_address_decode (&mp->remote_addr, &remote_addr); + //Do not byteswap. We store ports in network order + lport = mp->lport; + rport = mp->rport; + sw_if = clib_net_to_host_u32 (mp->swif); + + int input_is_ok = !ip46_address_is_zero (&local_addr) + && !ip46_address_is_zero (&remote_addr) + && + ((ip46_address_is_ip4 (&local_addr) && ip46_address_is_ip4 (&remote_addr)) + || (!ip46_address_is_ip4 (&local_addr) + && !ip46_address_is_ip4 (&remote_addr))) && lport != 0 && rport != 0; + + if (!input_is_ok) + { + rv = HICN_ERROR_UNSPECIFIED; + } + else + { + rv = hicn_face_udp_add (&local_addr, + &remote_addr, lport, rport, sw_if, face_id); + } + return rv; +} + +static void +vl_api_hicn_api_face_add_t_handler (vl_api_hicn_api_face_add_t * mp) +{ + vl_api_hicn_api_face_add_reply_t *rmp; + hicn_error_t rv = HICN_ERROR_NONE; + + hicn_main_t *sm = &hicn_main; + hicn_face_id_t face_id; + vl_api_face_type_t face_type = mp->type; + + switch (face_type) + { + case IP_FACE: + rv = hicn_api_face_ip_add (&(mp->face.ip), &face_id); + break; + case UDP_FACE: + rv = hicn_api_face_udp_add (&(mp->face.udp), &face_id); + break; + default: + rv = HICN_ERROR_UNSPECIFIED; + break; + } + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_FACE_ADD_REPLY /* , rmp, mp, rv */ ,( + { + rmp->faceid = clib_host_to_net_u32 ((u32) face_id); + rmp->retval = rv; + })); + /* *INDENT-ON* */ +} + +static void +vl_api_hicn_api_face_del_t_handler (vl_api_hicn_api_face_del_t * mp) +{ + vl_api_hicn_api_face_del_reply_t *rmp; + int rv = HICN_ERROR_FACE_NOT_FOUND; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + if (hicn_dpoi_idx_is_valid (faceid)) + { + hicn_face_t *face = hicn_dpoi_get_from_idx (faceid); + hicn_face_vft_t *vft = hicn_face_get_vft (face->shared.face_type); + rv = vft->hicn_face_del (faceid); + } + + REPLY_MACRO (VL_API_HICN_API_FACE_DEL_REPLY /* , rmp, mp, rv */ ); + +} + +static void +send_face_ip_details (hicn_face_t * face, vl_api_hicn_face_ip_t * mp) +{ + vnet_main_t *vnm = vnet_get_main (); + + hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data; + ip_address_encode (&face_ip->local_addr, IP46_TYPE_ANY, &mp->local_addr); + ip_address_encode (&face_ip->remote_addr, IP46_TYPE_ANY, &mp->remote_addr); + mp->flags = clib_host_to_net_u32 (face->shared.flags); + mp->swif = clib_net_to_host_u32 (face->shared.sw_if); + vnet_sw_interface_t *sw_interface = + vnet_get_sw_interface_or_null (vnm, face->shared.sw_if); + u8 *sbuf = 0; + if (sw_interface != NULL) + { + sbuf = + format (0, "%U", format_vnet_sw_interface_name, vnm, sw_interface); + strcpy ((char *) (mp->if_name), (char *) sbuf); + } +} + +static void +send_face_udp_details (hicn_face_t * face, vl_api_hicn_face_udp_t * mp) +{ + vnet_main_t *vnm = vnet_get_main (); + hicn_face_udp_t *face_udp = (hicn_face_udp_t *) face->data; + if (face_udp->hdrs.ip4.ip.ip_version_and_header_length == 0x45) + { + ip46_address_t src_addr = { 0 }; + ip46_address_t dst_addr = { 0 }; + ip46_address_set_ip4 (&src_addr, &(face_udp->hdrs.ip4.ip.src_address)); + ip46_address_set_ip4 (&dst_addr, &(face_udp->hdrs.ip4.ip.dst_address)); + + ip_address_encode (&src_addr, IP46_TYPE_ANY, &(mp->local_addr)); + ip_address_encode (&dst_addr, IP46_TYPE_ANY, &(mp->remote_addr)); + //Do not swap, they are already in network order + mp->lport = face_udp->hdrs.ip4.udp.src_port; + mp->rport = face_udp->hdrs.ip4.udp.dst_port; + } + else + { + ip46_address_t src_addr = { 0 }; + ip46_address_t dst_addr = { 0 }; + ip46_address_set_ip6 (&src_addr, &(face_udp->hdrs.ip6.ip.src_address)); + ip46_address_set_ip6 (&dst_addr, &(face_udp->hdrs.ip6.ip.dst_address)); + + ip_address_encode (&src_addr, IP46_TYPE_ANY, &(mp->local_addr)); + ip_address_encode (&dst_addr, IP46_TYPE_ANY, &(mp->remote_addr)); + //Do not swap, they are already in network order + mp->lport = face_udp->hdrs.ip6.udp.src_port; + mp->rport = face_udp->hdrs.ip6.udp.dst_port; + } + mp->flags = clib_host_to_net_u32 (face->shared.flags); + mp->swif = clib_net_to_host_u32 (face->shared.sw_if); + vnet_sw_interface_t *sw_interface = + vnet_get_sw_interface_or_null (vnm, face->shared.sw_if); + u8 *sbuf = 0; + if (sw_interface != NULL) + { + sbuf = + format (0, "%U", format_vnet_sw_interface_name, vnm, sw_interface); + strcpy ((char *) (mp->if_name), (char *) sbuf); + } +} + +static void +send_faces_details (vl_api_registration_t * reg, + hicn_face_t * face, u32 context) +{ + vl_api_hicn_api_faces_details_t *mp; + hicn_main_t *hm = &hicn_main; + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->faceid = clib_host_to_net_u32 (hicn_dpoi_get_index (face)); + mp->_vl_msg_id = htons (VL_API_HICN_API_FACES_DETAILS + hm->msg_id_base); + mp->context = context; + + if (face->shared.face_type == hicn_face_ip_type) + { + mp->type = IP_FACE; + send_face_ip_details (face, &(mp->face.ip)); + } + else if (face->shared.face_type == hicn_face_udp_type) + { + mp->type = UDP_FACE; + send_face_udp_details (face, &(mp->face.udp)); + } + + + vl_api_send_msg (reg, (u8 *) mp); +} + +static void + vl_api_hicn_api_faces_dump_t_handler (vl_api_hicn_api_faces_dump_t * mp) +{ + hicn_face_t *face; + vl_api_registration_t *reg; + + reg = vl_api_client_index_to_registration (mp->client_index); + if (!reg) + return; + + /* *INDENT-OFF* */ + pool_foreach (face, hicn_dpoi_face_pool, + ({ + send_faces_details (reg, face, mp->context); + })); + /* *INDENT-ON* */ +} + +static void + vl_api_hicn_api_face_get_t_handler (vl_api_hicn_api_face_get_t * mp) +{ + vl_api_hicn_api_face_get_reply_t *rmp; + int rv = 0; + + hicn_main_t *sm = &hicn_main; + + hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); + + /* *INDENT-OFF* */ + REPLY_MACRO2 (VL_API_HICN_API_FACE_GET_REPLY, ( + { + rv = hicn_dpoi_idx_is_valid(faceid); + if (rv) + { + hicn_face_t * face = hicn_dpoi_get_from_idx(faceid); + if (face->shared.face_type == hicn_face_ip_type) + { + rmp->type = IP_FACE; + send_face_ip_details(face, &(rmp->face.ip)); + } + else if (face->shared.face_type == hicn_face_udp_type) + { + rmp->type = UDP_FACE; + send_face_udp_details(face, &(rmp->face.udp)); + } + rv = HICN_ERROR_NONE; + } + else + { + rv = HICN_ERROR_FACE_NOT_FOUND; + } + rmp->retval = clib_host_to_net_u32(rv); + })); + /* *INDENT-ON* */ +} + static void send_face_stats_details (vl_api_registration_t * reg, hicn_face_t * face, u32 context) @@ -367,7 +618,7 @@ vl_api_hicn_api_route_nhops_add_t_handler (vl_api_hicn_api_route_nhops_add_t hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); u8 n_faces = mp->n_faces; @@ -402,7 +653,7 @@ static void vl_api_hicn_api_route_del_t_handler hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); rv = hicn_route_del (&prefix); @@ -418,7 +669,7 @@ static void vl_api_hicn_api_route_nhop_del_t_handler hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); hicn_face_id_t faceid = clib_net_to_host_u32 (mp->faceid); @@ -436,7 +687,7 @@ static void vl_api_hicn_api_route_get_t_handler hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); const dpo_id_t *hicn_dpo_id; const hicn_dpo_vft_t *hicn_dpo_vft; hicn_dpo_ctx_t *hicn_dpo_ctx; @@ -482,8 +733,7 @@ send_route_details (vl_api_registration_t * reg, hicn_dpo_ctx_t *hicn_dpo_ctx; u32 fib_index; - int rv = - hicn_route_get_dpo (pfx, &hicn_dpo_id, &fib_index); + int rv = hicn_route_get_dpo (pfx, &hicn_dpo_id, &fib_index); if (rv == HICN_ERROR_NONE) { @@ -494,8 +744,9 @@ send_route_details (vl_api_registration_t * reg, if (dpo_id_is_valid (&hicn_dpo_ctx->next_hops[i])) { mp->faceids[i] = - clib_host_to_net_u32 (((dpo_id_t *) & hicn_dpo_ctx-> - next_hops[i])->dpoi_index); + clib_host_to_net_u32 (((dpo_id_t *) & + hicn_dpo_ctx->next_hops[i])-> + dpoi_index); mp->nfaces++; } } @@ -566,7 +817,8 @@ static void fib_table_walk (fib_table->ft_index, FIB_PROTOCOL_IP4, vl_api_hicn_api_route_dump_walk, - &ctx);} + &ctx); + } )); pool_foreach (fib_table, im6->fibs, ( @@ -574,7 +826,8 @@ static void fib_table_walk (fib_table->ft_index, FIB_PROTOCOL_IP6, vl_api_hicn_api_route_dump_walk, - &ctx);} + &ctx); + } )); vec_foreach (lfeip, ctx.feis) @@ -647,11 +900,10 @@ static void vl_api_hicn_api_punting_add_t_handler hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); u32 swif = clib_net_to_host_u32 (mp->swif); - rv = - hicn_punt_interest_data_for_ip (vm, &prefix, swif, 0, NO_L2); + rv = hicn_punt_interest_data_for_ip (vm, &prefix, swif, 0, NO_L2); REPLY_MACRO (VL_API_HICN_API_PUNTING_ADD_REPLY /* , rmp, mp, rv */ ); } @@ -680,7 +932,7 @@ static void vl_api_hicn_api_register_prod_app_t_handler hicn_main_t *sm = &hicn_main; fib_prefix_t prefix; - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); u32 swif = clib_net_to_host_u32 (mp->swif); u32 cs_reserved = clib_net_to_host_u32 (mp->cs_reserved); u32 faceid; @@ -797,8 +1049,10 @@ hicn_face_api_entry_params_serialize (hicn_face_id_t faceid, if (face != NULL && face->shared.face_type == hicn_face_ip_type) { hicn_face_ip_t *face_ip = (hicn_face_ip_t *) face->data; - ip_address_encode(&face_ip->local_addr, IP46_TYPE_ANY, &reply->local_addr); - ip_address_encode(&face_ip->remote_addr, IP46_TYPE_ANY, &reply->remote_addr); + ip_address_encode (&face_ip->local_addr, IP46_TYPE_ANY, + &reply->local_addr); + ip_address_encode (&face_ip->remote_addr, IP46_TYPE_ANY, + &reply->remote_addr); reply->swif = clib_host_to_net_u32 (face->shared.sw_if); reply->flags = clib_host_to_net_u32 (face->shared.flags); reply->faceid = clib_host_to_net_u32 (faceid); diff --git a/hicn-plugin/src/hicn_api_test.c b/hicn-plugin/src/hicn_api_test.c index c29aa4a21..fa0e075f8 100644 --- a/hicn-plugin/src/hicn_api_test.c +++ b/hicn-plugin/src/hicn_api_test.c @@ -84,69 +84,94 @@ unformat_ip46_address (unformat_input_t * input, va_list * args) return 0; } -/* static ip46_type_t */ -/* ip_address_union_decode (const vl_api_address_union_t *in, */ -/* vl_api_address_family_t af, */ -/* ip46_address_t *out) */ -/* { */ -/* ip46_type_t type; */ - -/* switch (clib_net_to_host_u32 (af)) */ -/* { */ -/* case ADDRESS_IP4: */ -/* clib_memset (out, 0, sizeof (*out)); */ -/* clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); */ -/* type = IP46_TYPE_IP4; */ -/* break; */ -/* case ADDRESS_IP6: */ -/* clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); */ -/* type = IP46_TYPE_IP6; */ -/* break; */ -/* default: */ -/* ASSERT (!"Unkown address family in API address type"); */ -/* type = IP46_TYPE_ANY; */ -/* break; */ -/* } */ - -/* return type; */ -/* } */ - -/* static void */ -/* ip_address_union_encode (const ip46_address_t * in, */ -/* vl_api_address_family_t af, */ -/* vl_api_address_union_t * out) */ -/* { */ -/* if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) */ -/* memcpy (out->ip6.address, &in->ip6, sizeof (out->ip6)); */ -/* else */ -/* memcpy (out->ip4.address, &in->ip4, sizeof (out->ip4)); */ -/* } */ - -/* ip46_type_t ip_address_decode (const vl_api_address_t *in, ip46_address_t *out) */ -/* { */ -/* return (ip_address_union_decode (&in->un, in->af, out)); */ -/* } */ - -/* void ip_address_encode (const ip46_address_t *in, ip46_type_t type, */ -/* vl_api_address_t *out) */ -/* { */ -/* switch (type) */ -/* { */ -/* case IP46_TYPE_IP4: */ -/* out->af = clib_net_to_host_u32 (ADDRESS_IP4); */ -/* break; */ -/* case IP46_TYPE_IP6: */ -/* out->af = clib_net_to_host_u32 (ADDRESS_IP6); */ -/* break; */ -/* case IP46_TYPE_ANY: */ -/* if (ip46_address_is_ip4 (in)) */ -/* out->af = clib_net_to_host_u32 (ADDRESS_IP4); */ -/* else */ -/* out->af = clib_net_to_host_u32 (ADDRESS_IP6); */ -/* break; */ -/* } */ -/* ip_address_union_encode (in, out->af, &out->un); */ -/* } */ +static ip46_type_t +ip_address_union_decode (const vl_api_address_union_t * in, + vl_api_address_family_t af, ip46_address_t * out) +{ + ip46_type_t type; + + switch (clib_net_to_host_u32 (af)) + { + case ADDRESS_IP4: + clib_memset (out, 0, sizeof (*out)); + clib_memcpy (&out->ip4, &in->ip4, sizeof (out->ip4)); + type = IP46_TYPE_IP4; + break; + case ADDRESS_IP6: + clib_memcpy (&out->ip6, &in->ip6, sizeof (out->ip6)); + type = IP46_TYPE_IP6; + break; + default: + ASSERT (!"Unkown address family in API address type"); + type = IP46_TYPE_ANY; + break; + } + + return type; +} + +void +ip6_address_encode (const ip6_address_t * in, vl_api_ip6_address_t out) +{ + clib_memcpy (out, in, sizeof (*in)); +} + +void +ip6_address_decode (const vl_api_ip6_address_t in, ip6_address_t * out) +{ + clib_memcpy (out, in, sizeof (*out)); +} + +void +ip4_address_encode (const ip4_address_t * in, vl_api_ip4_address_t out) +{ + clib_memcpy (out, in, sizeof (*in)); +} + +void +ip4_address_decode (const vl_api_ip4_address_t in, ip4_address_t * out) +{ + clib_memcpy (out, in, sizeof (*out)); +} + +static void +ip_address_union_encode (const ip46_address_t * in, + vl_api_address_family_t af, + vl_api_address_union_t * out) +{ + if (ADDRESS_IP6 == clib_net_to_host_u32 (af)) + ip6_address_encode (&in->ip6, out->ip6); + else + ip4_address_encode (&in->ip4, out->ip4); +} + +ip46_type_t +ip_address_decode (const vl_api_address_t * in, ip46_address_t * out) +{ + return (ip_address_union_decode (&in->un, in->af, out)); +} + +void +ip_address_encode (const ip46_address_t * in, ip46_type_t type, + vl_api_address_t * out) +{ + switch (type) + { + case IP46_TYPE_IP4: + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + break; + case IP46_TYPE_IP6: + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; + case IP46_TYPE_ANY: + if (ip46_address_is_ip4 (in)) + out->af = clib_net_to_host_u32 (ADDRESS_IP4); + else + out->af = clib_net_to_host_u32 (ADDRESS_IP6); + break; + } + ip_address_union_encode (in, out->af, &out->un); +} ///////////////////////////////////////////////////// @@ -165,6 +190,7 @@ hicn_test_main_t hicn_test_main; #define foreach_standard_reply_retval_handler \ _(hicn_api_node_params_set_reply) \ _(hicn_api_face_ip_del_reply) \ +_(hicn_api_face_del_reply) \ _(hicn_api_route_nhops_add_reply) \ _(hicn_api_route_del_reply) \ _(hicn_api_route_nhop_del_reply) @@ -196,6 +222,10 @@ _(HICN_API_NODE_PARAMS_GET_REPLY, hicn_api_node_params_get_reply) \ _(HICN_API_NODE_STATS_GET_REPLY, hicn_api_node_stats_get_reply) \ _(HICN_API_FACE_IP_DEL_REPLY, hicn_api_face_ip_del_reply) \ _(HICN_API_FACE_IP_ADD_REPLY, hicn_api_face_ip_add_reply) \ +_(HICN_API_FACE_ADD_REPLY, hicn_api_face_add_reply) \ +_(HICN_API_FACE_DEL_REPLY, hicn_api_face_del_reply) \ +_(HICN_API_FACE_GET_REPLY, hicn_api_face_get_reply) \ +_(HICN_API_FACES_DETAILS, hicn_api_faces_details) \ _(HICN_API_FACE_STATS_DETAILS, hicn_api_face_stats_details) \ _(HICN_API_ROUTE_NHOPS_ADD_REPLY, hicn_api_route_nhops_add_reply) \ _(HICN_API_FACE_IP_PARAMS_GET_REPLY, hicn_api_face_ip_params_get_reply) \ @@ -393,22 +423,18 @@ api_hicn_api_face_ip_add (vat_main_t * vam) ip46_address_t remote_addr = { 0 }; int ret = HICN_ERROR_NONE; int sw_if = 0; - vl_api_hicn_api_face_ip_add_t *mp; + vl_api_hicn_api_face_add_t *mp; /* Parse args required to build the message */ while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { if (unformat - (input, "local %U", unformat_ip4_address, &local_addr.ip4)); - else - if (unformat - (input, "local %U", unformat_ip6_address, &local_addr.ip6)); - else - if (unformat - (input, "remote %U", unformat_ip4_address, &remote_addr.ip4)); + (input, "local %U", unformat_ip46_address, &local_addr, + IP46_TYPE_ANY)); else if (unformat - (input, "remote %U", unformat_ip6_address, &remote_addr.ip6)); + (input, "remote %U", unformat_ip46_address, &remote_addr, + IP46_TYPE_ANY)); else if (unformat (input, "intfc %d", &sw_if)); else { @@ -423,10 +449,11 @@ api_hicn_api_face_ip_add (vat_main_t * vam) return (1); } /* Construct the API message */ - M (HICN_API_FACE_IP_ADD, mp); - ip_address_decode (&mp->local_addr, &local_addr); - ip_address_decode (&mp->remote_addr, &remote_addr); - mp->swif = clib_host_to_net_u32 (sw_if); + M (HICN_API_FACE_ADD, mp); + mp->type = IP_FACE; + ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.ip.local_addr); + ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.ip.remote_addr); + mp->face.ip.swif = clib_host_to_net_u32 (sw_if); /* send it... */ S (mp); @@ -462,6 +489,85 @@ static void } static int +api_hicn_api_face_udp_add (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + ip46_address_t local_addr = ip46_address_initializer; + ip46_address_t remote_addr = ip46_address_initializer; + u32 sport = 0; + u32 dport = 0; + int ret = HICN_ERROR_NONE; + int sw_if = ~0; + vl_api_hicn_api_face_add_t *mp; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (input, "local %U port %u", unformat_ip46_address, &local_addr, + IP46_TYPE_ANY, &sport)); + else + if (unformat + (input, "remote %U port %u", unformat_ip46_address, &remote_addr, + IP46_TYPE_ANY, &dport)); + else if (unformat (input, "intfc %d", &sw_if)); + else + { + break; + } + } + + /* Check for presence of both addresses */ + if (ip46_address_is_zero (&remote_addr) + || ip46_address_is_zero (&local_addr) || sport == 0 || dport == 0) + { + clib_warning + ("Incomplete UDP face. Please specify local and remote address and port"); + return (1); + } + /* Construct the API message */ + M (HICN_API_FACE_ADD, mp); + mp->type = UDP_FACE; + ip_address_encode (&local_addr, IP46_TYPE_ANY, &mp->face.udp.local_addr); + ip_address_encode (&remote_addr, IP46_TYPE_ANY, &mp->face.udp.remote_addr); + mp->face.udp.lport = clib_host_to_net_u16 (sport); + mp->face.udp.rport = clib_host_to_net_u16 (dport); + mp->face.udp.swif = clib_host_to_net_u32 (sw_if); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static void + vl_api_hicn_api_face_add_reply_t_handler + (vl_api_hicn_api_face_add_reply_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + fformat (vam->ofp, "New Face ID: %d\n", ntohl (rmp->faceid)); +} + +static int api_hicn_api_face_ip_del (vat_main_t * vam) { unformat_input_t *input = vam->input; @@ -499,11 +605,48 @@ api_hicn_api_face_ip_del (vat_main_t * vam) } static int +api_hicn_api_face_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_del_t *mp; + u32 faceid = 0, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == ~0) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_DEL, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + +static int api_hicn_api_face_ip_params_get (vat_main_t * vam) { unformat_input_t *input = vam->input; vl_api_hicn_api_face_ip_params_get_t *mp; - u32 faceid = 0, ret; + u32 faceid = HICN_FACE_NULL, ret; while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) { @@ -517,7 +660,7 @@ api_hicn_api_face_ip_params_get (vat_main_t * vam) } //Check for presence of face ID - if (faceid == 0) + if (faceid == HICN_FACE_NULL) { clib_warning ("Please specify face ID"); return 1; @@ -560,8 +703,8 @@ static void return; } vec_reset_length (sbuf); - ip_address_decode(&rmp->local_addr, &local_addr); - ip_address_decode(&rmp->remote_addr, &remote_addr); + ip_address_decode (&rmp->local_addr, &local_addr); + ip_address_decode (&rmp->remote_addr, &remote_addr); sbuf = format (0, "local_addr %U remote_addr %U", format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address, @@ -569,11 +712,173 @@ static void fformat (vam->ofp, "%s swif %d flags %d\n", sbuf, - clib_net_to_host_u16 (rmp->swif), + clib_net_to_host_u32 (rmp->swif), clib_net_to_host_i32 (rmp->flags)); } -/* memif-dump API */ +static void format_ip_face (vl_api_hicn_face_ip_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + u8 *sbuf = 0; + ip46_address_t remote_addr; + ip46_address_t local_addr; + + vec_reset_length (sbuf); + ip_address_decode (&rmp->local_addr, &local_addr); + ip_address_decode (&rmp->remote_addr, &remote_addr); + sbuf = + format (0, "local_addr %U remote_addr %U", format_ip46_address, + &local_addr, 0 /*IP46_ANY_TYPE */ , format_ip46_address, + &remote_addr, 0 /*IP46_ANY_TYPE */ ); + + fformat (vam->ofp, "%s swif %d flags %d name %s\n", + sbuf, + clib_net_to_host_u32 (rmp->swif), + clib_net_to_host_i32 (rmp->flags), rmp->if_name); +} + +static void format_udp_face (vl_api_hicn_face_udp_t * rmp) +{ + vat_main_t *vam = hicn_test_main.vat_main; + u8 *sbuf = 0; + ip46_address_t remote_addr; + ip46_address_t local_addr; + + vec_reset_length (sbuf); + ip_address_decode (&rmp->local_addr, &local_addr); + ip_address_decode (&rmp->remote_addr, &remote_addr); + u16 lport = clib_net_to_host_u16 (rmp->lport); + u16 rport = clib_net_to_host_u16 (rmp->rport);; + sbuf = + format (0, "local_addr %U port %u remote_addr %U port %u", + format_ip46_address, &local_addr, 0 /*IP46_ANY_TYPE */ , lport, + format_ip46_address, + &remote_addr, 0 /*IP46_ANY_TYPE */ , rport); + + fformat (vam->ofp, "%s swif %d flags %d name %s\n", + sbuf, + clib_net_to_host_u16 (rmp->swif), + clib_net_to_host_i32 (rmp->flags), rmp->if_name); +} + +static int +api_hicn_api_faces_dump (vat_main_t * vam) +{ + hicn_test_main_t *hm = &hicn_test_main; + vl_api_hicn_api_faces_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (vam->json_output) + { + clib_warning ("JSON output not supported for faces_dump"); + return -99; + } + + M (HICN_API_FACES_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + mp_ping = vl_msg_api_alloc_as_if_client (sizeof (*mp_ping)); + mp_ping->_vl_msg_id = htons (hm->ping_id); + mp_ping->client_index = vam->my_client_index; + + fformat (vam->ofp, "Sending ping id=%d\n", hm->ping_id); + + vam->result_ready = 0; + S (mp_ping); + + W (ret); + return ret; +} + +static void + vl_api_hicn_api_faces_details_t_handler + (vl_api_hicn_api_faces_details_t * mp) +{ + if (mp->type == IP_FACE) + { + format_ip_face (&(mp->face.ip)); + } + else + { + format_udp_face (&(mp->face.udp)); + } +} + +static int +api_hicn_api_face_get (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_hicn_api_face_get_t *mp; + u32 faceid = HICN_FACE_NULL, ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "face %d", &faceid)) + {; + } + else + { + break; + } + } + + //Check for presence of face ID + if (faceid == HICN_FACE_NULL) + { + clib_warning ("Please specify face ID"); + return 1; + } + //Construct the API message + M (HICN_API_FACE_GET, mp); + mp->faceid = clib_host_to_net_u32 (faceid); + + //send it... + S (mp); + + //Wait for a reply... + W (ret); + + return ret; +} + + +static void + vl_api_hicn_api_face_get_reply_t_handler + (vl_api_hicn_api_face_get_reply_t * rmp) +{ + + vat_main_t *vam = hicn_test_main.vat_main; + i32 retval = ntohl (rmp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + return; + } + vam->retval = retval; + vam->result_ready = 1; + + if (vam->retval < 0) + { + //vpp_api_test infra will also print out string form of error + fformat (vam->ofp, " (API call error: %d)\n", vam->retval); + return; + } + + if (rmp->type == IP_FACE) + { + format_ip_face (&(rmp->face.ip)); + } + else + { + format_udp_face (&(rmp->face.udp)); + } +} + + + static int api_hicn_api_face_stats_dump (vat_main_t * vam) { @@ -632,7 +937,6 @@ static void clib_host_to_net_u64 (mp->dtx_bytes)); } - static int api_hicn_api_route_get (vat_main_t * vam) { @@ -655,14 +959,15 @@ api_hicn_api_route_get (vat_main_t * vam) } /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) { clib_warning ("Please specify a valid prefix..."); return 1; } //Construct the API message M (HICN_API_ROUTE_GET, mp); - ip_prefix_encode(&prefix, &mp->prefix); + ip_prefix_encode (&prefix, &mp->prefix); //send it... S (mp); @@ -764,7 +1069,7 @@ static void u8 *sbuf = 0; vec_reset_length (sbuf); - ip_prefix_decode(&mp->prefix, &prefix); + ip_prefix_decode (&mp->prefix, &prefix); sbuf = format (sbuf, "Prefix: %U/%u\n", format_ip46_address, &prefix.fp_addr, 0, prefix.fp_len); @@ -807,15 +1112,15 @@ api_hicn_api_route_nhops_add (vat_main_t * vam) } /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0) - || (faceid == 0)) + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0) || (faceid == 0)) { clib_warning ("Please specify prefix and faceid..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_NHOPS_ADD, mp); - ip_prefix_encode(&prefix, &mp->prefix); + ip_prefix_encode (&prefix, &mp->prefix); mp->face_ids[0] = clib_host_to_net_u32 (faceid); mp->n_faces = 1; @@ -851,14 +1156,15 @@ api_hicn_api_route_del (vat_main_t * vam) } /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_DEL, mp); - ip_prefix_encode(&prefix, &mp->prefix); + ip_prefix_encode (&prefix, &mp->prefix); /* send it... */ S (mp); @@ -895,15 +1201,15 @@ api_hicn_api_route_nhop_del (vat_main_t * vam) } /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0) - || (faceid == HICN_FACE_NULL)) + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0) || (faceid == HICN_FACE_NULL)) { clib_warning ("Please specify prefix and faceid..."); return 1; } /* Construct the API message */ M (HICN_API_ROUTE_NHOP_DEL, mp); - ip_prefix_encode(&prefix, &mp->prefix); + ip_prefix_encode (&prefix, &mp->prefix); mp->faceid = clib_host_to_net_u32 (faceid); @@ -1059,14 +1365,15 @@ api_hicn_api_register_prod_app (vat_main_t * vam) } /* Check parse */ - if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) || (prefix.fp_len == 0)) + if (((prefix.fp_addr.as_u64[0] == 0) && (prefix.fp_addr.as_u64[1] == 0)) + || (prefix.fp_len == 0)) { clib_warning ("Please specify prefix..."); return 1; } /* Construct the API message */ M (HICN_API_REGISTER_PROD_APP, mp); - ip_prefix_encode(&prefix, &mp->prefix); + ip_prefix_encode (&prefix, &mp->prefix); mp->swif = clib_host_to_net_u32 (swif); @@ -1143,14 +1450,15 @@ static void } ip46_address_t src_addr4 = ip46_address_initializer; ip46_address_t src_addr6 = ip46_address_initializer; - ip_address_decode(&mp->src_addr4, &src_addr4); - ip_address_decode(&mp->src_addr6, &src_addr6); + ip_address_decode (&mp->src_addr4, &src_addr4); + ip_address_decode (&mp->src_addr6, &src_addr6); fformat (vam->ofp, "ip4 address %U\n" "ip6 address :%U\n" "appif id :%d\n", - format_ip46_address, IP46_TYPE_ANY, &src_addr4, format_ip46_address, IP46_TYPE_ANY, &src_addr6); + format_ip46_address, IP46_TYPE_ANY, &src_addr4, + format_ip46_address, IP46_TYPE_ANY, &src_addr6); } /* @@ -1164,6 +1472,10 @@ _(hicn_api_node_params_get, "") \ _(hicn_api_node_stats_get, "") \ _(hicn_api_face_ip_del, "face <faceID>") \ _(hicn_api_face_ip_add, "local <address> remote <address> intfc <swif>")\ +_(hicn_api_face_udp_add, "local <address> port <port> remote <address> port <port> intfc <swif>") \ +_(hicn_api_face_del, "face <faceID>") \ +_(hicn_api_faces_dump, "") \ +_(hicn_api_face_get, "face <faceID>") \ _(hicn_api_face_stats_dump, "") \ _(hicn_api_route_nhops_add, "add prefix <IP4/IP6>/<subnet> face <faceID> weight <weight>") \ _(hicn_api_face_ip_params_get, "face <faceID>") \ |