From e86a8edd3c14fb41ace2a12efd17bc7772bf623f Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Fri, 5 Jan 2018 03:20:25 -0800 Subject: [PATCH] api: refactor vlibmemory - separate client/server code for both memory and socket apis - separate memory api code from generic vlib api code - move unix_shared_memory_fifo to svm and rename to svm_fifo_t - overall declutter Change-Id: I90cdd98ff74d0787d58825b914b0f1eafcfa4dc2 Signed-off-by: Florin Coras --- src/plugins/acl/acl.c | 20 +- src/plugins/gtpu/gtpu_api.c | 4 +- src/plugins/ioam/lib-trace/trace_api.c | 4 +- src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c | 4 +- src/plugins/memif/memif_api.c | 8 +- src/plugins/memif/memif_test.c | 2 +- src/plugins/nat/nat_api.c | 81 +- src/plugins/pppoe/pppoe_api.c | 4 +- src/plugins/stn/stn_api.c | 4 +- src/svm.am | 4 +- .../unix_shared_memory_queue.c => svm/queue.c} | 83 +- src/svm/queue.h | 68 + src/tests/vnet/session/tcp_echo.c | 34 +- src/tests/vnet/session/udp_echo.c | 32 +- src/vat/api_format.c | 2 +- src/vat/vat.h | 2 +- src/vcl/vppcom.c | 31 +- src/vlib-api.am | 23 +- src/vlib/node.c | 54 + src/vlib/node_funcs.h | 6 + src/vlibapi/api.h | 16 +- src/vlibapi/api_common.h | 12 +- src/vlibapi/api_helper_macros.h | 8 +- src/vlibapi/api_shared.c | 19 +- src/vlibapi/node_serialize.c | 59 +- src/vlibapi/node_unserialize.c | 227 - src/vlibmemory/api.h | 90 +- src/vlibmemory/api_common.h | 267 - src/vlibmemory/memory_api.c | 905 + src/vlibmemory/memory_api.h | 80 + src/vlibmemory/memory_client.c | 50 +- src/vlibmemory/memory_client.h | 46 + src/vlibmemory/memory_shared.c | 109 +- src/vlibmemory/memory_shared.h | 138 + src/vlibmemory/memory_vlib.c | 2803 --- src/vlibmemory/{socksvr_vlib.c => socket_api.c} | 35 +- src/vlibmemory/socket_api.h | 88 + src/vlibmemory/socket_client.c | 29 +- src/vlibmemory/socket_client.h | 64 + src/vlibmemory/unix_shared_memory_queue.h | 70 - src/vlibmemory/vlib_api.c | 750 + src/vlibmemory/vlib_api_cli.c | 1209 + src/vlibsocket/sockclnt_vlib.c | 6 +- src/vnet/bfd/bfd_api.c | 8 +- src/vnet/bier/bier_api.c | 20 +- src/vnet/classify/classify_api.c | 18 +- src/vnet/devices/ssvm/node.c | 8 +- src/vnet/devices/ssvm/ssvm_eth.c | 22 +- src/vnet/devices/ssvm/ssvm_eth.h | 3 +- src/vnet/devices/tap/tapv2_api.c | 11 +- src/vnet/devices/virtio/vhost_user_api.c | 10 +- src/vnet/dhcp/dhcp_api.c | 6 +- src/vnet/dns/resolver_process.c | 4 +- src/vnet/flow/flow_api.c | 9 +- src/vnet/geneve/geneve_api.c | 4 +- src/vnet/gre/gre_api.c | 4 +- src/vnet/interface_api.c | 13 +- src/vnet/ip/ip_api.c | 48 +- src/vnet/ip/punt_api.c | 4 +- src/vnet/ipsec-gre/ipsec_gre_api.c | 4 +- src/vnet/ipsec/ipsec_api.c | 9 +- src/vnet/l2/l2_api.c | 13 +- src/vnet/l2/l2_fib.c | 2 +- src/vnet/l2tp/l2tp_api.c | 4 +- src/vnet/lisp-cp/lisp_api.c | 41 +- src/vnet/lisp-cp/one_api.c | 41 +- src/vnet/lisp-gpe/lisp_gpe_api.c | 2 +- src/vnet/map/map_api.c | 7 +- src/vnet/mfib/mfib_signal.c | 2 +- src/vnet/mfib/mfib_signal.h | 6 +- src/vnet/mpls/mpls_api.c | 8 +- src/vnet/policer/policer_api.c | 4 +- src/vnet/session/application.c | 2 +- src/vnet/session/application.h | 2 +- src/vnet/session/segment_manager.c | 16 +- src/vnet/session/segment_manager.h | 10 +- src/vnet/session/session.c | 12 +- src/vnet/session/session.h | 6 +- src/vnet/session/session_api.c | 27 +- src/vnet/session/session_node.c | 10 +- src/vnet/span/span_api.c | 2 +- src/vnet/srv6/sr_api.c | 4 +- src/vnet/tcp/builtin_client.c | 2 +- src/vnet/tcp/builtin_client.h | 5 +- src/vnet/tcp/builtin_http_server.c | 11 +- src/vnet/tcp/builtin_proxy.c | 6 +- src/vnet/tcp/builtin_proxy.h | 7 +- src/vnet/tcp/builtin_server.c | 13 +- src/vnet/udp/builtin_server.c | 5 +- src/vnet/udp/udp_api.c | 36 +- src/vnet/unix/tap_api.c | 13 +- src/vnet/vxlan-gpe/vxlan_gpe_api.c | 4 +- src/vnet/vxlan/vxlan_api.c | 4 +- src/vpp-api/client/client.c | 14 +- src/vpp-api/java/jvpp-acl/jvpp_acl.c | 2 +- src/vpp-api/java/jvpp-acl/jvpp_acl.h | 2 +- src/vpp-api/java/jvpp-common/jvpp_common.h | 2 +- src/vpp-api/java/jvpp-core/jvpp_core.c | 4 +- src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.c | 2 +- src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.h | 2 +- .../java/jvpp-ioamexport/jvpp_ioam_export.c | 2 +- .../java/jvpp-ioamexport/jvpp_ioam_export.h | 2 +- src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c | 2 +- src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.h | 2 +- src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c | 2 +- src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.h | 2 +- src/vpp-api/java/jvpp-nat/jvpp_nat.c | 2 +- src/vpp-api/java/jvpp-nat/jvpp_nat.h | 2 +- src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.c | 2 +- src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.h | 2 +- src/vpp-api/vapi/vapi.c | 22 +- src/vpp/api/api.c | 15 +- src/vpp/api/api_format.c | 23266 ++++++++++++++++++- src/vpp/api/summary_stats_client.c | 2 +- src/vpp/api/test_client.c | 2 +- src/vpp/api/test_ha.c | 2 +- src/vpp/api/vat.h | 263 +- src/vpp/oam/oam_api.c | 2 +- src/vpp/stats/stats.c | 101 +- src/vpp/stats/stats.h | 2 +- src/vppinfra/file.h | 1 + 121 files changed, 27614 insertions(+), 4194 deletions(-) rename src/{vlibmemory/unix_shared_memory_queue.c => svm/queue.c} (83%) create mode 100644 src/svm/queue.h delete mode 100644 src/vlibapi/node_unserialize.c delete mode 100644 src/vlibmemory/api_common.h create mode 100644 src/vlibmemory/memory_api.c create mode 100644 src/vlibmemory/memory_api.h create mode 100644 src/vlibmemory/memory_client.h create mode 100644 src/vlibmemory/memory_shared.h delete mode 100644 src/vlibmemory/memory_vlib.c rename src/vlibmemory/{socksvr_vlib.c => socket_api.c} (96%) create mode 100644 src/vlibmemory/socket_api.h create mode 100644 src/vlibmemory/socket_client.h delete mode 100644 src/vlibmemory/unix_shared_memory_queue.h create mode 100644 src/vlibmemory/vlib_api.c create mode 100644 src/vlibmemory/vlib_api_cli.c mode change 120000 => 100644 src/vpp/api/api_format.c mode change 120000 => 100644 src/vpp/api/vat.h diff --git a/src/plugins/acl/acl.c b/src/plugins/acl/acl.c index a8699961b47..b93d3bca1c4 100644 --- a/src/plugins/acl/acl.c +++ b/src/plugins/acl/acl.c @@ -138,7 +138,7 @@ vl_api_acl_plugin_get_version_t_handler (vl_api_acl_plugin_get_version_t * mp) acl_main_t *am = &acl_main; vl_api_acl_plugin_get_version_reply_t *rmp; int msg_size = sizeof (*rmp); - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -1871,7 +1871,7 @@ copy_acl_rule_to_api_rule (vl_api_acl_rule_t * api_rule, acl_rule_t * r) } static void -send_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q, +send_acl_details (acl_main_t * am, svm_queue_t * q, acl_list_t * acl, u32 context) { vl_api_acl_details_t *mp; @@ -1909,7 +1909,7 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp) acl_list_t *acl; int rv = -1; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -1946,7 +1946,7 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp) static void send_acl_interface_list_details (acl_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, u32 sw_if_index, u32 context) { vl_api_acl_interface_list_details_t *mp; @@ -1999,7 +1999,7 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t * vnet_interface_main_t *im = &am->vnet_main->interface_main; u32 sw_if_index; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -2113,7 +2113,7 @@ static void } static void -send_macip_acl_details (acl_main_t * am, unix_shared_memory_queue_t * q, +send_macip_acl_details (acl_main_t * am, svm_queue_t * q, macip_acl_list_t * acl, u32 context) { vl_api_macip_acl_details_t *mp; @@ -2168,7 +2168,7 @@ vl_api_macip_acl_dump_t_handler (vl_api_macip_acl_dump_t * mp) acl_main_t *am = &acl_main; macip_acl_list_t *acl; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -2206,7 +2206,7 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t * vl_api_macip_acl_interface_get_reply_t *rmp; u32 count = vec_len (am->macip_acl_by_sw_if_index); int msg_size = sizeof (*rmp) + sizeof (rmp->acls[0]) * count; - unix_shared_memory_queue_t *q; + svm_queue_t *q; int i; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -2231,7 +2231,7 @@ vl_api_macip_acl_interface_get_t_handler (vl_api_macip_acl_interface_get_t * static void send_macip_acl_interface_list_details (acl_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, u32 sw_if_index, u32 acl_index, u32 context) { @@ -2257,7 +2257,7 @@ static void vl_api_macip_acl_interface_list_dump_t_handler (vl_api_macip_acl_interface_list_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; acl_main_t *am = &acl_main; u32 sw_if_index = ntohl (mp->sw_if_index); diff --git a/src/plugins/gtpu/gtpu_api.c b/src/plugins/gtpu/gtpu_api.c index 5a77ab7f851..1b93578a95d 100644 --- a/src/plugins/gtpu/gtpu_api.c +++ b/src/plugins/gtpu/gtpu_api.c @@ -148,7 +148,7 @@ out: } static void send_gtpu_tunnel_details - (gtpu_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (gtpu_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_gtpu_tunnel_details_t *rmp; ip4_main_t *im4 = &ip4_main; @@ -183,7 +183,7 @@ static void send_gtpu_tunnel_details static void vl_api_gtpu_tunnel_dump_t_handler (vl_api_gtpu_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; gtpu_main_t *gtm = >pu_main; gtpu_tunnel_t *t; u32 sw_if_index; diff --git a/src/plugins/ioam/lib-trace/trace_api.c b/src/plugins/ioam/lib-trace/trace_api.c index cd00c591fda..bb043f7c831 100644 --- a/src/plugins/ioam/lib-trace/trace_api.c +++ b/src/plugins/ioam/lib-trace/trace_api.c @@ -62,7 +62,7 @@ #define TRACE_REPLY_MACRO(t) \ do { \ - unix_shared_memory_queue_t * q = \ + svm_queue_t * q = \ vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ return; \ @@ -78,7 +78,7 @@ do { \ /* *INDENT-OFF* */ #define TRACE_REPLY_MACRO2(t, body) \ do { \ - unix_shared_memory_queue_t * q; \ + svm_queue_t * q; \ rv = vl_msg_api_pd_handler (mp, rv); \ q = vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ diff --git a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c index 3bc682bfbfb..870764eb971 100644 --- a/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c +++ b/src/plugins/ioam/lib-vxlan-gpe/vxlan_gpe_api.c @@ -61,7 +61,7 @@ #define VXLAN_GPE_REPLY_MACRO(t) \ do { \ - unix_shared_memory_queue_t * q = \ + svm_queue_t * q = \ vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ return; \ @@ -77,7 +77,7 @@ do { \ /* *INDENT-OFF* */ #define VXLAN_GPE_REPLY_MACRO2(t, body) \ do { \ - unix_shared_memory_queue_t * q; \ + svm_queue_t * q; \ rv = vl_msg_api_pd_handler (mp, rv); \ q = vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ diff --git a/src/plugins/memif/memif_api.c b/src/plugins/memif/memif_api.c index 684f53c5193..068fd3d69f0 100644 --- a/src/plugins/memif/memif_api.c +++ b/src/plugins/memif/memif_api.c @@ -60,7 +60,7 @@ */ #define REPLY_MACRO(t) \ do { \ - unix_shared_memory_queue_t * q = \ + svm_queue_t * q = \ vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ return; \ @@ -75,7 +75,7 @@ do { \ #define REPLY_MACRO2(t, body) \ do { \ - unix_shared_memory_queue_t * q = \ + svm_queue_t * q = \ vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ return; \ @@ -219,7 +219,7 @@ vl_api_memif_delete_t_handler (vl_api_memif_delete_t * mp) } static void -send_memif_details (unix_shared_memory_queue_t * q, +send_memif_details (svm_queue_t * q, memif_if_t * mif, vnet_sw_interface_t * swif, u8 * interface_name, u32 context) @@ -270,7 +270,7 @@ vl_api_memif_dump_t_handler (vl_api_memif_dump_t * mp) vnet_sw_interface_t *swif; memif_if_t *mif; u8 *if_name = 0; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) diff --git a/src/plugins/memif/memif_test.c b/src/plugins/memif/memif_test.c index 559d0f7d19f..00b3ad5d22c 100644 --- a/src/plugins/memif/memif_test.c +++ b/src/plugins/memif/memif_test.c @@ -361,7 +361,7 @@ vat_plugin_register (vat_main_t * vam) const char *id ## _CRC __attribute__ ((unused)) = #n "_" #crc; foreach_vl_msg_name_crc_vpe; #undef _ - mm->ping_id = vl_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); + mm->ping_id = vl_msg_api_get_msg_index ((u8 *) (VL_API_CONTROL_PING_CRC)); if (mm->msg_id_base != (u16) ~0) memif_vat_api_hookup (vam); diff --git a/src/plugins/nat/nat_api.c b/src/plugins/nat/nat_api.c index d0efb001843..bc192a782f6 100644 --- a/src/plugins/nat/nat_api.c +++ b/src/plugins/nat/nat_api.c @@ -174,8 +174,7 @@ vl_api_nat_set_workers_t_print (vl_api_nat_set_workers_t * mp, void *handle) } static void -send_nat_worker_details (u32 worker_index, unix_shared_memory_queue_t * q, - u32 context) +send_nat_worker_details (u32 worker_index, svm_queue_t * q, u32 context) { vl_api_nat_worker_details_t *rmp; snat_main_t *sm = &snat_main; @@ -196,7 +195,7 @@ send_nat_worker_details (u32 worker_index, unix_shared_memory_queue_t * q, static void vl_api_nat_worker_dump_t_handler (vl_api_nat_worker_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; u32 *worker_index; @@ -316,7 +315,7 @@ vl_api_nat_get_reass_t_print (vl_api_nat_get_reass_t * mp, void *handle) typedef struct nat_api_walk_ctx_t_ { - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 context; } nat_api_walk_ctx_t; @@ -369,7 +368,7 @@ nat_ip6_reass_walk_api (nat_reass_ip6_t * reass, void *arg) static void vl_api_nat_reass_dump_t_handler (vl_api_nat_reass_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -469,8 +468,7 @@ static void *vl_api_nat44_add_del_address_range_t_print static void send_nat44_address_details (snat_address_t * a, - unix_shared_memory_queue_t * q, u32 context, - u8 twice_nat) + svm_queue_t * q, u32 context, u8 twice_nat) { vl_api_nat44_address_details_t *rmp; snat_main_t *sm = &snat_main; @@ -495,7 +493,7 @@ send_nat44_address_details (snat_address_t * a, static void vl_api_nat44_address_dump_t_handler (vl_api_nat44_address_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_address_t *a; @@ -556,7 +554,7 @@ static void *vl_api_nat44_interface_add_del_feature_t_print static void send_nat44_interface_details (snat_interface_t * i, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_interface_details_t *rmp; snat_main_t *sm = &snat_main; @@ -576,7 +574,7 @@ send_nat44_interface_details (snat_interface_t * i, static void vl_api_nat44_interface_dump_t_handler (vl_api_nat44_interface_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_interface_t *i; @@ -638,8 +636,7 @@ static void *vl_api_nat44_interface_add_del_output_feature_t_print static void send_nat44_interface_output_feature_details (snat_interface_t * i, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_interface_output_feature_details_t *rmp; snat_main_t *sm = &snat_main; @@ -659,7 +656,7 @@ static void vl_api_nat44_interface_output_feature_dump_t_handler (vl_api_nat44_interface_output_feature_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_interface_t *i; @@ -745,8 +742,7 @@ static void *vl_api_nat44_add_del_static_mapping_t_print static void send_nat44_static_mapping_details (snat_static_mapping_t * m, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_static_mapping_details_t *rmp; snat_main_t *sm = &snat_main; @@ -771,8 +767,7 @@ send_nat44_static_mapping_details (snat_static_mapping_t * m, static void send_nat44_static_map_resolve_details (snat_static_map_resolve_t * m, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_static_mapping_details_t *rmp; snat_main_t *sm = &snat_main; @@ -798,7 +793,7 @@ static void vl_api_nat44_static_mapping_dump_t_handler (vl_api_nat44_static_mapping_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_static_mapping_t *m; snat_static_map_resolve_t *rp; @@ -891,8 +886,7 @@ static void *vl_api_nat44_add_del_identity_mapping_t_print static void send_nat44_identity_mapping_details (snat_static_mapping_t * m, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_identity_mapping_details_t *rmp; snat_main_t *sm = &snat_main; @@ -914,8 +908,7 @@ send_nat44_identity_mapping_details (snat_static_mapping_t * m, static void send_nat44_identity_map_resolve_details (snat_static_map_resolve_t * m, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_identity_mapping_details_t *rmp; snat_main_t *sm = &snat_main; @@ -938,7 +931,7 @@ static void vl_api_nat44_identity_mapping_dump_t_handler (vl_api_nat44_identity_mapping_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_static_mapping_t *m; snat_static_map_resolve_t *rp; @@ -1008,8 +1001,7 @@ static void *vl_api_nat44_add_del_interface_addr_t_print static void send_nat44_interface_addr_details (u32 sw_if_index, - unix_shared_memory_queue_t * q, - u32 context, u8 twice_nat) + svm_queue_t * q, u32 context, u8 twice_nat) { vl_api_nat44_interface_addr_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1029,7 +1021,7 @@ static void vl_api_nat44_interface_addr_dump_t_handler (vl_api_nat44_interface_addr_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; u32 *i; @@ -1057,8 +1049,7 @@ vl_api_nat44_interface_addr_dump_t_print (vl_api_nat44_interface_addr_dump_t * } static void -send_nat44_user_details (snat_user_t * u, unix_shared_memory_queue_t * q, - u32 context) +send_nat44_user_details (snat_user_t * u, svm_queue_t * q, u32 context) { vl_api_nat44_user_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1081,7 +1072,7 @@ send_nat44_user_details (snat_user_t * u, unix_shared_memory_queue_t * q, static void vl_api_nat44_user_dump_t_handler (vl_api_nat44_user_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; snat_user_t *u; @@ -1109,7 +1100,7 @@ vl_api_nat44_user_dump_t_print (vl_api_nat44_user_dump_t * mp, void *handle) static void send_nat44_user_session_details (snat_session_t * s, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_user_session_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1145,7 +1136,7 @@ static void vl_api_nat44_user_session_dump_t_handler (vl_api_nat44_user_session_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_main_per_thread_data_t *tsm; snat_session_t *s; @@ -1267,8 +1258,7 @@ static void *vl_api_nat44_add_del_lb_static_mapping_t_print static void send_nat44_lb_static_mapping_details (snat_static_mapping_t * m, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { vl_api_nat44_lb_static_mapping_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1306,7 +1296,7 @@ static void vl_api_nat44_lb_static_mapping_dump_t_handler (vl_api_nat44_lb_static_mapping_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_static_mapping_t *m; @@ -1397,7 +1387,7 @@ static void vl_api_nat44_forwarding_is_enabled_t_handler (vl_api_nat44_forwarding_is_enabled_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; vl_api_nat44_forwarding_is_enabled_reply_t *rmp; @@ -1562,8 +1552,7 @@ vl_api_nat_det_reverse_t_print (vl_api_nat_det_reverse_t * mp, void *handle) } static void -sent_nat_det_map_details (snat_det_map_t * m, unix_shared_memory_queue_t * q, - u32 context) +sent_nat_det_map_details (snat_det_map_t * m, svm_queue_t * q, u32 context) { vl_api_nat_det_map_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1587,7 +1576,7 @@ sent_nat_det_map_details (snat_det_map_t * m, unix_shared_memory_queue_t * q, static void vl_api_nat_det_map_dump_t_handler (vl_api_nat_det_map_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; snat_det_map_t *m; @@ -1778,7 +1767,7 @@ vl_api_nat_det_close_session_in_t_print (vl_api_nat_det_close_session_in_t * static void send_nat_det_session_details (snat_det_session_t * s, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_nat_det_session_details_t *rmp; snat_main_t *sm = &snat_main; @@ -1800,7 +1789,7 @@ send_nat_det_session_details (snat_det_session_t * s, static void vl_api_nat_det_session_dump_t_handler (vl_api_nat_det_session_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; snat_main_t *sm = &snat_main; ip4_address_t user_addr; snat_det_map_t *dm; @@ -1896,7 +1885,7 @@ static void *vl_api_nat64_add_del_pool_addr_range_t_print typedef struct nat64_api_walk_ctx_t_ { - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 context; nat64_db_t *db; } nat64_api_walk_ctx_t; @@ -1931,7 +1920,7 @@ nat64_api_pool_walk (snat_address_t * a, void *arg) static void vl_api_nat64_pool_addr_dump_t_handler (vl_api_nat64_pool_addr_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -2013,7 +2002,7 @@ nat64_api_interface_walk (snat_interface_t * i, void *arg) static void vl_api_nat64_interface_dump_t_handler (vl_api_nat64_interface_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -2111,7 +2100,7 @@ nat64_api_bib_walk (nat64_db_bib_entry_t * bibe, void *arg) static void vl_api_nat64_bib_dump_t_handler (vl_api_nat64_bib_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; nat64_main_t *nm = &nat64_main; nat64_db_t *db; @@ -2244,7 +2233,7 @@ nat64_api_st_walk (nat64_db_st_entry_t * ste, void *arg) static void vl_api_nat64_st_dump_t_handler (vl_api_nat64_st_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; nat64_main_t *nm = &nat64_main; nat64_db_t *db; @@ -2328,7 +2317,7 @@ nat64_api_prefix_walk (nat64_prefix_t * p, void *arg) static void vl_api_nat64_prefix_dump_t_handler (vl_api_nat64_prefix_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) diff --git a/src/plugins/pppoe/pppoe_api.c b/src/plugins/pppoe/pppoe_api.c index 04326572ce7..f8a02279cc9 100644 --- a/src/plugins/pppoe/pppoe_api.c +++ b/src/plugins/pppoe/pppoe_api.c @@ -118,7 +118,7 @@ out: } static void send_pppoe_session_details - (pppoe_session_t * t, unix_shared_memory_queue_t * q, u32 context) + (pppoe_session_t * t, svm_queue_t * q, u32 context) { vl_api_pppoe_session_details_t *rmp; ip4_main_t *im4 = &ip4_main; @@ -152,7 +152,7 @@ static void send_pppoe_session_details static void vl_api_pppoe_session_dump_t_handler (vl_api_pppoe_session_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; pppoe_main_t *pem = &pppoe_main; pppoe_session_t *t; u32 sw_if_index; diff --git a/src/plugins/stn/stn_api.c b/src/plugins/stn/stn_api.c index 02ea29b6443..73136e09f91 100644 --- a/src/plugins/stn/stn_api.c +++ b/src/plugins/stn/stn_api.c @@ -108,7 +108,7 @@ vl_api_stn_add_del_rule_t_handler (vl_api_stn_add_del_rule_t * mp) } static void -send_stn_rule (stn_rule_t *r, unix_shared_memory_queue_t *q, u32 context) +send_stn_rule (stn_rule_t *r, svm_queue_t *q, u32 context) { vl_api_stn_rule_details_t *rmp; @@ -137,7 +137,7 @@ send_stn_rule (stn_rule_t *r, unix_shared_memory_queue_t *q, u32 context) static void vl_api_stn_rules_dump_t_handler (vl_api_stn_rules_dump_t *mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; stn_main_t *stn = &stn_main; stn_rule_t *r; diff --git a/src/svm.am b/src/svm.am index 002c06cbef2..748ef147d0e 100644 --- a/src/svm.am +++ b/src/svm.am @@ -20,7 +20,8 @@ nobase_include_HEADERS += \ svm/svmdb.h \ svm/svm_fifo.h \ svm/svm_fifo_segment.h \ - svm/svm.h + svm/queue.h \ + svm/svm.h lib_LTLIBRARIES += libsvm.la libsvmdb.la @@ -29,6 +30,7 @@ libsvm_la_SOURCES = \ svm/ssvm.c \ svm/svm_fifo.c \ svm/svm_fifo_segment.c \ + svm/queue.c \ svm/memfd.c libsvm_la_LIBADD = libvppinfra.la -lrt -lpthread diff --git a/src/vlibmemory/unix_shared_memory_queue.c b/src/svm/queue.c similarity index 83% rename from src/vlibmemory/unix_shared_memory_queue.c rename to src/svm/queue.c index 4db4851c111..aef409277db 100644 --- a/src/vlibmemory/unix_shared_memory_queue.c +++ b/src/svm/queue.c @@ -1,6 +1,6 @@ /* *------------------------------------------------------------------ - * unix_shared_memory_queue.c - unidirectional shared-memory queues + * svm_queue.c - unidirectional shared-memory queues * * Copyright (c) 2009 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,6 +17,7 @@ *------------------------------------------------------------------ */ + #include #include #include @@ -24,11 +25,11 @@ #include #include #include -#include +#include #include /* - * unix_shared_memory_queue_init + * svm_queue_init * * nels = number of elements on the queue * elsize = element size, presumably 4 and cacheline-size will @@ -45,17 +46,15 @@ * You probably want to be on an svm data heap before calling this * function. */ -unix_shared_memory_queue_t * -unix_shared_memory_queue_init (int nels, - int elsize, - int consumer_pid, - int signal_when_queue_non_empty) +svm_queue_t * +svm_queue_init (int nels, + int elsize, int consumer_pid, int signal_when_queue_non_empty) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; pthread_mutexattr_t attr; pthread_condattr_t cattr; - q = clib_mem_alloc_aligned (sizeof (unix_shared_memory_queue_t) + q = clib_mem_alloc_aligned (sizeof (svm_queue_t) + nels * elsize, CLIB_CACHE_LINE_BYTES); memset (q, 0, sizeof (*q)); @@ -89,10 +88,10 @@ unix_shared_memory_queue_init (int nels, } /* - * unix_shared_memory_queue_free + * svm_queue_free */ void -unix_shared_memory_queue_free (unix_shared_memory_queue_t * q) +svm_queue_free (svm_queue_t * q) { (void) pthread_mutex_destroy (&q->mutex); (void) pthread_cond_destroy (&q->condvar); @@ -100,29 +99,28 @@ unix_shared_memory_queue_free (unix_shared_memory_queue_t * q) } void -unix_shared_memory_queue_lock (unix_shared_memory_queue_t * q) +svm_queue_lock (svm_queue_t * q) { pthread_mutex_lock (&q->mutex); } void -unix_shared_memory_queue_unlock (unix_shared_memory_queue_t * q) +svm_queue_unlock (svm_queue_t * q) { pthread_mutex_unlock (&q->mutex); } int -unix_shared_memory_queue_is_full (unix_shared_memory_queue_t * q) +svm_queue_is_full (svm_queue_t * q) { return q->cursize == q->maxsize; } /* - * unix_shared_memory_queue_add_nolock + * svm_queue_add_nolock */ int -unix_shared_memory_queue_add_nolock (unix_shared_memory_queue_t * q, - u8 * elem) +svm_queue_add_nolock (svm_queue_t * q, u8 * elem) { i8 *tailp; int need_broadcast = 0; @@ -156,7 +154,7 @@ unix_shared_memory_queue_add_nolock (unix_shared_memory_queue_t * q, } int -unix_shared_memory_queue_add_raw (unix_shared_memory_queue_t * q, u8 * elem) +svm_queue_add_raw (svm_queue_t * q, u8 * elem) { i8 *tailp; @@ -179,11 +177,10 @@ unix_shared_memory_queue_add_raw (unix_shared_memory_queue_t * q, u8 * elem) /* - * unix_shared_memory_queue_add + * svm_queue_add */ int -unix_shared_memory_queue_add (unix_shared_memory_queue_t * q, - u8 * elem, int nowait) +svm_queue_add (svm_queue_t * q, u8 * elem, int nowait) { i8 *tailp; int need_broadcast = 0; @@ -235,11 +232,10 @@ unix_shared_memory_queue_add (unix_shared_memory_queue_t * q, } /* - * unix_shared_memory_queue_add2 + * svm_queue_add2 */ int -unix_shared_memory_queue_add2 (unix_shared_memory_queue_t * q, u8 * elem, - u8 * elem2, int nowait) +svm_queue_add2 (svm_queue_t * q, u8 * elem, u8 * elem2, int nowait) { i8 *tailp; int need_broadcast = 0; @@ -300,11 +296,10 @@ unix_shared_memory_queue_add2 (unix_shared_memory_queue_t * q, u8 * elem, } /* - * unix_shared_memory_queue_sub + * svm_queue_sub */ int -unix_shared_memory_queue_sub (unix_shared_memory_queue_t * q, - u8 * elem, int nowait) +svm_queue_sub (svm_queue_t * q, u8 * elem, int nowait) { i8 *headp; int need_broadcast = 0; @@ -355,7 +350,37 @@ unix_shared_memory_queue_sub (unix_shared_memory_queue_t * q, } int -unix_shared_memory_queue_sub_raw (unix_shared_memory_queue_t * q, u8 * elem) +svm_queue_sub2 (svm_queue_t * q, u8 * elem) +{ + int need_broadcast; + i8 *headp; + + pthread_mutex_lock (&q->mutex); + if (q->cursize == 0) + { + pthread_mutex_unlock (&q->mutex); + return -1; + } + + headp = (i8 *) (&q->data[0] + q->elsize * q->head); + clib_memcpy (elem, headp, q->elsize); + + q->head++; + need_broadcast = (q->cursize == q->maxsize / 2); + q->cursize--; + + if (PREDICT_FALSE (q->head == q->maxsize)) + q->head = 0; + pthread_mutex_unlock (&q->mutex); + + if (need_broadcast) + (void) pthread_cond_broadcast (&q->condvar); + + return 0; +} + +int +svm_queue_sub_raw (svm_queue_t * q, u8 * elem) { i8 *headp; diff --git a/src/svm/queue.h b/src/svm/queue.h new file mode 100644 index 00000000000..dc1fc36e002 --- /dev/null +++ b/src/svm/queue.h @@ -0,0 +1,68 @@ +/* + *------------------------------------------------------------------ + * svm_queue.h - shared-memory queues + * + * Copyright (c) 2009 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef included_svm_queue_h +#define included_svm_queue_h + +#include + +typedef struct _svm_queue +{ + pthread_mutex_t mutex; /* 8 bytes */ + pthread_cond_t condvar; /* 8 bytes */ + int head; + int tail; + volatile int cursize; + int maxsize; + int elsize; + int consumer_pid; + int signal_when_queue_non_empty; + char data[0]; +} svm_queue_t; + +svm_queue_t *svm_queue_init (int nels, + int elsize, + int consumer_pid, + int signal_when_queue_non_empty); +void svm_queue_free (svm_queue_t * q); +int svm_queue_add (svm_queue_t * q, u8 * elem, int nowait); +int svm_queue_add2 (svm_queue_t * q, u8 * elem, u8 * elem2, int nowait); +int svm_queue_sub (svm_queue_t * q, u8 * elem, int nowait); +int svm_queue_sub2 (svm_queue_t * q, u8 * elem); +void svm_queue_lock (svm_queue_t * q); +void svm_queue_unlock (svm_queue_t * q); +int svm_queue_is_full (svm_queue_t * q); +int svm_queue_add_nolock (svm_queue_t * q, u8 * elem); +int svm_queue_sub_raw (svm_queue_t * q, u8 * elem); +int svm_queue_add_raw (svm_queue_t * q, u8 * elem); + +/* + * DEPRECATED please use svm_queue_t instead + */ +typedef svm_queue_t unix_shared_memory_queue_t; + +#endif /* included_svm_queue_h */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/tests/vnet/session/tcp_echo.c b/src/tests/vnet/session/tcp_echo.c index 30eb54dcdda..ed9e2f7b780 100644 --- a/src/tests/vnet/session/tcp_echo.c +++ b/src/tests/vnet/session/tcp_echo.c @@ -60,7 +60,7 @@ typedef enum typedef struct { /* vpe input queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* API client handle */ u32 my_client_index; @@ -88,10 +88,10 @@ typedef struct int drop_packets; /* Our event queue */ - unix_shared_memory_queue_t *our_event_queue; + svm_queue_t *our_event_queue; /* $$$ single thread only for the moment */ - unix_shared_memory_queue_t *vpp_event_queue; + svm_queue_t *vpp_event_queue; u8 *socket_name; @@ -271,8 +271,7 @@ vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t * } utm->our_event_queue = - uword_to_pointer (mp->app_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->app_event_queue_address, svm_queue_t *); utm->state = STATE_ATTACHED; } @@ -506,8 +505,7 @@ client_handle_event_queue (uri_tcp_test_main_t * utm) { session_fifo_event_t _e, *e = &_e;; - unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e, - 0 /* nowait */ ); + svm_queue_sub (utm->our_event_queue, (u8 *) e, 0 /* nowait */ ); switch (e->event_type) { case FIFO_EVENT_APP_RX: @@ -532,8 +530,7 @@ client_rx_thread_fn (void *arg) utm->client_bytes_received = 0; while (1) { - unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e, - 0 /* nowait */ ); + svm_queue_sub (utm->our_event_queue, (u8 *) e, 0 /* nowait */ ); switch (e->event_type) { case FIFO_EVENT_APP_RX: @@ -578,8 +575,7 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) } utm->vpp_event_queue = - uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *); /* * Setup session @@ -650,9 +646,8 @@ send_test_chunk (uri_tcp_test_main_t * utm, svm_fifo_t * tx_fifo, int mypid, evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - unix_shared_memory_queue_add (utm->vpp_event_queue, - (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (utm->vpp_event_queue, + (u8 *) & evt, 0 /* do wait for mutex */ ); } } } @@ -915,8 +910,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) clib_warning ("Accepted session from: %s:%d", ip_str, clib_net_to_host_u16 (mp->port)); utm->vpp_event_queue = - uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *); /* Allocate local session and set it up */ pool_get (utm->sessions, session); @@ -965,7 +959,7 @@ server_handle_fifo_event_rx (uri_tcp_test_main_t * utm, svm_fifo_t *rx_fifo, *tx_fifo; int n_read; session_fifo_event_t evt; - unix_shared_memory_queue_t *q; + svm_queue_t *q; session_t *session; int rv; u32 max_dequeue, offset, max_transfer, rx_buf_len; @@ -1019,8 +1013,7 @@ server_handle_fifo_event_rx (uri_tcp_test_main_t * utm, evt.event_type = FIFO_EVENT_APP_TX; q = utm->vpp_event_queue; - unix_shared_memory_queue_add (q, (u8 *) & evt, - 1 /* do wait for mutex */ ); + svm_queue_add (q, (u8 *) & evt, 1 /* do wait for mutex */ ); } } } @@ -1034,8 +1027,7 @@ server_handle_event_queue (uri_tcp_test_main_t * utm) while (1) { - unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e, - 0 /* nowait */ ); + svm_queue_sub (utm->our_event_queue, (u8 *) e, 0 /* nowait */ ); switch (e->event_type) { case FIFO_EVENT_APP_RX: diff --git a/src/tests/vnet/session/udp_echo.c b/src/tests/vnet/session/udp_echo.c index ac9411835ec..4e17a1748da 100644 --- a/src/tests/vnet/session/udp_echo.c +++ b/src/tests/vnet/session/udp_echo.c @@ -65,7 +65,7 @@ typedef struct typedef struct { /* vpe input queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* API client handle */ u32 my_client_index; @@ -91,10 +91,10 @@ typedef struct int i_am_master; /* Our event queue */ - unix_shared_memory_queue_t *our_event_queue; + svm_queue_t *our_event_queue; /* $$$ single thread only for the moment */ - unix_shared_memory_queue_t *vpp_event_queue; + svm_queue_t *vpp_event_queue; /* $$$$ hack: cut-through session index */ volatile u32 cut_through_session_index; @@ -233,8 +233,7 @@ vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t * } utm->our_event_queue = - uword_to_pointer (mp->app_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->app_event_queue_address, svm_queue_t *); } static void @@ -488,9 +487,8 @@ send_test_chunk (uri_udp_test_main_t * utm, svm_fifo_t * tx_fifo, int mypid, evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - unix_shared_memory_queue_add (utm->vpp_event_queue, - (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (utm->vpp_event_queue, + (u8 *) & evt, 0 /* do wait for mutex */ ); } } } @@ -636,7 +634,7 @@ vl_api_connect_uri_t_handler (vl_api_connect_uri_t * mp) svm_fifo_segment_main_t *sm = &svm_fifo_segment_main; svm_fifo_segment_create_args_t _a, *a = &_a; svm_fifo_segment_private_t *seg; - unix_shared_memory_queue_t *client_q; + svm_queue_t *client_q; vl_api_connect_session_reply_t *rmp; session_t *session = 0; int rv = 0; @@ -699,8 +697,7 @@ send_reply: vec_free (a->segment_name); - client_q = - uword_to_pointer (mp->client_queue_address, unix_shared_memory_queue_t *); + client_q = uword_to_pointer (mp->client_queue_address, svm_queue_t *); vl_msg_api_send_shmem (client_q, (u8 *) & rmp); } @@ -728,8 +725,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) start_time = clib_time_now (&utm->clib_time); utm->vpp_event_queue = - uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->vpp_event_queue_address, svm_queue_t *); pool_get (utm->sessions, session); @@ -850,7 +846,7 @@ vl_api_connect_session_reply_t_handler (vl_api_connect_session_reply_t * mp) { utm->connected_session = session - utm->sessions; utm->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + svm_queue_t *); } utm->state = STATE_READY; } @@ -921,7 +917,7 @@ server_handle_fifo_event_rx (uri_udp_test_main_t * utm, svm_fifo_t *rx_fifo, *tx_fifo; int nbytes; session_fifo_event_t evt; - unix_shared_memory_queue_t *q; + svm_queue_t *q; int rv; rx_fifo = e->fifo; @@ -946,8 +942,7 @@ server_handle_fifo_event_rx (uri_udp_test_main_t * utm, evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; q = utm->vpp_event_queue; - unix_shared_memory_queue_add (q, (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ ); } } @@ -961,8 +956,7 @@ server_handle_event_queue (uri_udp_test_main_t * utm) while (1) { - unix_shared_memory_queue_sub (utm->our_event_queue, (u8 *) e, - 0 /* nowait */ ); + svm_queue_sub (utm->our_event_queue, (u8 *) e, 0 /* nowait */ ); switch (e->event_type) { case FIFO_EVENT_APP_RX: diff --git a/src/vat/api_format.c b/src/vat/api_format.c index 88c64473518..4c13e11226f 100644 --- a/src/vat/api_format.c +++ b/src/vat/api_format.c @@ -22571,7 +22571,7 @@ get_msg_id (vat_main_t * vam) if (unformat (vam->input, "%s", &name_and_crc)) { - message_index = vl_api_get_msg_index (name_and_crc); + message_index = vl_msg_api_get_msg_index (name_and_crc); if (message_index == ~0) { print (vam->ofp, " '%s' not found", name_and_crc); diff --git a/src/vat/vat.h b/src/vat/vat.h index ddb4644848a..beeccd5dc67 100644 --- a/src/vat/vat.h +++ b/src/vat/vat.h @@ -119,7 +119,7 @@ typedef struct typedef struct { /* vpe input queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* interface name table */ uword *sw_if_index_by_interface_name; diff --git a/src/vcl/vppcom.c b/src/vcl/vppcom.c index dcf63d07063..ac40ab0efab 100644 --- a/src/vcl/vppcom.c +++ b/src/vcl/vppcom.c @@ -108,7 +108,7 @@ typedef struct u32 sm_seg_index; u32 client_context; u64 vpp_handle; - unix_shared_memory_queue_t *vpp_event_queue; + svm_queue_t *vpp_event_queue; /* Socket configuration state */ /* TBD: covert 'is_*' vars to bit in u8 flags; */ @@ -164,7 +164,7 @@ typedef struct vppcom_main_t_ int main_cpu; /* vpe input queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* API client handle */ u32 my_client_index; @@ -182,7 +182,7 @@ typedef struct vppcom_main_t_ clib_bitmap_t *ex_bitmap; /* Our event queue */ - unix_shared_memory_queue_t *app_event_queue; + svm_queue_t *app_event_queue; /* unique segment name counter */ u32 unique_segment_index; @@ -695,8 +695,7 @@ vl_api_application_attach_reply_t_handler (vl_api_application_attach_reply_t * } vcm->app_event_queue = - uword_to_pointer (mp->app_event_queue_address, - unix_shared_memory_queue_t *); + uword_to_pointer (mp->app_event_queue_address, svm_queue_t *); vcm->app_state = STATE_APP_ATTACHED; } @@ -896,7 +895,7 @@ done: */ session->is_cut_thru = is_cut_thru; session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + svm_queue_t *); rx_fifo = uword_to_pointer (mp->server_rx_fifo, svm_fifo_t *); rx_fifo->client_session_index = session_index; @@ -1180,7 +1179,7 @@ vl_api_accept_session_t_handler (vl_api_accept_session_t * mp) session->server_rx_fifo = rx_fifo; session->server_tx_fifo = tx_fifo; session->vpp_event_queue = uword_to_pointer (mp->vpp_event_queue_address, - unix_shared_memory_queue_t *); + svm_queue_t *); session->state = STATE_ACCEPT; session->is_cut_thru = 0; session->is_server = 1; @@ -1213,7 +1212,7 @@ vppcom_send_connect_session_reply (session_t * session, u32 session_index, { vl_api_connect_session_reply_t *rmp; u32 len; - unix_shared_memory_queue_t *client_q; + svm_queue_t *client_q; rmp = vl_msg_api_alloc (sizeof (*rmp)); memset (rmp, 0, sizeof (*rmp)); @@ -1243,8 +1242,7 @@ vppcom_send_connect_session_reply (session_t * session, u32 session_index, sizeof (rmp->lcl_ip)); rmp->is_ip4 = session->peer_addr.is_ip4; rmp->lcl_port = session->peer_port; - client_q = uword_to_pointer (session->client_queue_address, - unix_shared_memory_queue_t *); + client_q = uword_to_pointer (session->client_queue_address, svm_queue_t *); ASSERT (client_q); vl_msg_api_send_shmem (client_q, (u8 *) & rmp); } @@ -2626,9 +2624,9 @@ vppcom_session_accept (uint32_t listen_session_index, vppcom_endpt_t * ep, ssvm_lock_non_recursive (sh, 1); oldheap = ssvm_push_heap (sh); event_q = client_session->vpp_event_queue = - unix_shared_memory_queue_init (vcm->cfg.event_queue_size, - sizeof (session_fifo_event_t), - getpid (), 0 /* signal not sent */ ); + svm_queue_init (vcm->cfg.event_queue_size, + sizeof (session_fifo_event_t), + getpid (), 0 /* signal not sent */ ); ssvm_pop_heap (oldheap); ssvm_unlock_non_recursive (sh); } @@ -2959,7 +2957,7 @@ vppcom_session_read_ready (session_t * session, u32 session_index) session_fifo_event_t e; for (i = 0; i < n_to_dequeue; i++) - unix_shared_memory_queue_sub_raw (vcm->app_event_queue, (u8 *) & e); + svm_queue_sub_raw (vcm->app_event_queue, (u8 *) & e); pthread_mutex_unlock (&vcm->app_event_queue->mutex); } @@ -2973,7 +2971,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) { session_t *session = 0; svm_fifo_t *tx_fifo; - unix_shared_memory_queue_t *q; + svm_queue_t *q; session_fifo_event_t evt; int rv, n_write; char *fifo_str; @@ -3039,8 +3037,7 @@ vppcom_session_write (uint32_t session_index, void *buf, int n) VCL_LOCK_AND_GET_SESSION (session_index, &session); q = session->vpp_event_queue; ASSERT (q); - unix_shared_memory_queue_add (q, (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ ); clib_spinlock_unlock (&vcm->sessions_lockp); if (VPPCOM_DEBUG > 1) clib_warning ("[%d] vpp handle 0x%llx, sid %u: " diff --git a/src/vlib-api.am b/src/vlib-api.am index 5bbd4599729..f1fdb8d2228 100644 --- a/src/vlib-api.am +++ b/src/vlib-api.am @@ -22,15 +22,16 @@ libvlibmemory_la_SOURCES = \ vlibapi/node_serialize.c \ vlibmemory/api.h \ vlibmemory/memclnt.api \ + vlibmemory/memory_api.c \ vlibmemory/memory_shared.c \ - vlibmemory/memory_vlib.c \ - vlibmemory/socksvr_vlib.c \ - vlibmemory/unix_shared_memory_queue.c \ - vlibmemory/unix_shared_memory_queue.h \ + vlibmemory/socket_api.c \ + vlibmemory/vlib_api.c \ + vlibmemory/vlib_api_cli.c \ vlibmemory/vl_memory_api_h.h \ vlibmemory/vl_memory_msg_enum.h -nobase_include_HEADERS += vlibapi/api.h \ +nobase_include_HEADERS += \ + vlibapi/api.h \ vlibapi/api_common.h \ vlibapi/api_helper_macros.h \ vlibapi/vat_helper_macros.h @@ -40,23 +41,23 @@ libvlibmemoryclient_la_LIBADD = $(libvlibmemoryclient_la_DEPENDENCIES) -lpthread libvlibmemoryclient_la_SOURCES = \ vlibapi/api_helper_macros.h \ vlibapi/api_shared.c \ - vlibapi/node_unserialize.c \ - vlibmemory/api.h \ + vlibapi/node_serialize.c \ vlibmemory/memclnt.api \ vlibmemory/memory_client.c \ vlibmemory/memory_shared.c \ vlibmemory/socket_client.c \ - vlibmemory/unix_shared_memory_queue.c \ - vlibmemory/unix_shared_memory_queue.h \ vlibmemory/vl_memory_api_h.h \ vlibmemory/vl_memory_msg_enum.h nobase_include_HEADERS += \ vlibmemory/api.h \ - vlibmemory/api_common.h \ + vlibmemory/memory_api.h \ + vlibmemory/memory_shared.h \ + vlibmemory/memory_client.h \ + vlibmemory/socket_api.h \ + vlibmemory/socket_client.h \ vlibmemory/vl_memory_api_h.h \ vlibmemory/vl_memory_msg_enum.h \ - vlibmemory/unix_shared_memory_queue.h \ vlibmemory/memclnt.api.h BUILT_SOURCES += \ diff --git a/src/vlib/node.c b/src/vlib/node.c index e6739dc7cf9..17dd2ea87d4 100644 --- a/src/vlib/node.c +++ b/src/vlib/node.c @@ -543,6 +543,60 @@ vlib_register_all_static_nodes (vlib_main_t * vm) } } +vlib_node_t *** +vlib_node_get_nodes (vlib_main_t * vm, u32 max_threads, int include_stats) +{ + vlib_node_main_t *nm = &vm->node_main; + vlib_node_t *n; + static vlib_node_t ***node_dups; + vlib_node_t **nodes; + static vlib_main_t **stat_vms; + vlib_main_t *stat_vm; + uword i, j; + u32 threads_to_serialize; + + vec_reset_length (node_dups); + + if (vec_len (stat_vms) == 0) + { + for (i = 0; i < vec_len (vlib_mains); i++) + { + stat_vm = vlib_mains[i]; + if (stat_vm) + vec_add1 (stat_vms, stat_vm); + } + } + + threads_to_serialize = clib_min (max_threads, vec_len (stat_vms)); + + /* + * Barrier sync across stats scraping. + * Otherwise, the counts will be grossly inaccurate. + */ + vlib_worker_thread_barrier_sync (vm); + + for (j = 0; j < threads_to_serialize; j++) + { + stat_vm = stat_vms[j]; + nm = &stat_vm->node_main; + + if (include_stats) + { + for (i = 0; i < vec_len (nm->nodes); i++) + { + n = nm->nodes[i]; + vlib_node_sync_stats (stat_vm, n); + } + } + + nodes = vec_dup (nm->nodes); + vec_add1 (node_dups, nodes); + } + vlib_worker_thread_barrier_release (vm); + + return node_dups; +} + clib_error_t * vlib_node_main_init (vlib_main_t * vm) { diff --git a/src/vlib/node_funcs.h b/src/vlib/node_funcs.h index 0734476cb8f..6607d31f67e 100644 --- a/src/vlib/node_funcs.h +++ b/src/vlib/node_funcs.h @@ -1122,6 +1122,12 @@ vlib_node_add_named_next (vlib_main_t * vm, uword node, char *name) return vlib_node_add_named_next_with_slot (vm, node, name, ~0); } +/** + * Get list of nodes + */ +vlib_node_t ***vlib_node_get_nodes (vlib_main_t * vm, u32 max_threads, + int include_stats); + /* Query node given name. */ vlib_node_t *vlib_get_node_by_name (vlib_main_t * vm, u8 * name); diff --git a/src/vlibapi/api.h b/src/vlibapi/api.h index 6820a541cba..48c3813452e 100644 --- a/src/vlibapi/api.h +++ b/src/vlibapi/api.h @@ -23,16 +23,15 @@ #include #include #include +#include #include -#include #include #include /* *INDENT-OFF* */ -typedef CLIB_PACKED -(struct - { - u8 endian; u8 wrapped; +typedef CLIB_PACKED ( struct { + u8 endian; + u8 wrapped; u32 nitems; }) vl_api_trace_file_header_t; /* *INDENT-ON* */ @@ -56,7 +55,6 @@ int vl_msg_api_trace_save (api_main_t * am, _error; \ }) - #define _VL_MSG_API_FUNCTION_SYMBOL(x, type) \ _vl_msg_api_##type##_function_##x @@ -117,10 +115,10 @@ void vl_msg_api_add_msg_name_crc (api_main_t * am, const char *string, void vl_msg_api_add_version (api_main_t * am, const char *string, u32 major, u32 minor, u32 patch); /* node_serialize.c prototypes */ -u8 *vlib_node_serialize (vlib_node_main_t * nm, u8 * vector, - u32 max_threads, int include_nexts, - int include_stats); +u8 *vlib_node_serialize (vlib_main_t * vm, vlib_node_t *** node_dups, + u8 * vector, int include_nexts, int include_stats); vlib_node_t **vlib_node_unserialize (u8 * vector); + u32 vl_msg_api_get_msg_length (void *msg_arg); #endif /* included_api_h */ diff --git a/src/vlibapi/api_common.h b/src/vlibapi/api_common.h index 56b036d7f07..055164812de 100644 --- a/src/vlibapi/api_common.h +++ b/src/vlibapi/api_common.h @@ -26,7 +26,7 @@ #include #include -#include +#include /** API registration types */ @@ -56,7 +56,7 @@ typedef struct vl_api_registration_ int unanswered_pings; /** shared memory only: pointer to client input queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; svm_region_t *vlib_rp; void *shmem_hdr; @@ -133,7 +133,7 @@ typedef struct /** Message header structure */ typedef struct msgbuf_ { - unix_shared_memory_queue_t *q; /**< message allocated in this shmem ring */ + svm_queue_t *q; /**< message allocated in this shmem ring */ u32 data_len; /**< message length not including header */ u32 gc_mark_timestamp; /**< message garbage collector mark TS */ u8 data[0]; /**< actual message begins here */ @@ -155,7 +155,7 @@ void vl_msg_api_set_handlers (int msg_id, char *msg_name, void vl_msg_api_clean_handlers (int msg_id); void vl_msg_api_config (vl_msg_api_msg_config_t *); void vl_msg_api_set_cleanup_handler (int msg_id, void *fp); -void vl_msg_api_queue_handler (unix_shared_memory_queue_t * q); +void vl_msg_api_queue_handler (svm_queue_t * q); void vl_msg_api_barrier_sync (void) __attribute__ ((weak)); void vl_msg_api_barrier_release (void) __attribute__ ((weak)); @@ -176,7 +176,7 @@ int vl_msg_api_pd_handler (void *mp, int rv); void vl_msg_api_set_first_available_msg_id (u16 first_avail); u16 vl_msg_api_get_msg_ids (const char *name, int n); -u32 vl_api_get_msg_index (u8 * name_and_crc); +u32 vl_msg_api_get_msg_index (u8 * name_and_crc); typedef clib_error_t *(vl_msg_api_init_function_t) (u32 client_index); @@ -297,7 +297,7 @@ typedef struct u64 api_pvt_heap_size; /** Peer input queue pointer */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /** * All VLIB-side message handlers use my_client_index to identify diff --git a/src/vlibapi/api_helper_macros.h b/src/vlibapi/api_helper_macros.h index fc9374f8a26..23340425978 100644 --- a/src/vlibapi/api_helper_macros.h +++ b/src/vlibapi/api_helper_macros.h @@ -40,7 +40,7 @@ do { \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ \ - vl_msg_api_send (rp, (u8 *)rmp); \ + vl_api_send_msg (rp, (u8 *)rmp); \ } while(0); #define REPLY_MACRO2(t, body) \ @@ -56,7 +56,7 @@ do { \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ - vl_msg_api_send (rp, (u8 *)rmp); \ + vl_api_send_msg (rp, (u8 *)rmp); \ } while(0); #define REPLY_MACRO3(t, n, body) \ @@ -72,7 +72,7 @@ do { \ rmp->context = mp->context; \ rmp->retval = ntohl(rv); \ do {body;} while (0); \ - vl_msg_api_send (rp, (u8 *)rmp); \ + vl_api_send_msg (rp, (u8 *)rmp); \ } while(0); #define REPLY_MACRO4(t, n, body) \ @@ -103,7 +103,7 @@ do { \ rmp->retval = ntohl(rv); \ if (!is_error) \ do {body;} while (0); \ - vl_msg_api_send (rp, (u8 *)rmp); \ + vl_api_send_msg (rp, (u8 *)rmp); \ } while(0); /* "trust, but verify" */ diff --git a/src/vlibapi/api_shared.c b/src/vlibapi/api_shared.c index 4d11b519cf2..d4196264064 100644 --- a/src/vlibapi/api_shared.c +++ b/src/vlibapi/api_shared.c @@ -754,11 +754,11 @@ vl_msg_api_set_cleanup_handler (int msg_id, void *fp) } void -vl_msg_api_queue_handler (unix_shared_memory_queue_t * q) +vl_msg_api_queue_handler (svm_queue_t * q) { uword msg; - while (!unix_shared_memory_queue_sub (q, (u8 *) & msg, 0)) + while (!svm_queue_sub (q, (u8 *) & msg, 0)) vl_msg_api_handler ((void *) msg); } @@ -940,6 +940,21 @@ vl_msg_api_add_version (api_main_t * am, const char *string, vec_add1 (am->api_version_list, version); } +u32 +vl_msg_api_get_msg_index (u8 * name_and_crc) +{ + api_main_t *am = &api_main; + uword *p; + + if (am->msg_index_by_name_and_crc) + { + p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc); + if (p) + return p[0]; + } + return ~0; +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/vlibapi/node_serialize.c b/src/vlibapi/node_serialize.c index 50e5c41c219..575de11b8cc 100644 --- a/src/vlibapi/node_serialize.c +++ b/src/vlibapi/node_serialize.c @@ -16,9 +16,6 @@ #include -extern void vl_msg_api_barrier_sync (void); -extern void vl_msg_api_barrier_release (void); - /* serialized representation of state strings */ #define foreach_state_string_code \ @@ -50,72 +47,24 @@ static char *state_strings[] = { * to recycle a vector / avoid memory allocation, etc. * Switch heaps before/after to serialize into API client shared memory. */ - u8 * -vlib_node_serialize (vlib_node_main_t * nm, u8 * vector, - u32 max_threads, int include_nexts, int include_stats) +vlib_node_serialize (vlib_main_t * vm, vlib_node_t *** node_dups, u8 * vector, + int include_nexts, int include_stats) { serialize_main_t _sm, *sm = &_sm; - vlib_main_t *vm = vlib_get_main (); vlib_node_t *n; - static vlib_node_t ***node_dups; vlib_node_t **nodes; - static vlib_main_t **stat_vms; - vlib_main_t *stat_vm; u8 *namep; u32 name_bytes; uword i, j, k; u64 l, v, c, d; state_string_enum_t state_code; - u32 threads_to_serialize; - - vec_reset_length (node_dups); - - if (vec_len (stat_vms) == 0) - { - for (i = 0; i < vec_len (vlib_mains); i++) - { - stat_vm = vlib_mains[i]; - if (stat_vm) - vec_add1 (stat_vms, stat_vm); - } - } - - threads_to_serialize = clib_min (max_threads, vec_len (stat_vms)); - - /* - * Barrier sync across stats scraping. - * Otherwise, the counts will be grossly inaccurate. - */ - vl_msg_api_barrier_sync (); - - for (j = 0; j < threads_to_serialize; j++) - { - stat_vm = stat_vms[j]; - nm = &stat_vm->node_main; - - if (include_stats) - { - for (i = 0; i < vec_len (nm->nodes); i++) - { - n = nm->nodes[i]; - vlib_node_sync_stats (stat_vm, n); - } - } - - nodes = vec_dup (nm->nodes); - - vec_add1 (node_dups, nodes); - } - vl_msg_api_barrier_release (); serialize_open_vector (sm, vector); + serialize_likely_small_unsigned_integer (sm, vec_len (node_dups)); - serialize_likely_small_unsigned_integer (sm, vec_len (stat_vms)); - - for (j = 0; j < vec_len (stat_vms); j++) + for (j = 0; j < vec_len (node_dups); j++) { - stat_vm = stat_vms[j]; nodes = node_dups[j]; serialize_likely_small_unsigned_integer (sm, vec_len (nodes)); diff --git a/src/vlibapi/node_unserialize.c b/src/vlibapi/node_unserialize.c deleted file mode 100644 index bb0edfedda1..00000000000 --- a/src/vlibapi/node_unserialize.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2016 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include - -#include - -/* serialized representation of state strings */ - -#define foreach_state_string_code \ -_(STATE_DONE, "done") \ -_(STATE_DISABLED, "disabled") \ -_(STATE_TIME_WAIT, "time wait") \ -_(STATE_EVENT_WAIT, "event wait") \ -_(STATE_ANY_WAIT, "any wait") \ -_(STATE_POLLING, "polling") \ -_(STATE_INTERRUPT_WAIT, "interrupt wait") \ -_(STATE_INTERNAL, "internal") - -typedef enum -{ -#define _(a,b) a, - foreach_state_string_code -#undef _ -} state_string_enum_t; - -static char *state_strings[] = { -#define _(a,b) b, - foreach_state_string_code -#undef _ -}; - -vlib_node_t *** -vlib_node_unserialize (u8 * vector) -{ - serialize_main_t _sm, *sm = &_sm; - u32 nnodes, nnexts; - u32 nstat_vms; - vlib_node_t *node; - vlib_node_t **nodes; - vlib_node_t ***nodes_by_thread = 0; - int i, j, k; - u64 l, v, c, d; - state_string_enum_t state_code; - int stats_present; - - serialize_open_vector (sm, vector); - - nstat_vms = unserialize_likely_small_unsigned_integer (sm); - - vec_validate (nodes_by_thread, nstat_vms - 1); - _vec_len (nodes_by_thread) = 0; - - for (i = 0; i < nstat_vms; i++) - { - nnodes = unserialize_likely_small_unsigned_integer (sm); - - nodes = 0; - vec_validate (nodes, nnodes - 1); - vec_add1 (nodes_by_thread, nodes); - - for (j = 0; j < nnodes; j++) - { - node = 0; - vec_validate (node, 0); - nodes[j] = node; - - unserialize_cstring (sm, (char **) &(node->name)); - state_code = unserialize_likely_small_unsigned_integer (sm); - node->state_string = (u8 *) state_strings[state_code]; - - node->type = unserialize_likely_small_unsigned_integer (sm); - nnexts = unserialize_likely_small_unsigned_integer (sm); - if (nnexts > 0) - vec_validate (node->next_nodes, nnexts - 1); - for (k = 0; k < nnexts; k++) - node->next_nodes[k] = - unserialize_likely_small_unsigned_integer (sm); - - stats_present = unserialize_likely_small_unsigned_integer (sm); - - if (stats_present) - { - /* total clocks */ - unserialize_integer (sm, &l, 8); - node->stats_total.clocks = l; - node->stats_last_clear.clocks = 0; - - /* Total calls */ - unserialize_integer (sm, &c, 8); - node->stats_total.calls = c; - - /* Total vectors */ - unserialize_integer (sm, &v, 8); - node->stats_total.vectors = v; - - /* Total suspends */ - unserialize_integer (sm, &d, 8); - node->stats_total.suspends = d; - } - } - } - return nodes_by_thread; -} - -#if TEST_CODE - -static clib_error_t * -test_node_serialize_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - vlib_node_main_t *nm = &vm->node_main; - u8 *vector = 0; - vlib_node_t ***nodes_by_thread; - vlib_node_t **nodes; - vlib_node_t *node; - vlib_node_t *next_node; - int i, j, k; - u32 max_threads = (u32) ~ 0; - int include_nexts = 0; - int include_stats = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "max-threads %d", &max_threads)) - ; - else if (unformat (input, "stats")) - include_stats = 1; - else if (unformat (input, "nexts")) - include_nexts = 1; - else - break; - } - - /* - * Keep the number of memcpy ops to a minimum (e.g. 1). - * The current size of the serialized vector is - * slightly under 4K. - */ - vec_validate (vector, 16383); - vec_reset_length (vector); - - vector = vlib_node_serialize (nm, vector, max_threads, - include_nexts, include_stats); - - vlib_cli_output (vm, "result vector %d bytes", vec_len (vector)); - - nodes_by_thread = vlib_node_unserialize (vector); - - vec_free (vector); - - for (i = 0; i < vec_len (nodes_by_thread); i++) - { - nodes = nodes_by_thread[i]; - - vlib_cli_output (vm, "thread %d", i); - - for (j = 0; j < vec_len (nodes); j++) - { - node = nodes[j]; - - vlib_cli_output (vm, "[%d] %s state %s", j, node->name, - node->state_string); - - vlib_cli_output - (vm, " clocks %lld calls %lld suspends" - " %lld vectors %lld", - node->stats_total.clocks, - node->stats_total.calls, - node->stats_total.suspends, node->stats_total.vectors); - - for (k = 0; k < vec_len (node->next_nodes); k++) - { - if (node->next_nodes[k] != ~0) - { - next_node = nodes[node->next_nodes[k]]; - vlib_cli_output (vm, " [%d] %s", k, next_node->name); - } - } - } - } - - for (j = 0; j < vec_len (nodes_by_thread); j++) - { - nodes = nodes_by_thread[j]; - - for (i = 0; i < vec_len (nodes); i++) - { - vec_free (nodes[i]->name); - vec_free (nodes[i]->next_nodes); - vec_free (nodes[i]); - } - vec_free (nodes); - } - vec_free (nodes_by_thread); - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (test_node_serialize_node, static) = { - .path = "test node serialize", - .short_help = "test node serialize [max-threads NN] nexts stats", - .function = test_node_serialize_command_fn, -}; -/* *INDENT-ON* */ -#endif - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/api.h b/src/vlibmemory/api.h index 5c32f5308de..4f869a64be3 100644 --- a/src/vlibmemory/api.h +++ b/src/vlibmemory/api.h @@ -1,7 +1,5 @@ /* *------------------------------------------------------------------ - * api.h - * * Copyright (c) 2009 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,41 +15,85 @@ *------------------------------------------------------------------ */ -#ifndef included_vlibmemory_api_h -#define included_vlibmemory_api_h +#ifndef included_vlibmemory_api_common_h +#define included_vlibmemory_api_common_h -#include -#include -#include -#include +#include #include -#include +#include +#include +#include +#include + +void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); +u16 vl_client_get_first_plugin_msg_id (const char *plugin_name); +void vl_api_send_pending_rpc_requests (vlib_main_t * vm); +u8 *vl_api_serialize_message_table (api_main_t * am, u8 * vector); -static inline u32 -vl_msg_api_handle_get_epoch (u32 index) +always_inline void +vl_api_send_msg (vl_api_registration_t * rp, u8 * elem) { - return (index & VL_API_EPOCH_MASK); + if (PREDICT_FALSE (rp->registration_type > REGISTRATION_TYPE_SHMEM)) + { + vl_socket_api_send (rp, elem); + } + else + { + vl_msg_api_send_shmem (rp->vl_input_queue, (u8 *) & elem); + } } -static inline u32 -vl_msg_api_handle_get_index (u32 index) +always_inline vl_api_registration_t * +vl_api_client_index_to_registration (u32 index) { - return (index >> VL_API_EPOCH_SHIFT); + if (PREDICT_FALSE (socket_main.current_rp != 0)) + return socket_main.current_rp; + + return (vl_mem_api_client_index_to_registration (index)); } -static inline u32 -vl_msg_api_handle_from_index_and_epoch (u32 index, u32 epoch) +/* + * vl_api_clnt process data used by transports (socket api in particular) + */ +extern vlib_node_registration_t vl_api_clnt_node; +extern volatile int **vl_api_queue_cursizes; + +typedef enum vl_api_clnt_process_events { - u32 handle; - ASSERT (index < 0x00FFFFFF); + QUEUE_SIGNAL_EVENT = 1, + SOCKET_READ_EVENT +} vl_api_clnt_process_events_t; - handle = (index << VL_API_EPOCH_SHIFT) | (epoch & VL_API_EPOCH_MASK); - return handle; -} +#define foreach_histogram_bucket \ +_(400) \ +_(200) \ +_(100) \ +_(10) + +typedef enum +{ +#define _(n) SLEEP_##n##_US, + foreach_histogram_bucket +#undef _ + SLEEP_N_BUCKETS, +} histogram_index_t; -void vl_enable_disable_memory_api (vlib_main_t * vm, int yesno); +extern u64 vector_rate_histogram[]; + +/* + * sockclnt APIs XXX are these actually used anywhere? + */ +vl_api_registration_t *sockclnt_get_registration (u32 index); +void socksvr_add_pending_output (struct clib_file *uf, + struct vl_api_registration_ *cf, + u8 * buffer, uword buffer_bytes); +void vl_socket_process_msg (struct clib_file *uf, + struct vl_api_registration_ *rp, i8 * input_v); +u32 sockclnt_open_index (char *client_name, char *hostname, int port); +void sockclnt_close_index (u32 index); +void vl_client_msg_api_send (vl_api_registration_t * cm, u8 * elem); -#endif /* included_vlibmemory_api_h */ +#endif /* included_vlibmemory_api_common_h */ /* * fd.io coding-style-patch-verification: ON diff --git a/src/vlibmemory/api_common.h b/src/vlibmemory/api_common.h deleted file mode 100644 index bd0da10d569..00000000000 --- a/src/vlibmemory/api_common.h +++ /dev/null @@ -1,267 +0,0 @@ -/* - *------------------------------------------------------------------ - * Copyright (c) 2009 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#ifndef included_vlibmemory_api_common_h -#define included_vlibmemory_api_common_h - -#include -#include -#include -#include - -/* Allocated in shared memory */ - -/* - * Ring-allocation scheme for client API messages - * - * Only one proc/thread has control of a given message buffer. - * To free a buffer allocated from one of these rings, we clear - * a field in the buffer (header), and leave. - * - * No locks, no hits, no errors... - */ -typedef struct ring_alloc_ -{ - unix_shared_memory_queue_t *rp; - u16 size; - u16 nitems; - u32 hits; - u32 misses; -} ring_alloc_t; - -typedef enum -{ - VL_API_VLIB_RING, - VL_API_CLIENT_RING, - VL_API_QUEUE -} vl_api_shm_config_type_t; - -typedef struct vl_api_ring_config_ -{ - u8 type; - u8 _pad; - u16 count; - u32 size; -} vl_api_shm_elem_config_t; - -STATIC_ASSERT (sizeof (vl_api_shm_elem_config_t) == 8, - "Size must be exactly 8 bytes"); - -/* - * Initializers for the (shared-memory) rings - * _(size, n). Note: each msg has space for a header. - */ -#define foreach_vl_aring_size \ -_(64+sizeof(ring_alloc_t), 1024) \ -_(256+sizeof(ring_alloc_t), 128) \ -_(1024+sizeof(ring_alloc_t), 64) - -#define foreach_clnt_aring_size \ - _(1024+sizeof(ring_alloc_t), 1024) \ - _(2048+sizeof(ring_alloc_t), 128) \ - _(4096+sizeof(ring_alloc_t), 8) - -typedef struct vl_shmem_hdr_ -{ - int version; - - /* getpid () for the VLIB client process */ - volatile int vl_pid; - - /* Client sends VLIB msgs here. */ - unix_shared_memory_queue_t *vl_input_queue; - - /* Vector of rings; one for each size. */ - - /* VLIB allocates buffers to send msgs to clients here. */ - ring_alloc_t *vl_rings; - - /* Clients allocate buffer to send msgs to VLIB here. */ - ring_alloc_t *client_rings; - - /* Number of detected application restarts */ - u32 application_restarts; - - /* Number of messages reclaimed during application restart */ - u32 restart_reclaims; - - /* Number of garbage-collected messages */ - u32 garbage_collects; -} vl_shmem_hdr_t; - -#define VL_SHM_VERSION 2 - -#define VL_API_EPOCH_MASK 0xFF -#define VL_API_EPOCH_SHIFT 8 - -void *vl_msg_api_alloc (int nbytes); -void *vl_msg_api_alloc_or_null (int nbytes); -void *vl_msg_api_alloc_as_if_client (int nbytes); -void *vl_msg_api_alloc_as_if_client_or_null (int nbytes); -void vl_msg_api_free (void *a); -int vl_map_shmem (const char *region_name, int is_vlib); -void vl_register_mapped_shmem_region (svm_region_t * rp); -void vl_unmap_shmem (void); -void vl_msg_api_send_shmem (unix_shared_memory_queue_t * q, u8 * elem); -void vl_msg_api_send_shmem_nolock (unix_shared_memory_queue_t * q, u8 * elem); -void vl_msg_api_send (vl_api_registration_t * rp, u8 * elem); -int vl_client_connect (const char *name, int ctx_quota, int input_queue_size); -void vl_client_disconnect (void); -unix_shared_memory_queue_t *vl_api_client_index_to_input_queue (u32 index); -vl_api_registration_t *vl_api_client_index_to_registration (u32 index); -int vl_client_api_map (const char *region_name); -void vl_client_api_unmap (void); -void vl_set_memory_region_name (const char *name); -void vl_set_memory_root_path (const char *root_path); -void vl_set_memory_uid (int uid); -void vl_set_memory_gid (int gid); -void vl_set_global_memory_baseva (u64 baseva); -void vl_set_global_memory_size (u64 size); -void vl_set_api_memory_size (u64 size); -void vl_set_global_pvt_heap_size (u64 size); -void vl_set_api_pvt_heap_size (u64 size); -void vl_client_disconnect_from_vlib (void); -int vl_client_connect_to_vlib (const char *svm_name, const char *client_name, - int rx_queue_size); -int vl_client_connect_to_vlib_no_rx_pthread (const char *svm_name, - const char *client_name, - int rx_queue_size); -int vl_client_connect_to_vlib_no_map (const char *svm_name, - const char *client_name, - int rx_queue_size); -u16 vl_client_get_first_plugin_msg_id (const char *plugin_name); - -void vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length); -u32 vl_api_memclnt_create_internal (char *, unix_shared_memory_queue_t *); -void vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config, - int is_vlib, int is_private_region); -void vl_client_install_client_message_handlers (void); -void vl_api_send_pending_rpc_requests (vlib_main_t * vm); - -/* API messages over sockets */ - -extern vlib_node_registration_t memclnt_node; -extern volatile int **vl_api_queue_cursizes; - -/* Events sent to the memclnt process */ -#define QUEUE_SIGNAL_EVENT 1 -#define SOCKET_READ_EVENT 2 - -#define API_SOCKET_FILE "/run/vpp-api.sock" - -typedef struct -{ - clib_file_t *clib_file; - vl_api_registration_t *regp; - u8 *data; -} vl_socket_args_for_process_t; - -typedef struct -{ - /* Server port number */ - u8 *socket_name; - - /* By default, localhost... */ - u32 bind_address; - - /* - * (listen, server, client) registrations. Shared memory - * registrations are in shared memory - */ - vl_api_registration_t *registration_pool; - /* - * Chain-drag variables, so message API handlers - * (generally) don't know whether they're talking to a socket - * or to a shared-memory connection. - */ - vl_api_registration_t *current_rp; - clib_file_t *current_uf; - /* One input buffer, shared across all sockets */ - i8 *input_buffer; - - /* pool of process args for socket clients */ - vl_socket_args_for_process_t *process_args; - - /* Listen for API connections here */ - clib_socket_t socksvr_listen_socket; -} socket_main_t; - -extern socket_main_t socket_main; - -typedef struct -{ - int socket_fd; - /* Temporarily disable the connection, so we can keep it around... */ - int socket_enable; - - clib_socket_t client_socket; - - u32 socket_buffer_size; - u8 *socket_tx_buffer; - u8 *socket_rx_buffer; - u32 socket_tx_nbytes; - int control_pings_outstanding; - - u8 *name; - clib_time_t clib_time; -} socket_client_main_t; - -extern socket_client_main_t socket_client_main; - -#define SOCKET_CLIENT_DEFAULT_BUFFER_SIZE 4096 - -void socksvr_add_pending_output (struct clib_file *uf, - struct vl_api_registration_ *cf, - u8 * buffer, uword buffer_bytes); - -void vl_free_socket_registration_index (u32 pool_index); -void vl_socket_process_msg (struct clib_file *uf, - struct vl_api_registration_ *rp, i8 * input_v); -clib_error_t *vl_socket_read_ready (struct clib_file *uf); -void vl_socket_add_pending_output (struct clib_file *uf, - struct vl_api_registration_ *rp, - u8 * buffer, uword buffer_bytes); -void vl_socket_add_pending_output_no_flush (struct clib_file *uf, - struct vl_api_registration_ *rp, - u8 * buffer, uword buffer_bytes); -clib_error_t *vl_socket_write_ready (struct clib_file *uf); -void vl_socket_api_send (vl_api_registration_t * rp, u8 * elem); -u32 sockclnt_open_index (char *client_name, char *hostname, int port); -void sockclnt_close_index (u32 index); -void vl_client_msg_api_send (vl_api_registration_t * cm, u8 * elem); -vl_api_registration_t *sockclnt_get_registration (u32 index); -void vl_api_socket_process_msg (clib_file_t * uf, vl_api_registration_t * rp, - i8 * input_v); - -int vl_socket_client_connect (char *socket_path, char *client_name, - u32 socket_buffer_size); -int vl_socket_client_init_shm (vl_api_shm_elem_config_t * config); -void vl_socket_client_disconnect (void); -int vl_socket_client_read (int wait); -int vl_socket_client_write (void); -void vl_socket_client_enable_disable (int enable); -void *vl_socket_client_msg_alloc (int nbytes); - -#endif /* included_vlibmemory_api_common_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/memory_api.c b/src/vlibmemory/memory_api.c new file mode 100644 index 00000000000..d049a625015 --- /dev/null +++ b/src/vlibmemory/memory_api.c @@ -0,0 +1,905 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ +#include + +#include +#include +#include +#include + +#include /* enumerate all vlib messages */ + +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +/* instantiate all the endian swap functions we know about */ +#define vl_endianfun +#include +#undef vl_endianfun + +static inline void * +vl_api_memclnt_create_t_print (vl_api_memclnt_create_t * a, void *handle) +{ + vl_print (handle, "vl_api_memclnt_create_t:\n"); + vl_print (handle, "name: %s\n", a->name); + vl_print (handle, "input_queue: 0x%wx\n", a->input_queue); + vl_print (handle, "context: %u\n", (unsigned) a->context); + vl_print (handle, "ctx_quota: %ld\n", (long) a->ctx_quota); + return handle; +} + +static inline void * +vl_api_memclnt_delete_t_print (vl_api_memclnt_delete_t * a, void *handle) +{ + vl_print (handle, "vl_api_memclnt_delete_t:\n"); + vl_print (handle, "index: %u\n", (unsigned) a->index); + vl_print (handle, "handle: 0x%wx\n", a->handle); + return handle; +} + +volatile int **vl_api_queue_cursizes; + +static void +memclnt_queue_callback (vlib_main_t * vm) +{ + int i; + api_main_t *am = &api_main; + + if (PREDICT_FALSE (vec_len (vl_api_queue_cursizes) != + 1 + vec_len (am->vlib_private_rps))) + { + vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; + svm_queue_t *q; + + if (shmem_hdr == 0) + return; + + q = shmem_hdr->vl_input_queue; + if (q == 0) + return; + + vec_add1 (vl_api_queue_cursizes, &q->cursize); + + for (i = 0; i < vec_len (am->vlib_private_rps); i++) + { + svm_region_t *vlib_rp = am->vlib_private_rps[i]; + + shmem_hdr = (void *) vlib_rp->user_ctx; + q = shmem_hdr->vl_input_queue; + vec_add1 (vl_api_queue_cursizes, &q->cursize); + } + } + + for (i = 0; i < vec_len (vl_api_queue_cursizes); i++) + { + if (*vl_api_queue_cursizes[i]) + { + vm->queue_signal_pending = 1; + vm->api_queue_nonempty = 1; + vlib_process_signal_event (vm, vl_api_clnt_node.index, + /* event_type */ QUEUE_SIGNAL_EVENT, + /* event_data */ 0); + break; + } + } +} + +/* + * vl_api_memclnt_create_internal + */ +u32 +vl_api_memclnt_create_internal (char *name, svm_queue_t * q) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + svm_region_t *svm; + void *oldheap; + api_main_t *am = &api_main; + + ASSERT (vlib_get_thread_index () == 0); + pool_get (am->vl_clients, regpp); + + svm = am->vlib_rp; + + pthread_mutex_lock (&svm->mutex); + oldheap = svm_push_data_heap (svm); + *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); + + regp = *regpp; + memset (regp, 0, sizeof (*regp)); + regp->registration_type = REGISTRATION_TYPE_SHMEM; + regp->vl_api_registration_pool_index = regpp - am->vl_clients; + regp->vlib_rp = svm; + regp->shmem_hdr = am->shmem_hdr; + + regp->vl_input_queue = q; + regp->name = format (0, "%s%c", name, 0); + + pthread_mutex_unlock (&svm->mutex); + svm_pop_heap (oldheap); + return vl_msg_api_handle_from_index_and_epoch + (regp->vl_api_registration_pool_index, + am->shmem_hdr->application_restarts); +} + +/* + * vl_api_memclnt_create_t_handler + */ +void +vl_api_memclnt_create_t_handler (vl_api_memclnt_create_t * mp) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + vl_api_memclnt_create_reply_t *rp; + svm_region_t *svm; + svm_queue_t *q; + int rv = 0; + void *oldheap; + api_main_t *am = &api_main; + + /* + * This is tortured. Maintain a vlib-address-space private + * pool of client registrations. We use the shared-memory virtual + * address of client structure as a handle, to allow direct + * manipulation of context quota vbls from the client library. + * + * This scheme causes trouble w/ API message trace replay, since + * some random VA from clib_mem_alloc() certainly won't + * occur in the Linux sim. The (very) few places + * that care need to use the pool index. + * + * Putting the registration object(s) into a pool in shared memory and + * using the pool index as a handle seems like a great idea. + * Unfortunately, each and every reference to that pool would need + * to be protected by a mutex: + * + * Client VLIB + * ------ ---- + * convert pool index to + * pointer. + * + * expand pool + * + * kaboom! + */ + + pool_get (am->vl_clients, regpp); + + svm = am->vlib_rp; + + pthread_mutex_lock (&svm->mutex); + oldheap = svm_push_data_heap (svm); + *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); + + regp = *regpp; + memset (regp, 0, sizeof (*regp)); + regp->registration_type = REGISTRATION_TYPE_SHMEM; + regp->vl_api_registration_pool_index = regpp - am->vl_clients; + regp->vlib_rp = svm; + regp->shmem_hdr = am->shmem_hdr; + + q = regp->vl_input_queue = (svm_queue_t *) (uword) mp->input_queue; + + regp->name = format (0, "%s", mp->name); + vec_add1 (regp->name, 0); + + if (am->serialized_message_table_in_shmem == 0) + am->serialized_message_table_in_shmem = + vl_api_serialize_message_table (am, 0); + + pthread_mutex_unlock (&svm->mutex); + svm_pop_heap (oldheap); + + rp = vl_msg_api_alloc (sizeof (*rp)); + rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_REPLY); + rp->handle = (uword) regp; + rp->index = vl_msg_api_handle_from_index_and_epoch + (regp->vl_api_registration_pool_index, + am->shmem_hdr->application_restarts); + rp->context = mp->context; + rp->response = ntohl (rv); + rp->message_table = + pointer_to_uword (am->serialized_message_table_in_shmem); + + vl_msg_api_send_shmem (q, (u8 *) & rp); +} + +int +vl_api_call_reaper_functions (u32 client_index) +{ + clib_error_t *error = 0; + _vl_msg_api_function_list_elt_t *i; + + i = api_main.reaper_function_registrations; + while (i) + { + error = i->f (client_index); + if (error) + clib_error_report (error); + i = i->next_init_function; + } + return 0; +} + +/* + * vl_api_memclnt_delete_t_handler + */ +void +vl_api_memclnt_delete_t_handler (vl_api_memclnt_delete_t * mp) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + vl_api_memclnt_delete_reply_t *rp; + svm_region_t *svm; + void *oldheap; + api_main_t *am = &api_main; + u32 handle, client_index, epoch; + + handle = mp->index; + + if (vl_api_call_reaper_functions (handle)) + return; + + epoch = vl_msg_api_handle_get_epoch (handle); + client_index = vl_msg_api_handle_get_index (handle); + + if (epoch != (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)) + { + clib_warning + ("Stale clnt delete index %d old epoch %d cur epoch %d", + client_index, epoch, + (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)); + return; + } + + regpp = am->vl_clients + client_index; + + if (!pool_is_free (am->vl_clients, regpp)) + { + int i; + regp = *regpp; + svm = am->vlib_rp; + int private_registration = 0; + + /* + * Note: the API message handling path will set am->vlib_rp + * as appropriate for pairwise / private memory segments + */ + rp = vl_msg_api_alloc (sizeof (*rp)); + rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE_REPLY); + rp->handle = mp->handle; + rp->response = 1; + + vl_msg_api_send_shmem (regp->vl_input_queue, (u8 *) & rp); + + if (client_index != regp->vl_api_registration_pool_index) + { + clib_warning ("mismatch client_index %d pool_index %d", + client_index, regp->vl_api_registration_pool_index); + vl_msg_api_free (rp); + return; + } + + /* For horizontal scaling, add a hash table... */ + for (i = 0; i < vec_len (am->vlib_private_rps); i++) + { + /* Is this a pairwise / private API segment? */ + if (am->vlib_private_rps[i] == svm) + { + /* Note: account for the memfd header page */ + u64 virtual_base = svm->virtual_base - MMAP_PAGESIZE; + u64 virtual_size = svm->virtual_size + MMAP_PAGESIZE; + + /* + * Kill the registration pool element before we make + * the index vanish forever + */ + pool_put_index (am->vl_clients, + regp->vl_api_registration_pool_index); + + vec_delete (am->vlib_private_rps, 1, i); + /* Kill it, accounting for the memfd header page */ + if (munmap ((void *) virtual_base, virtual_size) < 0) + clib_unix_warning ("munmap"); + /* Reset the queue-length-address cache */ + vec_reset_length (vl_api_queue_cursizes); + private_registration = 1; + break; + } + } + + /* No dangling references, please */ + *regpp = 0; + + if (private_registration == 0) + { + pool_put_index (am->vl_clients, + regp->vl_api_registration_pool_index); + pthread_mutex_lock (&svm->mutex); + oldheap = svm_push_data_heap (svm); + /* Poison the old registration */ + memset (regp, 0xF1, sizeof (*regp)); + clib_mem_free (regp); + pthread_mutex_unlock (&svm->mutex); + svm_pop_heap (oldheap); + /* + * These messages must be freed manually, since they're set up + * as "bounce" messages. In the private_registration == 1 case, + * we kill the shared-memory segment which contains the message + * with munmap. + */ + vl_msg_api_free (mp); + } + } + else + { + clib_warning ("unknown client ID %d", mp->index); + } +} + +/** + * client answered a ping, stave off the grim reaper... + */ +void + vl_api_memclnt_keepalive_reply_t_handler + (vl_api_memclnt_keepalive_reply_t * mp) +{ + vl_api_registration_t *regp; + vlib_main_t *vm = vlib_get_main (); + + regp = vl_api_client_index_to_registration (mp->context); + if (regp) + { + regp->last_heard = vlib_time_now (vm); + regp->unanswered_pings = 0; + } + else + clib_warning ("BUG: anonymous memclnt_keepalive_reply"); +} + +/** + * We can send ourselves these messages if someone uses the + * builtin binary api test tool... + */ +static void +vl_api_memclnt_keepalive_t_handler (vl_api_memclnt_keepalive_t * mp) +{ + vl_api_memclnt_keepalive_reply_t *rmp; + api_main_t *am; + vl_shmem_hdr_t *shmem_hdr; + + am = &api_main; + shmem_hdr = am->shmem_hdr; + + rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_MEMCLNT_KEEPALIVE_REPLY); + rmp->context = mp->context; + vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & rmp); +} + +#define foreach_vlib_api_msg \ +_(MEMCLNT_CREATE, memclnt_create) \ +_(MEMCLNT_DELETE, memclnt_delete) \ +_(MEMCLNT_KEEPALIVE, memclnt_keepalive) \ +_(MEMCLNT_KEEPALIVE_REPLY, memclnt_keepalive_reply) \ + +/* + * memory_api_init + */ +int +vl_mem_api_init (const char *region_name) +{ + int rv; + api_main_t *am = &api_main; + vl_msg_api_msg_config_t cfg; + vl_msg_api_msg_config_t *c = &cfg; + vl_shmem_hdr_t *shm; + vlib_main_t *vm = vlib_get_main (); + + memset (c, 0, sizeof (*c)); + + if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0) + return rv; + +#define _(N,n) do { \ + c->id = VL_API_##N; \ + c->name = #n; \ + c->handler = vl_api_##n##_t_handler; \ + c->cleanup = vl_noop_handler; \ + c->endian = vl_api_##n##_t_endian; \ + c->print = vl_api_##n##_t_print; \ + c->size = sizeof(vl_api_##n##_t); \ + c->traced = 1; /* trace, so these msgs print */ \ + c->replay = 0; /* don't replay client create/delete msgs */ \ + c->message_bounce = 0; /* don't bounce this message */ \ + vl_msg_api_config(c);} while (0); + + foreach_vlib_api_msg; +#undef _ + + /* + * special-case freeing of memclnt_delete messages, so we can + * simply munmap pairwise / private API segments... + */ + am->message_bounce[VL_API_MEMCLNT_DELETE] = 1; + am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE_REPLY] = 1; + + vlib_set_queue_signal_callback (vm, memclnt_queue_callback); + + shm = am->shmem_hdr; + ASSERT (shm && shm->vl_input_queue); + + /* Make a note so we can always find the primary region easily */ + am->vlib_primary_rp = am->vlib_rp; + + return 0; +} + +static void +send_memclnt_keepalive (vl_api_registration_t * regp, f64 now) +{ + vl_api_memclnt_keepalive_t *mp; + svm_queue_t *q; + api_main_t *am = &api_main; + svm_region_t *save_vlib_rp = am->vlib_rp; + vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr; + + q = regp->vl_input_queue; + + /* + * If the queue head is moving, assume that the client is processing + * messages and skip the ping. This heuristic may fail if the queue + * is in the same position as last time, net of wrapping; in which + * case, the client will receive a keepalive. + */ + if (regp->last_queue_head != q->head) + { + regp->last_heard = now; + regp->unanswered_pings = 0; + regp->last_queue_head = q->head; + return; + } + + /* + * push/pop shared memory segment, so this routine + * will work with "normal" as well as "private segment" + * memory clients.. + */ + + am->vlib_rp = regp->vlib_rp; + am->shmem_hdr = regp->shmem_hdr; + + mp = vl_msg_api_alloc (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_MEMCLNT_KEEPALIVE); + mp->context = mp->client_index = + vl_msg_api_handle_from_index_and_epoch + (regp->vl_api_registration_pool_index, + am->shmem_hdr->application_restarts); + + regp->unanswered_pings++; + + /* Failure-to-send due to a stuffed queue is absolutely expected */ + if (svm_queue_add (q, (u8 *) & mp, 1 /* nowait */ )) + vl_msg_api_free (mp); + + am->vlib_rp = save_vlib_rp; + am->shmem_hdr = save_shmem_hdr; +} + +void +vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + static u32 *dead_indices; + static u32 *confused_indices; + + vec_reset_length (dead_indices); + vec_reset_length (confused_indices); + + /* *INDENT-OFF* */ + pool_foreach (regpp, am->vl_clients, + ({ + regp = *regpp; + if (regp) + { + /* If we haven't heard from this client recently... */ + if (regp->last_heard < (now - 10.0)) + { + if (regp->unanswered_pings == 2) + { + svm_queue_t *q; + q = regp->vl_input_queue; + if (kill (q->consumer_pid, 0) >=0) + { + clib_warning ("REAPER: lazy binary API client '%s'", + regp->name); + regp->unanswered_pings = 0; + regp->last_heard = now; + } + else + { + clib_warning ("REAPER: binary API client '%s' died", + regp->name); + vec_add1(dead_indices, regpp - am->vl_clients); + } + } + else + send_memclnt_keepalive (regp, now); + } + else + regp->unanswered_pings = 0; + } + else + { + clib_warning ("NULL client registration index %d", + regpp - am->vl_clients); + vec_add1 (confused_indices, regpp - am->vl_clients); + } + })); + /* *INDENT-ON* */ + /* This should "never happen," but if it does, fix it... */ + if (PREDICT_FALSE (vec_len (confused_indices) > 0)) + { + int i; + for (i = 0; i < vec_len (confused_indices); i++) + { + pool_put_index (am->vl_clients, confused_indices[i]); + } + } + + if (PREDICT_FALSE (vec_len (dead_indices) > 0)) + { + int i; + svm_region_t *svm; + void *oldheap; + + /* Allow the application to clean up its registrations */ + for (i = 0; i < vec_len (dead_indices); i++) + { + regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]); + if (regpp) + { + u32 handle; + + handle = vl_msg_api_handle_from_index_and_epoch + (dead_indices[i], shm->application_restarts); + (void) vl_api_call_reaper_functions (handle); + } + } + + svm = am->vlib_rp; + pthread_mutex_lock (&svm->mutex); + oldheap = svm_push_data_heap (svm); + + for (i = 0; i < vec_len (dead_indices); i++) + { + regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]); + if (regpp) + { + /* Is this a pairwise SVM segment? */ + if ((*regpp)->vlib_rp != svm) + { + int i; + svm_region_t *dead_rp = (*regpp)->vlib_rp; + /* Note: account for the memfd header page */ + u64 virtual_base = dead_rp->virtual_base - MMAP_PAGESIZE; + u64 virtual_size = dead_rp->virtual_size + MMAP_PAGESIZE; + + /* For horizontal scaling, add a hash table... */ + for (i = 0; i < vec_len (am->vlib_private_rps); i++) + if (am->vlib_private_rps[i] == dead_rp) + { + vec_delete (am->vlib_private_rps, 1, i); + goto found; + } + clib_warning ("private rp %llx AWOL", dead_rp); + + found: + /* Kill it, accounting for the memfd header page */ + if (munmap ((void *) virtual_base, virtual_size) < 0) + clib_unix_warning ("munmap"); + /* Reset the queue-length-address cache */ + vec_reset_length (vl_api_queue_cursizes); + } + else + { + /* Poison the old registration */ + memset (*regpp, 0xF3, sizeof (**regpp)); + clib_mem_free (*regpp); + } + /* no dangling references, please */ + *regpp = 0; + } + else + { + svm_pop_heap (oldheap); + clib_warning ("Duplicate free, client index %d", + regpp - am->vl_clients); + oldheap = svm_push_data_heap (svm); + } + } + + svm_client_scan_this_region_nolock (am->vlib_rp); + + pthread_mutex_unlock (&svm->mutex); + svm_pop_heap (oldheap); + for (i = 0; i < vec_len (dead_indices); i++) + pool_put_index (am->vl_clients, dead_indices[i]); + } +} + +static inline int +void_mem_api_handle_msg_i (api_main_t * am, vlib_main_t * vm, + vlib_node_runtime_t * node, svm_queue_t * q) +{ + uword mp; + if (!svm_queue_sub2 (q, (u8 *) & mp)) + { + vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node); + return 0; + } + return -1; +} + +int +vl_mem_api_handle_msg_main (vlib_main_t * vm, vlib_node_runtime_t * node) +{ + api_main_t *am = &api_main; + return void_mem_api_handle_msg_i (am, vm, node, + am->shmem_hdr->vl_input_queue); +} + +int +vl_mem_api_handle_msg_private (vlib_main_t * vm, vlib_node_runtime_t * node, + u32 reg_index) +{ + api_main_t *am = &api_main; + vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr; + svm_region_t *vlib_rp, *save_vlib_rp = am->vlib_rp; + svm_queue_t *q; + int rv; + + vlib_rp = am->vlib_rp = am->vlib_private_rps[reg_index]; + + am->shmem_hdr = (void *) vlib_rp->user_ctx; + q = am->shmem_hdr->vl_input_queue; + + rv = void_mem_api_handle_msg_i (am, vm, node, q); + + am->shmem_hdr = save_shmem_hdr; + am->vlib_rp = save_vlib_rp; + + return rv; +} + +vl_api_registration_t * +vl_mem_api_client_index_to_registration (u32 handle) +{ + vl_api_registration_t **regpp; + vl_api_registration_t *regp; + api_main_t *am = &api_main; + u32 index; + + index = vl_msg_api_handle_get_index (handle); + if ((am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK) + != vl_msg_api_handle_get_epoch (handle)) + { + vl_msg_api_increment_missing_client_counter (); + return 0; + } + + regpp = am->vl_clients + index; + + if (pool_is_free (am->vl_clients, regpp)) + { + vl_msg_api_increment_missing_client_counter (); + return 0; + } + regp = *regpp; + return (regp); +} + +svm_queue_t * +vl_api_client_index_to_input_queue (u32 index) +{ + vl_api_registration_t *regp; + api_main_t *am = &api_main; + + /* Special case: vlib trying to send itself a message */ + if (index == (u32) ~ 0) + return (am->shmem_hdr->vl_input_queue); + + regp = vl_mem_api_client_index_to_registration (index); + if (!regp) + return 0; + return (regp->vl_input_queue); +} + +static clib_error_t * +setup_memclnt_exit (vlib_main_t * vm) +{ + atexit (vl_unmap_shmem); + return 0; +} + +VLIB_INIT_FUNCTION (setup_memclnt_exit); + +u8 * +format_api_message_rings (u8 * s, va_list * args) +{ + api_main_t *am = va_arg (*args, api_main_t *); + vl_shmem_hdr_t *shmem_hdr = va_arg (*args, vl_shmem_hdr_t *); + int main_segment = va_arg (*args, int); + ring_alloc_t *ap; + int i; + + if (shmem_hdr == 0) + return format (s, "%8s %8s %8s %8s %8s\n", + "Owner", "Size", "Nitems", "Hits", "Misses"); + + ap = shmem_hdr->vl_rings; + + for (i = 0; i < vec_len (shmem_hdr->vl_rings); i++) + { + s = format (s, "%8s %8d %8d %8d %8d\n", + "vlib", ap->size, ap->nitems, ap->hits, ap->misses); + ap++; + } + + ap = shmem_hdr->client_rings; + + for (i = 0; i < vec_len (shmem_hdr->client_rings); i++) + { + s = format (s, "%8s %8d %8d %8d %8d\n", + "clnt", ap->size, ap->nitems, ap->hits, ap->misses); + ap++; + } + + if (main_segment) + { + s = format (s, "%d ring miss fallback allocations\n", am->ring_misses); + s = format + (s, + "%d application restarts, %d reclaimed msgs, %d garbage collects\n", + shmem_hdr->application_restarts, shmem_hdr->restart_reclaims, + shmem_hdr->garbage_collects); + } + return s; +} + +static clib_error_t * +vl_api_ring_command (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cli_cmd) +{ + int i; + vl_shmem_hdr_t *shmem_hdr; + api_main_t *am = &api_main; + + /* First, dump the primary region rings.. */ + + if (am->vlib_primary_rp == 0 || am->vlib_primary_rp->user_ctx == 0) + { + vlib_cli_output (vm, "Shared memory segment not initialized...\n"); + return 0; + } + + shmem_hdr = (void *) am->vlib_primary_rp->user_ctx; + + vlib_cli_output (vm, "Main API segment rings:"); + + vlib_cli_output (vm, "%U", format_api_message_rings, am, + 0 /* print header */ , 0 /* notused */ ); + + vlib_cli_output (vm, "%U", format_api_message_rings, am, + shmem_hdr, 1 /* main segment */ ); + + for (i = 0; i < vec_len (am->vlib_private_rps); i++) + { + svm_region_t *vlib_rp = am->vlib_private_rps[i]; + shmem_hdr = (void *) vlib_rp->user_ctx; + vl_api_registration_t **regpp; + vl_api_registration_t *regp = 0; + + /* For horizontal scaling, add a hash table... */ + /* *INDENT-OFF* */ + pool_foreach (regpp, am->vl_clients, + ({ + regp = *regpp; + if (regp && regp->vlib_rp == vlib_rp) + { + vlib_cli_output (vm, "%s segment rings:", regp->name); + goto found; + } + })); + vlib_cli_output (vm, "regp %llx not found?", regp); + continue; + /* *INDENT-ON* */ + found: + vlib_cli_output (vm, "%U", format_api_message_rings, am, + 0 /* print header */ , 0 /* notused */ ); + vlib_cli_output (vm, "%U", format_api_message_rings, am, + shmem_hdr, 0 /* main segment */ ); + } + + return 0; +} + +/*? + * Display binary api message allocation ring statistics +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_ring_command, static) = +{ + .path = "show api ring-stats", + .short_help = "Message ring statistics", + .function = vl_api_ring_command, +}; +/* *INDENT-ON* */ + +clib_error_t * +vlibmemory_init (vlib_main_t * vm) +{ + api_main_t *am = &api_main; + svm_map_region_args_t _a, *a = &_a; + clib_error_t *error; + + memset (a, 0, sizeof (*a)); + a->root_path = am->root_path; + a->name = SVM_GLOBAL_REGION_NAME; + a->baseva = (am->global_baseva != 0) ? + am->global_baseva : SVM_GLOBAL_REGION_BASEVA; + a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE; + a->flags = SVM_FLAGS_NODATA; + a->uid = am->api_uid; + a->gid = am->api_gid; + a->pvt_heap_size = + (am->global_pvt_heap_size != + 0) ? am->global_pvt_heap_size : SVM_PVT_MHEAP_SIZE; + + svm_region_init_args (a); + + error = vlib_call_init_function (vm, vlibsocket_init); + + return error; +} + +VLIB_INIT_FUNCTION (vlibmemory_init); + +void +vl_set_memory_region_name (const char *name) +{ + api_main_t *am = &api_main; + am->region_name = name; +} + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/memory_api.h b/src/vlibmemory/memory_api.h new file mode 100644 index 00000000000..9b87f5a18fd --- /dev/null +++ b/src/vlibmemory/memory_api.h @@ -0,0 +1,80 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef SRC_VLIBMEMORY_MEMORY_API_H_ +#define SRC_VLIBMEMORY_MEMORY_API_H_ + +#include +#include +#include +#include +#include + +svm_queue_t *vl_api_client_index_to_input_queue (u32 index); +int vl_mem_api_init (const char *region_name); +void vl_mem_api_dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, + f64 now); +int vl_mem_api_handle_msg_main (vlib_main_t * vm, vlib_node_runtime_t * node); +int vl_mem_api_handle_msg_private (vlib_main_t * vm, + vlib_node_runtime_t * node, u32 reg_index); +vl_api_registration_t *vl_mem_api_client_index_to_registration (u32 handle); +void vl_mem_api_enable_disable (vlib_main_t * vm, int yesno); +u32 vl_api_memclnt_create_internal (char *, svm_queue_t *); + +static inline u32 +vl_msg_api_handle_get_epoch (u32 index) +{ + return (index & VL_API_EPOCH_MASK); +} + +static inline u32 +vl_msg_api_handle_get_index (u32 index) +{ + return (index >> VL_API_EPOCH_SHIFT); +} + +static inline u32 +vl_msg_api_handle_from_index_and_epoch (u32 index, u32 epoch) +{ + u32 handle; + ASSERT (index < 0x00FFFFFF); + + handle = (index << VL_API_EPOCH_SHIFT) | (epoch & VL_API_EPOCH_MASK); + return handle; +} + +#define VL_MEM_API_LOG_Q_LEN(fmt,qlen) \ +if (TRACE_VLIB_MEMORY_QUEUE) \ + do { \ + ELOG_TYPE_DECLARE (e) = { \ + .format = fmt, \ + .format_args = "i4", \ + }; \ + struct { u32 len; } *ed; \ + ed = ELOG_DATA (&vm->elog_main, e); \ + ed->len = qlen; \ + } while (0) + +#endif /* SRC_VLIBMEMORY_MEMORY_API_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/memory_client.c b/src/vlibmemory/memory_client.c index c47f25e6e3d..1bb2fe86136 100644 --- a/src/vlibmemory/memory_client.c +++ b/src/vlibmemory/memory_client.c @@ -17,33 +17,15 @@ *------------------------------------------------------------------ */ -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include +#include #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include + +/* A hack. vl_client_get_first_plugin_msg_id depends on it */ +#include #include @@ -77,7 +59,7 @@ memory_client_main_t memory_client_main; static void * rx_thread_fn (void *arg) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; memory_client_main_t *mm = &memory_client_main; api_main_t *am = &api_main; int i; @@ -178,7 +160,7 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size) svm_region_t *svm; vl_api_memclnt_create_t *mp; vl_api_memclnt_create_reply_t *rp; - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; vl_shmem_hdr_t *shmem_hdr; int rv = 0; void *oldheap; @@ -208,8 +190,7 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size) pthread_mutex_lock (&svm->mutex); oldheap = svm_push_data_heap (svm); vl_input_queue = - unix_shared_memory_queue_init (input_queue_size, sizeof (uword), - getpid (), 0); + svm_queue_init (input_queue_size, sizeof (uword), getpid (), 0); pthread_mutex_unlock (&svm->mutex); svm_pop_heap (oldheap); @@ -235,8 +216,8 @@ vl_client_connect (const char *name, int ctx_quota, int input_queue_size) /* Wait up to 10 seconds */ for (i = 0; i < 1000; i++) { - qstatus = unix_shared_memory_queue_sub (vl_input_queue, (u8 *) & rp, - 1 /* nowait */ ); + qstatus = svm_queue_sub (vl_input_queue, (u8 *) & rp, + 1 /* nowait */ ); if (qstatus == 0) goto read_one_msg; ts.tv_sec = 0; @@ -270,7 +251,7 @@ vl_api_memclnt_delete_reply_t_handler (vl_api_memclnt_delete_reply_t * mp) pthread_mutex_lock (&am->vlib_rp->mutex); oldheap = svm_push_data_heap (am->vlib_rp); - unix_shared_memory_queue_free (am->vl_input_queue); + svm_queue_free (am->vl_input_queue); pthread_mutex_unlock (&am->vlib_rp->mutex); svm_pop_heap (oldheap); @@ -284,7 +265,7 @@ vl_client_disconnect (void) { vl_api_memclnt_delete_t *mp; vl_api_memclnt_delete_reply_t *rp; - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; vl_shmem_hdr_t *shmem_hdr; time_t begin; api_main_t *am = &api_main; @@ -323,7 +304,7 @@ vl_client_disconnect (void) am->shmem_hdr = 0; break; } - if (unix_shared_memory_queue_sub (vl_input_queue, (u8 *) & rp, 1) < 0) + if (svm_queue_sub (vl_input_queue, (u8 *) & rp, 1) < 0) continue; /* drain the queue */ @@ -365,7 +346,6 @@ _(MEMCLNT_CREATE_REPLY, memclnt_create_reply) \ _(MEMCLNT_DELETE_REPLY, memclnt_delete_reply) \ _(MEMCLNT_KEEPALIVE, memclnt_keepalive) - void vl_client_install_client_message_handlers (void) { diff --git a/src/vlibmemory/memory_client.h b/src/vlibmemory/memory_client.h new file mode 100644 index 00000000000..5b4f090af9a --- /dev/null +++ b/src/vlibmemory/memory_client.h @@ -0,0 +1,46 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef SRC_VLIBMEMORY_MEMORY_CLIENT_H_ +#define SRC_VLIBMEMORY_MEMORY_CLIENT_H_ + +#include + +int vl_client_connect (const char *name, int ctx_quota, int input_queue_size); +void vl_client_disconnect (void); +int vl_client_api_map (const char *region_name); +void vl_client_api_unmap (void); +void vl_client_disconnect_from_vlib (void); +int vl_client_connect_to_vlib (const char *svm_name, const char *client_name, + int rx_queue_size); +int vl_client_connect_to_vlib_no_rx_pthread (const char *svm_name, + const char *client_name, + int rx_queue_size); +int vl_client_connect_to_vlib_no_map (const char *svm_name, + const char *client_name, + int rx_queue_size); +void vl_client_install_client_message_handlers (void); + +#endif /* SRC_VLIBMEMORY_MEMORY_CLIENT_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/memory_shared.c b/src/vlibmemory/memory_shared.c index 0a3c23cbb3e..19285df9efe 100644 --- a/src/vlibmemory/memory_shared.c +++ b/src/vlibmemory/memory_shared.c @@ -25,22 +25,20 @@ #include #include #include + #include #include #include +#include #include #include -#include -#include - +#include #include #define vl_typedefs #include #undef vl_typedefs -socket_main_t socket_main; - #define DEBUG_MESSAGE_BUFFER_OVERRUN 0 static inline void * @@ -49,7 +47,7 @@ vl_msg_api_alloc_internal (int nbytes, int pool, int may_return_null) int i; msgbuf_t *rv; ring_alloc_t *ap; - unix_shared_memory_queue_t *q; + svm_queue_t *q; void *oldheap; vl_shmem_hdr_t *shmem_hdr; api_main_t *am = &api_main; @@ -376,13 +374,13 @@ vl_api_default_mem_config (vl_shmem_hdr_t * shmem_hdr) vlib_input_queue_length = am->vlib_input_queue_length; shmem_hdr->vl_input_queue = - unix_shared_memory_queue_init (vlib_input_queue_length, sizeof (uword), - getpid (), am->vlib_signal); + svm_queue_init (vlib_input_queue_length, sizeof (uword), + getpid (), am->vlib_signal); #define _(sz,n) \ do { \ ring_alloc_t _rp; \ - _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \ + _rp.rp = svm_queue_init ((n), (sz), 0, 0); \ _rp.size = (sz); \ _rp.nitems = n; \ _rp.hits = 0; \ @@ -396,7 +394,7 @@ vl_api_default_mem_config (vl_shmem_hdr_t * shmem_hdr) #define _(sz,n) \ do { \ ring_alloc_t _rp; \ - _rp.rp = unix_shared_memory_queue_init ((n), (sz), 0, 0); \ + _rp.rp = svm_queue_init ((n), (sz), 0, 0); \ _rp.size = (sz); \ _rp.nitems = n; \ _rp.hits = 0; \ @@ -427,10 +425,9 @@ vl_api_mem_config (vl_shmem_hdr_t * hdr, vl_api_shm_elem_config_t * config) switch (c->type) { case VL_API_QUEUE: - hdr->vl_input_queue = unix_shared_memory_queue_init (c->count, - c->size, - getpid (), - am->vlib_signal); + hdr->vl_input_queue = svm_queue_init (c->count, + c->size, + getpid (), am->vlib_signal); continue; case VL_API_VLIB_RING: vec_add2 (hdr->vl_rings, rp, 1); @@ -444,7 +441,7 @@ vl_api_mem_config (vl_shmem_hdr_t * hdr, vl_api_shm_elem_config_t * config) } size = sizeof (ring_alloc_t) + c->size; - rp->rp = unix_shared_memory_queue_init (c->count, size, 0, 0); + rp->rp = svm_queue_init (c->count, size, 0, 0); rp->size = size; rp->nitems = c->count; rp->hits = 0; @@ -493,7 +490,6 @@ vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config, pthread_mutex_unlock (&vlib_rp->mutex); } - int vl_map_shmem (const char *region_name, int is_vlib) { @@ -548,7 +544,7 @@ vl_map_shmem (const char *region_name, int is_vlib) am->our_pid = getpid (); if (is_vlib) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; uword old_msg; /* * application restart. Reset cached pids, API message @@ -581,9 +577,7 @@ vl_map_shmem (const char *region_name, int is_vlib) mutex_ok: am->vlib_rp = vlib_rp; - while (unix_shared_memory_queue_sub (q, - (u8 *) & old_msg, - 1 /* nowait */ ) + while (svm_queue_sub (q, (u8 *) & old_msg, 1 /* nowait */ ) != -2 /* queue underflow */ ) { vl_msg_api_free_nolock ((void *) old_msg); @@ -676,7 +670,7 @@ vl_unmap_shmem (void) } void -vl_msg_api_send_shmem (unix_shared_memory_queue_t * q, u8 * elem) +vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem) { api_main_t *am = &api_main; uword *trace = (uword *) elem; @@ -684,11 +678,11 @@ vl_msg_api_send_shmem (unix_shared_memory_queue_t * q, u8 * elem) if (am->tx_trace && am->tx_trace->enabled) vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]); - (void) unix_shared_memory_queue_add (q, elem, 0 /* nowait */ ); + (void) svm_queue_add (q, elem, 0 /* nowait */ ); } void -vl_msg_api_send_shmem_nolock (unix_shared_memory_queue_t * q, u8 * elem) +vl_msg_api_send_shmem_nolock (svm_queue_t * q, u8 * elem) { api_main_t *am = &api_main; uword *trace = (uword *) elem; @@ -696,74 +690,7 @@ vl_msg_api_send_shmem_nolock (unix_shared_memory_queue_t * q, u8 * elem) if (am->tx_trace && am->tx_trace->enabled) vl_msg_api_trace (am, am->tx_trace, (void *) trace[0]); - (void) unix_shared_memory_queue_add_nolock (q, elem); -} - -u32 -vl_api_get_msg_index (u8 * name_and_crc) -{ - api_main_t *am = &api_main; - uword *p; - - if (am->msg_index_by_name_and_crc) - { - p = hash_get_mem (am->msg_index_by_name_and_crc, name_and_crc); - if (p) - return p[0]; - } - return ~0; -} - -static inline vl_api_registration_t * -vl_api_client_index_to_registration_internal (u32 handle) -{ - vl_api_registration_t **regpp; - vl_api_registration_t *regp; - api_main_t *am = &api_main; - u32 index; - - index = vl_msg_api_handle_get_index (handle); - if ((am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK) - != vl_msg_api_handle_get_epoch (handle)) - { - vl_msg_api_increment_missing_client_counter (); - return 0; - } - - regpp = am->vl_clients + index; - - if (pool_is_free (am->vl_clients, regpp)) - { - vl_msg_api_increment_missing_client_counter (); - return 0; - } - regp = *regpp; - return (regp); -} - -vl_api_registration_t * -vl_api_client_index_to_registration (u32 index) -{ - if (PREDICT_FALSE (socket_main.current_rp != 0)) - return socket_main.current_rp; - - return (vl_api_client_index_to_registration_internal (index)); -} - -unix_shared_memory_queue_t * -vl_api_client_index_to_input_queue (u32 index) -{ - vl_api_registration_t *regp; - api_main_t *am = &api_main; - - /* Special case: vlib trying to send itself a message */ - if (index == (u32) ~ 0) - return (am->shmem_hdr->vl_input_queue); - - regp = vl_api_client_index_to_registration_internal (index); - if (!regp) - return 0; - return (regp->vl_input_queue); + (void) svm_queue_add_nolock (q, elem); } /* diff --git a/src/vlibmemory/memory_shared.h b/src/vlibmemory/memory_shared.h new file mode 100644 index 00000000000..f60224a1815 --- /dev/null +++ b/src/vlibmemory/memory_shared.h @@ -0,0 +1,138 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef SRC_VLIBMEMORY_MEMORY_SHARED_H_ +#define SRC_VLIBMEMORY_MEMORY_SHARED_H_ + +#include +#include + +/* Allocated in shared memory */ + +/* + * Ring-allocation scheme for client API messages + * + * Only one proc/thread has control of a given message buffer. + * To free a buffer allocated from one of these rings, we clear + * a field in the buffer (header), and leave. + * + * No locks, no hits, no errors... + */ +typedef struct ring_alloc_ +{ + svm_queue_t *rp; + u16 size; + u16 nitems; + u32 hits; + u32 misses; +} ring_alloc_t; + +typedef enum +{ + VL_API_VLIB_RING, + VL_API_CLIENT_RING, + VL_API_QUEUE +} vl_api_shm_config_type_t; + +typedef struct vl_api_shm_elem_config_ +{ + u8 type; + u8 _pad; + u16 count; + u32 size; +} vl_api_shm_elem_config_t; + +STATIC_ASSERT (sizeof (vl_api_shm_elem_config_t) == 8, + "Size must be exactly 8 bytes"); + +/* + * Initializers for the (shared-memory) rings + * _(size, n). Note: each msg has space for a header. + */ +#define foreach_vl_aring_size \ +_(64+sizeof(ring_alloc_t), 1024) \ +_(256+sizeof(ring_alloc_t), 128) \ +_(1024+sizeof(ring_alloc_t), 64) + +#define foreach_clnt_aring_size \ + _(1024+sizeof(ring_alloc_t), 1024) \ + _(2048+sizeof(ring_alloc_t), 128) \ + _(4096+sizeof(ring_alloc_t), 8) + +typedef struct vl_shmem_hdr_ +{ + int version; + + /* getpid () for the VLIB client process */ + volatile int vl_pid; + + /* Client sends VLIB msgs here. */ + svm_queue_t *vl_input_queue; + + /* Vector of rings; one for each size. */ + + /* VLIB allocates buffers to send msgs to clients here. */ + ring_alloc_t *vl_rings; + + /* Clients allocate buffer to send msgs to VLIB here. */ + ring_alloc_t *client_rings; + + /* Number of detected application restarts */ + u32 application_restarts; + + /* Number of messages reclaimed during application restart */ + u32 restart_reclaims; + + /* Number of garbage-collected messages */ + u32 garbage_collects; +} vl_shmem_hdr_t; + +#define VL_SHM_VERSION 2 +#define VL_API_EPOCH_MASK 0xFF +#define VL_API_EPOCH_SHIFT 8 + +void *vl_msg_api_alloc (int nbytes); +void *vl_msg_api_alloc_or_null (int nbytes); +void *vl_msg_api_alloc_as_if_client (int nbytes); +void *vl_msg_api_alloc_as_if_client_or_null (int nbytes); +void vl_msg_api_free (void *a); +int vl_map_shmem (const char *region_name, int is_vlib); +void vl_unmap_shmem (void); +void vl_register_mapped_shmem_region (svm_region_t * rp); +void vl_msg_api_send_shmem (svm_queue_t * q, u8 * elem); +void vl_msg_api_send_shmem_nolock (svm_queue_t * q, u8 * elem); +void vl_set_memory_region_name (const char *name); +void vl_set_memory_root_path (const char *root_path); +void vl_set_memory_uid (int uid); +void vl_set_memory_gid (int gid); +void vl_set_global_memory_baseva (u64 baseva); +void vl_set_global_memory_size (u64 size); +void vl_set_api_memory_size (u64 size); +void vl_set_global_pvt_heap_size (u64 size); +void vl_set_api_pvt_heap_size (u64 size); +void vl_init_shmem (svm_region_t * vlib_rp, vl_api_shm_elem_config_t * config, + int is_vlib, int is_private_region); + +#endif /* SRC_VLIBMEMORY_MEMORY_SHARED_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/memory_vlib.c b/src/vlibmemory/memory_vlib.c deleted file mode 100644 index 345b40412c0..00000000000 --- a/src/vlibmemory/memory_vlib.c +++ /dev/null @@ -1,2803 +0,0 @@ -/* - *------------------------------------------------------------------ - * memory_vlib.c - * - * Copyright (c) 2009 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @file - * @brief Binary API messaging via shared memory - * Low-level, primary provisioning interface - */ -/*? %%clicmd:group_label Binary API CLI %% ?*/ -/*? %%syscfg:group_label Binary API configuration %% ?*/ - -#define TRACE_VLIB_MEMORY_QUEUE 0 - -#include /* enumerate all vlib messages */ - -#define vl_typedefs /* define message structures */ -#include -#undef vl_typedefs - -/* instantiate all the print functions we know about */ -#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) -#define vl_printfun -#include -#undef vl_printfun - -static inline void * -vl_api_memclnt_create_t_print (vl_api_memclnt_create_t * a, void *handle) -{ - vl_print (handle, "vl_api_memclnt_create_t:\n"); - vl_print (handle, "name: %s\n", a->name); - vl_print (handle, "input_queue: 0x%wx\n", a->input_queue); - vl_print (handle, "context: %u\n", (unsigned) a->context); - vl_print (handle, "ctx_quota: %ld\n", (long) a->ctx_quota); - return handle; -} - -static inline void * -vl_api_memclnt_delete_t_print (vl_api_memclnt_delete_t * a, void *handle) -{ - vl_print (handle, "vl_api_memclnt_delete_t:\n"); - vl_print (handle, "index: %u\n", (unsigned) a->index); - vl_print (handle, "handle: 0x%wx\n", a->handle); - return handle; -} - -static inline void * -vl_api_trace_plugin_msg_ids_t_print (vl_api_trace_plugin_msg_ids_t * a, - void *handle) -{ - vl_print (handle, "vl_api_trace_plugin_msg_ids: %s first %u last %u\n", - a->plugin_name, - clib_host_to_net_u16 (a->first_msg_id), - clib_host_to_net_u16 (a->last_msg_id)); - return handle; -} - -/* instantiate all the endian swap functions we know about */ -#define vl_endianfun -#include -#undef vl_endianfun - -extern void vl_socket_api_send (vl_api_registration_t * rp, u8 * elem); - -void -vl_msg_api_send (vl_api_registration_t * rp, u8 * elem) -{ - if (PREDICT_FALSE (rp->registration_type > REGISTRATION_TYPE_SHMEM)) - { - vl_socket_api_send (rp, elem); - } - else - { - vl_msg_api_send_shmem (rp->vl_input_queue, (u8 *) & elem); - } -} - -u8 * -vl_api_serialize_message_table (api_main_t * am, u8 * vector) -{ - serialize_main_t _sm, *sm = &_sm; - hash_pair_t *hp; - u32 nmsg = hash_elts (am->msg_index_by_name_and_crc); - - serialize_open_vector (sm, vector); - - /* serialize the count */ - serialize_integer (sm, nmsg, sizeof (u32)); - - /* *INDENT-OFF* */ - hash_foreach_pair (hp, am->msg_index_by_name_and_crc, - ({ - serialize_likely_small_unsigned_integer (sm, hp->value[0]); - serialize_cstring (sm, (char *) hp->key); - })); - /* *INDENT-ON* */ - - return serialize_close_vector (sm); -} - -/* - * vl_api_memclnt_create_internal - */ - -u32 -vl_api_memclnt_create_internal (char *name, unix_shared_memory_queue_t * q) -{ - vl_api_registration_t **regpp; - vl_api_registration_t *regp; - svm_region_t *svm; - void *oldheap; - api_main_t *am = &api_main; - - ASSERT (vlib_get_thread_index () == 0); - pool_get (am->vl_clients, regpp); - - svm = am->vlib_rp; - - pthread_mutex_lock (&svm->mutex); - oldheap = svm_push_data_heap (svm); - *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); - - regp = *regpp; - memset (regp, 0, sizeof (*regp)); - regp->registration_type = REGISTRATION_TYPE_SHMEM; - regp->vl_api_registration_pool_index = regpp - am->vl_clients; - regp->vlib_rp = svm; - regp->shmem_hdr = am->shmem_hdr; - - regp->vl_input_queue = q; - regp->name = format (0, "%s%c", name, 0); - - pthread_mutex_unlock (&svm->mutex); - svm_pop_heap (oldheap); - return vl_msg_api_handle_from_index_and_epoch - (regp->vl_api_registration_pool_index, - am->shmem_hdr->application_restarts); -} - - -/* - * vl_api_memclnt_create_t_handler - */ -void -vl_api_memclnt_create_t_handler (vl_api_memclnt_create_t * mp) -{ - vl_api_registration_t **regpp; - vl_api_registration_t *regp; - vl_api_memclnt_create_reply_t *rp; - svm_region_t *svm; - unix_shared_memory_queue_t *q; - int rv = 0; - void *oldheap; - api_main_t *am = &api_main; - - /* - * This is tortured. Maintain a vlib-address-space private - * pool of client registrations. We use the shared-memory virtual - * address of client structure as a handle, to allow direct - * manipulation of context quota vbls from the client library. - * - * This scheme causes trouble w/ API message trace replay, since - * some random VA from clib_mem_alloc() certainly won't - * occur in the Linux sim. The (very) few places - * that care need to use the pool index. - * - * Putting the registration object(s) into a pool in shared memory and - * using the pool index as a handle seems like a great idea. - * Unfortunately, each and every reference to that pool would need - * to be protected by a mutex: - * - * Client VLIB - * ------ ---- - * convert pool index to - * pointer. - * - * expand pool - * - * kaboom! - */ - - pool_get (am->vl_clients, regpp); - - svm = am->vlib_rp; - - pthread_mutex_lock (&svm->mutex); - oldheap = svm_push_data_heap (svm); - *regpp = clib_mem_alloc (sizeof (vl_api_registration_t)); - - regp = *regpp; - memset (regp, 0, sizeof (*regp)); - regp->registration_type = REGISTRATION_TYPE_SHMEM; - regp->vl_api_registration_pool_index = regpp - am->vl_clients; - regp->vlib_rp = svm; - regp->shmem_hdr = am->shmem_hdr; - - q = regp->vl_input_queue = (unix_shared_memory_queue_t *) (uword) - mp->input_queue; - - regp->name = format (0, "%s", mp->name); - vec_add1 (regp->name, 0); - - if (am->serialized_message_table_in_shmem == 0) - am->serialized_message_table_in_shmem = - vl_api_serialize_message_table (am, 0); - - pthread_mutex_unlock (&svm->mutex); - svm_pop_heap (oldheap); - - rp = vl_msg_api_alloc (sizeof (*rp)); - rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_CREATE_REPLY); - rp->handle = (uword) regp; - rp->index = vl_msg_api_handle_from_index_and_epoch - (regp->vl_api_registration_pool_index, - am->shmem_hdr->application_restarts); - rp->context = mp->context; - rp->response = ntohl (rv); - rp->message_table = - pointer_to_uword (am->serialized_message_table_in_shmem); - - vl_msg_api_send_shmem (q, (u8 *) & rp); -} - -static int -call_reaper_functions (u32 client_index) -{ - clib_error_t *error = 0; - _vl_msg_api_function_list_elt_t *i; - - i = api_main.reaper_function_registrations; - while (i) - { - error = i->f (client_index); - if (error) - clib_error_report (error); - i = i->next_init_function; - } - return 0; -} - -/* - * vl_api_memclnt_delete_t_handler - */ -void -vl_api_memclnt_delete_t_handler (vl_api_memclnt_delete_t * mp) -{ - vl_api_registration_t **regpp; - vl_api_registration_t *regp; - vl_api_memclnt_delete_reply_t *rp; - svm_region_t *svm; - void *oldheap; - api_main_t *am = &api_main; - u32 handle, client_index, epoch; - - handle = mp->index; - - if (call_reaper_functions (handle)) - return; - - epoch = vl_msg_api_handle_get_epoch (handle); - client_index = vl_msg_api_handle_get_index (handle); - - if (epoch != (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)) - { - clib_warning - ("Stale clnt delete index %d old epoch %d cur epoch %d", - client_index, epoch, - (am->shmem_hdr->application_restarts & VL_API_EPOCH_MASK)); - return; - } - - regpp = am->vl_clients + client_index; - - if (!pool_is_free (am->vl_clients, regpp)) - { - int i; - regp = *regpp; - svm = am->vlib_rp; - int private_registration = 0; - - /* - * Note: the API message handling path will set am->vlib_rp - * as appropriate for pairwise / private memory segments - */ - rp = vl_msg_api_alloc (sizeof (*rp)); - rp->_vl_msg_id = ntohs (VL_API_MEMCLNT_DELETE_REPLY); - rp->handle = mp->handle; - rp->response = 1; - - vl_msg_api_send_shmem (regp->vl_input_queue, (u8 *) & rp); - - if (client_index != regp->vl_api_registration_pool_index) - { - clib_warning ("mismatch client_index %d pool_index %d", - client_index, regp->vl_api_registration_pool_index); - vl_msg_api_free (rp); - return; - } - - /* For horizontal scaling, add a hash table... */ - for (i = 0; i < vec_len (am->vlib_private_rps); i++) - { - /* Is this a pairwise / private API segment? */ - if (am->vlib_private_rps[i] == svm) - { - /* Note: account for the memfd header page */ - u64 virtual_base = svm->virtual_base - MMAP_PAGESIZE; - u64 virtual_size = svm->virtual_size + MMAP_PAGESIZE; - - /* - * Kill the registration pool element before we make - * the index vanish forever - */ - pool_put_index (am->vl_clients, - regp->vl_api_registration_pool_index); - - vec_delete (am->vlib_private_rps, 1, i); - /* Kill it, accounting for the memfd header page */ - if (munmap ((void *) virtual_base, virtual_size) < 0) - clib_unix_warning ("munmap"); - /* Reset the queue-length-address cache */ - vec_reset_length (vl_api_queue_cursizes); - private_registration = 1; - break; - } - } - - /* No dangling references, please */ - *regpp = 0; - - if (private_registration == 0) - { - pool_put_index (am->vl_clients, - regp->vl_api_registration_pool_index); - pthread_mutex_lock (&svm->mutex); - oldheap = svm_push_data_heap (svm); - /* Poison the old registration */ - memset (regp, 0xF1, sizeof (*regp)); - clib_mem_free (regp); - pthread_mutex_unlock (&svm->mutex); - svm_pop_heap (oldheap); - /* - * These messages must be freed manually, since they're set up - * as "bounce" messages. In the private_registration == 1 case, - * we kill the shared-memory segment which contains the message - * with munmap. - */ - vl_msg_api_free (mp); - } - } - else - { - clib_warning ("unknown client ID %d", mp->index); - } -} - -static void -vl_api_get_first_msg_id_t_handler (vl_api_get_first_msg_id_t * mp) -{ - vl_api_get_first_msg_id_reply_t *rmp; - vl_api_registration_t *regp; - uword *p; - api_main_t *am = &api_main; - vl_api_msg_range_t *rp; - u8 name[64]; - u16 first_msg_id = ~0; - int rv = -7; /* VNET_API_ERROR_INVALID_VALUE */ - - regp = vl_api_client_index_to_registration (mp->client_index); - if (!regp) - return; - - if (am->msg_range_by_name == 0) - goto out; - - strncpy ((char *) name, (char *) mp->name, ARRAY_LEN (name) - 1); - - p = hash_get_mem (am->msg_range_by_name, name); - if (p == 0) - goto out; - - rp = vec_elt_at_index (am->msg_ranges, p[0]); - first_msg_id = rp->first_msg_id; - rv = 0; - -out: - rmp = vl_msg_api_alloc (sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID_REPLY); - rmp->context = mp->context; - rmp->retval = ntohl (rv); - rmp->first_msg_id = ntohs (first_msg_id); - vl_msg_api_send (regp, (u8 *) rmp); -} - -/** - * client answered a ping, stave off the grim reaper... - */ - -void - vl_api_memclnt_keepalive_reply_t_handler - (vl_api_memclnt_keepalive_reply_t * mp) -{ - vl_api_registration_t *regp; - vlib_main_t *vm = vlib_get_main (); - - regp = vl_api_client_index_to_registration (mp->context); - if (regp) - { - regp->last_heard = vlib_time_now (vm); - regp->unanswered_pings = 0; - } - else - clib_warning ("BUG: anonymous memclnt_keepalive_reply"); -} - -/** - * We can send ourselves these messages if someone uses the - * builtin binary api test tool... - */ -static void -vl_api_memclnt_keepalive_t_handler (vl_api_memclnt_keepalive_t * mp) -{ - vl_api_memclnt_keepalive_reply_t *rmp; - api_main_t *am; - vl_shmem_hdr_t *shmem_hdr; - - am = &api_main; - shmem_hdr = am->shmem_hdr; - - rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp)); - memset (rmp, 0, sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_MEMCLNT_KEEPALIVE_REPLY); - rmp->context = mp->context; - vl_msg_api_send_shmem (shmem_hdr->vl_input_queue, (u8 *) & rmp); -} - -void -vl_api_api_versions_t_handler (vl_api_api_versions_t * mp) -{ - api_main_t *am = &api_main; - vl_api_api_versions_reply_t *rmp; - unix_shared_memory_queue_t *q; - u32 nmsg = vec_len (am->api_version_list); - int msg_size = sizeof (*rmp) + sizeof (rmp->api_versions[0]) * nmsg; - int i; - - q = vl_api_client_index_to_input_queue (mp->client_index); - if (q == 0) - return; - - rmp = vl_msg_api_alloc (msg_size); - memset (rmp, 0, msg_size); - rmp->_vl_msg_id = ntohs (VL_API_API_VERSIONS_REPLY); - - /* fill in the message */ - rmp->context = mp->context; - rmp->count = htonl (nmsg); - - for (i = 0; i < nmsg; ++i) - { - api_version_t *vl = &am->api_version_list[i]; - rmp->api_versions[i].major = htonl (vl->major); - rmp->api_versions[i].minor = htonl (vl->minor); - rmp->api_versions[i].patch = htonl (vl->patch); - strncpy ((char *) rmp->api_versions[i].name, vl->name, 64 - 1); - } - - vl_msg_api_send_shmem (q, (u8 *) & rmp); - -} - -#define foreach_vlib_api_msg \ -_(MEMCLNT_CREATE, memclnt_create) \ -_(MEMCLNT_DELETE, memclnt_delete) \ -_(GET_FIRST_MSG_ID, get_first_msg_id) \ -_(MEMCLNT_KEEPALIVE, memclnt_keepalive) \ -_(MEMCLNT_KEEPALIVE_REPLY, memclnt_keepalive_reply) \ -_(API_VERSIONS, api_versions) - -/* - * vl_api_init - */ -static int -memory_api_init (const char *region_name) -{ - int rv; - api_main_t *am = &api_main; - vl_msg_api_msg_config_t cfg; - vl_msg_api_msg_config_t *c = &cfg; - - memset (c, 0, sizeof (*c)); - - if ((rv = vl_map_shmem (region_name, 1 /* is_vlib */ )) < 0) - return rv; - -#define _(N,n) do { \ - c->id = VL_API_##N; \ - c->name = #n; \ - c->handler = vl_api_##n##_t_handler; \ - c->cleanup = vl_noop_handler; \ - c->endian = vl_api_##n##_t_endian; \ - c->print = vl_api_##n##_t_print; \ - c->size = sizeof(vl_api_##n##_t); \ - c->traced = 1; /* trace, so these msgs print */ \ - c->replay = 0; /* don't replay client create/delete msgs */ \ - c->message_bounce = 0; /* don't bounce this message */ \ - vl_msg_api_config(c);} while (0); - - foreach_vlib_api_msg; -#undef _ - - /* - * special-case freeing of memclnt_delete messages, so we can - * simply munmap pairwise / private API segments... - */ - am->message_bounce[VL_API_MEMCLNT_DELETE] = 1; - am->is_mp_safe[VL_API_MEMCLNT_KEEPALIVE_REPLY] = 1; - - return 0; -} - -#define foreach_histogram_bucket \ -_(400) \ -_(200) \ -_(100) \ -_(10) - -typedef enum -{ -#define _(n) SLEEP_##n##_US, - foreach_histogram_bucket -#undef _ - SLEEP_N_BUCKETS, -} histogram_index_t; - -static u64 vector_rate_histogram[SLEEP_N_BUCKETS]; - -static void memclnt_queue_callback (vlib_main_t * vm); - -/* - * Callback to send ourselves a plugin numbering-space trace msg - */ -static void -send_one_plugin_msg_ids_msg (u8 * name, u16 first_msg_id, u16 last_msg_id) -{ - vl_api_trace_plugin_msg_ids_t *mp; - api_main_t *am = &api_main; - vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; - unix_shared_memory_queue_t *q; - - mp = vl_msg_api_alloc_as_if_client (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - - mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_TRACE_PLUGIN_MSG_IDS); - strncpy ((char *) mp->plugin_name, (char *) name, - sizeof (mp->plugin_name) - 1); - mp->first_msg_id = clib_host_to_net_u16 (first_msg_id); - mp->last_msg_id = clib_host_to_net_u16 (last_msg_id); - - q = shmem_hdr->vl_input_queue; - - vl_msg_api_send_shmem (q, (u8 *) & mp); -} - -static void -send_memclnt_keepalive (vl_api_registration_t * regp, f64 now) -{ - vl_api_memclnt_keepalive_t *mp; - unix_shared_memory_queue_t *q; - api_main_t *am = &api_main; - svm_region_t *save_vlib_rp = am->vlib_rp; - vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr; - - q = regp->vl_input_queue; - - /* - * If the queue head is moving, assume that the client is processing - * messages and skip the ping. This heuristic may fail if the queue - * is in the same position as last time, net of wrapping; in which - * case, the client will receive a keepalive. - */ - if (regp->last_queue_head != q->head) - { - regp->last_heard = now; - regp->unanswered_pings = 0; - regp->last_queue_head = q->head; - return; - } - - /* - * push/pop shared memory segment, so this routine - * will work with "normal" as well as "private segment" - * memory clients.. - */ - - am->vlib_rp = regp->vlib_rp; - am->shmem_hdr = regp->shmem_hdr; - - mp = vl_msg_api_alloc (sizeof (*mp)); - memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_MEMCLNT_KEEPALIVE); - mp->context = mp->client_index = - vl_msg_api_handle_from_index_and_epoch - (regp->vl_api_registration_pool_index, - am->shmem_hdr->application_restarts); - - regp->unanswered_pings++; - - /* Failure-to-send due to a stuffed queue is absolutely expected */ - if (unix_shared_memory_queue_add (q, (u8 *) & mp, 1 /* nowait */ )) - vl_msg_api_free (mp); - - am->vlib_rp = save_vlib_rp; - am->shmem_hdr = save_shmem_hdr; -} - -static void -dead_client_scan (api_main_t * am, vl_shmem_hdr_t * shm, f64 now) -{ - - vl_api_registration_t **regpp; - vl_api_registration_t *regp; - static u32 *dead_indices; - static u32 *confused_indices; - - vec_reset_length (dead_indices); - vec_reset_length (confused_indices); - - /* *INDENT-OFF* */ - pool_foreach (regpp, am->vl_clients, - ({ - regp = *regpp; - if (regp) - { - /* If we haven't heard from this client recently... */ - if (regp->last_heard < (now - 10.0)) - { - if (regp->unanswered_pings == 2) - { - unix_shared_memory_queue_t *q; - q = regp->vl_input_queue; - if (kill (q->consumer_pid, 0) >=0) - { - clib_warning ("REAPER: lazy binary API client '%s'", - regp->name); - regp->unanswered_pings = 0; - regp->last_heard = now; - } - else - { - clib_warning ("REAPER: binary API client '%s' died", - regp->name); - vec_add1(dead_indices, regpp - am->vl_clients); - } - } - else - send_memclnt_keepalive (regp, now); - } - else - regp->unanswered_pings = 0; - } - else - { - clib_warning ("NULL client registration index %d", - regpp - am->vl_clients); - vec_add1 (confused_indices, regpp - am->vl_clients); - } - })); - /* *INDENT-ON* */ - /* This should "never happen," but if it does, fix it... */ - if (PREDICT_FALSE (vec_len (confused_indices) > 0)) - { - int i; - for (i = 0; i < vec_len (confused_indices); i++) - { - pool_put_index (am->vl_clients, confused_indices[i]); - } - } - - if (PREDICT_FALSE (vec_len (dead_indices) > 0)) - { - int i; - svm_region_t *svm; - void *oldheap; - - /* Allow the application to clean up its registrations */ - for (i = 0; i < vec_len (dead_indices); i++) - { - regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]); - if (regpp) - { - u32 handle; - - handle = vl_msg_api_handle_from_index_and_epoch - (dead_indices[i], shm->application_restarts); - (void) call_reaper_functions (handle); - } - } - - svm = am->vlib_rp; - pthread_mutex_lock (&svm->mutex); - oldheap = svm_push_data_heap (svm); - - for (i = 0; i < vec_len (dead_indices); i++) - { - regpp = pool_elt_at_index (am->vl_clients, dead_indices[i]); - if (regpp) - { - /* Is this a pairwise SVM segment? */ - if ((*regpp)->vlib_rp != svm) - { - int i; - svm_region_t *dead_rp = (*regpp)->vlib_rp; - /* Note: account for the memfd header page */ - u64 virtual_base = dead_rp->virtual_base - MMAP_PAGESIZE; - u64 virtual_size = dead_rp->virtual_size + MMAP_PAGESIZE; - - /* For horizontal scaling, add a hash table... */ - for (i = 0; i < vec_len (am->vlib_private_rps); i++) - if (am->vlib_private_rps[i] == dead_rp) - { - vec_delete (am->vlib_private_rps, 1, i); - goto found; - } - clib_warning ("private rp %llx AWOL", dead_rp); - - found: - /* Kill it, accounting for the memfd header page */ - if (munmap ((void *) virtual_base, virtual_size) < 0) - clib_unix_warning ("munmap"); - /* Reset the queue-length-address cache */ - vec_reset_length (vl_api_queue_cursizes); - } - else - { - /* Poison the old registration */ - memset (*regpp, 0xF3, sizeof (**regpp)); - clib_mem_free (*regpp); - } - /* no dangling references, please */ - *regpp = 0; - } - else - { - svm_pop_heap (oldheap); - clib_warning ("Duplicate free, client index %d", - regpp - am->vl_clients); - oldheap = svm_push_data_heap (svm); - } - } - - svm_client_scan_this_region_nolock (am->vlib_rp); - - pthread_mutex_unlock (&svm->mutex); - svm_pop_heap (oldheap); - for (i = 0; i < vec_len (dead_indices); i++) - pool_put_index (am->vl_clients, dead_indices[i]); - } -} - - -static uword -memclnt_process (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * f) -{ - uword mp; - vl_shmem_hdr_t *shm; - unix_shared_memory_queue_t *q; - clib_error_t *e; - int rv; - api_main_t *am = &api_main; - f64 dead_client_scan_time; - f64 sleep_time, start_time; - f64 vector_rate; - clib_error_t *socksvr_api_init (vlib_main_t * vm); - clib_error_t *error; - int i; - vl_socket_args_for_process_t *a; - uword event_type; - uword *event_data = 0; - int private_segment_rotor = 0; - svm_region_t *vlib_rp; - f64 now; - - vlib_set_queue_signal_callback (vm, memclnt_queue_callback); - - if ((rv = memory_api_init (am->region_name)) < 0) - { - clib_warning ("memory_api_init returned %d, quitting...", rv); - return 0; - } - - if ((error = socksvr_api_init (vm))) - { - clib_error_report (error); - clib_warning ("socksvr_api_init failed, quitting..."); - return 0; - } - - shm = am->shmem_hdr; - ASSERT (shm); - q = shm->vl_input_queue; - ASSERT (q); - /* Make a note so we can always find the primary region easily */ - am->vlib_primary_rp = am->vlib_rp; - - e = vlib_call_init_exit_functions - (vm, vm->api_init_function_registrations, 1 /* call_once */ ); - if (e) - clib_error_report (e); - - sleep_time = 10.0; - dead_client_scan_time = vlib_time_now (vm) + 10.0; - - /* - * Send plugin message range messages for each plugin we loaded - */ - for (i = 0; i < vec_len (am->msg_ranges); i++) - { - vl_api_msg_range_t *rp = am->msg_ranges + i; - send_one_plugin_msg_ids_msg (rp->name, rp->first_msg_id, - rp->last_msg_id); - } - - /* - * Save the api message table snapshot, if configured - */ - if (am->save_msg_table_filename) - { - int fd, rv; - u8 *chroot_file; - u8 *serialized_message_table; - - /* - * Snapshoot the api message table. - */ - if (strstr ((char *) am->save_msg_table_filename, "..") - || index ((char *) am->save_msg_table_filename, '/')) - { - clib_warning ("illegal save-message-table filename '%s'", - am->save_msg_table_filename); - goto skip_save; - } - - chroot_file = format (0, "/tmp/%s%c", am->save_msg_table_filename, 0); - - fd = creat ((char *) chroot_file, 0644); - - if (fd < 0) - { - clib_unix_warning ("creat"); - goto skip_save; - } - - serialized_message_table = vl_api_serialize_message_table (am, 0); - - rv = write (fd, serialized_message_table, - vec_len (serialized_message_table)); - - if (rv != vec_len (serialized_message_table)) - clib_unix_warning ("write"); - - rv = close (fd); - if (rv < 0) - clib_unix_warning ("close"); - - vec_free (chroot_file); - vec_free (serialized_message_table); - } - -skip_save: - - /* $$$ pay attention to frame size, control CPU usage */ - while (1) - { - i8 *headp; - int need_broadcast; - - /* - * There's a reason for checking the queue before - * sleeping. If the vlib application crashes, it's entirely - * possible for a client to enqueue a connect request - * during the process restart interval. - * - * Unless some force of physics causes the new incarnation - * of the application to process the request, the client will - * sit and wait for Godot... - */ - vector_rate = vlib_last_vector_length_per_node (vm); - start_time = vlib_time_now (vm); - while (1) - { - pthread_mutex_lock (&q->mutex); - if (q->cursize == 0) - { - vm->api_queue_nonempty = 0; - pthread_mutex_unlock (&q->mutex); - - if (TRACE_VLIB_MEMORY_QUEUE) - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = - { - .format = "q-underflow: len %d", - .format_args = "i4", - }; - /* *INDENT-ON* */ - struct - { - u32 len; - } *ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->len = 0; - } - sleep_time = 20.0; - break; - } - - headp = (i8 *) (q->data + sizeof (uword) * q->head); - clib_memcpy (&mp, headp, sizeof (uword)); - - q->head++; - need_broadcast = (q->cursize == q->maxsize / 2); - q->cursize--; - - if (PREDICT_FALSE (q->head == q->maxsize)) - q->head = 0; - pthread_mutex_unlock (&q->mutex); - if (need_broadcast) - (void) pthread_cond_broadcast (&q->condvar); - - vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node); - - /* Allow no more than 10us without a pause */ - if (vlib_time_now (vm) > start_time + 10e-6) - { - int index = SLEEP_400_US; - if (vector_rate > 40.0) - sleep_time = 400e-6; - else if (vector_rate > 20.0) - { - index = SLEEP_200_US; - sleep_time = 200e-6; - } - else if (vector_rate >= 1.0) - { - index = SLEEP_100_US; - sleep_time = 100e-6; - } - else - { - index = SLEEP_10_US; - sleep_time = 10e-6; - } - vector_rate_histogram[index] += 1; - break; - } - } - - /* - * see if we have any private api shared-memory segments - * If so, push required context variables, and process - * a message. - */ - if (PREDICT_FALSE (vec_len (am->vlib_private_rps))) - { - unix_shared_memory_queue_t *save_vlib_input_queue = q; - vl_shmem_hdr_t *save_shmem_hdr = am->shmem_hdr; - svm_region_t *save_vlib_rp = am->vlib_rp; - - vlib_rp = am->vlib_rp = am->vlib_private_rps[private_segment_rotor]; - - am->shmem_hdr = (void *) vlib_rp->user_ctx; - q = am->shmem_hdr->vl_input_queue; - - pthread_mutex_lock (&q->mutex); - if (q->cursize > 0) - { - headp = (i8 *) (q->data + sizeof (uword) * q->head); - clib_memcpy (&mp, headp, sizeof (uword)); - - q->head++; - need_broadcast = (q->cursize == q->maxsize / 2); - q->cursize--; - - if (PREDICT_FALSE (q->head == q->maxsize)) - q->head = 0; - pthread_mutex_unlock (&q->mutex); - - if (need_broadcast) - (void) pthread_cond_broadcast (&q->condvar); - - vl_msg_api_handler_with_vm_node (am, (void *) mp, vm, node); - } - else - pthread_mutex_unlock (&q->mutex); - - q = save_vlib_input_queue; - am->shmem_hdr = save_shmem_hdr; - am->vlib_rp = save_vlib_rp; - - private_segment_rotor++; - if (private_segment_rotor >= vec_len (am->vlib_private_rps)) - private_segment_rotor = 0; - } - - vlib_process_wait_for_event_or_clock (vm, sleep_time); - vec_reset_length (event_data); - event_type = vlib_process_get_events (vm, &event_data); - now = vlib_time_now (vm); - - switch (event_type) - { - case QUEUE_SIGNAL_EVENT: - vm->queue_signal_pending = 0; - break; - - case SOCKET_READ_EVENT: - for (i = 0; i < vec_len (event_data); i++) - { - a = pool_elt_at_index (socket_main.process_args, event_data[i]); - vl_api_socket_process_msg (a->clib_file, a->regp, - (i8 *) a->data); - vec_free (a->data); - pool_put (socket_main.process_args, a); - } - break; - - /* Timeout... */ - case -1: - break; - - default: - clib_warning ("unknown event type %d", event_type); - break; - } - - if (now > dead_client_scan_time) - { - dead_client_scan (am, shm, now); - dead_client_scan_time = vlib_time_now (vm) + 10.0; - } - - if (TRACE_VLIB_MEMORY_QUEUE) - { - /* *INDENT-OFF* */ - ELOG_TYPE_DECLARE (e) = { - .format = "q-awake: len %d", - .format_args = "i4", - }; - /* *INDENT-ON* */ - struct - { - u32 len; - } *ed; - ed = ELOG_DATA (&vm->elog_main, e); - ed->len = q->cursize; - } - } - - return 0; -} -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (memclnt_node) = -{ - .function = memclnt_process, - .type = VLIB_NODE_TYPE_PROCESS, - .name = "api-rx-from-ring", - .state = VLIB_NODE_STATE_DISABLED, -}; -/* *INDENT-ON* */ - - -static clib_error_t * -vl_api_show_histogram_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cli_cmd) -{ - u64 total_counts = 0; - int i; - - for (i = 0; i < SLEEP_N_BUCKETS; i++) - { - total_counts += vector_rate_histogram[i]; - } - - if (total_counts == 0) - { - vlib_cli_output (vm, "No control-plane activity."); - return 0; - } - -#define _(n) \ - do { \ - f64 percent; \ - percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \ - / (f64) total_counts; \ - percent *= 100.0; \ - vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \ - vector_rate_histogram[SLEEP_##n##_US], \ - percent); \ - } while (0); - foreach_histogram_bucket; -#undef _ - - return 0; -} - -/*? - * Display the binary api sleep-time histogram -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = -{ - .path = "show api histogram", - .short_help = "show api histogram", - .function = vl_api_show_histogram_command, -}; -/* *INDENT-ON* */ - -static clib_error_t * -vl_api_clear_histogram_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cli_cmd) -{ - int i; - - for (i = 0; i < SLEEP_N_BUCKETS; i++) - vector_rate_histogram[i] = 0; - return 0; -} - -/*? - * Clear the binary api sleep-time histogram -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_clear_api_histogram_command, static) = -{ - .path = "clear api histogram", - .short_help = "clear api histogram", - .function = vl_api_clear_histogram_command, -}; -/* *INDENT-ON* */ - -volatile int **vl_api_queue_cursizes; - -static void -memclnt_queue_callback (vlib_main_t * vm) -{ - int i; - api_main_t *am = &api_main; - - if (PREDICT_FALSE (vec_len (vl_api_queue_cursizes) != - 1 + vec_len (am->vlib_private_rps))) - { - vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; - unix_shared_memory_queue_t *q; - - if (shmem_hdr == 0) - return; - - q = shmem_hdr->vl_input_queue; - if (q == 0) - return; - - vec_add1 (vl_api_queue_cursizes, &q->cursize); - - for (i = 0; i < vec_len (am->vlib_private_rps); i++) - { - svm_region_t *vlib_rp = am->vlib_private_rps[i]; - - shmem_hdr = (void *) vlib_rp->user_ctx; - q = shmem_hdr->vl_input_queue; - vec_add1 (vl_api_queue_cursizes, &q->cursize); - } - } - - for (i = 0; i < vec_len (vl_api_queue_cursizes); i++) - { - if (*vl_api_queue_cursizes[i]) - { - vm->queue_signal_pending = 1; - vm->api_queue_nonempty = 1; - vlib_process_signal_event (vm, memclnt_node.index, - /* event_type */ QUEUE_SIGNAL_EVENT, - /* event_data */ 0); - break; - } - } -} - -void -vl_enable_disable_memory_api (vlib_main_t * vm, int enable) -{ - vlib_node_set_state (vm, memclnt_node.index, - (enable - ? VLIB_NODE_STATE_POLLING - : VLIB_NODE_STATE_DISABLED)); -} - -static uword -api_rx_from_node (vlib_main_t * vm, - vlib_node_runtime_t * node, vlib_frame_t * frame) -{ - uword n_packets = frame->n_vectors; - uword n_left_from; - u32 *from; - static u8 *long_msg; - - vec_validate (long_msg, 4095); - n_left_from = frame->n_vectors; - from = vlib_frame_args (frame); - - while (n_left_from > 0) - { - u32 bi0; - vlib_buffer_t *b0; - void *msg; - uword msg_len; - - bi0 = from[0]; - b0 = vlib_get_buffer (vm, bi0); - from += 1; - n_left_from -= 1; - - msg = b0->data + b0->current_data; - msg_len = b0->current_length; - if (b0->flags & VLIB_BUFFER_NEXT_PRESENT) - { - ASSERT (long_msg != 0); - _vec_len (long_msg) = 0; - vec_add (long_msg, msg, msg_len); - while (b0->flags & VLIB_BUFFER_NEXT_PRESENT) - { - b0 = vlib_get_buffer (vm, b0->next_buffer); - msg = b0->data + b0->current_data; - msg_len = b0->current_length; - vec_add (long_msg, msg, msg_len); - } - msg = long_msg; - } - vl_msg_api_handler_no_trace_no_free (msg); - } - - /* Free what we've been given. */ - vlib_buffer_free (vm, vlib_frame_args (frame), n_packets); - - return n_packets; -} - -/* *INDENT-OFF* */ -VLIB_REGISTER_NODE (api_rx_from_node_node,static) = { - .function = api_rx_from_node, - .type = VLIB_NODE_TYPE_INTERNAL, - .vector_size = 4, - .name = "api-rx-from-node", -}; -/* *INDENT-ON* */ - -static clib_error_t * -setup_memclnt_exit (vlib_main_t * vm) -{ - atexit (vl_unmap_shmem); - return 0; -} - -VLIB_INIT_FUNCTION (setup_memclnt_exit); - -u8 * -format_api_message_rings (u8 * s, va_list * args) -{ - api_main_t *am = va_arg (*args, api_main_t *); - vl_shmem_hdr_t *shmem_hdr = va_arg (*args, vl_shmem_hdr_t *); - int main_segment = va_arg (*args, int); - ring_alloc_t *ap; - int i; - - if (shmem_hdr == 0) - return format (s, "%8s %8s %8s %8s %8s\n", - "Owner", "Size", "Nitems", "Hits", "Misses"); - - ap = shmem_hdr->vl_rings; - - for (i = 0; i < vec_len (shmem_hdr->vl_rings); i++) - { - s = format (s, "%8s %8d %8d %8d %8d\n", - "vlib", ap->size, ap->nitems, ap->hits, ap->misses); - ap++; - } - - ap = shmem_hdr->client_rings; - - for (i = 0; i < vec_len (shmem_hdr->client_rings); i++) - { - s = format (s, "%8s %8d %8d %8d %8d\n", - "clnt", ap->size, ap->nitems, ap->hits, ap->misses); - ap++; - } - - if (main_segment) - { - s = format (s, "%d ring miss fallback allocations\n", am->ring_misses); - s = format - (s, - "%d application restarts, %d reclaimed msgs, %d garbage collects\n", - shmem_hdr->application_restarts, shmem_hdr->restart_reclaims, - shmem_hdr->garbage_collects); - } - return s; -} - - -static clib_error_t * -vl_api_ring_command (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cli_cmd) -{ - int i; - vl_shmem_hdr_t *shmem_hdr; - api_main_t *am = &api_main; - - /* First, dump the primary region rings.. */ - - if (am->vlib_primary_rp == 0 || am->vlib_primary_rp->user_ctx == 0) - { - vlib_cli_output (vm, "Shared memory segment not initialized...\n"); - return 0; - } - - shmem_hdr = (void *) am->vlib_primary_rp->user_ctx; - - vlib_cli_output (vm, "Main API segment rings:"); - - vlib_cli_output (vm, "%U", format_api_message_rings, am, - 0 /* print header */ , 0 /* notused */ ); - - vlib_cli_output (vm, "%U", format_api_message_rings, am, - shmem_hdr, 1 /* main segment */ ); - - for (i = 0; i < vec_len (am->vlib_private_rps); i++) - { - svm_region_t *vlib_rp = am->vlib_private_rps[i]; - shmem_hdr = (void *) vlib_rp->user_ctx; - vl_api_registration_t **regpp; - vl_api_registration_t *regp = 0; - - /* For horizontal scaling, add a hash table... */ - /* *INDENT-OFF* */ - pool_foreach (regpp, am->vl_clients, - ({ - regp = *regpp; - if (regp && regp->vlib_rp == vlib_rp) - { - vlib_cli_output (vm, "%s segment rings:", regp->name); - goto found; - } - })); - vlib_cli_output (vm, "regp %llx not found?", regp); - continue; - /* *INDENT-ON* */ - found: - vlib_cli_output (vm, "%U", format_api_message_rings, am, - 0 /* print header */ , 0 /* notused */ ); - vlib_cli_output (vm, "%U", format_api_message_rings, am, - shmem_hdr, 0 /* main segment */ ); - } - - return 0; -} - -void dump_socket_clients (vlib_main_t * vm, api_main_t * am) - __attribute__ ((weak)); - -void -dump_socket_clients (vlib_main_t * vm, api_main_t * am) -{ -} - -static clib_error_t * -vl_api_client_command (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cli_cmd) -{ - vl_api_registration_t **regpp, *regp; - unix_shared_memory_queue_t *q; - char *health; - api_main_t *am = &api_main; - u32 *confused_indices = 0; - - if (!pool_elts (am->vl_clients)) - goto socket_clients; - vlib_cli_output (vm, "Shared memory clients"); - vlib_cli_output (vm, "%20s %8s %14s %18s %s", - "Name", "PID", "Queue Length", "Queue VA", "Health"); - - /* *INDENT-OFF* */ - pool_foreach (regpp, am->vl_clients, - ({ - regp = *regpp; - - if (regp) - { - if (regp->unanswered_pings > 0) - health = "questionable"; - else - health = "OK"; - - q = regp->vl_input_queue; - - vlib_cli_output (vm, "%20s %8d %14d 0x%016llx %s\n", - regp->name, q->consumer_pid, q->cursize, - q, health); - } - else - { - clib_warning ("NULL client registration index %d", - regpp - am->vl_clients); - vec_add1 (confused_indices, regpp - am->vl_clients); - } - })); - /* *INDENT-ON* */ - - /* This should "never happen," but if it does, fix it... */ - if (PREDICT_FALSE (vec_len (confused_indices) > 0)) - { - int i; - for (i = 0; i < vec_len (confused_indices); i++) - { - pool_put_index (am->vl_clients, confused_indices[i]); - } - } - vec_free (confused_indices); - - if (am->missing_clients) - vlib_cli_output (vm, "%u messages with missing clients", - am->missing_clients); -socket_clients: - dump_socket_clients (vm, am); - - return 0; -} - -static clib_error_t * -vl_api_status_command (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cli_cmd) -{ - api_main_t *am = &api_main; - - // check if rx_trace and tx_trace are not null pointers - - if (am->rx_trace == 0) - { - vlib_cli_output (vm, "RX Trace disabled\n"); - } - else - { - if (am->rx_trace->enabled == 0) - vlib_cli_output (vm, "RX Trace disabled\n"); - else - vlib_cli_output (vm, "RX Trace enabled\n"); - } - - if (am->tx_trace == 0) - { - vlib_cli_output (vm, "TX Trace disabled\n"); - } - else - { - if (am->tx_trace->enabled == 0) - vlib_cli_output (vm, "TX Trace disabled\n"); - else - vlib_cli_output (vm, "TX Trace enabled\n"); - } - - return 0; -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_command, static) = -{ - .path = "show api", - .short_help = "Show API information", -}; -/* *INDENT-ON* */ - -/*? - * Display binary api message allocation ring statistics -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_ring_command, static) = -{ - .path = "show api ring-stats", - .short_help = "Message ring statistics", - .function = vl_api_ring_command, -}; -/* *INDENT-ON* */ - -/*? - * Display current api client connections -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_clients_command, static) = -{ - .path = "show api clients", - .short_help = "Client information", - .function = vl_api_client_command, -}; -/* *INDENT-ON* */ - -/*? - * Display the current api message tracing status -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_status_command, static) = -{ - .path = "show api trace-status", - .short_help = "Display API trace status", - .function = vl_api_status_command, -}; -/* *INDENT-ON* */ - -static clib_error_t * -vl_api_message_table_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cli_cmd) -{ - api_main_t *am = &api_main; - int i; - int verbose = 0; - - if (unformat (input, "verbose")) - verbose = 1; - - - if (verbose == 0) - vlib_cli_output (vm, "%-4s %s", "ID", "Name"); - else - vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce", - "MP-safe"); - - for (i = 1; i < vec_len (am->msg_names); i++) - { - if (verbose == 0) - { - vlib_cli_output (vm, "%-4d %s", i, - am->msg_names[i] ? am->msg_names[i] : - " [no handler]"); - } - else - { - vlib_cli_output (vm, "%-4d %-40s %6d %7d", i, - am->msg_names[i] ? am->msg_names[i] : - " [no handler]", am->message_bounce[i], - am->is_mp_safe[i]); - } - } - - return 0; -} - -/*? - * Display the current api message decode tables -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_message_table_command, static) = -{ - .path = "show api message-table", - .short_help = "Message Table", - .function = vl_api_message_table_command, -}; -/* *INDENT-ON* */ - -static clib_error_t * -vl_api_trace_command (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cli_cmd) -{ - u32 nitems = 1024; - vl_api_trace_which_t which = VL_API_TRACE_RX; - api_main_t *am = &api_main; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx")) - goto configure; - else if (unformat (input, "tx nitems %u", &nitems) - || unformat (input, "tx")) - { - which = VL_API_TRACE_RX; - goto configure; - } - else if (unformat (input, "on rx")) - { - vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 1); - } - else if (unformat (input, "on tx")) - { - vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 1); - } - else if (unformat (input, "on")) - { - vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 1); - } - else if (unformat (input, "off")) - { - vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 0); - vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 0); - } - else if (unformat (input, "free")) - { - vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 0); - vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 0); - vl_msg_api_trace_free (am, VL_API_TRACE_RX); - vl_msg_api_trace_free (am, VL_API_TRACE_TX); - } - else if (unformat (input, "debug on")) - { - am->msg_print_flag = 1; - } - else if (unformat (input, "debug off")) - { - am->msg_print_flag = 0; - } - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - return 0; - -configure: - if (vl_msg_api_trace_configure (am, which, nitems)) - { - vlib_cli_output (vm, "warning: trace configure error (%d, %d)", - which, nitems); - } - - return 0; -} - -/*? - * Control the binary API trace mechanism -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (trace, static) = -{ - .path = "set api-trace [on][on tx][on rx][off][free][debug on][debug off]", - .short_help = "API trace", - .function = vl_api_trace_command, -}; -/* *INDENT-ON* */ - -clib_error_t * -vlibmemory_init (vlib_main_t * vm) -{ - api_main_t *am = &api_main; - svm_map_region_args_t _a, *a = &_a; - clib_error_t *error; - - memset (a, 0, sizeof (*a)); - a->root_path = am->root_path; - a->name = SVM_GLOBAL_REGION_NAME; - a->baseva = (am->global_baseva != 0) ? - am->global_baseva : SVM_GLOBAL_REGION_BASEVA; - a->size = (am->global_size != 0) ? am->global_size : SVM_GLOBAL_REGION_SIZE; - a->flags = SVM_FLAGS_NODATA; - a->uid = am->api_uid; - a->gid = am->api_gid; - a->pvt_heap_size = - (am->global_pvt_heap_size != - 0) ? am->global_pvt_heap_size : SVM_PVT_MHEAP_SIZE; - - svm_region_init_args (a); - - error = vlib_call_init_function (vm, vlibsocket_init); - - return error; -} - -VLIB_INIT_FUNCTION (vlibmemory_init); - -void -vl_set_memory_region_name (const char *name) -{ - api_main_t *am = &api_main; - - am->region_name = name; -} - -static int -range_compare (vl_api_msg_range_t * a0, vl_api_msg_range_t * a1) -{ - int len0, len1, clen; - - len0 = vec_len (a0->name); - len1 = vec_len (a1->name); - clen = len0 < len1 ? len0 : len1; - return (strncmp ((char *) a0->name, (char *) a1->name, clen)); -} - -static u8 * -format_api_msg_range (u8 * s, va_list * args) -{ - vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *); - - if (rp == 0) - s = format (s, "%-50s%9s%9s", "Name", "First-ID", "Last-ID"); - else - s = format (s, "%-50s%9d%9d", rp->name, rp->first_msg_id, - rp->last_msg_id); - - return s; -} - -static clib_error_t * -vl_api_show_plugin_command (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cli_cmd) -{ - api_main_t *am = &api_main; - vl_api_msg_range_t *rp = 0; - int i; - - if (vec_len (am->msg_ranges) == 0) - { - vlib_cli_output (vm, "No plugin API message ranges configured..."); - return 0; - } - - rp = vec_dup (am->msg_ranges); - - vec_sort_with_function (rp, range_compare); - - vlib_cli_output (vm, "Plugin API message ID ranges...\n"); - vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ ); - - for (i = 0; i < vec_len (rp); i++) - vlib_cli_output (vm, "%U", format_api_msg_range, rp + i); - - vec_free (rp); - - return 0; -} - -/*? - * Display the plugin binary API message range table -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (cli_show_api_plugin_command, static) = -{ - .path = "show api plugin", - .short_help = "show api plugin", - .function = vl_api_show_plugin_command, -}; -/* *INDENT-ON* */ - -static void -vl_api_rpc_call_t_handler (vl_api_rpc_call_t * mp) -{ - vl_api_rpc_call_reply_t *rmp; - int (*fp) (void *); - i32 rv = 0; - vlib_main_t *vm = vlib_get_main (); - - if (mp->function == 0) - { - rv = -1; - clib_warning ("rpc NULL function pointer"); - } - - else - { - if (mp->need_barrier_sync) - vlib_worker_thread_barrier_sync (vm); - - fp = uword_to_pointer (mp->function, int (*)(void *)); - rv = fp (mp->data); - - if (mp->need_barrier_sync) - vlib_worker_thread_barrier_release (vm); - } - - if (mp->send_reply) - { - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); - if (q) - { - rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp)); - rmp->_vl_msg_id = ntohs (VL_API_RPC_CALL_REPLY); - rmp->context = mp->context; - rmp->retval = rv; - vl_msg_api_send_shmem (q, (u8 *) & rmp); - } - } - if (mp->multicast) - { - clib_warning ("multicast not yet implemented..."); - } -} - -static void -vl_api_rpc_call_reply_t_handler (vl_api_rpc_call_reply_t * mp) -{ - clib_warning ("unimplemented"); -} - -void -vl_api_send_pending_rpc_requests (vlib_main_t * vm) -{ - api_main_t *am = &api_main; - vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; - unix_shared_memory_queue_t *q; - int i; - - /* - * Use the "normal" control-plane mechanism for the main thread. - * Well, almost. if the main input queue is full, we cannot - * block. Otherwise, we can expect a barrier sync timeout. - */ - q = shmem_hdr->vl_input_queue; - - for (i = 0; i < vec_len (vm->pending_rpc_requests); i++) - { - while (pthread_mutex_trylock (&q->mutex)) - vlib_worker_thread_barrier_check (); - - while (PREDICT_FALSE (unix_shared_memory_queue_is_full (q))) - { - pthread_mutex_unlock (&q->mutex); - vlib_worker_thread_barrier_check (); - while (pthread_mutex_trylock (&q->mutex)) - vlib_worker_thread_barrier_check (); - } - - vl_msg_api_send_shmem_nolock (q, (u8 *) (vm->pending_rpc_requests + i)); - - pthread_mutex_unlock (&q->mutex); - } - _vec_len (vm->pending_rpc_requests) = 0; -} - -always_inline void -vl_api_rpc_call_main_thread_inline (void *fp, u8 * data, u32 data_length, - u8 force_rpc) -{ - vl_api_rpc_call_t *mp; - vlib_main_t *vm = vlib_get_main (); - - /* Main thread and not a forced RPC: call the function directly */ - if ((force_rpc == 0) && (vlib_get_thread_index () == 0)) - { - void (*call_fp) (void *); - - vlib_worker_thread_barrier_sync (vm); - - call_fp = fp; - call_fp (data); - - vlib_worker_thread_barrier_release (vm); - return; - } - - /* Otherwise, actually do an RPC */ - mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length); - - memset (mp, 0, sizeof (*mp)); - clib_memcpy (mp->data, data, data_length); - mp->_vl_msg_id = ntohs (VL_API_RPC_CALL); - mp->function = pointer_to_uword (fp); - mp->need_barrier_sync = 1; - - vec_add1 (vm->pending_rpc_requests, (uword) mp); -} - -/* - * Check if called from worker threads. - * If so, make rpc call of fp through shmem. - * Otherwise, call fp directly - */ -void -vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length) -{ - vl_api_rpc_call_main_thread_inline (fp, data, data_length, /*force_rpc */ - 0); -} - -/* - * Always make rpc call of fp through shmem, useful for calling from threads - * not setup as worker threads, such as DPDK callback thread - */ -void -vl_api_force_rpc_call_main_thread (void *fp, u8 * data, u32 data_length) -{ - vl_api_rpc_call_main_thread_inline (fp, data, data_length, /*force_rpc */ - 1); -} - -static void -vl_api_trace_plugin_msg_ids_t_handler (vl_api_trace_plugin_msg_ids_t * mp) -{ - api_main_t *am = &api_main; - vl_api_msg_range_t *rp; - uword *p; - - /* Noop (except for tracing) during normal operation */ - if (am->replay_in_progress == 0) - return; - - p = hash_get_mem (am->msg_range_by_name, mp->plugin_name); - if (p == 0) - { - clib_warning ("WARNING: traced plugin '%s' not in current image", - mp->plugin_name); - return; - } - - rp = vec_elt_at_index (am->msg_ranges, p[0]); - if (rp->first_msg_id != clib_net_to_host_u16 (mp->first_msg_id)) - { - clib_warning ("WARNING: traced plugin '%s' first message id %d not %d", - mp->plugin_name, clib_net_to_host_u16 (mp->first_msg_id), - rp->first_msg_id); - } - - if (rp->last_msg_id != clib_net_to_host_u16 (mp->last_msg_id)) - { - clib_warning ("WARNING: traced plugin '%s' last message id %d not %d", - mp->plugin_name, clib_net_to_host_u16 (mp->last_msg_id), - rp->last_msg_id); - } -} - -#define foreach_rpc_api_msg \ -_(RPC_CALL,rpc_call) \ -_(RPC_CALL_REPLY,rpc_call_reply) - -#define foreach_plugin_trace_msg \ -_(TRACE_PLUGIN_MSG_IDS,trace_plugin_msg_ids) - -/* - * Set the rpc callback at our earliest possible convenience. - * This avoids ordering issues between thread_init() -> start_workers and - * an init function which we could define here. If we ever intend to use - * vlib all by itself, we can't create a link-time dependency on - * an init function here and a typical "call foo_init first" - * guitar lick. - */ - -extern void *rpc_call_main_thread_cb_fn; - -static clib_error_t * -rpc_api_hookup (vlib_main_t * vm) -{ - api_main_t *am = &api_main; -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 0 /* do not trace */); - foreach_rpc_api_msg; -#undef _ - -#define _(N,n) \ - vl_msg_api_set_handlers(VL_API_##N, #n, \ - vl_api_##n##_t_handler, \ - vl_noop_handler, \ - vl_noop_handler, \ - vl_api_##n##_t_print, \ - sizeof(vl_api_##n##_t), 1 /* do trace */); - foreach_plugin_trace_msg; -#undef _ - - /* No reason to halt the parade to create a trace record... */ - am->is_mp_safe[VL_API_TRACE_PLUGIN_MSG_IDS] = 1; - rpc_call_main_thread_cb_fn = vl_api_rpc_call_main_thread; - return 0; -} - -VLIB_API_INIT_FUNCTION (rpc_api_hookup); - -typedef enum -{ - DUMP, - CUSTOM_DUMP, - REPLAY, - INITIALIZERS, -} vl_api_replay_t; - -u8 * -format_vl_msg_api_trace_status (u8 * s, va_list * args) -{ - api_main_t *am = va_arg (*args, api_main_t *); - vl_api_trace_which_t which = va_arg (*args, vl_api_trace_which_t); - vl_api_trace_t *tp; - char *trace_name; - - switch (which) - { - case VL_API_TRACE_TX: - tp = am->tx_trace; - trace_name = "TX trace"; - break; - - case VL_API_TRACE_RX: - tp = am->rx_trace; - trace_name = "RX trace"; - break; - - default: - abort (); - } - - if (tp == 0) - { - s = format (s, "%s: not yet configured.\n", trace_name); - return s; - } - - s = format (s, "%s: used %d of %d items, %s enabled, %s wrapped\n", - trace_name, vec_len (tp->traces), tp->nitems, - tp->enabled ? "is" : "is not", tp->wrapped ? "has" : "has not"); - return s; -} - -void vl_msg_api_custom_dump_configure (api_main_t * am) - __attribute__ ((weak)); -void -vl_msg_api_custom_dump_configure (api_main_t * am) -{ -} - -static void -vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, - u32 first_index, u32 last_index, - vl_api_replay_t which) -{ - vl_api_trace_file_header_t *hp; - int i, fd; - struct stat statb; - size_t file_size; - u8 *msg; - u8 endian_swap_needed = 0; - api_main_t *am = &api_main; - u8 *tmpbuf = 0; - u32 nitems; - void **saved_print_handlers = 0; - - fd = open ((char *) filename, O_RDONLY); - - if (fd < 0) - { - vlib_cli_output (vm, "Couldn't open %s\n", filename); - return; - } - - if (fstat (fd, &statb) < 0) - { - vlib_cli_output (vm, "Couldn't stat %s\n", filename); - close (fd); - return; - } - - if (!(statb.st_mode & S_IFREG) || (statb.st_size < sizeof (*hp))) - { - vlib_cli_output (vm, "File not plausible: %s\n", filename); - close (fd); - return; - } - - file_size = statb.st_size; - file_size = (file_size + 4095) & ~(4096); - - hp = mmap (0, file_size, PROT_READ, MAP_PRIVATE, fd, 0); - - if (hp == (vl_api_trace_file_header_t *) MAP_FAILED) - { - vlib_cli_output (vm, "mmap failed: %s\n", filename); - close (fd); - return; - } - close (fd); - - if ((clib_arch_is_little_endian && hp->endian == VL_API_BIG_ENDIAN) - || (clib_arch_is_big_endian && hp->endian == VL_API_LITTLE_ENDIAN)) - endian_swap_needed = 1; - - if (endian_swap_needed) - nitems = ntohl (hp->nitems); - else - nitems = hp->nitems; - - if (last_index == (u32) ~ 0) - { - last_index = nitems - 1; - } - - if (first_index >= nitems || last_index >= nitems) - { - vlib_cli_output (vm, "Range (%d, %d) outside file range (0, %d)\n", - first_index, last_index, nitems - 1); - munmap (hp, file_size); - return; - } - if (hp->wrapped) - vlib_cli_output (vm, - "Note: wrapped/incomplete trace, results may vary\n"); - - if (which == CUSTOM_DUMP) - { - saved_print_handlers = (void **) vec_dup (am->msg_print_handlers); - vl_msg_api_custom_dump_configure (am); - } - - - msg = (u8 *) (hp + 1); - - for (i = 0; i < first_index; i++) - { - trace_cfg_t *cfgp; - int size; - u16 msg_id; - - size = clib_host_to_net_u32 (*(u32 *) msg); - msg += sizeof (u32); - - if (clib_arch_is_little_endian) - msg_id = ntohs (*((u16 *) msg)); - else - msg_id = *((u16 *) msg); - - cfgp = am->api_trace_cfg + msg_id; - if (!cfgp) - { - vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); - munmap (hp, file_size); - return; - } - msg += size; - } - - if (which == REPLAY) - am->replay_in_progress = 1; - - for (; i <= last_index; i++) - { - trace_cfg_t *cfgp; - u16 *msg_idp; - u16 msg_id; - int size; - - if (which == DUMP) - vlib_cli_output (vm, "---------- trace %d -----------\n", i); - - size = clib_host_to_net_u32 (*(u32 *) msg); - msg += sizeof (u32); - - if (clib_arch_is_little_endian) - msg_id = ntohs (*((u16 *) msg)); - else - msg_id = *((u16 *) msg); - - cfgp = am->api_trace_cfg + msg_id; - if (!cfgp) - { - vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); - munmap (hp, file_size); - vec_free (tmpbuf); - am->replay_in_progress = 0; - return; - } - - /* Copy the buffer (from the read-only mmap'ed file) */ - vec_validate (tmpbuf, size - 1 + sizeof (uword)); - clib_memcpy (tmpbuf + sizeof (uword), msg, size); - memset (tmpbuf, 0xf, sizeof (uword)); - - /* - * Endian swap if needed. All msg data is supposed to be - * in network byte order. All msg handlers are supposed to - * know that. The generic message dumpers don't know that. - * One could fix apigen, I suppose. - */ - if ((which == DUMP && clib_arch_is_little_endian) || endian_swap_needed) - { - void (*endian_fp) (void *); - if (msg_id >= vec_len (am->msg_endian_handlers) - || (am->msg_endian_handlers[msg_id] == 0)) - { - vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id); - munmap (hp, file_size); - vec_free (tmpbuf); - am->replay_in_progress = 0; - return; - } - endian_fp = am->msg_endian_handlers[msg_id]; - (*endian_fp) (tmpbuf + sizeof (uword)); - } - - /* msg_id always in network byte order */ - if (clib_arch_is_little_endian) - { - msg_idp = (u16 *) (tmpbuf + sizeof (uword)); - *msg_idp = msg_id; - } - - switch (which) - { - case CUSTOM_DUMP: - case DUMP: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id]) - { - u8 *(*print_fp) (void *, void *); - - print_fp = (void *) am->msg_print_handlers[msg_id]; - (*print_fp) (tmpbuf + sizeof (uword), vm); - } - else - { - vlib_cli_output (vm, "Skipping msg id %d: no print fcn\n", - msg_id); - break; - } - break; - - case INITIALIZERS: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id]) - { - u8 *s; - int j; - u8 *(*print_fp) (void *, void *); - - print_fp = (void *) am->msg_print_handlers[msg_id]; - - vlib_cli_output (vm, "/*"); - - (*print_fp) (tmpbuf + sizeof (uword), vm); - vlib_cli_output (vm, "*/\n"); - - s = format (0, "static u8 * vl_api_%s_%d[%d] = {", - am->msg_names[msg_id], i, - am->api_trace_cfg[msg_id].size); - - for (j = 0; j < am->api_trace_cfg[msg_id].size; j++) - { - if ((j & 7) == 0) - s = format (s, "\n "); - s = format (s, "0x%02x,", tmpbuf[sizeof (uword) + j]); - } - s = format (s, "\n};\n%c", 0); - vlib_cli_output (vm, (char *) s); - vec_free (s); - } - break; - - case REPLAY: - if (msg_id < vec_len (am->msg_print_handlers) && - am->msg_print_handlers[msg_id] && cfgp->replay_enable) - { - void (*handler) (void *); - - handler = (void *) am->msg_handlers[msg_id]; - - if (!am->is_mp_safe[msg_id]) - vl_msg_api_barrier_sync (); - (*handler) (tmpbuf + sizeof (uword)); - if (!am->is_mp_safe[msg_id]) - vl_msg_api_barrier_release (); - } - else - { - if (cfgp->replay_enable) - vlib_cli_output (vm, "Skipping msg id %d: no handler\n", - msg_id); - break; - } - break; - } - - _vec_len (tmpbuf) = 0; - msg += size; - } - - if (saved_print_handlers) - { - clib_memcpy (am->msg_print_handlers, saved_print_handlers, - vec_len (am->msg_print_handlers) * sizeof (void *)); - vec_free (saved_print_handlers); - } - - munmap (hp, file_size); - vec_free (tmpbuf); - am->replay_in_progress = 0; -} - -static clib_error_t * -api_trace_command_fn (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - u32 nitems = 256 << 10; - api_main_t *am = &api_main; - vl_api_trace_which_t which = VL_API_TRACE_RX; - u8 *filename; - u32 first = 0; - u32 last = (u32) ~ 0; - FILE *fp; - int rv; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "on") || unformat (input, "enable")) - { - if (unformat (input, "nitems %d", &nitems)) - ; - vl_msg_api_trace_configure (am, which, nitems); - vl_msg_api_trace_onoff (am, which, 1 /* on */ ); - } - else if (unformat (input, "off")) - { - vl_msg_api_trace_onoff (am, which, 0); - } - else if (unformat (input, "save %s", &filename)) - { - u8 *chroot_filename; - if (strstr ((char *) filename, "..") - || index ((char *) filename, '/')) - { - vlib_cli_output (vm, "illegal characters in filename '%s'", - filename); - return 0; - } - - chroot_filename = format (0, "/tmp/%s%c", filename, 0); - - vec_free (filename); - - fp = fopen ((char *) chroot_filename, "w"); - if (fp == NULL) - { - vlib_cli_output (vm, "Couldn't create %s\n", chroot_filename); - return 0; - } - rv = vl_msg_api_trace_save (am, which, fp); - fclose (fp); - if (rv == -1) - vlib_cli_output (vm, "API Trace data not present\n"); - else if (rv == -2) - vlib_cli_output (vm, "File for writing is closed\n"); - else if (rv == -10) - vlib_cli_output (vm, "Error while writing header to file\n"); - else if (rv == -11) - vlib_cli_output (vm, "Error while writing trace to file\n"); - else if (rv == -12) - vlib_cli_output (vm, - "Error while writing end of buffer trace to file\n"); - else if (rv == -13) - vlib_cli_output (vm, - "Error while writing start of buffer trace to file\n"); - else if (rv < 0) - vlib_cli_output (vm, "Unkown error while saving: %d", rv); - else - vlib_cli_output (vm, "API trace saved to %s\n", chroot_filename); - vec_free (chroot_filename); - } - else if (unformat (input, "dump %s", &filename)) - { - vl_msg_api_process_file (vm, filename, first, last, DUMP); - } - else if (unformat (input, "custom-dump %s", &filename)) - { - vl_msg_api_process_file (vm, filename, first, last, CUSTOM_DUMP); - } - else if (unformat (input, "replay %s", &filename)) - { - vl_msg_api_process_file (vm, filename, first, last, REPLAY); - } - else if (unformat (input, "initializers %s", &filename)) - { - vl_msg_api_process_file (vm, filename, first, last, INITIALIZERS); - } - else if (unformat (input, "tx")) - { - which = VL_API_TRACE_TX; - } - else if (unformat (input, "first %d", &first)) - { - ; - } - else if (unformat (input, "last %d", &last)) - { - ; - } - else if (unformat (input, "status")) - { - vlib_cli_output (vm, "%U", format_vl_msg_api_trace_status, - am, which); - } - else if (unformat (input, "free")) - { - vl_msg_api_trace_onoff (am, which, 0); - vl_msg_api_trace_free (am, which); - } - else if (unformat (input, "post-mortem-on")) - vl_msg_api_post_mortem_dump_enable_disable (1 /* enable */ ); - else if (unformat (input, "post-mortem-off")) - vl_msg_api_post_mortem_dump_enable_disable (0 /* enable */ ); - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - return 0; -} - -/*? - * Display, replay, or save a binary API trace -?*/ - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (api_trace_command, static) = -{ - .path = "api trace", - .short_help = - "api trace [on|off][dump|save|replay ][status][free][post-mortem-on]", - .function = api_trace_command_fn, -}; -/* *INDENT-ON* */ - -static clib_error_t * -api_config_fn (vlib_main_t * vm, unformat_input_t * input) -{ - u32 nitems = 256 << 10; - vl_api_trace_which_t which = VL_API_TRACE_RX; - api_main_t *am = &api_main; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "on") || unformat (input, "enable")) - { - if (unformat (input, "nitems %d", &nitems)) - ; - vl_msg_api_trace_configure (am, which, nitems); - vl_msg_api_trace_onoff (am, which, 1 /* on */ ); - vl_msg_api_post_mortem_dump_enable_disable (1 /* enable */ ); - } - else if (unformat (input, "save-api-table %s", - &am->save_msg_table_filename)) - ; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - return 0; -} - -/*? - * This module has three configuration parameters: - * "on" or "enable" - enables binary api tracing - * "nitems " - sets the size of the circular buffer to - * "save-api-table " - dumps the API message table to /tmp/ -?*/ -VLIB_CONFIG_FUNCTION (api_config_fn, "api-trace"); - -static clib_error_t * -api_queue_config_fn (vlib_main_t * vm, unformat_input_t * input) -{ - api_main_t *am = &api_main; - u32 nitems; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "length %d", &nitems) || - (unformat (input, "len %d", &nitems))) - { - if (nitems >= 1024) - am->vlib_input_queue_length = nitems; - else - clib_warning ("vlib input queue length %d too small, ignored", - nitems); - } - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - return 0; -} - -VLIB_CONFIG_FUNCTION (api_queue_config_fn, "api-queue"); - -static u8 * -extract_name (u8 * s) -{ - u8 *rv; - - rv = vec_dup (s); - - while (vec_len (rv) && rv[vec_len (rv)] != '_') - _vec_len (rv)--; - - rv[vec_len (rv)] = 0; - - return rv; -} - -static u8 * -extract_crc (u8 * s) -{ - int i; - u8 *rv; - - rv = vec_dup (s); - - for (i = vec_len (rv) - 1; i >= 0; i--) - { - if (rv[i] == '_') - { - vec_delete (rv, i + 1, 0); - break; - } - } - return rv; -} - -typedef struct -{ - u8 *name_and_crc; - u8 *name; - u8 *crc; - u32 msg_index; - int which; -} msg_table_unserialize_t; - -static int -table_id_cmp (void *a1, void *a2) -{ - msg_table_unserialize_t *n1 = a1; - msg_table_unserialize_t *n2 = a2; - - return (n1->msg_index - n2->msg_index); -} - -static int -table_name_and_crc_cmp (void *a1, void *a2) -{ - msg_table_unserialize_t *n1 = a1; - msg_table_unserialize_t *n2 = a2; - - return strcmp ((char *) n1->name_and_crc, (char *) n2->name_and_crc); -} - -static clib_error_t * -dump_api_table_file_command_fn (vlib_main_t * vm, - unformat_input_t * input, - vlib_cli_command_t * cmd) -{ - u8 *filename = 0; - api_main_t *am = &api_main; - serialize_main_t _sm, *sm = &_sm; - clib_error_t *error; - u32 nmsgs; - u32 msg_index; - u8 *name_and_crc; - int compare_current = 0; - int numeric_sort = 0; - msg_table_unserialize_t *table = 0, *item; - u32 i; - u32 ndifferences = 0; - - while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) - { - if (unformat (input, "file %s", &filename)) - ; - else if (unformat (input, "compare-current") - || unformat (input, "compare")) - compare_current = 1; - else if (unformat (input, "numeric")) - numeric_sort = 1; - else - return clib_error_return (0, "unknown input `%U'", - format_unformat_error, input); - } - - if (numeric_sort && compare_current) - return clib_error_return - (0, "Comparison and numeric sorting are incompatible"); - - if (filename == 0) - return clib_error_return (0, "File not specified"); - - /* Load the serialized message table from the table dump */ - - error = unserialize_open_clib_file (sm, (char *) filename); - - if (error) - return error; - - unserialize_integer (sm, &nmsgs, sizeof (u32)); - - for (i = 0; i < nmsgs; i++) - { - msg_index = unserialize_likely_small_unsigned_integer (sm); - unserialize_cstring (sm, (char **) &name_and_crc); - vec_add2 (table, item, 1); - item->msg_index = msg_index; - item->name_and_crc = name_and_crc; - item->name = extract_name (name_and_crc); - item->crc = extract_crc (name_and_crc); - item->which = 0; /* file */ - } - serialize_close (sm); - - /* Compare with the current image? */ - if (compare_current) - { - /* Append the current message table */ - u8 *tblv = vl_api_serialize_message_table (am, 0); - - serialize_open_vector (sm, tblv); - unserialize_integer (sm, &nmsgs, sizeof (u32)); - - for (i = 0; i < nmsgs; i++) - { - msg_index = unserialize_likely_small_unsigned_integer (sm); - unserialize_cstring (sm, (char **) &name_and_crc); - - vec_add2 (table, item, 1); - item->msg_index = msg_index; - item->name_and_crc = name_and_crc; - item->name = extract_name (name_and_crc); - item->crc = extract_crc (name_and_crc); - item->which = 1; /* current_image */ - } - vec_free (tblv); - } - - /* Sort the table. */ - if (numeric_sort) - vec_sort_with_function (table, table_id_cmp); - else - vec_sort_with_function (table, table_name_and_crc_cmp); - - if (compare_current) - { - ndifferences = 0; - - /* - * In this case, the recovered table will have two entries per - * API message. So, if entries i and i+1 match, the message definitions - * are identical. Otherwise, the crc is different, or a message is - * present in only one of the tables. - */ - vlib_cli_output (vm, "%=60s %s", "Message Name", "Result"); - - for (i = 0; i < vec_len (table);) - { - /* Last message lonely? */ - if (i == vec_len (table) - 1) - { - ndifferences++; - goto last_unique; - } - - /* Identical pair? */ - if (!strncmp - ((char *) table[i].name_and_crc, - (char *) table[i + 1].name_and_crc, - vec_len (table[i].name_and_crc))) - { - i += 2; - continue; - } - - ndifferences++; - - /* Only in one of two tables? */ - if (strncmp ((char *) table[i].name, (char *) table[i + 1].name, - vec_len (table[i].name))) - { - last_unique: - vlib_cli_output (vm, "%-60s only in %s", - table[i].name, table[i].which ? - "image" : "file"); - i++; - continue; - } - /* In both tables, but with different signatures */ - vlib_cli_output (vm, "%-60s definition changed", table[i].name); - i += 2; - } - if (ndifferences == 0) - vlib_cli_output (vm, "No api message signature differences found."); - else - vlib_cli_output (vm, "Found %u api message signature differences", - ndifferences); - goto cleanup; - } - - /* Dump the table, sorted as shown above */ - vlib_cli_output (vm, "%=60s %=8s %=10s", "Message name", "MsgID", "CRC"); - - for (i = 0; i < vec_len (table); i++) - { - item = table + i; - vlib_cli_output (vm, "%-60s %8u %10s", item->name, - item->msg_index, item->crc); - } - -cleanup: - for (i = 0; i < vec_len (table); i++) - { - vec_free (table[i].name_and_crc); - vec_free (table[i].name); - vec_free (table[i].crc); - } - - vec_free (table); - - return 0; -} - -/*? - * Displays a serialized API message decode table, sorted by message name - * - * @cliexpar - * @cliexstart{show api dump file } - * Message name MsgID CRC - * accept_session 407 8e2a127e - * accept_session_reply 408 67d8c22a - * add_node_next 549 e4202993 - * add_node_next_reply 550 e89d6eed - * etc. - * @cliexend -?*/ - -/*? - * Compares a serialized API message decode table with the current image - * - * @cliexpar - * @cliexstart{show api dump file compare} - * ip_add_del_route definition changed - * ip_table_add_del definition changed - * l2_macs_event only in image - * vnet_ip4_fib_counters only in file - * vnet_ip4_nbr_counters only in file - * @cliexend -?*/ - -/*? - * Display a serialized API message decode table, compare a saved - * decode table with the current image, to establish API differences. - * -?*/ -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (dump_api_table_file, static) = -{ - .path = "show api dump", - .short_help = "show api dump file [numeric | compare-current]", - .function = dump_api_table_file_command_fn, -}; -/* *INDENT-ON* */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/socksvr_vlib.c b/src/vlibmemory/socket_api.c similarity index 96% rename from src/vlibmemory/socksvr_vlib.c rename to src/vlibmemory/socket_api.c index 314e2eb60d3..3d505359d3b 100644 --- a/src/vlibmemory/socksvr_vlib.c +++ b/src/vlibmemory/socket_api.c @@ -21,12 +21,11 @@ #include #include #include -#include -#include - #include #include +#include +#include #include #include @@ -46,8 +45,10 @@ #include #undef vl_endianfun +socket_main_t socket_main; + void -dump_socket_clients (vlib_main_t * vm, api_main_t * am) +vl_sock_api_dump_clients (vlib_main_t * vm, api_main_t * am) { vl_api_registration_t *reg; socket_main_t *sm = &socket_main; @@ -117,7 +118,7 @@ vl_socket_api_send (vl_api_registration_t * rp, u8 * elem) } void -vl_free_socket_registration_index (u32 pool_index) +vl_socket_free_registration_index (u32 pool_index) { int i; vl_api_registration_t *rp; @@ -141,7 +142,7 @@ vl_free_socket_registration_index (u32 pool_index) } void -vl_api_socket_process_msg (clib_file_t * uf, vl_api_registration_t * rp, +vl_socket_process_api_msg (clib_file_t * uf, vl_api_registration_t * rp, i8 * input_v) { msgbuf_t *mbp = (msgbuf_t *) input_v; @@ -181,7 +182,7 @@ vl_socket_read_ready (clib_file_t * uf) if (!pool_is_free (socket_main.registration_pool, rp)) { u32 index = rp - socket_main.registration_pool; - vl_free_socket_registration_index (index); + vl_socket_free_registration_index (index); } else { @@ -248,7 +249,7 @@ vl_socket_read_ready (clib_file_t * uf) a->regp = rp; a->data = data_for_process; - vlib_process_signal_event (vm, memclnt_node.index, + vlib_process_signal_event (vm, vl_api_clnt_node.index, SOCKET_READ_EVENT, a - socket_main.process_args); if (n > (msg_len + sizeof (*mbp))) @@ -326,7 +327,7 @@ vl_socket_write_ready (clib_file_t * uf) #endif clib_file_del (fm, uf); - vl_free_socket_registration_index (rp - socket_main.registration_pool); + vl_socket_free_registration_index (rp - socket_main.registration_pool); return 0; } @@ -344,7 +345,7 @@ vl_socket_error_ready (clib_file_t * uf) rp = pool_elt_at_index (socket_main.registration_pool, uf->private_data); clib_file_del (fm, uf); - vl_free_socket_registration_index (rp - socket_main.registration_pool); + vl_socket_free_registration_index (rp - socket_main.registration_pool); return 0; } @@ -417,7 +418,7 @@ vl_api_sockclnt_create_t_handler (vl_api_sockclnt_create_t * mp) rp->context = mp->context; rp->response = htonl (rv); - vl_msg_api_send (regp, (u8 *) rp); + vl_api_send_msg (regp, (u8 *) rp); } /* @@ -438,11 +439,11 @@ vl_api_sockclnt_delete_t_handler (vl_api_sockclnt_delete_t * mp) rp->handle = mp->handle; rp->response = htonl (1); - vl_msg_api_send (regp, (u8 *) rp); + vl_api_send_msg (regp, (u8 *) rp); clib_file_del (&file_main, file_main.file_pool + regp->clib_file_index); - vl_free_socket_registration_index (mp->index); + vl_socket_free_registration_index (mp->index); } else { @@ -597,7 +598,7 @@ reply: rmp->context = mp->context; rmp->retval = htonl (rv); - vl_msg_api_send (regp, (u8 *) rmp); + vl_api_send_msg (regp, (u8 *) rmp); if (rv != 0) return; @@ -652,7 +653,7 @@ reply: rmp->context = mp->context; rmp->retval = htonl (rv); - vl_msg_api_send (regp, (u8 *) rmp); + vl_api_send_msg (regp, (u8 *) rmp); if (rv != 0) return; @@ -675,7 +676,7 @@ _(SOCK_INIT_SHM, sock_init_shm) \ _(MEMFD_SEGMENT_CREATE, memfd_segment_create) clib_error_t * -socksvr_api_init (vlib_main_t * vm) +vl_sock_api_init (vlib_main_t * vm) { clib_file_main_t *fm = &file_main; clib_file_t template = { 0 }; @@ -752,7 +753,7 @@ socket_exit (vlib_main_t * vm) pool_foreach (rp, sm->registration_pool, ({ clib_file_del (fm, fm->file_pool + rp->clib_file_index); index = rp->vl_api_registration_pool_index; - vl_free_socket_registration_index (index); + vl_socket_free_registration_index (index); })); /* *INDENT-ON* */ } diff --git a/src/vlibmemory/socket_api.h b/src/vlibmemory/socket_api.h new file mode 100644 index 00000000000..69610e8997a --- /dev/null +++ b/src/vlibmemory/socket_api.h @@ -0,0 +1,88 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef SRC_VLIBMEMORY_SOCKET_API_H_ +#define SRC_VLIBMEMORY_SOCKET_API_H_ + +#include +#include + +#define API_SOCKET_FILE "/run/vpp-api.sock" + +typedef struct +{ + clib_file_t *clib_file; + vl_api_registration_t *regp; + u8 *data; +} vl_socket_args_for_process_t; + +typedef struct +{ + /* Server port number */ + u8 *socket_name; + + /* By default, localhost... */ + u32 bind_address; + + /* + * (listen, server, client) registrations. Shared memory + * registrations are in shared memory + */ + vl_api_registration_t *registration_pool; + /* + * Chain-drag variables, so message API handlers + * (generally) don't know whether they're talking to a socket + * or to a shared-memory connection. + */ + vl_api_registration_t *current_rp; + clib_file_t *current_uf; + /* One input buffer, shared across all sockets */ + i8 *input_buffer; + + /* pool of process args for socket clients */ + vl_socket_args_for_process_t *process_args; + + /* Listen for API connections here */ + clib_socket_t socksvr_listen_socket; +} socket_main_t; + +extern socket_main_t socket_main; + +void vl_socket_free_registration_index (u32 pool_index); +clib_error_t *vl_socket_read_ready (struct clib_file *uf); +void vl_socket_add_pending_output (struct clib_file *uf, + struct vl_api_registration_ *rp, + u8 * buffer, uword buffer_bytes); +void vl_socket_add_pending_output_no_flush (struct clib_file *uf, + struct vl_api_registration_ *rp, + u8 * buffer, uword buffer_bytes); +clib_error_t *vl_socket_write_ready (struct clib_file *uf); +void vl_socket_api_send (vl_api_registration_t * rp, u8 * elem); +void vl_socket_process_api_msg (clib_file_t * uf, vl_api_registration_t * rp, + i8 * input_v); +void vl_sock_api_dump_clients (vlib_main_t * vm, api_main_t * am); +clib_error_t *vl_sock_api_init (vlib_main_t * vm); + +#endif /* SRC_VLIBMEMORY_SOCKET_API_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/socket_client.c b/src/vlibmemory/socket_client.c index d7a9ad5fe86..4567f65e6e1 100644 --- a/src/vlibmemory/socket_client.c +++ b/src/vlibmemory/socket_client.c @@ -18,35 +18,12 @@ */ #include -#include -#include -#include #define __USE_GNU #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include + #include -#include +#include +#include #include diff --git a/src/vlibmemory/socket_client.h b/src/vlibmemory/socket_client.h new file mode 100644 index 00000000000..10191db6410 --- /dev/null +++ b/src/vlibmemory/socket_client.h @@ -0,0 +1,64 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef SRC_VLIBMEMORY_SOCKET_CLIENT_H_ +#define SRC_VLIBMEMORY_SOCKET_CLIENT_H_ + +#include +#include +#include + +typedef struct +{ + int socket_fd; + /* Temporarily disable the connection, so we can keep it around... */ + int socket_enable; + + clib_socket_t client_socket; + + u32 socket_buffer_size; + u8 *socket_tx_buffer; + u8 *socket_rx_buffer; + u32 socket_tx_nbytes; + int control_pings_outstanding; + + u8 *name; + clib_time_t clib_time; +} socket_client_main_t; + +extern socket_client_main_t socket_client_main; + +#define SOCKET_CLIENT_DEFAULT_BUFFER_SIZE 4096 + +int vl_socket_client_connect (char *socket_path, char *client_name, + u32 socket_buffer_size); +void vl_socket_client_disconnect (void); +int vl_socket_client_read (int wait); +int vl_socket_client_write (void); +void vl_socket_client_enable_disable (int enable); +void *vl_socket_client_msg_alloc (int nbytes); +int vl_socket_client_init_shm (vl_api_shm_elem_config_t * config); + +#endif /* SRC_VLIBMEMORY_SOCKET_CLIENT_H_ */ + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/unix_shared_memory_queue.h b/src/vlibmemory/unix_shared_memory_queue.h deleted file mode 100644 index 27de3218223..00000000000 --- a/src/vlibmemory/unix_shared_memory_queue.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - *------------------------------------------------------------------ - * unix_shared_memory_queue.h - shared-memory queues - * - * Copyright (c) 2009 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------ - */ - -#ifndef included_unix_shared_memory_queue_h -#define included_unix_shared_memory_queue_h - -#include - -typedef struct _unix_shared_memory_queue -{ - pthread_mutex_t mutex; /* 8 bytes */ - pthread_cond_t condvar; /* 8 bytes */ - int head; - int tail; - volatile int cursize; - int maxsize; - int elsize; - int consumer_pid; - int signal_when_queue_non_empty; - char data[0]; -} unix_shared_memory_queue_t; - -unix_shared_memory_queue_t *unix_shared_memory_queue_init (int nels, - int elsize, - int consumer_pid, - int - signal_when_queue_non_empty); -void unix_shared_memory_queue_free (unix_shared_memory_queue_t * q); -int unix_shared_memory_queue_add (unix_shared_memory_queue_t * q, u8 * elem, - int nowait); -int unix_shared_memory_queue_add2 (unix_shared_memory_queue_t * q, u8 * elem, - u8 * elem2, int nowait); -int unix_shared_memory_queue_sub (unix_shared_memory_queue_t * q, u8 * elem, - int nowait); -void unix_shared_memory_queue_lock (unix_shared_memory_queue_t * q); -void unix_shared_memory_queue_unlock (unix_shared_memory_queue_t * q); -int unix_shared_memory_queue_is_full (unix_shared_memory_queue_t * q); -int unix_shared_memory_queue_add_nolock (unix_shared_memory_queue_t * q, - u8 * elem); - -int unix_shared_memory_queue_sub_raw (unix_shared_memory_queue_t * q, - u8 * elem); -int unix_shared_memory_queue_add_raw (unix_shared_memory_queue_t * q, - u8 * elem); - -#endif /* included_unix_shared_memory_queue_h */ - -/* - * fd.io coding-style-patch-verification: ON - * - * Local Variables: - * eval: (c-set-style "gnu") - * End: - */ diff --git a/src/vlibmemory/vlib_api.c b/src/vlibmemory/vlib_api.c new file mode 100644 index 00000000000..9465cfc30d6 --- /dev/null +++ b/src/vlibmemory/vlib_api.c @@ -0,0 +1,750 @@ +/* + *------------------------------------------------------------------ + * vlib_api.c VLIB API implementation + * + * Copyright (c) 2009 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * @file + * @brief Binary API messaging via shared memory + * Low-level, primary provisioning interface + */ +/*? %%clicmd:group_label Binary API CLI %% ?*/ +/*? %%syscfg:group_label Binary API configuration %% ?*/ + +#define TRACE_VLIB_MEMORY_QUEUE 0 + +#include /* enumerate all vlib messages */ + +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__) +#define vl_printfun +#include +#undef vl_printfun + +static inline void * +vl_api_trace_plugin_msg_ids_t_print (vl_api_trace_plugin_msg_ids_t * a, + void *handle) +{ + vl_print (handle, "vl_api_trace_plugin_msg_ids: %s first %u last %u\n", + a->plugin_name, + clib_host_to_net_u16 (a->first_msg_id), + clib_host_to_net_u16 (a->last_msg_id)); + return handle; +} + +/* instantiate all the endian swap functions we know about */ +#define vl_endianfun +#include +#undef vl_endianfun + +u8 * +vl_api_serialize_message_table (api_main_t * am, u8 * vector) +{ + serialize_main_t _sm, *sm = &_sm; + hash_pair_t *hp; + u32 nmsg = hash_elts (am->msg_index_by_name_and_crc); + + serialize_open_vector (sm, vector); + + /* serialize the count */ + serialize_integer (sm, nmsg, sizeof (u32)); + + /* *INDENT-OFF* */ + hash_foreach_pair (hp, am->msg_index_by_name_and_crc, + ({ + serialize_likely_small_unsigned_integer (sm, hp->value[0]); + serialize_cstring (sm, (char *) hp->key); + })); + /* *INDENT-ON* */ + + return serialize_close_vector (sm); +} + +static void +vl_api_get_first_msg_id_t_handler (vl_api_get_first_msg_id_t * mp) +{ + vl_api_get_first_msg_id_reply_t *rmp; + vl_api_registration_t *regp; + uword *p; + api_main_t *am = &api_main; + vl_api_msg_range_t *rp; + u8 name[64]; + u16 first_msg_id = ~0; + int rv = -7; /* VNET_API_ERROR_INVALID_VALUE */ + + regp = vl_api_client_index_to_registration (mp->client_index); + if (!regp) + return; + + if (am->msg_range_by_name == 0) + goto out; + + strncpy ((char *) name, (char *) mp->name, ARRAY_LEN (name) - 1); + + p = hash_get_mem (am->msg_range_by_name, name); + if (p == 0) + goto out; + + rp = vec_elt_at_index (am->msg_ranges, p[0]); + first_msg_id = rp->first_msg_id; + rv = 0; + +out: + rmp = vl_msg_api_alloc (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_GET_FIRST_MSG_ID_REPLY); + rmp->context = mp->context; + rmp->retval = ntohl (rv); + rmp->first_msg_id = ntohs (first_msg_id); + vl_api_send_msg (regp, (u8 *) rmp); +} + +void +vl_api_api_versions_t_handler (vl_api_api_versions_t * mp) +{ + api_main_t *am = &api_main; + vl_api_api_versions_reply_t *rmp; + svm_queue_t *q; + u32 nmsg = vec_len (am->api_version_list); + int msg_size = sizeof (*rmp) + sizeof (rmp->api_versions[0]) * nmsg; + int i; + + q = vl_api_client_index_to_input_queue (mp->client_index); + if (q == 0) + return; + + rmp = vl_msg_api_alloc (msg_size); + memset (rmp, 0, msg_size); + rmp->_vl_msg_id = ntohs (VL_API_API_VERSIONS_REPLY); + + /* fill in the message */ + rmp->context = mp->context; + rmp->count = htonl (nmsg); + + for (i = 0; i < nmsg; ++i) + { + api_version_t *vl = &am->api_version_list[i]; + rmp->api_versions[i].major = htonl (vl->major); + rmp->api_versions[i].minor = htonl (vl->minor); + rmp->api_versions[i].patch = htonl (vl->patch); + strncpy ((char *) rmp->api_versions[i].name, vl->name, 64 - 1); + } + + vl_msg_api_send_shmem (q, (u8 *) & rmp); +} + +#define foreach_vlib_api_msg \ +_(GET_FIRST_MSG_ID, get_first_msg_id) \ +_(API_VERSIONS, api_versions) + +/* + * vl_api_init + */ +static int +vlib_api_init (void) +{ + vl_msg_api_msg_config_t cfg; + vl_msg_api_msg_config_t *c = &cfg; + + memset (c, 0, sizeof (*c)); + +#define _(N,n) do { \ + c->id = VL_API_##N; \ + c->name = #n; \ + c->handler = vl_api_##n##_t_handler; \ + c->cleanup = vl_noop_handler; \ + c->endian = vl_api_##n##_t_endian; \ + c->print = vl_api_##n##_t_print; \ + c->size = sizeof(vl_api_##n##_t); \ + c->traced = 1; /* trace, so these msgs print */ \ + c->replay = 0; /* don't replay client create/delete msgs */ \ + c->message_bounce = 0; /* don't bounce this message */ \ + vl_msg_api_config(c);} while (0); + + foreach_vlib_api_msg; +#undef _ + + return 0; +} + +u64 vector_rate_histogram[SLEEP_N_BUCKETS]; + +/* + * Callback to send ourselves a plugin numbering-space trace msg + */ +static void +send_one_plugin_msg_ids_msg (u8 * name, u16 first_msg_id, u16 last_msg_id) +{ + vl_api_trace_plugin_msg_ids_t *mp; + api_main_t *am = &api_main; + vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; + svm_queue_t *q; + + mp = vl_msg_api_alloc_as_if_client (sizeof (*mp)); + memset (mp, 0, sizeof (*mp)); + + mp->_vl_msg_id = clib_host_to_net_u16 (VL_API_TRACE_PLUGIN_MSG_IDS); + strncpy ((char *) mp->plugin_name, (char *) name, + sizeof (mp->plugin_name) - 1); + mp->first_msg_id = clib_host_to_net_u16 (first_msg_id); + mp->last_msg_id = clib_host_to_net_u16 (last_msg_id); + + q = shmem_hdr->vl_input_queue; + + vl_msg_api_send_shmem (q, (u8 *) & mp); +} + +void +vl_api_save_msg_table (void) +{ + u8 *serialized_message_table; + api_main_t *am = &api_main; + u8 *chroot_file; + int fd, rv; + + /* + * Snapshoot the api message table. + */ + if (strstr ((char *) am->save_msg_table_filename, "..") + || index ((char *) am->save_msg_table_filename, '/')) + { + clib_warning ("illegal save-message-table filename '%s'", + am->save_msg_table_filename); + return; + } + + chroot_file = format (0, "/tmp/%s%c", am->save_msg_table_filename, 0); + + fd = creat ((char *) chroot_file, 0644); + + if (fd < 0) + { + clib_unix_warning ("creat"); + return; + } + + serialized_message_table = vl_api_serialize_message_table (am, 0); + + rv = write (fd, serialized_message_table, + vec_len (serialized_message_table)); + + if (rv != vec_len (serialized_message_table)) + clib_unix_warning ("write"); + + rv = close (fd); + if (rv < 0) + clib_unix_warning ("close"); + + vec_free (chroot_file); + vec_free (serialized_message_table); +} + +static uword +vl_api_clnt_process (vlib_main_t * vm, vlib_node_runtime_t * node, + vlib_frame_t * f) +{ + int private_segment_rotor = 0, i, rv; + vl_socket_args_for_process_t *a; + vl_shmem_hdr_t *shm; + svm_queue_t *q; + clib_error_t *e; + api_main_t *am = &api_main; + f64 dead_client_scan_time; + f64 sleep_time, start_time; + f64 vector_rate; + clib_error_t *error; + uword event_type; + uword *event_data = 0; + f64 now; + + if ((rv = vl_mem_api_init (am->region_name)) < 0) + { + clib_warning ("memory_api_init returned %d, quitting...", rv); + return 0; + } + + if ((error = vl_sock_api_init (vm))) + { + clib_error_report (error); + clib_warning ("socksvr_api_init failed, quitting..."); + return 0; + } + + if ((rv = vlib_api_init ()) < 0) + { + clib_warning ("vlib_api_init returned %d, quitting...", rv); + return 0; + } + + shm = am->shmem_hdr; + q = shm->vl_input_queue; + + e = vlib_call_init_exit_functions + (vm, vm->api_init_function_registrations, 1 /* call_once */ ); + if (e) + clib_error_report (e); + + sleep_time = 10.0; + dead_client_scan_time = vlib_time_now (vm) + 10.0; + + /* + * Send plugin message range messages for each plugin we loaded + */ + for (i = 0; i < vec_len (am->msg_ranges); i++) + { + vl_api_msg_range_t *rp = am->msg_ranges + i; + send_one_plugin_msg_ids_msg (rp->name, rp->first_msg_id, + rp->last_msg_id); + } + + /* + * Save the api message table snapshot, if configured + */ + if (am->save_msg_table_filename) + vl_api_save_msg_table (); + + /* $$$ pay attention to frame size, control CPU usage */ + while (1) + { + /* + * There's a reason for checking the queue before + * sleeping. If the vlib application crashes, it's entirely + * possible for a client to enqueue a connect request + * during the process restart interval. + * + * Unless some force of physics causes the new incarnation + * of the application to process the request, the client will + * sit and wait for Godot... + */ + vector_rate = vlib_last_vector_length_per_node (vm); + start_time = vlib_time_now (vm); + while (1) + { + if (vl_mem_api_handle_msg_main (vm, node)) + { + vm->api_queue_nonempty = 0; + VL_MEM_API_LOG_Q_LEN ("q-underflow: len %d", 0); + sleep_time = 20.0; + break; + } + + /* Allow no more than 10us without a pause */ + if (vlib_time_now (vm) > start_time + 10e-6) + { + int index = SLEEP_400_US; + if (vector_rate > 40.0) + sleep_time = 400e-6; + else if (vector_rate > 20.0) + { + index = SLEEP_200_US; + sleep_time = 200e-6; + } + else if (vector_rate >= 1.0) + { + index = SLEEP_100_US; + sleep_time = 100e-6; + } + else + { + index = SLEEP_10_US; + sleep_time = 10e-6; + } + vector_rate_histogram[index] += 1; + break; + } + } + + /* + * see if we have any private api shared-memory segments + * If so, push required context variables, and process + * a message. + */ + if (PREDICT_FALSE (vec_len (am->vlib_private_rps))) + { + vl_mem_api_handle_msg_private (vm, node, private_segment_rotor++); + if (private_segment_rotor >= vec_len (am->vlib_private_rps)) + private_segment_rotor = 0; + } + + vlib_process_wait_for_event_or_clock (vm, sleep_time); + vec_reset_length (event_data); + event_type = vlib_process_get_events (vm, &event_data); + now = vlib_time_now (vm); + + switch (event_type) + { + case QUEUE_SIGNAL_EVENT: + vm->queue_signal_pending = 0; + VL_MEM_API_LOG_Q_LEN ("q-awake: len %d", q->cursize); + + break; + case SOCKET_READ_EVENT: + for (i = 0; i < vec_len (event_data); i++) + { + a = pool_elt_at_index (socket_main.process_args, event_data[i]); + vl_socket_process_api_msg (a->clib_file, a->regp, + (i8 *) a->data); + vec_free (a->data); + pool_put (socket_main.process_args, a); + } + break; + + /* Timeout... */ + case -1: + break; + + default: + clib_warning ("unknown event type %d", event_type); + break; + } + + if (now > dead_client_scan_time) + { + vl_mem_api_dead_client_scan (am, shm, now); + dead_client_scan_time = vlib_time_now (vm) + 10.0; + } + } + + return 0; +} +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (vl_api_clnt_node) = +{ + .function = vl_api_clnt_process, + .type = VLIB_NODE_TYPE_PROCESS, + .name = "api-rx-from-ring", + .state = VLIB_NODE_STATE_DISABLED, +}; +/* *INDENT-ON* */ + +void +vl_mem_api_enable_disable (vlib_main_t * vm, int enable) +{ + vlib_node_set_state (vm, vl_api_clnt_node.index, + (enable + ? VLIB_NODE_STATE_POLLING + : VLIB_NODE_STATE_DISABLED)); +} + +static uword +api_rx_from_node (vlib_main_t * vm, + vlib_node_runtime_t * node, vlib_frame_t * frame) +{ + uword n_packets = frame->n_vectors; + uword n_left_from; + u32 *from; + static u8 *long_msg; + + vec_validate (long_msg, 4095); + n_left_from = frame->n_vectors; + from = vlib_frame_args (frame); + + while (n_left_from > 0) + { + u32 bi0; + vlib_buffer_t *b0; + void *msg; + uword msg_len; + + bi0 = from[0]; + b0 = vlib_get_buffer (vm, bi0); + from += 1; + n_left_from -= 1; + + msg = b0->data + b0->current_data; + msg_len = b0->current_length; + if (b0->flags & VLIB_BUFFER_NEXT_PRESENT) + { + ASSERT (long_msg != 0); + _vec_len (long_msg) = 0; + vec_add (long_msg, msg, msg_len); + while (b0->flags & VLIB_BUFFER_NEXT_PRESENT) + { + b0 = vlib_get_buffer (vm, b0->next_buffer); + msg = b0->data + b0->current_data; + msg_len = b0->current_length; + vec_add (long_msg, msg, msg_len); + } + msg = long_msg; + } + vl_msg_api_handler_no_trace_no_free (msg); + } + + /* Free what we've been given. */ + vlib_buffer_free (vm, vlib_frame_args (frame), n_packets); + + return n_packets; +} + +/* *INDENT-OFF* */ +VLIB_REGISTER_NODE (api_rx_from_node_node,static) = { + .function = api_rx_from_node, + .type = VLIB_NODE_TYPE_INTERNAL, + .vector_size = 4, + .name = "api-rx-from-node", +}; +/* *INDENT-ON* */ + +static void +vl_api_rpc_call_t_handler (vl_api_rpc_call_t * mp) +{ + vl_api_rpc_call_reply_t *rmp; + int (*fp) (void *); + i32 rv = 0; + vlib_main_t *vm = vlib_get_main (); + + if (mp->function == 0) + { + rv = -1; + clib_warning ("rpc NULL function pointer"); + } + + else + { + if (mp->need_barrier_sync) + vlib_worker_thread_barrier_sync (vm); + + fp = uword_to_pointer (mp->function, int (*)(void *)); + rv = fp (mp->data); + + if (mp->need_barrier_sync) + vlib_worker_thread_barrier_release (vm); + } + + if (mp->send_reply) + { + svm_queue_t *q = vl_api_client_index_to_input_queue (mp->client_index); + if (q) + { + rmp = vl_msg_api_alloc_as_if_client (sizeof (*rmp)); + rmp->_vl_msg_id = ntohs (VL_API_RPC_CALL_REPLY); + rmp->context = mp->context; + rmp->retval = rv; + vl_msg_api_send_shmem (q, (u8 *) & rmp); + } + } + if (mp->multicast) + { + clib_warning ("multicast not yet implemented..."); + } +} + +static void +vl_api_rpc_call_reply_t_handler (vl_api_rpc_call_reply_t * mp) +{ + clib_warning ("unimplemented"); +} + +void +vl_api_send_pending_rpc_requests (vlib_main_t * vm) +{ + api_main_t *am = &api_main; + vl_shmem_hdr_t *shmem_hdr = am->shmem_hdr; + svm_queue_t *q; + int i; + + /* + * Use the "normal" control-plane mechanism for the main thread. + * Well, almost. if the main input queue is full, we cannot + * block. Otherwise, we can expect a barrier sync timeout. + */ + q = shmem_hdr->vl_input_queue; + + for (i = 0; i < vec_len (vm->pending_rpc_requests); i++) + { + while (pthread_mutex_trylock (&q->mutex)) + vlib_worker_thread_barrier_check (); + + while (PREDICT_FALSE (svm_queue_is_full (q))) + { + pthread_mutex_unlock (&q->mutex); + vlib_worker_thread_barrier_check (); + while (pthread_mutex_trylock (&q->mutex)) + vlib_worker_thread_barrier_check (); + } + + vl_msg_api_send_shmem_nolock (q, (u8 *) (vm->pending_rpc_requests + i)); + + pthread_mutex_unlock (&q->mutex); + } + _vec_len (vm->pending_rpc_requests) = 0; +} + +always_inline void +vl_api_rpc_call_main_thread_inline (void *fp, u8 * data, u32 data_length, + u8 force_rpc) +{ + vl_api_rpc_call_t *mp; + vlib_main_t *vm = vlib_get_main (); + + /* Main thread and not a forced RPC: call the function directly */ + if ((force_rpc == 0) && (vlib_get_thread_index () == 0)) + { + void (*call_fp) (void *); + + vlib_worker_thread_barrier_sync (vm); + + call_fp = fp; + call_fp (data); + + vlib_worker_thread_barrier_release (vm); + return; + } + + /* Otherwise, actually do an RPC */ + mp = vl_msg_api_alloc_as_if_client (sizeof (*mp) + data_length); + + memset (mp, 0, sizeof (*mp)); + clib_memcpy (mp->data, data, data_length); + mp->_vl_msg_id = ntohs (VL_API_RPC_CALL); + mp->function = pointer_to_uword (fp); + mp->need_barrier_sync = 1; + + vec_add1 (vm->pending_rpc_requests, (uword) mp); +} + +/* + * Check if called from worker threads. + * If so, make rpc call of fp through shmem. + * Otherwise, call fp directly + */ +void +vl_api_rpc_call_main_thread (void *fp, u8 * data, u32 data_length) +{ + vl_api_rpc_call_main_thread_inline (fp, data, data_length, /*force_rpc */ + 0); +} + +/* + * Always make rpc call of fp through shmem, useful for calling from threads + * not setup as worker threads, such as DPDK callback thread + */ +void +vl_api_force_rpc_call_main_thread (void *fp, u8 * data, u32 data_length) +{ + vl_api_rpc_call_main_thread_inline (fp, data, data_length, /*force_rpc */ + 1); +} + +static void +vl_api_trace_plugin_msg_ids_t_handler (vl_api_trace_plugin_msg_ids_t * mp) +{ + api_main_t *am = &api_main; + vl_api_msg_range_t *rp; + uword *p; + + /* Noop (except for tracing) during normal operation */ + if (am->replay_in_progress == 0) + return; + + p = hash_get_mem (am->msg_range_by_name, mp->plugin_name); + if (p == 0) + { + clib_warning ("WARNING: traced plugin '%s' not in current image", + mp->plugin_name); + return; + } + + rp = vec_elt_at_index (am->msg_ranges, p[0]); + if (rp->first_msg_id != clib_net_to_host_u16 (mp->first_msg_id)) + { + clib_warning ("WARNING: traced plugin '%s' first message id %d not %d", + mp->plugin_name, clib_net_to_host_u16 (mp->first_msg_id), + rp->first_msg_id); + } + + if (rp->last_msg_id != clib_net_to_host_u16 (mp->last_msg_id)) + { + clib_warning ("WARNING: traced plugin '%s' last message id %d not %d", + mp->plugin_name, clib_net_to_host_u16 (mp->last_msg_id), + rp->last_msg_id); + } +} + +#define foreach_rpc_api_msg \ +_(RPC_CALL,rpc_call) \ +_(RPC_CALL_REPLY,rpc_call_reply) + +#define foreach_plugin_trace_msg \ +_(TRACE_PLUGIN_MSG_IDS,trace_plugin_msg_ids) + +/* + * Set the rpc callback at our earliest possible convenience. + * This avoids ordering issues between thread_init() -> start_workers and + * an init function which we could define here. If we ever intend to use + * vlib all by itself, we can't create a link-time dependency on + * an init function here and a typical "call foo_init first" + * guitar lick. + */ + +extern void *rpc_call_main_thread_cb_fn; + +static clib_error_t * +rpc_api_hookup (vlib_main_t * vm) +{ + api_main_t *am = &api_main; +#define _(N,n) \ + vl_msg_api_set_handlers(VL_API_##N, #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 0 /* do not trace */); + foreach_rpc_api_msg; +#undef _ + +#define _(N,n) \ + vl_msg_api_set_handlers(VL_API_##N, #n, \ + vl_api_##n##_t_handler, \ + vl_noop_handler, \ + vl_noop_handler, \ + vl_api_##n##_t_print, \ + sizeof(vl_api_##n##_t), 1 /* do trace */); + foreach_plugin_trace_msg; +#undef _ + + /* No reason to halt the parade to create a trace record... */ + am->is_mp_safe[VL_API_TRACE_PLUGIN_MSG_IDS] = 1; + rpc_call_main_thread_cb_fn = vl_api_rpc_call_main_thread; + return 0; +} + +VLIB_API_INIT_FUNCTION (rpc_api_hookup); + +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibmemory/vlib_api_cli.c b/src/vlibmemory/vlib_api_cli.c new file mode 100644 index 00000000000..d4d7c1c63dc --- /dev/null +++ b/src/vlibmemory/vlib_api_cli.c @@ -0,0 +1,1209 @@ +/* + *------------------------------------------------------------------ + * Copyright (c) 2018 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include + +#include +#include + +static clib_error_t * +vl_api_show_histogram_command (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cli_cmd) +{ + u64 total_counts = 0; + int i; + + for (i = 0; i < SLEEP_N_BUCKETS; i++) + { + total_counts += vector_rate_histogram[i]; + } + + if (total_counts == 0) + { + vlib_cli_output (vm, "No control-plane activity."); + return 0; + } + +#define _(n) \ + do { \ + f64 percent; \ + percent = ((f64) vector_rate_histogram[SLEEP_##n##_US]) \ + / (f64) total_counts; \ + percent *= 100.0; \ + vlib_cli_output (vm, "Sleep %3d us: %llu, %.2f%%",n, \ + vector_rate_histogram[SLEEP_##n##_US], \ + percent); \ + } while (0); + foreach_histogram_bucket; +#undef _ + + return 0; +} + +/*? + * Display the binary api sleep-time histogram +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_histogram_command, static) = +{ + .path = "show api histogram", + .short_help = "show api histogram", + .function = vl_api_show_histogram_command, +}; +/* *INDENT-ON* */ + +static clib_error_t * +vl_api_clear_histogram_command (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cli_cmd) +{ + int i; + + for (i = 0; i < SLEEP_N_BUCKETS; i++) + vector_rate_histogram[i] = 0; + return 0; +} + +/*? + * Clear the binary api sleep-time histogram +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_clear_api_histogram_command, static) = +{ + .path = "clear api histogram", + .short_help = "clear api histogram", + .function = vl_api_clear_histogram_command, +}; +/* *INDENT-ON* */ + +static clib_error_t * +vl_api_client_command (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cli_cmd) +{ + vl_api_registration_t **regpp, *regp; + svm_queue_t *q; + char *health; + api_main_t *am = &api_main; + u32 *confused_indices = 0; + + if (!pool_elts (am->vl_clients)) + goto socket_clients; + vlib_cli_output (vm, "Shared memory clients"); + vlib_cli_output (vm, "%20s %8s %14s %18s %s", + "Name", "PID", "Queue Length", "Queue VA", "Health"); + + /* *INDENT-OFF* */ + pool_foreach (regpp, am->vl_clients, + ({ + regp = *regpp; + + if (regp) + { + if (regp->unanswered_pings > 0) + health = "questionable"; + else + health = "OK"; + + q = regp->vl_input_queue; + + vlib_cli_output (vm, "%20s %8d %14d 0x%016llx %s\n", + regp->name, q->consumer_pid, q->cursize, + q, health); + } + else + { + clib_warning ("NULL client registration index %d", + regpp - am->vl_clients); + vec_add1 (confused_indices, regpp - am->vl_clients); + } + })); + /* *INDENT-ON* */ + + /* This should "never happen," but if it does, fix it... */ + if (PREDICT_FALSE (vec_len (confused_indices) > 0)) + { + int i; + for (i = 0; i < vec_len (confused_indices); i++) + { + pool_put_index (am->vl_clients, confused_indices[i]); + } + } + vec_free (confused_indices); + + if (am->missing_clients) + vlib_cli_output (vm, "%u messages with missing clients", + am->missing_clients); +socket_clients: + vl_sock_api_dump_clients (vm, am); + + return 0; +} + +static clib_error_t * +vl_api_status_command (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cli_cmd) +{ + api_main_t *am = &api_main; + + /* check if rx_trace and tx_trace are not null pointers */ + if (am->rx_trace == 0) + { + vlib_cli_output (vm, "RX Trace disabled\n"); + } + else + { + if (am->rx_trace->enabled == 0) + vlib_cli_output (vm, "RX Trace disabled\n"); + else + vlib_cli_output (vm, "RX Trace enabled\n"); + } + + if (am->tx_trace == 0) + { + vlib_cli_output (vm, "TX Trace disabled\n"); + } + else + { + if (am->tx_trace->enabled == 0) + vlib_cli_output (vm, "TX Trace disabled\n"); + else + vlib_cli_output (vm, "TX Trace enabled\n"); + } + + return 0; +} + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_command, static) = +{ + .path = "show api", + .short_help = "Show API information", +}; +/* *INDENT-ON* */ + +/*? + * Display current api client connections +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_clients_command, static) = +{ + .path = "show api clients", + .short_help = "Client information", + .function = vl_api_client_command, +}; +/* *INDENT-ON* */ + +/*? + * Display the current api message tracing status +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_status_command, static) = +{ + .path = "show api trace-status", + .short_help = "Display API trace status", + .function = vl_api_status_command, +}; +/* *INDENT-ON* */ + +static clib_error_t * +vl_api_message_table_command (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cli_cmd) +{ + api_main_t *am = &api_main; + int i; + int verbose = 0; + + if (unformat (input, "verbose")) + verbose = 1; + + + if (verbose == 0) + vlib_cli_output (vm, "%-4s %s", "ID", "Name"); + else + vlib_cli_output (vm, "%-4s %-40s %6s %7s", "ID", "Name", "Bounce", + "MP-safe"); + + for (i = 1; i < vec_len (am->msg_names); i++) + { + if (verbose == 0) + { + vlib_cli_output (vm, "%-4d %s", i, + am->msg_names[i] ? am->msg_names[i] : + " [no handler]"); + } + else + { + vlib_cli_output (vm, "%-4d %-40s %6d %7d", i, + am->msg_names[i] ? am->msg_names[i] : + " [no handler]", am->message_bounce[i], + am->is_mp_safe[i]); + } + } + + return 0; +} + +/*? + * Display the current api message decode tables +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_message_table_command, static) = +{ + .path = "show api message-table", + .short_help = "Message Table", + .function = vl_api_message_table_command, +}; +/* *INDENT-ON* */ + +static int +range_compare (vl_api_msg_range_t * a0, vl_api_msg_range_t * a1) +{ + int len0, len1, clen; + + len0 = vec_len (a0->name); + len1 = vec_len (a1->name); + clen = len0 < len1 ? len0 : len1; + return (strncmp ((char *) a0->name, (char *) a1->name, clen)); +} + +static u8 * +format_api_msg_range (u8 * s, va_list * args) +{ + vl_api_msg_range_t *rp = va_arg (*args, vl_api_msg_range_t *); + + if (rp == 0) + s = format (s, "%-50s%9s%9s", "Name", "First-ID", "Last-ID"); + else + s = format (s, "%-50s%9d%9d", rp->name, rp->first_msg_id, + rp->last_msg_id); + + return s; +} + +static clib_error_t * +vl_api_show_plugin_command (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cli_cmd) +{ + api_main_t *am = &api_main; + vl_api_msg_range_t *rp = 0; + int i; + + if (vec_len (am->msg_ranges) == 0) + { + vlib_cli_output (vm, "No plugin API message ranges configured..."); + return 0; + } + + rp = vec_dup (am->msg_ranges); + + vec_sort_with_function (rp, range_compare); + + vlib_cli_output (vm, "Plugin API message ID ranges...\n"); + vlib_cli_output (vm, "%U", format_api_msg_range, 0 /* header */ ); + + for (i = 0; i < vec_len (rp); i++) + vlib_cli_output (vm, "%U", format_api_msg_range, rp + i); + + vec_free (rp); + + return 0; +} + +/*? + * Display the plugin binary API message range table +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (cli_show_api_plugin_command, static) = +{ + .path = "show api plugin", + .short_help = "show api plugin", + .function = vl_api_show_plugin_command, +}; +/* *INDENT-ON* */ + +typedef enum +{ + DUMP, + CUSTOM_DUMP, + REPLAY, + INITIALIZERS, +} vl_api_replay_t; + +u8 * +format_vl_msg_api_trace_status (u8 * s, va_list * args) +{ + api_main_t *am = va_arg (*args, api_main_t *); + vl_api_trace_which_t which = va_arg (*args, vl_api_trace_which_t); + vl_api_trace_t *tp; + char *trace_name; + + switch (which) + { + case VL_API_TRACE_TX: + tp = am->tx_trace; + trace_name = "TX trace"; + break; + + case VL_API_TRACE_RX: + tp = am->rx_trace; + trace_name = "RX trace"; + break; + + default: + abort (); + } + + if (tp == 0) + { + s = format (s, "%s: not yet configured.\n", trace_name); + return s; + } + + s = format (s, "%s: used %d of %d items, %s enabled, %s wrapped\n", + trace_name, vec_len (tp->traces), tp->nitems, + tp->enabled ? "is" : "is not", tp->wrapped ? "has" : "has not"); + return s; +} + +void vl_msg_api_custom_dump_configure (api_main_t * am) + __attribute__ ((weak)); +void +vl_msg_api_custom_dump_configure (api_main_t * am) +{ +} + +static void +vl_msg_api_process_file (vlib_main_t * vm, u8 * filename, + u32 first_index, u32 last_index, + vl_api_replay_t which) +{ + vl_api_trace_file_header_t *hp; + int i, fd; + struct stat statb; + size_t file_size; + u8 *msg; + u8 endian_swap_needed = 0; + api_main_t *am = &api_main; + u8 *tmpbuf = 0; + u32 nitems; + void **saved_print_handlers = 0; + + fd = open ((char *) filename, O_RDONLY); + + if (fd < 0) + { + vlib_cli_output (vm, "Couldn't open %s\n", filename); + return; + } + + if (fstat (fd, &statb) < 0) + { + vlib_cli_output (vm, "Couldn't stat %s\n", filename); + close (fd); + return; + } + + if (!(statb.st_mode & S_IFREG) || (statb.st_size < sizeof (*hp))) + { + vlib_cli_output (vm, "File not plausible: %s\n", filename); + close (fd); + return; + } + + file_size = statb.st_size; + file_size = (file_size + 4095) & ~(4096); + + hp = mmap (0, file_size, PROT_READ, MAP_PRIVATE, fd, 0); + + if (hp == (vl_api_trace_file_header_t *) MAP_FAILED) + { + vlib_cli_output (vm, "mmap failed: %s\n", filename); + close (fd); + return; + } + close (fd); + + if ((clib_arch_is_little_endian && hp->endian == VL_API_BIG_ENDIAN) + || (clib_arch_is_big_endian && hp->endian == VL_API_LITTLE_ENDIAN)) + endian_swap_needed = 1; + + if (endian_swap_needed) + nitems = ntohl (hp->nitems); + else + nitems = hp->nitems; + + if (last_index == (u32) ~ 0) + { + last_index = nitems - 1; + } + + if (first_index >= nitems || last_index >= nitems) + { + vlib_cli_output (vm, "Range (%d, %d) outside file range (0, %d)\n", + first_index, last_index, nitems - 1); + munmap (hp, file_size); + return; + } + if (hp->wrapped) + vlib_cli_output (vm, + "Note: wrapped/incomplete trace, results may vary\n"); + + if (which == CUSTOM_DUMP) + { + saved_print_handlers = (void **) vec_dup (am->msg_print_handlers); + vl_msg_api_custom_dump_configure (am); + } + + + msg = (u8 *) (hp + 1); + + for (i = 0; i < first_index; i++) + { + trace_cfg_t *cfgp; + int size; + u16 msg_id; + + size = clib_host_to_net_u32 (*(u32 *) msg); + msg += sizeof (u32); + + if (clib_arch_is_little_endian) + msg_id = ntohs (*((u16 *) msg)); + else + msg_id = *((u16 *) msg); + + cfgp = am->api_trace_cfg + msg_id; + if (!cfgp) + { + vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); + munmap (hp, file_size); + return; + } + msg += size; + } + + if (which == REPLAY) + am->replay_in_progress = 1; + + for (; i <= last_index; i++) + { + trace_cfg_t *cfgp; + u16 *msg_idp; + u16 msg_id; + int size; + + if (which == DUMP) + vlib_cli_output (vm, "---------- trace %d -----------\n", i); + + size = clib_host_to_net_u32 (*(u32 *) msg); + msg += sizeof (u32); + + if (clib_arch_is_little_endian) + msg_id = ntohs (*((u16 *) msg)); + else + msg_id = *((u16 *) msg); + + cfgp = am->api_trace_cfg + msg_id; + if (!cfgp) + { + vlib_cli_output (vm, "Ugh: msg id %d no trace config\n", msg_id); + munmap (hp, file_size); + vec_free (tmpbuf); + am->replay_in_progress = 0; + return; + } + + /* Copy the buffer (from the read-only mmap'ed file) */ + vec_validate (tmpbuf, size - 1 + sizeof (uword)); + clib_memcpy (tmpbuf + sizeof (uword), msg, size); + memset (tmpbuf, 0xf, sizeof (uword)); + + /* + * Endian swap if needed. All msg data is supposed to be + * in network byte order. All msg handlers are supposed to + * know that. The generic message dumpers don't know that. + * One could fix apigen, I suppose. + */ + if ((which == DUMP && clib_arch_is_little_endian) || endian_swap_needed) + { + void (*endian_fp) (void *); + if (msg_id >= vec_len (am->msg_endian_handlers) + || (am->msg_endian_handlers[msg_id] == 0)) + { + vlib_cli_output (vm, "Ugh: msg id %d no endian swap\n", msg_id); + munmap (hp, file_size); + vec_free (tmpbuf); + am->replay_in_progress = 0; + return; + } + endian_fp = am->msg_endian_handlers[msg_id]; + (*endian_fp) (tmpbuf + sizeof (uword)); + } + + /* msg_id always in network byte order */ + if (clib_arch_is_little_endian) + { + msg_idp = (u16 *) (tmpbuf + sizeof (uword)); + *msg_idp = msg_id; + } + + switch (which) + { + case CUSTOM_DUMP: + case DUMP: + if (msg_id < vec_len (am->msg_print_handlers) && + am->msg_print_handlers[msg_id]) + { + u8 *(*print_fp) (void *, void *); + + print_fp = (void *) am->msg_print_handlers[msg_id]; + (*print_fp) (tmpbuf + sizeof (uword), vm); + } + else + { + vlib_cli_output (vm, "Skipping msg id %d: no print fcn\n", + msg_id); + break; + } + break; + + case INITIALIZERS: + if (msg_id < vec_len (am->msg_print_handlers) && + am->msg_print_handlers[msg_id]) + { + u8 *s; + int j; + u8 *(*print_fp) (void *, void *); + + print_fp = (void *) am->msg_print_handlers[msg_id]; + + vlib_cli_output (vm, "/*"); + + (*print_fp) (tmpbuf + sizeof (uword), vm); + vlib_cli_output (vm, "*/\n"); + + s = format (0, "static u8 * vl_api_%s_%d[%d] = {", + am->msg_names[msg_id], i, + am->api_trace_cfg[msg_id].size); + + for (j = 0; j < am->api_trace_cfg[msg_id].size; j++) + { + if ((j & 7) == 0) + s = format (s, "\n "); + s = format (s, "0x%02x,", tmpbuf[sizeof (uword) + j]); + } + s = format (s, "\n};\n%c", 0); + vlib_cli_output (vm, (char *) s); + vec_free (s); + } + break; + + case REPLAY: + if (msg_id < vec_len (am->msg_print_handlers) && + am->msg_print_handlers[msg_id] && cfgp->replay_enable) + { + void (*handler) (void *); + + handler = (void *) am->msg_handlers[msg_id]; + + if (!am->is_mp_safe[msg_id]) + vl_msg_api_barrier_sync (); + (*handler) (tmpbuf + sizeof (uword)); + if (!am->is_mp_safe[msg_id]) + vl_msg_api_barrier_release (); + } + else + { + if (cfgp->replay_enable) + vlib_cli_output (vm, "Skipping msg id %d: no handler\n", + msg_id); + break; + } + break; + } + + _vec_len (tmpbuf) = 0; + msg += size; + } + + if (saved_print_handlers) + { + clib_memcpy (am->msg_print_handlers, saved_print_handlers, + vec_len (am->msg_print_handlers) * sizeof (void *)); + vec_free (saved_print_handlers); + } + + munmap (hp, file_size); + vec_free (tmpbuf); + am->replay_in_progress = 0; +} + +static clib_error_t * +api_trace_command_fn (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cmd) +{ + u32 nitems = 256 << 10; + api_main_t *am = &api_main; + vl_api_trace_which_t which = VL_API_TRACE_RX; + u8 *filename; + u32 first = 0; + u32 last = (u32) ~ 0; + FILE *fp; + int rv; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "on") || unformat (input, "enable")) + { + if (unformat (input, "nitems %d", &nitems)) + ; + vl_msg_api_trace_configure (am, which, nitems); + vl_msg_api_trace_onoff (am, which, 1 /* on */ ); + } + else if (unformat (input, "off")) + { + vl_msg_api_trace_onoff (am, which, 0); + } + else if (unformat (input, "save %s", &filename)) + { + u8 *chroot_filename; + if (strstr ((char *) filename, "..") + || index ((char *) filename, '/')) + { + vlib_cli_output (vm, "illegal characters in filename '%s'", + filename); + return 0; + } + + chroot_filename = format (0, "/tmp/%s%c", filename, 0); + + vec_free (filename); + + fp = fopen ((char *) chroot_filename, "w"); + if (fp == NULL) + { + vlib_cli_output (vm, "Couldn't create %s\n", chroot_filename); + return 0; + } + rv = vl_msg_api_trace_save (am, which, fp); + fclose (fp); + if (rv == -1) + vlib_cli_output (vm, "API Trace data not present\n"); + else if (rv == -2) + vlib_cli_output (vm, "File for writing is closed\n"); + else if (rv == -10) + vlib_cli_output (vm, "Error while writing header to file\n"); + else if (rv == -11) + vlib_cli_output (vm, "Error while writing trace to file\n"); + else if (rv == -12) + vlib_cli_output (vm, + "Error while writing end of buffer trace to file\n"); + else if (rv == -13) + vlib_cli_output (vm, + "Error while writing start of buffer trace to file\n"); + else if (rv < 0) + vlib_cli_output (vm, "Unkown error while saving: %d", rv); + else + vlib_cli_output (vm, "API trace saved to %s\n", chroot_filename); + vec_free (chroot_filename); + } + else if (unformat (input, "dump %s", &filename)) + { + vl_msg_api_process_file (vm, filename, first, last, DUMP); + } + else if (unformat (input, "custom-dump %s", &filename)) + { + vl_msg_api_process_file (vm, filename, first, last, CUSTOM_DUMP); + } + else if (unformat (input, "replay %s", &filename)) + { + vl_msg_api_process_file (vm, filename, first, last, REPLAY); + } + else if (unformat (input, "initializers %s", &filename)) + { + vl_msg_api_process_file (vm, filename, first, last, INITIALIZERS); + } + else if (unformat (input, "tx")) + { + which = VL_API_TRACE_TX; + } + else if (unformat (input, "first %d", &first)) + { + ; + } + else if (unformat (input, "last %d", &last)) + { + ; + } + else if (unformat (input, "status")) + { + vlib_cli_output (vm, "%U", format_vl_msg_api_trace_status, + am, which); + } + else if (unformat (input, "free")) + { + vl_msg_api_trace_onoff (am, which, 0); + vl_msg_api_trace_free (am, which); + } + else if (unformat (input, "post-mortem-on")) + vl_msg_api_post_mortem_dump_enable_disable (1 /* enable */ ); + else if (unformat (input, "post-mortem-off")) + vl_msg_api_post_mortem_dump_enable_disable (0 /* enable */ ); + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + return 0; +} + +/*? + * Display, replay, or save a binary API trace +?*/ + +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (api_trace_command, static) = +{ + .path = "api trace", + .short_help = "api trace [on|off][first ][last ][status][free]" + "[post-mortem-on][dump|custom-dump|save|replay ]", + .function = api_trace_command_fn, +}; +/* *INDENT-ON* */ + +static clib_error_t * +vl_api_trace_command (vlib_main_t * vm, + unformat_input_t * input, vlib_cli_command_t * cli_cmd) +{ + u32 nitems = 1024; + vl_api_trace_which_t which = VL_API_TRACE_RX; + api_main_t *am = &api_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "rx nitems %u", &nitems) || unformat (input, "rx")) + goto configure; + else if (unformat (input, "tx nitems %u", &nitems) + || unformat (input, "tx")) + { + which = VL_API_TRACE_RX; + goto configure; + } + else if (unformat (input, "on rx")) + { + vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 1); + } + else if (unformat (input, "on tx")) + { + vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 1); + } + else if (unformat (input, "on")) + { + vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 1); + } + else if (unformat (input, "off")) + { + vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 0); + vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 0); + } + else if (unformat (input, "free")) + { + vl_msg_api_trace_onoff (am, VL_API_TRACE_RX, 0); + vl_msg_api_trace_onoff (am, VL_API_TRACE_TX, 0); + vl_msg_api_trace_free (am, VL_API_TRACE_RX); + vl_msg_api_trace_free (am, VL_API_TRACE_TX); + } + else if (unformat (input, "debug on")) + { + am->msg_print_flag = 1; + } + else if (unformat (input, "debug off")) + { + am->msg_print_flag = 0; + } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + return 0; + +configure: + if (vl_msg_api_trace_configure (am, which, nitems)) + { + vlib_cli_output (vm, "warning: trace configure error (%d, %d)", + which, nitems); + } + + return 0; +} + +/*? + * Control the binary API trace mechanism +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (trace, static) = +{ + .path = "set api-trace [on][on tx][on rx][off][free][debug on][debug off]", + .short_help = "API trace", + .function = vl_api_trace_command, +}; +/* *INDENT-ON* */ + +static clib_error_t * +api_trace_config_fn (vlib_main_t * vm, unformat_input_t * input) +{ + u32 nitems = 256 << 10; + vl_api_trace_which_t which = VL_API_TRACE_RX; + api_main_t *am = &api_main; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "on") || unformat (input, "enable")) + { + if (unformat (input, "nitems %d", &nitems)) + ; + vl_msg_api_trace_configure (am, which, nitems); + vl_msg_api_trace_onoff (am, which, 1 /* on */ ); + vl_msg_api_post_mortem_dump_enable_disable (1 /* enable */ ); + } + else if (unformat (input, "save-api-table %s", + &am->save_msg_table_filename)) + ; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + return 0; +} + +/*? + * This module has three configuration parameters: + * "on" or "enable" - enables binary api tracing + * "nitems " - sets the size of the circular buffer to + * "save-api-table " - dumps the API message table to /tmp/ +?*/ +VLIB_CONFIG_FUNCTION (api_trace_config_fn, "api-trace"); + +static clib_error_t * +api_queue_config_fn (vlib_main_t * vm, unformat_input_t * input) +{ + api_main_t *am = &api_main; + u32 nitems; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "length %d", &nitems) || + (unformat (input, "len %d", &nitems))) + { + if (nitems >= 1024) + am->vlib_input_queue_length = nitems; + else + clib_warning ("vlib input queue length %d too small, ignored", + nitems); + } + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + return 0; +} + +VLIB_CONFIG_FUNCTION (api_queue_config_fn, "api-queue"); + +static u8 * +extract_name (u8 * s) +{ + u8 *rv; + + rv = vec_dup (s); + + while (vec_len (rv) && rv[vec_len (rv)] != '_') + _vec_len (rv)--; + + rv[vec_len (rv)] = 0; + + return rv; +} + +static u8 * +extract_crc (u8 * s) +{ + int i; + u8 *rv; + + rv = vec_dup (s); + + for (i = vec_len (rv) - 1; i >= 0; i--) + { + if (rv[i] == '_') + { + vec_delete (rv, i + 1, 0); + break; + } + } + return rv; +} + +typedef struct +{ + u8 *name_and_crc; + u8 *name; + u8 *crc; + u32 msg_index; + int which; +} msg_table_unserialize_t; + +static int +table_id_cmp (void *a1, void *a2) +{ + msg_table_unserialize_t *n1 = a1; + msg_table_unserialize_t *n2 = a2; + + return (n1->msg_index - n2->msg_index); +} + +static int +table_name_and_crc_cmp (void *a1, void *a2) +{ + msg_table_unserialize_t *n1 = a1; + msg_table_unserialize_t *n2 = a2; + + return strcmp ((char *) n1->name_and_crc, (char *) n2->name_and_crc); +} + +static clib_error_t * +dump_api_table_file_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 *filename = 0; + api_main_t *am = &api_main; + serialize_main_t _sm, *sm = &_sm; + clib_error_t *error; + u32 nmsgs; + u32 msg_index; + u8 *name_and_crc; + int compare_current = 0; + int numeric_sort = 0; + msg_table_unserialize_t *table = 0, *item; + u32 i; + u32 ndifferences = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "file %s", &filename)) + ; + else if (unformat (input, "compare-current") + || unformat (input, "compare")) + compare_current = 1; + else if (unformat (input, "numeric")) + numeric_sort = 1; + else + return clib_error_return (0, "unknown input `%U'", + format_unformat_error, input); + } + + if (numeric_sort && compare_current) + return clib_error_return + (0, "Comparison and numeric sorting are incompatible"); + + if (filename == 0) + return clib_error_return (0, "File not specified"); + + /* Load the serialized message table from the table dump */ + + error = unserialize_open_clib_file (sm, (char *) filename); + + if (error) + return error; + + unserialize_integer (sm, &nmsgs, sizeof (u32)); + + for (i = 0; i < nmsgs; i++) + { + msg_index = unserialize_likely_small_unsigned_integer (sm); + unserialize_cstring (sm, (char **) &name_and_crc); + vec_add2 (table, item, 1); + item->msg_index = msg_index; + item->name_and_crc = name_and_crc; + item->name = extract_name (name_and_crc); + item->crc = extract_crc (name_and_crc); + item->which = 0; /* file */ + } + serialize_close (sm); + + /* Compare with the current image? */ + if (compare_current) + { + /* Append the current message table */ + u8 *tblv = vl_api_serialize_message_table (am, 0); + + serialize_open_vector (sm, tblv); + unserialize_integer (sm, &nmsgs, sizeof (u32)); + + for (i = 0; i < nmsgs; i++) + { + msg_index = unserialize_likely_small_unsigned_integer (sm); + unserialize_cstring (sm, (char **) &name_and_crc); + + vec_add2 (table, item, 1); + item->msg_index = msg_index; + item->name_and_crc = name_and_crc; + item->name = extract_name (name_and_crc); + item->crc = extract_crc (name_and_crc); + item->which = 1; /* current_image */ + } + vec_free (tblv); + } + + /* Sort the table. */ + if (numeric_sort) + vec_sort_with_function (table, table_id_cmp); + else + vec_sort_with_function (table, table_name_and_crc_cmp); + + if (compare_current) + { + ndifferences = 0; + + /* + * In this case, the recovered table will have two entries per + * API message. So, if entries i and i+1 match, the message definitions + * are identical. Otherwise, the crc is different, or a message is + * present in only one of the tables. + */ + vlib_cli_output (vm, "%=60s %s", "Message Name", "Result"); + + for (i = 0; i < vec_len (table);) + { + /* Last message lonely? */ + if (i == vec_len (table) - 1) + { + ndifferences++; + goto last_unique; + } + + /* Identical pair? */ + if (!strncmp + ((char *) table[i].name_and_crc, + (char *) table[i + 1].name_and_crc, + vec_len (table[i].name_and_crc))) + { + i += 2; + continue; + } + + ndifferences++; + + /* Only in one of two tables? */ + if (strncmp ((char *) table[i].name, (char *) table[i + 1].name, + vec_len (table[i].name))) + { + last_unique: + vlib_cli_output (vm, "%-60s only in %s", + table[i].name, table[i].which ? + "image" : "file"); + i++; + continue; + } + /* In both tables, but with different signatures */ + vlib_cli_output (vm, "%-60s definition changed", table[i].name); + i += 2; + } + if (ndifferences == 0) + vlib_cli_output (vm, "No api message signature differences found."); + else + vlib_cli_output (vm, "Found %u api message signature differences", + ndifferences); + goto cleanup; + } + + /* Dump the table, sorted as shown above */ + vlib_cli_output (vm, "%=60s %=8s %=10s", "Message name", "MsgID", "CRC"); + + for (i = 0; i < vec_len (table); i++) + { + item = table + i; + vlib_cli_output (vm, "%-60s %8u %10s", item->name, + item->msg_index, item->crc); + } + +cleanup: + for (i = 0; i < vec_len (table); i++) + { + vec_free (table[i].name_and_crc); + vec_free (table[i].name); + vec_free (table[i].crc); + } + + vec_free (table); + + return 0; +} + +/*? + * Displays a serialized API message decode table, sorted by message name + * + * @cliexpar + * @cliexstart{show api dump file } + * Message name MsgID CRC + * accept_session 407 8e2a127e + * accept_session_reply 408 67d8c22a + * add_node_next 549 e4202993 + * add_node_next_reply 550 e89d6eed + * etc. + * @cliexend +?*/ + +/*? + * Compares a serialized API message decode table with the current image + * + * @cliexpar + * @cliexstart{show api dump file compare} + * ip_add_del_route definition changed + * ip_table_add_del definition changed + * l2_macs_event only in image + * vnet_ip4_fib_counters only in file + * vnet_ip4_nbr_counters only in file + * @cliexend +?*/ + +/*? + * Display a serialized API message decode table, compare a saved + * decode table with the current image, to establish API differences. + * +?*/ +/* *INDENT-OFF* */ +VLIB_CLI_COMMAND (dump_api_table_file, static) = +{ + .path = "show api dump", + .short_help = "show api dump file [numeric | compare-current]", + .function = dump_api_table_file_command_fn, +}; + +/* *INDENT-ON* */ +/* + * fd.io coding-style-patch-verification: ON + * + * Local Variables: + * eval: (c-set-style "gnu") + * End: + */ diff --git a/src/vlibsocket/sockclnt_vlib.c b/src/vlibsocket/sockclnt_vlib.c index 0df32d527ed..34470c56266 100644 --- a/src/vlibsocket/sockclnt_vlib.c +++ b/src/vlibsocket/sockclnt_vlib.c @@ -65,7 +65,7 @@ vl_api_sockclnt_delete_reply_t_handler (vl_api_sockclnt_delete_reply_t * mp) vl_api_registration_t *rp = socket_main.current_rp; clib_file_del (fm, uf); - vl_free_socket_registration_index (rp->vl_api_registration_pool_index); + vl_socket_free_registration_index (rp->vl_api_registration_pool_index); } u32 @@ -143,7 +143,7 @@ sockclnt_open_index (char *client_name, char *hostname, int port) } strncpy ((char *) mp->name, my_hostname, sizeof (mp->name) - 1); - vl_msg_api_send (rp, (u8 *) mp); + vl_api_send_msg (rp, (u8 *) mp); return rp - socket_main.registration_pool; } @@ -165,7 +165,7 @@ sockclnt_close_index (u32 index) mp->_vl_msg_id = ntohs (VL_API_SOCKCLNT_DELETE); mp->handle = rp->server_handle; mp->index = rp->server_index; - vl_msg_api_send (rp, (u8 *) mp); + vl_api_send_msg (rp, (u8 *) mp); } vl_api_registration_t * diff --git a/src/vnet/bfd/bfd_api.c b/src/vnet/bfd/bfd_api.c index 185c03cf86f..0d5d1239626 100644 --- a/src/vnet/bfd/bfd_api.c +++ b/src/vnet/bfd/bfd_api.c @@ -140,7 +140,7 @@ vl_api_bfd_udp_del_t_handler (vl_api_bfd_udp_del_t * mp) } void -send_bfd_udp_session_details (unix_shared_memory_queue_t * q, u32 context, +send_bfd_udp_session_details (svm_queue_t * q, u32 context, bfd_session_t * bs) { if (bs->transport != BFD_TRANSPORT_UDP4 && @@ -199,7 +199,7 @@ bfd_event (bfd_main_t * bm, bfd_session_t * bs) { vpe_api_main_t *vam = &vpe_api_main; vpe_client_registration_t *reg; - unix_shared_memory_queue_t *q; + svm_queue_t *q; /* *INDENT-OFF* */ pool_foreach (reg, vam->bfd_events_registrations, ({ q = vl_api_client_index_to_input_queue (reg->client_index); @@ -220,7 +220,7 @@ bfd_event (bfd_main_t * bm, bfd_session_t * bs) static void vl_api_bfd_udp_session_dump_t_handler (vl_api_bfd_udp_session_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -274,7 +274,7 @@ vl_api_bfd_auth_del_key_t_handler (vl_api_bfd_auth_del_key_t * mp) static void vl_api_bfd_auth_keys_dump_t_handler (vl_api_bfd_auth_keys_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); diff --git a/src/vnet/bier/bier_api.c b/src/vnet/bier/bier_api.c index 3da6c192f1f..f4d37321c53 100644 --- a/src/vnet/bier/bier_api.c +++ b/src/vnet/bier/bier_api.c @@ -106,7 +106,7 @@ vl_api_bier_table_add_del_t_handler (vl_api_bier_table_add_del_t * mp) } static void -send_bier_table_details (unix_shared_memory_queue_t * q, +send_bier_table_details (svm_queue_t * q, u32 context, const bier_table_t *bt) { @@ -130,7 +130,7 @@ send_bier_table_details (unix_shared_memory_queue_t * q, static void vl_api_bier_table_dump_t_handler (vl_api_bier_table_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; bier_table_t *bt; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -252,7 +252,7 @@ done: typedef struct bier_route_details_walk_t_ { - unix_shared_memory_queue_t * q; + svm_queue_t * q; u32 context; } bier_route_details_walk_t; @@ -302,7 +302,7 @@ send_bier_route_details (const bier_table_t *bt, static void vl_api_bier_route_dump_t_handler (vl_api_bier_route_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -371,7 +371,7 @@ vl_api_bier_imp_del_t_handler (vl_api_bier_imp_del_t * mp) } static void -send_bier_imp_details (unix_shared_memory_queue_t * q, +send_bier_imp_details (svm_queue_t * q, u32 context, const bier_imp_t *bi) { @@ -406,7 +406,7 @@ send_bier_imp_details (unix_shared_memory_queue_t * q, static void vl_api_bier_imp_dump_t_handler (vl_api_bier_imp_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; bier_imp_t *bi; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -446,7 +446,7 @@ vl_api_bier_disp_table_add_del_t_handler (vl_api_bier_disp_table_add_del_t * mp) } static void -send_bier_disp_table_details (unix_shared_memory_queue_t * q, +send_bier_disp_table_details (svm_queue_t * q, u32 context, const bier_disp_table_t *bdt) { @@ -467,7 +467,7 @@ send_bier_disp_table_details (unix_shared_memory_queue_t * q, static void vl_api_bier_disp_table_dump_t_handler (vl_api_bier_disp_table_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; bier_disp_table_t *bdt; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -603,7 +603,7 @@ done: typedef struct bier_disp_entry_details_walk_t_ { - unix_shared_memory_queue_t * q; + svm_queue_t * q; u32 context; } bier_disp_entry_details_walk_t; @@ -661,7 +661,7 @@ send_bier_disp_entry_details (const bier_disp_table_t *bdt, static void vl_api_bier_disp_entry_dump_t_handler (vl_api_bier_disp_entry_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) diff --git a/src/vnet/classify/classify_api.c b/src/vnet/classify/classify_api.c index d314ddeaafd..94340f8729a 100644 --- a/src/vnet/classify/classify_api.c +++ b/src/vnet/classify/classify_api.c @@ -182,8 +182,7 @@ static void static void send_policer_classify_details (u32 sw_if_index, - u32 table_index, - unix_shared_memory_queue_t * q, u32 context) + u32 table_index, svm_queue_t * q, u32 context) { vl_api_policer_classify_details_t *mp; @@ -200,7 +199,7 @@ send_policer_classify_details (u32 sw_if_index, static void vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; policer_classify_main_t *pcm = &policer_classify_main; u32 *vec_tbl; int i; @@ -227,7 +226,7 @@ vl_api_policer_classify_dump_t_handler (vl_api_policer_classify_dump_t * mp) static void vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -312,7 +311,7 @@ static void static void vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -360,7 +359,7 @@ vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t * mp) } static void -send_classify_session_details (unix_shared_memory_queue_t * q, +send_classify_session_details (svm_queue_t * q, u32 table_id, u32 match_length, vnet_classify_entry_t * e, u32 context) @@ -385,7 +384,7 @@ static void vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump_t * mp) { vnet_classify_main_t *cm = &vnet_classify_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 table_id = ntohl (mp->table_id); vnet_classify_table_t *t; @@ -456,8 +455,7 @@ static void static void send_flow_classify_details (u32 sw_if_index, - u32 table_index, - unix_shared_memory_queue_t * q, u32 context) + u32 table_index, svm_queue_t * q, u32 context) { vl_api_flow_classify_details_t *mp; @@ -474,7 +472,7 @@ send_flow_classify_details (u32 sw_if_index, static void vl_api_flow_classify_dump_t_handler (vl_api_flow_classify_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; flow_classify_main_t *pcm = &flow_classify_main; u32 *vec_tbl; int i; diff --git a/src/vnet/devices/ssvm/node.c b/src/vnet/devices/ssvm/node.c index b7a8db0528c..344b357662c 100644 --- a/src/vnet/devices/ssvm/node.c +++ b/src/vnet/devices/ssvm/node.c @@ -70,7 +70,7 @@ ssvm_eth_device_input (ssvm_eth_main_t * em, { ssvm_shared_header_t *sh = intfc->sh; vlib_main_t *vm = em->vlib_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; ssvm_eth_queue_elt_t *elt, *elts; u32 elt_index; u32 my_pid = intfc->my_pid; @@ -101,9 +101,9 @@ ssvm_eth_device_input (ssvm_eth_main_t * em, return 0; if (intfc->i_am_master) - q = (unix_shared_memory_queue_t *) (sh->opaque[TO_MASTER_Q_INDEX]); + q = (svm_queue_t *) (sh->opaque[TO_MASTER_Q_INDEX]); else - q = (unix_shared_memory_queue_t *) (sh->opaque[TO_SLAVE_Q_INDEX]); + q = (svm_queue_t *) (sh->opaque[TO_SLAVE_Q_INDEX]); /* Nothing to do? */ if (q->cursize == 0) @@ -118,7 +118,7 @@ ssvm_eth_device_input (ssvm_eth_main_t * em, ; while (q->cursize > 0) { - unix_shared_memory_queue_sub_raw (q, (u8 *) & elt_index); + svm_queue_sub_raw (q, (u8 *) & elt_index); ASSERT (elt_index < 2048); vec_add1 (intfc->rx_queue, elt_index); } diff --git a/src/vnet/devices/ssvm/ssvm_eth.c b/src/vnet/devices/ssvm/ssvm_eth.c index db4fafa9a14..8a0cebe29d4 100644 --- a/src/vnet/devices/ssvm/ssvm_eth.c +++ b/src/vnet/devices/ssvm/ssvm_eth.c @@ -38,7 +38,7 @@ ssvm_eth_create (ssvm_eth_main_t * em, u8 * name, int is_master) ssvm_private_t *intfc; void *oldheap; clib_error_t *e; - unix_shared_memory_queue_t *q; + svm_queue_t *q; ssvm_shared_header_t *sh; ssvm_eth_queue_elt_t *elts; u32 *elt_indices; @@ -71,13 +71,13 @@ ssvm_eth_create (ssvm_eth_main_t * em, u8 * name, int is_master) sh = intfc->sh; oldheap = ssvm_push_heap (sh); - q = unix_shared_memory_queue_init (em->queue_elts, sizeof (u32), - 0 /* consumer pid not interesting */ , - 0 /* signal not sent */ ); + q = svm_queue_init (em->queue_elts, sizeof (u32), + 0 /* consumer pid not interesting */ , + 0 /* signal not sent */ ); sh->opaque[TO_MASTER_Q_INDEX] = (void *) q; - q = unix_shared_memory_queue_init (em->queue_elts, sizeof (u32), - 0 /* consumer pid not interesting */ , - 0 /* signal not sent */ ); + q = svm_queue_init (em->queue_elts, sizeof (u32), + 0 /* consumer pid not interesting */ , + 0 /* signal not sent */ ); sh->opaque[TO_SLAVE_Q_INDEX] = (void *) q; /* @@ -246,7 +246,7 @@ ssvm_eth_interface_tx (vlib_main_t * vm, vnet_interface_output_runtime_t *rd = (void *) node->runtime_data; ssvm_private_t *intfc = vec_elt_at_index (em->intfcs, rd->dev_instance); ssvm_shared_header_t *sh = intfc->sh; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 *from; u32 n_left; ssvm_eth_queue_elt_t *elts, *elt, *prev_elt; @@ -265,9 +265,9 @@ ssvm_eth_interface_tx (vlib_main_t * vm, u32 *elt_indices; if (i_am_master) - q = (unix_shared_memory_queue_t *) sh->opaque[TO_SLAVE_Q_INDEX]; + q = (svm_queue_t *) sh->opaque[TO_SLAVE_Q_INDEX]; else - q = (unix_shared_memory_queue_t *) sh->opaque[TO_MASTER_Q_INDEX]; + q = (svm_queue_t *) sh->opaque[TO_MASTER_Q_INDEX]; queue_lock = (u32 *) q; @@ -366,7 +366,7 @@ ssvm_eth_interface_tx (vlib_main_t * vm, while (__sync_lock_test_and_set (queue_lock, 1)) ; - unix_shared_memory_queue_add_raw (q, (u8 *) & elt_index); + svm_queue_add_raw (q, (u8 *) & elt_index); CLIB_MEMORY_BARRIER (); *queue_lock = 0; diff --git a/src/vnet/devices/ssvm/ssvm_eth.h b/src/vnet/devices/ssvm/ssvm_eth.h index 7f9aaad3e82..a506b4b7312 100644 --- a/src/vnet/devices/ssvm/ssvm_eth.h +++ b/src/vnet/devices/ssvm/ssvm_eth.h @@ -28,9 +28,8 @@ #include #include #include -#include - #include +#include extern vnet_device_class_t ssvm_eth_device_class; extern vlib_node_registration_t ssvm_eth_input_node; diff --git a/src/vnet/devices/tap/tapv2_api.c b/src/vnet/devices/tap/tapv2_api.c index 841d21e2d25..e161ed6c397 100644 --- a/src/vnet/devices/tap/tapv2_api.c +++ b/src/vnet/devices/tap/tapv2_api.c @@ -54,7 +54,7 @@ vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp) { vlib_main_t *vm = vlib_get_main (); vl_api_tap_create_v2_reply_t *rmp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; tap_create_if_args_t _a, *ap = &_a; memset (ap, 0, sizeof (*ap)); @@ -113,8 +113,7 @@ vl_api_tap_create_v2_t_handler (vl_api_tap_create_v2_t * mp) static void tap_send_sw_interface_event_deleted (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - u32 sw_if_index) + svm_queue_t * q, u32 sw_if_index) { vl_api_sw_interface_event_t *mp; @@ -136,7 +135,7 @@ vl_api_tap_delete_v2_t_handler (vl_api_tap_delete_v2_t * mp) int rv; vpe_api_main_t *vam = &vpe_api_main; vl_api_tap_delete_v2_reply_t *rmp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 sw_if_index = ntohl (mp->sw_if_index); rv = tap_delete_if (vm, sw_if_index); @@ -158,7 +157,7 @@ vl_api_tap_delete_v2_t_handler (vl_api_tap_delete_v2_t * mp) static void tap_send_sw_interface_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, tap_interface_details_t * tap_if, u32 context) { vl_api_sw_interface_tap_v2_details_t *mp; @@ -199,7 +198,7 @@ vl_api_sw_interface_tap_v2_dump_t_handler (vl_api_sw_interface_tap_v2_dump_t * { int rv; vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; tap_interface_details_t *tapifs = NULL; tap_interface_details_t *tap_if = NULL; diff --git a/src/vnet/devices/virtio/vhost_user_api.c b/src/vnet/devices/virtio/vhost_user_api.c index 78599241d3e..9ddd3387a72 100644 --- a/src/vnet/devices/virtio/vhost_user_api.c +++ b/src/vnet/devices/virtio/vhost_user_api.c @@ -53,8 +53,7 @@ _(SW_INTERFACE_VHOST_USER_DUMP, sw_interface_vhost_user_dump) */ static void send_sw_interface_event_deleted (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - u32 sw_if_index) + svm_queue_t * q, u32 sw_if_index) { vl_api_sw_interface_event_t *mp; @@ -137,8 +136,7 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp) REPLY_MACRO (VL_API_DELETE_VHOST_USER_IF_REPLY); if (!rv) { - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); + svm_queue_t *q = vl_api_client_index_to_input_queue (mp->client_index); if (!q) return; @@ -149,7 +147,7 @@ vl_api_delete_vhost_user_if_t_handler (vl_api_delete_vhost_user_if_t * mp) static void send_sw_interface_vhost_user_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, vhost_user_intf_details_t * vui, u32 context) { @@ -184,7 +182,7 @@ static void vlib_main_t *vm = vlib_get_main (); vhost_user_intf_details_t *ifaces = NULL; vhost_user_intf_details_t *vuid = NULL; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) diff --git a/src/vnet/dhcp/dhcp_api.c b/src/vnet/dhcp/dhcp_api.c index ad96e027f57..24411af9b5c 100644 --- a/src/vnet/dhcp/dhcp_api.c +++ b/src/vnet/dhcp/dhcp_api.c @@ -110,7 +110,7 @@ static void vl_api_dhcp_proxy_config_t_handler static void vl_api_dhcp_proxy_dump_t_handler (vl_api_dhcp_proxy_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -125,7 +125,7 @@ dhcp_send_details (fib_protocol_t proto, void *opaque, u32 context, dhcp_proxy_t * proxy) { vl_api_dhcp_proxy_details_t *mp; - unix_shared_memory_queue_t *q = opaque; + svm_queue_t *q = opaque; vl_api_dhcp_server_t *v_server; dhcp_server_t *server; fib_table_t *s_fib; @@ -208,7 +208,7 @@ dhcp_compl_event_callback (u32 client_index, u32 pid, u8 * hostname, u8 mask_width, u8 is_ipv6, u8 * host_address, u8 * router_address, u8 * host_mac) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vl_api_dhcp_compl_event_t *mp; u32 len; diff --git a/src/vnet/dns/resolver_process.c b/src/vnet/dns/resolver_process.c index 23bbd3bd7bb..47d8a95ea16 100644 --- a/src/vnet/dns/resolver_process.c +++ b/src/vnet/dns/resolver_process.c @@ -124,7 +124,7 @@ resolve_event (dns_main_t * dm, f64 now, u8 * reply) if (min_ttl != ~0) ep->expiration_time = now + min_ttl; rmp->retval = clib_host_to_net_u32 (rv); - vl_msg_api_send (regp, (u8 *) rmp); + vl_api_send_msg (regp, (u8 *) rmp); } break; @@ -145,7 +145,7 @@ resolve_event (dns_main_t * dm, f64 now, u8 * reply) if (min_ttl != ~0) ep->expiration_time = now + min_ttl; rmp->retval = clib_host_to_net_u32 (rv); - vl_msg_api_send (regp, (u8 *) rmp); + vl_api_send_msg (regp, (u8 *) rmp); } break; diff --git a/src/vnet/flow/flow_api.c b/src/vnet/flow/flow_api.c index 52a608ca6e7..4aa025314f7 100644 --- a/src/vnet/flow/flow_api.c +++ b/src/vnet/flow/flow_api.c @@ -148,7 +148,7 @@ static void vl_api_ipfix_exporter_dump_t_handler (vl_api_ipfix_exporter_dump_t * mp) { flow_report_main_t *frm = &flow_report_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; vl_api_ipfix_exporter_details_t *rmp; ip4_main_t *im = &ip4_main; u32 vrf_id; @@ -211,7 +211,7 @@ static void (vl_api_ipfix_classify_stream_dump_t * mp) { flow_report_classify_main_t *fcm = &flow_report_classify_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; vl_api_ipfix_classify_stream_details_t *rmp; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -308,8 +308,7 @@ out: static void send_ipfix_classify_table_details (u32 table_index, - unix_shared_memory_queue_t * q, - u32 context) + svm_queue_t * q, u32 context) { flow_report_classify_main_t *fcm = &flow_report_classify_main; vl_api_ipfix_classify_table_details_t *mp; @@ -332,7 +331,7 @@ static void (vl_api_ipfix_classify_table_dump_t * mp) { flow_report_classify_main_t *fcm = &flow_report_classify_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 i; q = vl_api_client_index_to_input_queue (mp->client_index); diff --git a/src/vnet/geneve/geneve_api.c b/src/vnet/geneve/geneve_api.c index 1239bfc24c0..2708d15f99e 100644 --- a/src/vnet/geneve/geneve_api.c +++ b/src/vnet/geneve/geneve_api.c @@ -113,7 +113,7 @@ out: } static void send_geneve_tunnel_details - (geneve_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (geneve_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_geneve_tunnel_details_t *rmp; ip4_main_t *im4 = &ip4_main; @@ -148,7 +148,7 @@ static void send_geneve_tunnel_details static void vl_api_geneve_tunnel_dump_t_handler (vl_api_geneve_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; geneve_main_t *vxm = &geneve_main; geneve_tunnel_t *t; u32 sw_if_index; diff --git a/src/vnet/gre/gre_api.c b/src/vnet/gre/gre_api.c index bcf01e2153f..baccc5fa601 100644 --- a/src/vnet/gre/gre_api.c +++ b/src/vnet/gre/gre_api.c @@ -94,7 +94,7 @@ out: } static void send_gre_tunnel_details - (gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (gre_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_gre_tunnel_details_t *rmp; u8 is_ipv6 = t->tunnel_dst.fp_proto == FIB_PROTOCOL_IP6 ? 1 : 0; @@ -128,7 +128,7 @@ static void send_gre_tunnel_details static void vl_api_gre_tunnel_dump_t_handler (vl_api_gre_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; gre_main_t *gm = &gre_main; gre_tunnel_t *t; u32 sw_if_index; diff --git a/src/vnet/interface_api.c b/src/vnet/interface_api.c index 09f9b3fc178..d3f170ff94b 100644 --- a/src/vnet/interface_api.c +++ b/src/vnet/interface_api.c @@ -241,7 +241,7 @@ send_sw_interface_details (vpe_api_main_t * am, if (tag) strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); - vl_msg_api_send (rp, (u8 *) mp); + vl_api_send_msg (rp, (u8 *) mp); } static void @@ -529,7 +529,7 @@ ip_table_bind (fib_protocol_t fproto, } static void -send_sw_interface_get_table_reply (unix_shared_memory_queue_t * q, +send_sw_interface_get_table_reply (svm_queue_t * q, u32 context, int retval, u32 vrf_id) { vl_api_sw_interface_get_table_reply_t *mp; @@ -547,7 +547,7 @@ send_sw_interface_get_table_reply (unix_shared_memory_queue_t * q, static void vl_api_sw_interface_get_table_t_handler (vl_api_sw_interface_get_table_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; fib_table_t *fib_table = 0; u32 sw_if_index = ~0; u32 fib_index = ~0; @@ -724,8 +724,7 @@ event_data_cmp (void *a1, void *a2) static void send_sw_interface_event (vpe_api_main_t * am, vpe_client_registration_t * reg, - unix_shared_memory_queue_t * q, - vnet_sw_interface_t * swif) + svm_queue_t * q, vnet_sw_interface_t * swif) { vl_api_sw_interface_event_t *mp; vnet_main_t *vnm = am->vnet_main; @@ -755,7 +754,7 @@ link_state_process (vlib_main_t * vm, vpe_client_registration_t *reg; int i; u32 prev_sw_if_index; - unix_shared_memory_queue_t *q; + svm_queue_t *q; vam->link_state_process_up = 1; @@ -949,7 +948,7 @@ vl_api_create_vlan_subif_t_handler (vl_api_create_vlan_subif_t * mp) uword *p; vnet_interface_main_t *im = &vnm->interface_main; u64 sup_and_sub_key; - unix_shared_memory_queue_t *q; + svm_queue_t *q; clib_error_t *error; VALIDATE_SW_IF_INDEX (mp); diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index 599a66b3672..d0982e94f9e 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -107,8 +107,7 @@ send_ip_neighbor_details (u32 sw_if_index, u8 is_ipv6, u8 is_static, u8 * mac_address, - u8 * ip_address, - unix_shared_memory_queue_t * q, u32 context) + u8 * ip_address, svm_queue_t * q, u32 context) { vl_api_ip_neighbor_details_t *mp; @@ -128,7 +127,7 @@ send_ip_neighbor_details (u32 sw_if_index, static void vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -202,7 +201,7 @@ copy_fib_next_hop (fib_route_path_encode_t * api_rpath, void *fp_arg) static void send_ip_fib_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, const fib_table_t * table, const fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) @@ -287,7 +286,7 @@ static void vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip4_main_t *im = &ip4_main; fib_table_t *fib_table; fib_node_index_t *lfeip; @@ -330,7 +329,7 @@ vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) static void send_ip6_fib_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, const fib_table_t * table, const fib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) @@ -414,7 +413,7 @@ api_ip6_fib_table_put_entries (clib_bihash_kv_24_8_t * kvp, void *arg) } static void -api_ip6_fib_table_get_all (unix_shared_memory_queue_t * q, +api_ip6_fib_table_get_all (svm_queue_t * q, vl_api_ip6_fib_dump_t * mp, fib_table_t * fib_table) { @@ -449,7 +448,7 @@ api_ip6_fib_table_get_all (unix_shared_memory_queue_t * q, static void vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip6_main_t *im6 = &ip6_main; fib_table_t *fib_table; @@ -466,7 +465,7 @@ vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) } static void -send_ip_mfib_details (unix_shared_memory_queue_t * q, +send_ip_mfib_details (svm_queue_t * q, u32 context, u32 table_id, fib_node_index_t mfei) { fib_route_path_encode_t *api_rpath, *api_rpaths = NULL; @@ -531,7 +530,7 @@ vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg) static void vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip4_main_t *im = &ip4_main; mfib_table_t *mfib_table; fib_node_index_t *mfeip; @@ -569,7 +568,7 @@ vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) static void send_ip6_mfib_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, u32 table_id, mfib_prefix_t * pfx, fib_route_path_encode_t * api_rpaths, u32 context) @@ -628,7 +627,7 @@ static void vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip6_main_t *im = &ip6_main; mfib_table_t *mfib_table; fib_node_index_t *mfeip; @@ -1419,8 +1418,7 @@ vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp) static void send_ip_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, u32 sw_if_index, - u8 is_ipv6, u32 context) + svm_queue_t * q, u32 sw_if_index, u8 is_ipv6, u32 context) { vl_api_ip_details_t *mp; @@ -1437,7 +1435,7 @@ send_ip_details (vpe_api_main_t * am, static void send_ip_address_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, u8 * ip, u16 prefix_length, u32 sw_if_index, u8 is_ipv6, u32 context) { @@ -1468,7 +1466,7 @@ static void vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip6_address_t *r6; ip4_address_t *r4; ip6_main_t *im6 = &ip6_main; @@ -1523,7 +1521,7 @@ vl_api_ip_dump_t_handler (vl_api_ip_dump_t * mp) vnet_main_t *vnm = vnet_get_main (); vlib_main_t *vm = vlib_get_main (); vnet_interface_main_t *im = &vnm->interface_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; vnet_sw_interface_t *si, *sorted_sis; u32 sw_if_index = ~0; @@ -1670,7 +1668,7 @@ static void } static void -send_ip6nd_proxy_details (unix_shared_memory_queue_t * q, +send_ip6nd_proxy_details (svm_queue_t * q, u32 context, const ip46_address_t * addr, u32 sw_if_index) { @@ -1714,7 +1712,7 @@ vl_api_ip6nd_proxy_dump_t_handler (vl_api_ip6nd_proxy_dump_t * mp) }; fib_node_index_t *feip; fib_prefix_t pfx; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -1829,7 +1827,7 @@ static void } void -vl_mfib_signal_send_one (unix_shared_memory_queue_t * q, +vl_mfib_signal_send_one (svm_queue_t * q, u32 context, const mfib_signal_t * mfs) { vl_api_mfib_signal_details_t *mp; @@ -1884,7 +1882,7 @@ vl_mfib_signal_send_one (unix_shared_memory_queue_t * q, static void vl_api_mfib_signal_dump_t_handler (vl_api_mfib_signal_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -2112,7 +2110,7 @@ handle_ip4_arp_event (u32 pool_index) vlib_main_t *vm = vam->vlib_main; vl_api_ip4_arp_event_t *event; vl_api_ip4_arp_event_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; /* Client can cancel, die, etc. */ if (pool_is_free_index (vam->arp_events, pool_index)) @@ -2161,7 +2159,7 @@ handle_ip6_nd_event (u32 pool_index) vlib_main_t *vm = vam->vlib_main; vl_api_ip6_nd_event_t *event; vl_api_ip6_nd_event_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; /* Client can cancel, die, etc. */ if (pool_is_free_index (vam->nd_events, pool_index)) @@ -2336,7 +2334,7 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) /* *INDENT-OFF* */ pool_foreach(reg, vpe_api_main.wc_ip4_arp_events_registrations, ({ - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (reg->client_index); if (q && q->cursize < q->maxsize) { @@ -2375,7 +2373,7 @@ wc_arp_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f) /* *INDENT-OFF* */ pool_foreach(reg, vpe_api_main.wc_ip6_nd_events_registrations, ({ - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (reg->client_index); if (q && q->cursize < q->maxsize) { diff --git a/src/vnet/ip/punt_api.c b/src/vnet/ip/punt_api.c index 6e6dee2457e..33fc3f931a7 100644 --- a/src/vnet/ip/punt_api.c +++ b/src/vnet/ip/punt_api.c @@ -70,7 +70,7 @@ vl_api_punt_socket_register_t_handler (vl_api_punt_socket_register_t * mp) vlib_main_t *vm = vlib_get_main (); int rv = 0; clib_error_t *error; - unix_shared_memory_queue_t *q; + svm_queue_t *q; error = vnet_punt_socket_add (vm, ntohl (mp->header_version), mp->is_ip4, mp->l4_protocol, @@ -102,7 +102,7 @@ vl_api_punt_socket_deregister_t_handler (vl_api_punt_socket_deregister_t * mp) vlib_main_t *vm = vlib_get_main (); int rv = 0; clib_error_t *error; - unix_shared_memory_queue_t *q; + svm_queue_t *q; error = vnet_punt_socket_del (vm, mp->is_ip4, mp->l4_protocol, ntohs (mp->l4_port)); diff --git a/src/vnet/ipsec-gre/ipsec_gre_api.c b/src/vnet/ipsec-gre/ipsec_gre_api.c index a7ea1490bae..af3003004b9 100644 --- a/src/vnet/ipsec-gre/ipsec_gre_api.c +++ b/src/vnet/ipsec-gre/ipsec_gre_api.c @@ -83,7 +83,7 @@ out: } static void send_ipsec_gre_tunnel_details - (ipsec_gre_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (ipsec_gre_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_ipsec_gre_tunnel_details_t *rmp; @@ -103,7 +103,7 @@ static void send_ipsec_gre_tunnel_details static void vl_api_ipsec_gre_tunnel_dump_t_handler (vl_api_ipsec_gre_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ipsec_gre_main_t *igm = &ipsec_gre_main; ipsec_gre_tunnel_t *t; u32 sw_if_index; diff --git a/src/vnet/ipsec/ipsec_api.c b/src/vnet/ipsec/ipsec_api.c index 5fbf86bb7e3..361bddbc8d0 100644 --- a/src/vnet/ipsec/ipsec_api.c +++ b/src/vnet/ipsec/ipsec_api.c @@ -252,8 +252,7 @@ out: } static void -send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q, - u32 context) +send_ipsec_spd_details (ipsec_policy_t * p, svm_queue_t * q, u32 context) { vl_api_ipsec_spd_details_t *mp; @@ -296,7 +295,7 @@ send_ipsec_spd_details (ipsec_policy_t * p, unix_shared_memory_queue_t * q, static void vl_api_ipsec_spd_dump_t_handler (vl_api_ipsec_spd_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ipsec_main_t *im = &ipsec_main; ipsec_policy_t *policy; ipsec_spd_t *spd; @@ -400,7 +399,7 @@ vl_api_ipsec_tunnel_if_add_del_t_handler (vl_api_ipsec_tunnel_if_add_del_t * } static void -send_ipsec_sa_details (ipsec_sa_t * sa, unix_shared_memory_queue_t * q, +send_ipsec_sa_details (ipsec_sa_t * sa, svm_queue_t * q, u32 context, u32 sw_if_index) { vl_api_ipsec_sa_details_t *mp; @@ -463,7 +462,7 @@ send_ipsec_sa_details (ipsec_sa_t * sa, unix_shared_memory_queue_t * q, static void vl_api_ipsec_sa_dump_t_handler (vl_api_ipsec_sa_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ipsec_main_t *im = &ipsec_main; vnet_main_t *vnm = im->vnet_main; ipsec_sa_t *sa; diff --git a/src/vnet/l2/l2_api.c b/src/vnet/l2/l2_api.c index f62bad14b00..206b41f142c 100644 --- a/src/vnet/l2/l2_api.c +++ b/src/vnet/l2/l2_api.c @@ -72,7 +72,7 @@ _(BRIDGE_DOMAIN_SET_MAC_AGE, bridge_domain_set_mac_age) \ _(SW_INTERFACE_SET_VPATH, sw_interface_set_vpath) static void -send_l2_xconnect_details (unix_shared_memory_queue_t * q, u32 context, +send_l2_xconnect_details (svm_queue_t * q, u32 context, u32 rx_sw_if_index, u32 tx_sw_if_index) { vl_api_l2_xconnect_details_t *mp; @@ -90,7 +90,7 @@ send_l2_xconnect_details (unix_shared_memory_queue_t * q, u32 context, static void vl_api_l2_xconnect_dump_t_handler (vl_api_l2_xconnect_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vnet_main_t *vnm = vnet_get_main (); vnet_interface_main_t *im = &vnm->interface_main; l2input_main_t *l2im = &l2input_main; @@ -126,7 +126,7 @@ vl_api_l2_fib_clear_table_t_handler (vl_api_l2_fib_clear_table_t * mp) static void send_l2fib_table_entry (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, l2fib_entry_key_t * l2fe_key, l2fib_entry_result_t * l2fe_res, u32 context) { @@ -158,7 +158,7 @@ vl_api_l2_fib_table_dump_t_handler (vl_api_l2_fib_table_dump_t * mp) l2fib_entry_result_t *l2fe_res = NULL; u32 ni, bd_id = ntohl (mp->bd_id); u32 bd_index; - unix_shared_memory_queue_t *q; + svm_queue_t *q; uword *p; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -439,7 +439,7 @@ vl_api_bridge_domain_add_del_t_handler (vl_api_bridge_domain_add_del_t * mp) static void send_bridge_domain_details (l2input_main_t * l2im, - unix_shared_memory_queue_t * q, + svm_queue_t * q, l2_bridge_domain_t * bd_config, u32 n_sw_ifs, u32 context) { @@ -489,8 +489,7 @@ vl_api_bridge_domain_dump_t_handler (vl_api_bridge_domain_dump_t * mp) bd_main_t *bdm = &bd_main; l2input_main_t *l2im = &l2input_main; - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); + svm_queue_t *q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) return; diff --git a/src/vnet/l2/l2_fib.c b/src/vnet/l2/l2_fib.c index 4a784470049..66bb8e3f3c7 100644 --- a/src/vnet/l2/l2_fib.c +++ b/src/vnet/l2/l2_fib.c @@ -962,7 +962,7 @@ l2fib_scan (vlib_main_t * vm, f64 start_time, u8 event_only) u32 client = lm->client_pid; u32 cl_idx = lm->client_index; vl_api_l2_macs_event_t *mp = 0; - unix_shared_memory_queue_t *q = 0; + svm_queue_t *q = 0; if (client) { diff --git a/src/vnet/l2tp/l2tp_api.c b/src/vnet/l2tp/l2tp_api.c index 88d758c9ff0..aaba2b04e19 100644 --- a/src/vnet/l2tp/l2tp_api.c +++ b/src/vnet/l2tp/l2tp_api.c @@ -51,7 +51,7 @@ _(SW_IF_L2TPV3_TUNNEL_DUMP, sw_if_l2tpv3_tunnel_dump) static void send_sw_if_l2tpv3_tunnel_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, l2t_session_t * s, l2t_main_t * lm, u32 context) { @@ -91,7 +91,7 @@ vl_api_sw_if_l2tpv3_tunnel_dump_t_handler (vl_api_sw_if_l2tpv3_tunnel_dump_t * { vpe_api_main_t *am = &vpe_api_main; l2t_main_t *lm = &l2t_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; l2t_session_t *session; q = vl_api_client_index_to_input_queue (mp->client_index); diff --git a/src/vnet/lisp-cp/lisp_api.c b/src/vnet/lisp-cp/lisp_api.c index f1b68d477ae..9946f28f131 100644 --- a/src/vnet/lisp-cp/lisp_api.c +++ b/src/vnet/lisp-cp/lisp_api.c @@ -420,7 +420,7 @@ vl_api_lisp_use_petr_t_handler (vl_api_lisp_use_petr_t * mp) static void vl_api_show_lisp_use_petr_t_handler (vl_api_show_lisp_use_petr_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_lisp_use_petr_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; @@ -583,8 +583,7 @@ send_reply: static void send_lisp_locator_details (lisp_cp_main_t * lcm, - locator_t * loc, - unix_shared_memory_queue_t * q, u32 context) + locator_t * loc, svm_queue_t * q, u32 context) { vl_api_lisp_locator_details_t *rmp; @@ -613,7 +612,7 @@ static void vl_api_lisp_locator_dump_t_handler (vl_api_lisp_locator_dump_t * mp) { u8 *ls_name = 0; - unix_shared_memory_queue_t *q = 0; + svm_queue_t *q = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = 0; locator_t *loc = 0; @@ -657,8 +656,7 @@ out: static void send_lisp_locator_set_details (lisp_cp_main_t * lcm, locator_set_t * lsit, - unix_shared_memory_queue_t * q, - u32 context, u32 ls_index) + svm_queue_t * q, u32 context, u32 ls_index) { vl_api_lisp_locator_set_details_t *rmp; u8 *str = 0; @@ -688,7 +686,7 @@ send_lisp_locator_set_details (lisp_cp_main_t * lcm, static void vl_api_lisp_locator_set_dump_t_handler (vl_api_lisp_locator_set_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = NULL; u8 filter; @@ -768,8 +766,7 @@ fid_type_to_api_type (fid_address_t * fid) static void send_lisp_eid_table_details (mapping_t * mapit, - unix_shared_memory_queue_t * q, - u32 context, u8 filter) + svm_queue_t * q, u32 context, u8 filter) { fid_address_t *fid; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); @@ -864,7 +861,7 @@ static void vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp) { u32 mi; - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *mapit = NULL; gid_address_t _eid, *eid = &_eid; @@ -903,8 +900,7 @@ vl_api_lisp_eid_table_dump_t_handler (vl_api_lisp_eid_table_dump_t * mp) } static void -send_lisp_map_server_details (ip_address_t * ip, - unix_shared_memory_queue_t * q, u32 context) +send_lisp_map_server_details (ip_address_t * ip, svm_queue_t * q, u32 context) { vl_api_lisp_map_server_details_t *rmp = NULL; @@ -937,7 +933,7 @@ send_lisp_map_server_details (ip_address_t * ip, static void vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); lisp_msmr_t *mr; @@ -955,7 +951,7 @@ vl_api_lisp_map_server_dump_t_handler (vl_api_lisp_map_server_dump_t * mp) static void send_lisp_map_resolver_details (ip_address_t * ip, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_lisp_map_resolver_details_t *rmp = NULL; @@ -988,7 +984,7 @@ send_lisp_map_resolver_details (ip_address_t * ip, static void vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); lisp_msmr_t *mr; @@ -1005,8 +1001,7 @@ vl_api_lisp_map_resolver_dump_t_handler (vl_api_lisp_map_resolver_dump_t * mp) } static void -send_eid_table_map_pair (hash_pair_t * p, - unix_shared_memory_queue_t * q, u32 context) +send_eid_table_map_pair (hash_pair_t * p, svm_queue_t * q, u32 context) { vl_api_lisp_eid_table_map_details_t *rmp = NULL; @@ -1024,7 +1019,7 @@ static void vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); hash_pair_t *p; uword *vni_table = 0; @@ -1053,7 +1048,7 @@ vl_api_lisp_eid_table_map_dump_t_handler (vl_api_lisp_eid_table_map_dump_t * } static void -send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context) +send_eid_table_vni (u32 vni, svm_queue_t * q, u32 context) { vl_api_lisp_eid_table_vni_details_t *rmp = 0; @@ -1166,7 +1161,7 @@ vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t * { hash_pair_t *p; u32 *vnis = 0; - unix_shared_memory_queue_t *q = 0; + svm_queue_t *q = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); q = vl_api_client_index_to_input_queue (mp->client_index); @@ -1198,7 +1193,7 @@ vl_api_lisp_eid_table_vni_dump_t_handler (vl_api_lisp_eid_table_vni_dump_t * static void vl_api_show_lisp_status_t_handler (vl_api_show_lisp_status_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_lisp_status_reply_t *rmp = NULL; int rv = 0; @@ -1221,7 +1216,7 @@ static void vl_api_lisp_get_map_request_itr_rlocs_t_handler (vl_api_lisp_get_map_request_itr_rlocs_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_lisp_get_map_request_itr_rlocs_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *loc_set = 0; @@ -1259,7 +1254,7 @@ static void static void vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_lisp_pitr_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; diff --git a/src/vnet/lisp-cp/one_api.c b/src/vnet/lisp-cp/one_api.c index 0708bf033f9..7afbf7f9582 100644 --- a/src/vnet/lisp-cp/one_api.c +++ b/src/vnet/lisp-cp/one_api.c @@ -70,7 +70,7 @@ #define REPLY_DETAILS(t, body) \ do { \ - unix_shared_memory_queue_t * q; \ + svm_queue_t * q; \ rv = vl_msg_api_pd_handler (mp, rv); \ q = vl_api_client_index_to_input_queue (mp->client_index); \ if (!q) \ @@ -537,7 +537,7 @@ vl_api_one_use_petr_t_handler (vl_api_one_use_petr_t * mp) static void vl_api_show_one_use_petr_t_handler (vl_api_show_one_use_petr_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_one_use_petr_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; @@ -698,8 +698,7 @@ send_reply: static void send_one_locator_details (lisp_cp_main_t * lcm, - locator_t * loc, - unix_shared_memory_queue_t * q, u32 context) + locator_t * loc, svm_queue_t * q, u32 context) { vl_api_one_locator_details_t *rmp; @@ -728,7 +727,7 @@ static void vl_api_one_locator_dump_t_handler (vl_api_one_locator_dump_t * mp) { u8 *ls_name = 0; - unix_shared_memory_queue_t *q = 0; + svm_queue_t *q = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = 0; locator_t *loc = 0; @@ -772,8 +771,7 @@ out: static void send_one_locator_set_details (lisp_cp_main_t * lcm, locator_set_t * lsit, - unix_shared_memory_queue_t * q, - u32 context, u32 ls_index) + svm_queue_t * q, u32 context, u32 ls_index) { vl_api_one_locator_set_details_t *rmp; u8 *str = 0; @@ -803,7 +801,7 @@ send_one_locator_set_details (lisp_cp_main_t * lcm, static void vl_api_one_locator_set_dump_t_handler (vl_api_one_locator_set_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); locator_set_t *lsit = NULL; u8 filter; @@ -883,8 +881,7 @@ fid_type_to_api_type (fid_address_t * fid) static void send_one_eid_table_details (mapping_t * mapit, - unix_shared_memory_queue_t * q, - u32 context, u8 filter) + svm_queue_t * q, u32 context, u8 filter) { fid_address_t *fid; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); @@ -985,7 +982,7 @@ static void vl_api_one_eid_table_dump_t_handler (vl_api_one_eid_table_dump_t * mp) { u32 mi; - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *mapit = NULL; gid_address_t _eid, *eid = &_eid; @@ -1024,8 +1021,7 @@ vl_api_one_eid_table_dump_t_handler (vl_api_one_eid_table_dump_t * mp) } static void -send_one_map_server_details (ip_address_t * ip, - unix_shared_memory_queue_t * q, u32 context) +send_one_map_server_details (ip_address_t * ip, svm_queue_t * q, u32 context) { vl_api_one_map_server_details_t *rmp = NULL; @@ -1058,7 +1054,7 @@ send_one_map_server_details (ip_address_t * ip, static void vl_api_one_map_server_dump_t_handler (vl_api_one_map_server_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); lisp_msmr_t *mr; @@ -1076,7 +1072,7 @@ vl_api_one_map_server_dump_t_handler (vl_api_one_map_server_dump_t * mp) static void send_one_map_resolver_details (ip_address_t * ip, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_one_map_resolver_details_t *rmp = NULL; @@ -1109,7 +1105,7 @@ send_one_map_resolver_details (ip_address_t * ip, static void vl_api_one_map_resolver_dump_t_handler (vl_api_one_map_resolver_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); lisp_msmr_t *mr; @@ -1126,8 +1122,7 @@ vl_api_one_map_resolver_dump_t_handler (vl_api_one_map_resolver_dump_t * mp) } static void -send_eid_table_map_pair (hash_pair_t * p, - unix_shared_memory_queue_t * q, u32 context) +send_eid_table_map_pair (hash_pair_t * p, svm_queue_t * q, u32 context) { vl_api_one_eid_table_map_details_t *rmp = NULL; @@ -1144,7 +1139,7 @@ send_eid_table_map_pair (hash_pair_t * p, static void vl_api_one_eid_table_map_dump_t_handler (vl_api_one_eid_table_map_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); hash_pair_t *p; uword *vni_table = 0; @@ -1173,7 +1168,7 @@ vl_api_one_eid_table_map_dump_t_handler (vl_api_one_eid_table_map_dump_t * mp) } static void -send_eid_table_vni (u32 vni, unix_shared_memory_queue_t * q, u32 context) +send_eid_table_vni (u32 vni, svm_queue_t * q, u32 context) { vl_api_one_eid_table_vni_details_t *rmp = 0; @@ -1296,7 +1291,7 @@ vl_api_one_eid_table_vni_dump_t_handler (vl_api_one_eid_table_vni_dump_t * mp) { hash_pair_t *p; u32 *vnis = 0; - unix_shared_memory_queue_t *q = 0; + svm_queue_t *q = 0; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); q = vl_api_client_index_to_input_queue (mp->client_index); @@ -1375,7 +1370,7 @@ static void static void vl_api_show_one_nsh_mapping_t_handler (vl_api_show_one_nsh_mapping_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_one_nsh_mapping_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; @@ -1424,7 +1419,7 @@ vl_api_show_one_nsh_mapping_t_handler (vl_api_show_one_nsh_mapping_t * mp) static void vl_api_show_one_pitr_t_handler (vl_api_show_one_pitr_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; vl_api_show_one_pitr_reply_t *rmp = NULL; lisp_cp_main_t *lcm = vnet_lisp_cp_get_main (); mapping_t *m; diff --git a/src/vnet/lisp-gpe/lisp_gpe_api.c b/src/vnet/lisp-gpe/lisp_gpe_api.c index 4ed480c4fd8..86b2f6cbc69 100644 --- a/src/vnet/lisp-gpe/lisp_gpe_api.c +++ b/src/vnet/lisp-gpe/lisp_gpe_api.c @@ -154,7 +154,7 @@ static void lisp_fwd_path_t *path; vl_api_gpe_fwd_entry_path_details_t *rmp = NULL; lisp_gpe_main_t *lgm = &lisp_gpe_main; - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; lisp_gpe_fwd_entry_t *lfe; gpe_fwd_entry_path_dump_t_net_to_host (mp); diff --git a/src/vnet/map/map_api.c b/src/vnet/map/map_api.c index 35b82d42b16..8ff73ec71e2 100644 --- a/src/vnet/map/map_api.c +++ b/src/vnet/map/map_api.c @@ -110,7 +110,7 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp) vl_api_map_domain_details_t *rmp; map_main_t *mm = &map_main; map_domain_t *d; - unix_shared_memory_queue_t *q; + svm_queue_t *q; if (pool_elts (mm->domains) == 0) return; @@ -149,7 +149,7 @@ vl_api_map_domain_dump_t_handler (vl_api_map_domain_dump_t * mp) static void vl_api_map_rule_dump_t_handler (vl_api_map_rule_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; u16 i; ip6_address_t dst; vl_api_map_rule_details_t *rmp; @@ -199,8 +199,7 @@ vl_api_map_summary_stats_t_handler (vl_api_map_summary_stats_t * mp) u64 total_pkts[VLIB_N_RX_TX]; u64 total_bytes[VLIB_N_RX_TX]; map_main_t *mm = &map_main; - unix_shared_memory_queue_t *q = - vl_api_client_index_to_input_queue (mp->client_index); + svm_queue_t *q = vl_api_client_index_to_input_queue (mp->client_index); if (!q) return; diff --git a/src/vnet/mfib/mfib_signal.c b/src/vnet/mfib/mfib_signal.c index cd486da32f8..38e4bbabb3c 100644 --- a/src/vnet/mfib/mfib_signal.c +++ b/src/vnet/mfib/mfib_signal.c @@ -91,7 +91,7 @@ mfib_signal_lock_release (void) } int -mfib_signal_send_one (struct _unix_shared_memory_queue *q, +mfib_signal_send_one (struct _svm_queue *q, u32 context) { u32 li, si; diff --git a/src/vnet/mfib/mfib_signal.h b/src/vnet/mfib/mfib_signal.h index 732d8aff3e9..4dd60a6dace 100644 --- a/src/vnet/mfib/mfib_signal.h +++ b/src/vnet/mfib/mfib_signal.h @@ -47,12 +47,12 @@ extern void mfib_signal_remove_itf(const mfib_itf_t *mfi); extern void mfib_signal_module_init(void); -struct _unix_shared_memory_queue; +struct _svm_queue; -extern void vl_mfib_signal_send_one(struct _unix_shared_memory_queue *q, +extern void vl_mfib_signal_send_one(struct _svm_queue *q, u32 context, const mfib_signal_t *mfs); -extern int mfib_signal_send_one(struct _unix_shared_memory_queue *q, +extern int mfib_signal_send_one(struct _svm_queue *q, u32 context); #endif diff --git a/src/vnet/mpls/mpls_api.c b/src/vnet/mpls/mpls_api.c index a772f7869ea..d9f40501526 100644 --- a/src/vnet/mpls/mpls_api.c +++ b/src/vnet/mpls/mpls_api.c @@ -376,7 +376,7 @@ static void typedef struct mpls_tunnel_send_walk_ctx_t_ { - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 index; u32 context; } mpls_tunnel_send_walk_ctx_t; @@ -433,7 +433,7 @@ send_mpls_tunnel_entry (u32 mti, void *arg) static void vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) @@ -449,7 +449,7 @@ vl_api_mpls_tunnel_dump_t_handler (vl_api_mpls_tunnel_dump_t * mp) static void send_mpls_fib_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, const fib_table_t * table, u32 label, u32 eos, fib_route_path_encode_t * api_rpaths, u32 context) @@ -507,7 +507,7 @@ static void vl_api_mpls_fib_dump_t_handler (vl_api_mpls_fib_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; mpls_main_t *mm = &mpls_main; fib_table_t *fib_table; mpls_fib_t *mpls_fib; diff --git a/src/vnet/policer/policer_api.c b/src/vnet/policer/policer_api.c index 686ed508a59..a658076685b 100644 --- a/src/vnet/policer/policer_api.c +++ b/src/vnet/policer/policer_api.c @@ -96,7 +96,7 @@ static void send_policer_details (u8 * name, sse2_qos_pol_cfg_params_st * config, policer_read_response_type_st * templ, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_policer_details_t *mp; @@ -136,7 +136,7 @@ send_policer_details (u8 * name, static void vl_api_policer_dump_t_handler (vl_api_policer_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vnet_policer_main_t *pm = &vnet_policer_main; hash_pair_t *hp; uword *p; diff --git a/src/vnet/session/application.c b/src/vnet/session/application.c index f6151b6b487..8090e75a6dc 100644 --- a/src/vnet/session/application.c +++ b/src/vnet/session/application.c @@ -76,7 +76,7 @@ application_local_session_table (application_t * app) int application_api_queue_is_full (application_t * app) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; /* builtin servers are always OK */ if (app->api_client_index == ~0) diff --git a/src/vnet/session/application.h b/src/vnet/session/application.h index 2892bc59f12..fd6454f21af 100644 --- a/src/vnet/session/application.h +++ b/src/vnet/session/application.h @@ -72,7 +72,7 @@ typedef struct _application u32 ns_index; /** Application listens for events on this svm queue */ - unix_shared_memory_queue_t *event_queue; + svm_queue_t *event_queue; /* * Callbacks: shoulder-taps for the server/client diff --git a/src/vnet/session/segment_manager.c b/src/vnet/session/segment_manager.c index 9e6a1b55cbb..dc3e4c9e648 100644 --- a/src/vnet/session/segment_manager.c +++ b/src/vnet/session/segment_manager.c @@ -530,12 +530,12 @@ segment_manager_dealloc_fifos (u32 svm_segment_index, svm_fifo_t * rx_fifo, /** * Allocates shm queue in the first segment */ -unix_shared_memory_queue_t * +svm_queue_t * segment_manager_alloc_queue (segment_manager_t * sm, u32 queue_size) { ssvm_shared_header_t *sh; svm_fifo_segment_private_t *segment; - unix_shared_memory_queue_t *q; + svm_queue_t *q; void *oldheap; ASSERT (sm->segment_indices != 0); @@ -544,10 +544,9 @@ segment_manager_alloc_queue (segment_manager_t * sm, u32 queue_size) sh = segment->ssvm.sh; oldheap = ssvm_push_heap (sh); - q = unix_shared_memory_queue_init (queue_size, - sizeof (session_fifo_event_t), - 0 /* consumer pid */ , - 0 /* signal when queue non-empty */ ); + q = svm_queue_init (queue_size, + sizeof (session_fifo_event_t), 0 /* consumer pid */ , + 0 /* signal when queue non-empty */ ); ssvm_pop_heap (oldheap); return q; } @@ -556,8 +555,7 @@ segment_manager_alloc_queue (segment_manager_t * sm, u32 queue_size) * Frees shm queue allocated in the first segment */ void -segment_manager_dealloc_queue (segment_manager_t * sm, - unix_shared_memory_queue_t * q) +segment_manager_dealloc_queue (segment_manager_t * sm, svm_queue_t * q) { ssvm_shared_header_t *sh; svm_fifo_segment_private_t *segment; @@ -569,7 +567,7 @@ segment_manager_dealloc_queue (segment_manager_t * sm, sh = segment->ssvm.sh; oldheap = ssvm_push_heap (sh); - unix_shared_memory_queue_free (q); + svm_queue_free (q); ssvm_pop_heap (oldheap); } diff --git a/src/vnet/session/segment_manager.h b/src/vnet/session/segment_manager.h index 9d2d141e7b4..41e2308928f 100644 --- a/src/vnet/session/segment_manager.h +++ b/src/vnet/session/segment_manager.h @@ -17,8 +17,7 @@ #include #include - -#include +#include #include #include @@ -113,10 +112,9 @@ segment_manager_alloc_session_fifos (segment_manager_t * sm, void segment_manager_dealloc_fifos (u32 svm_segment_index, svm_fifo_t * rx_fifo, svm_fifo_t * tx_fifo); -unix_shared_memory_queue_t *segment_manager_alloc_queue (segment_manager_t * - sm, u32 queue_size); -void segment_manager_dealloc_queue (segment_manager_t * sm, - unix_shared_memory_queue_t * q); +svm_queue_t *segment_manager_alloc_queue (segment_manager_t * + sm, u32 queue_size); +void segment_manager_dealloc_queue (segment_manager_t * sm, svm_queue_t * q); void segment_manager_app_detach (segment_manager_t * sm); segment_manager_properties_t *segment_manager_properties_alloc (void); diff --git a/src/vnet/session/session.c b/src/vnet/session/session.c index 408a1f5caf0..adcbb2924d8 100644 --- a/src/vnet/session/session.c +++ b/src/vnet/session/session.c @@ -33,7 +33,7 @@ session_send_evt_to_thread (u64 session_handle, fifo_event_type_t evt_type, { u32 tries = 0; session_fifo_event_t evt = { {0}, }; - unix_shared_memory_queue_t *q; + svm_queue_t *q; evt.event_type = evt_type; if (evt_type == FIFO_EVENT_RPC) @@ -45,7 +45,7 @@ session_send_evt_to_thread (u64 session_handle, fifo_event_type_t evt_type, evt.session_handle = session_handle; q = session_manager_get_vpp_event_queue (thread_index); - while (unix_shared_memory_queue_add (q, (u8 *) & evt, 1)) + while (svm_queue_add (q, (u8 *) & evt, 1)) { if (tries++ == 3) { @@ -443,7 +443,7 @@ session_enqueue_notify (stream_session_t * s, u8 block) { application_t *app; session_fifo_event_t evt; - unix_shared_memory_queue_t *q; + svm_queue_t *q; if (PREDICT_FALSE (s->session_state == SESSION_STATE_CLOSED)) { @@ -479,8 +479,8 @@ session_enqueue_notify (stream_session_t * s, u8 block) /* Based on request block (or not) for lack of space */ if (block || PREDICT_TRUE (q->cursize < q->maxsize)) - unix_shared_memory_queue_add (app->event_queue, (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (app->event_queue, (u8 *) & evt, + 0 /* do wait for mutex */ ); else { clib_warning ("fifo full"); @@ -980,7 +980,7 @@ session_vpp_event_queue_allocate (session_manager_main_t * smm, event_queue_length = smm->configured_event_queue_length; smm->vpp_event_queues[thread_index] = - unix_shared_memory_queue_init + svm_queue_init (event_queue_length, sizeof (session_fifo_event_t), 0 /* consumer pid */ , 0 /* (do not) send signal when queue non-empty */ ); diff --git a/src/vnet/session/session.h b/src/vnet/session/session.h index b76e56de50b..5e017c6c852 100644 --- a/src/vnet/session/session.h +++ b/src/vnet/session/session.h @@ -18,9 +18,9 @@ #include #include #include -#include #include #include +#include #define HALF_OPEN_LOOKUP_INVALID_VALUE ((u64)~0) #define INVALID_INDEX ((u32)~0) @@ -147,7 +147,7 @@ struct _session_manager_main session_fifo_event_t **pending_disconnects; /** vpp fifo event queue */ - unix_shared_memory_queue_t **vpp_event_queues; + svm_queue_t **vpp_event_queues; /** Unique segment name counter */ u32 unique_segment_name_counter; @@ -455,7 +455,7 @@ void session_register_transport (transport_proto_t transport_proto, clib_error_t *vnet_session_enable_disable (vlib_main_t * vm, u8 is_en); -always_inline unix_shared_memory_queue_t * +always_inline svm_queue_t * session_manager_get_vpp_event_queue (u32 thread_index) { return session_manager_main.vpp_event_queues[thread_index]; diff --git a/src/vnet/session/session_api.c b/src/vnet/session/session_api.c index 804fc23539a..75bdedfe9ce 100755 --- a/src/vnet/session/session_api.c +++ b/src/vnet/session/session_api.c @@ -62,7 +62,7 @@ send_add_segment_callback (u32 api_client_index, const u8 * segment_name, u32 segment_size) { vl_api_map_another_segment_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = vl_api_client_index_to_input_queue (api_client_index); @@ -85,7 +85,7 @@ static int send_session_accept_callback (stream_session_t * s) { vl_api_accept_session_t *mp; - unix_shared_memory_queue_t *q, *vpp_queue; + svm_queue_t *q, *vpp_queue; application_t *server = application_get (s->app_index); transport_connection_t *tc; transport_proto_vft_t *tp_vft; @@ -132,7 +132,7 @@ static void send_session_disconnect_callback (stream_session_t * s) { vl_api_disconnect_session_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; application_t *app = application_get (s->app_index); q = vl_api_client_index_to_input_queue (app->api_client_index); @@ -151,7 +151,7 @@ static void send_session_reset_callback (stream_session_t * s) { vl_api_reset_session_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; application_t *app = application_get (s->app_index); q = vl_api_client_index_to_input_queue (app->api_client_index); @@ -171,9 +171,9 @@ send_session_connected_callback (u32 app_index, u32 api_context, stream_session_t * s, u8 is_fail) { vl_api_connect_session_reply_t *mp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; application_t *app; - unix_shared_memory_queue_t *vpp_queue; + svm_queue_t *vpp_queue; transport_connection_t *tc; app = application_get (app_index); @@ -221,7 +221,7 @@ static int redirect_connect_callback (u32 server_api_client_index, void *mp_arg) { vl_api_connect_sock_t *mp = mp_arg; - unix_shared_memory_queue_t *server_q, *client_q; + svm_queue_t *server_q, *client_q; segment_manager_properties_t *props; vlib_main_t *vm = vlib_get_main (); f64 timeout = vlib_time_now (vm) + 0.5; @@ -263,8 +263,7 @@ redirect_connect_callback (u32 server_api_client_index, void *mp_arg) while (vlib_time_now (vm) < timeout) { - rv = - unix_shared_memory_queue_add (server_q, (u8 *) & mp, 1 /*nowait */ ); + rv = svm_queue_add (server_q, (u8 *) & mp, 1 /*nowait */ ); switch (rv) { /* correctly enqueued */ @@ -736,7 +735,7 @@ vl_api_connect_sock_t_handler (vl_api_connect_sock_t * mp) app = application_lookup (mp->client_index); if (app) { - unix_shared_memory_queue_t *client_q; + svm_queue_t *client_q; ip46_address_t *ip46 = (ip46_address_t *) mp->ip; client_q = vl_api_client_index_to_input_queue (mp->client_index); @@ -871,7 +870,7 @@ vl_api_session_rule_add_del_t_handler (vl_api_session_rule_add_del_t * mp) static void send_session_rule_details4 (mma_rule_16_t * rule, u8 is_local, u8 transport_proto, u32 appns_index, u8 * tag, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_session_rules_details_t *rmp = 0; session_mask_or_match_4_t *match = @@ -908,7 +907,7 @@ send_session_rule_details4 (mma_rule_16_t * rule, u8 is_local, static void send_session_rule_details6 (mma_rule_40_t * rule, u8 is_local, u8 transport_proto, u32 appns_index, u8 * tag, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { vl_api_session_rules_details_t *rmp = 0; session_mask_or_match_6_t *match = @@ -945,7 +944,7 @@ send_session_rule_details6 (mma_rule_40_t * rule, u8 is_local, static void send_session_rules_table_details (session_rules_table_t * srt, u8 fib_proto, u8 tp, u8 is_local, u32 appns_index, - unix_shared_memory_queue_t * q, u32 context) + svm_queue_t * q, u32 context) { mma_rule_16_t *rule16; mma_rule_40_t *rule40; @@ -984,7 +983,7 @@ send_session_rules_table_details (session_rules_table_t * srt, u8 fib_proto, static void vl_api_session_rules_dump_t_handler (vl_api_one_map_server_dump_t * mp) { - unix_shared_memory_queue_t *q = NULL; + svm_queue_t *q = NULL; session_table_t *st; u8 tp; diff --git a/src/vnet/session/session_node.c b/src/vnet/session/session_node.c index e9cfc7be8aa..a1608f4a412 100644 --- a/src/vnet/session/session_node.c +++ b/src/vnet/session/session_node.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include vlib_node_registration_t session_queue_node; @@ -406,7 +406,7 @@ dump_thread_0_event_queue (void) int i, index; i8 *headp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; q = smm->vpp_event_queues[my_thread_index]; index = q->head; @@ -486,7 +486,7 @@ u8 session_node_lookup_fifo_event (svm_fifo_t * f, session_fifo_event_t * e) { session_manager_main_t *smm = vnet_get_session_manager_main (); - unix_shared_memory_queue_t *q; + svm_queue_t *q; session_fifo_event_t *pending_event_vector, *evt; int i, index, found = 0; i8 *headp; @@ -533,7 +533,7 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, session_fifo_event_t *my_pending_event_vector, *pending_disconnects, *e; session_fifo_event_t *my_fifo_events; u32 n_to_dequeue, n_events; - unix_shared_memory_queue_t *q; + svm_queue_t *q; application_t *app; int n_tx_packets = 0; u32 my_thread_index = vm->thread_index; @@ -586,7 +586,7 @@ session_queue_node_fn (vlib_main_t * vm, vlib_node_runtime_t * node, for (i = 0; i < n_to_dequeue; i++) { vec_add2 (my_fifo_events, e, 1); - unix_shared_memory_queue_sub_raw (q, (u8 *) e); + svm_queue_sub_raw (q, (u8 *) e); } /* The other side of the connection is not polling */ diff --git a/src/vnet/span/span_api.c b/src/vnet/span/span_api.c index 64a71a2ed69..40dc4f35137 100644 --- a/src/vnet/span/span_api.c +++ b/src/vnet/span/span_api.c @@ -66,7 +66,7 @@ static void vl_api_sw_interface_span_dump_t_handler (vl_api_sw_interface_span_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; span_interface_t *si; vl_api_sw_interface_span_details_t *rmp; span_main_t *sm = &span_main; diff --git a/src/vnet/srv6/sr_api.c b/src/vnet/srv6/sr_api.c index 789bb27386c..8f5f4f90e5d 100644 --- a/src/vnet/srv6/sr_api.c +++ b/src/vnet/srv6/sr_api.c @@ -191,7 +191,7 @@ static void vl_api_sr_steering_add_del_t_handler } static void send_sr_localsid_details - (ip6_sr_localsid_t * t, unix_shared_memory_queue_t * q, u32 context) + (ip6_sr_localsid_t * t, svm_queue_t * q, u32 context) { vl_api_sr_localsids_details_t *rmp; @@ -212,7 +212,7 @@ static void send_sr_localsid_details static void vl_api_sr_localsids_dump_t_handler (vl_api_sr_localsids_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; ip6_sr_main_t *sm = &sr_main; ip6_sr_localsid_t *t; diff --git a/src/vnet/tcp/builtin_client.c b/src/vnet/tcp/builtin_client.c index 319b70f2008..b073459c52e 100644 --- a/src/vnet/tcp/builtin_client.c +++ b/src/vnet/tcp/builtin_client.c @@ -100,7 +100,7 @@ send_test_chunk (tclient_main_t * tm, session_t * s) evt.fifo = txf; evt.event_type = FIFO_EVENT_APP_TX; - if (unix_shared_memory_queue_add + if (svm_queue_add (tm->vpp_event_queue[txf->master_thread_index], (u8 *) & evt, 0 /* do wait for mutex */ )) clib_warning ("could not enqueue event"); diff --git a/src/vnet/tcp/builtin_client.h b/src/vnet/tcp/builtin_client.h index a214ae1e1b1..be8ea002639 100644 --- a/src/vnet/tcp/builtin_client.h +++ b/src/vnet/tcp/builtin_client.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -47,8 +46,8 @@ typedef struct /* * Application setup parameters */ - unix_shared_memory_queue_t *vl_input_queue; /**< vpe input queue */ - unix_shared_memory_queue_t **vpp_event_queue; + svm_queue_t *vl_input_queue; /**< vpe input queue */ + svm_queue_t **vpp_event_queue; u32 cli_node_index; /**< cli process node index */ u32 my_client_index; /**< loopback API client handle */ diff --git a/src/vnet/tcp/builtin_http_server.c b/src/vnet/tcp/builtin_http_server.c index 6e1cd8e770e..356cfd86b91 100644 --- a/src/vnet/tcp/builtin_http_server.c +++ b/src/vnet/tcp/builtin_http_server.c @@ -32,7 +32,7 @@ typedef struct typedef struct { u8 **rx_buf; - unix_shared_memory_queue_t **vpp_queue; + svm_queue_t **vpp_queue; u64 byte_index; uword *handler_by_get_request; @@ -40,7 +40,7 @@ typedef struct u32 *free_http_cli_process_node_indices; /* Sever's event queue */ - unix_shared_memory_queue_t *vl_input_queue; + svm_queue_t *vl_input_queue; /* API client handle */ u32 my_client_index; @@ -175,9 +175,8 @@ send_data (stream_session_t * s, u8 * data) evt.fifo = s->server_tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - unix_shared_memory_queue_add (hsm->vpp_queue[s->thread_index], - (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (hsm->vpp_queue[s->thread_index], + (u8 *) & evt, 0 /* do wait for mutex */ ); } delay = 10e-3; } @@ -377,7 +376,7 @@ http_server_rx_callback (stream_session_t * s) evt.rpc_args.fp = alloc_http_process_callback; evt.rpc_args.arg = args; evt.event_type = FIFO_EVENT_RPC; - unix_shared_memory_queue_add + svm_queue_add (session_manager_get_vpp_event_queue (0 /* main thread */ ), (u8 *) & evt, 0 /* do wait for mutex */ ); } diff --git a/src/vnet/tcp/builtin_proxy.c b/src/vnet/tcp/builtin_proxy.c index 7f70df39069..974830ea756 100644 --- a/src/vnet/tcp/builtin_proxy.c +++ b/src/vnet/tcp/builtin_proxy.c @@ -185,7 +185,7 @@ server_rx_callback (stream_session_t * s) { evt.fifo = active_open_tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - if (unix_shared_memory_queue_add + if (svm_queue_add (bpm->active_open_event_queue[thread_index], (u8 *) & evt, 0 /* do wait for mutex */ )) clib_warning ("failed to enqueue tx evt"); @@ -299,7 +299,7 @@ active_open_connected_callback (u32 app_index, u32 opaque, { evt.fifo = s->server_tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - if (unix_shared_memory_queue_add + if (svm_queue_add (bpm->active_open_event_queue[thread_index], (u8 *) & evt, 0 /* do wait for mutex */ )) clib_warning ("failed to enqueue tx evt"); @@ -343,7 +343,7 @@ active_open_rx_callback (stream_session_t * s) { evt.fifo = server_rx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - if (unix_shared_memory_queue_add + if (svm_queue_add (bpm->server_event_queue[thread_index], (u8 *) & evt, 0 /* do wait for mutex */ )) clib_warning ("failed to enqueue server rx evt"); diff --git a/src/vnet/tcp/builtin_proxy.h b/src/vnet/tcp/builtin_proxy.h index c8cde5f70e6..780f8b65b90 100644 --- a/src/vnet/tcp/builtin_proxy.h +++ b/src/vnet/tcp/builtin_proxy.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -40,10 +39,10 @@ typedef struct typedef struct { - unix_shared_memory_queue_t *vl_input_queue; /**< vpe input queue */ + svm_queue_t *vl_input_queue; /**< vpe input queue */ /** per-thread vectors */ - unix_shared_memory_queue_t **server_event_queue; - unix_shared_memory_queue_t **active_open_event_queue; + svm_queue_t **server_event_queue; + svm_queue_t **active_open_event_queue; u8 **rx_buf; /**< intermediate rx buffers */ u32 cli_node_index; /**< cli process node index */ diff --git a/src/vnet/tcp/builtin_server.c b/src/vnet/tcp/builtin_server.c index 26cbfe77727..eafef8227e2 100644 --- a/src/vnet/tcp/builtin_server.c +++ b/src/vnet/tcp/builtin_server.c @@ -23,8 +23,8 @@ typedef struct /* * Server app parameters */ - unix_shared_memory_queue_t **vpp_queue; - unix_shared_memory_queue_t *vl_input_queue; /**< Sever's event queue */ + svm_queue_t **vpp_queue; + svm_queue_t *vl_input_queue; /**< Sever's event queue */ u32 app_index; /**< Server app index */ u32 my_client_index; /**< API client handle */ @@ -186,14 +186,14 @@ builtin_server_rx_callback (stream_session_t * s) /* Program self-tap to retry */ if (svm_fifo_set_event (rx_fifo)) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; evt.fifo = rx_fifo; evt.event_type = FIFO_EVENT_BUILTIN_RX; q = bsm->vpp_queue[thread_index]; if (PREDICT_FALSE (q->cursize == q->maxsize)) clib_warning ("out of event queue space"); - else if (unix_shared_memory_queue_add (q, (u8 *) & evt, 0)) + else if (svm_queue_add (q, (u8 *) & evt, 0)) clib_warning ("failed to enqueue self-tap"); if (bsm->rx_retries[thread_index][s->session_index] == 500000) @@ -231,9 +231,8 @@ builtin_server_rx_callback (stream_session_t * s) evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; - if (unix_shared_memory_queue_add (bsm->vpp_queue[s->thread_index], - (u8 *) & evt, - 0 /* do wait for mutex */ )) + if (svm_queue_add (bsm->vpp_queue[s->thread_index], + (u8 *) & evt, 0 /* do wait for mutex */ )) clib_warning ("failed to enqueue tx evt"); } diff --git a/src/vnet/udp/builtin_server.c b/src/vnet/udp/builtin_server.c index 05a47031dc2..73914cbc143 100644 --- a/src/vnet/udp/builtin_server.c +++ b/src/vnet/udp/builtin_server.c @@ -62,7 +62,7 @@ builtin_server_rx_callback (stream_session_t * s) int actual_transfer; u8 *my_copy_buffer; session_fifo_event_t evt; - unix_shared_memory_queue_t *q; + svm_queue_t *q; my_copy_buffer = copy_buffers[s->thread_index]; rx_fifo = s->server_rx_fifo; @@ -90,8 +90,7 @@ builtin_server_rx_callback (stream_session_t * s) evt.fifo = tx_fifo; evt.event_type = FIFO_EVENT_APP_TX; q = session_manager_get_vpp_event_queue (s->thread_index); - unix_shared_memory_queue_add (q, (u8 *) & evt, - 0 /* do wait for mutex */ ); + svm_queue_add (q, (u8 *) & evt, 0 /* do wait for mutex */ ); } return 0; diff --git a/src/vnet/udp/udp_api.c b/src/vnet/udp/udp_api.c index e65235a5396..dddc6f9470d 100644 --- a/src/vnet/udp/udp_api.c +++ b/src/vnet/udp/udp_api.c @@ -43,8 +43,7 @@ _(UDP_ENCAP_DUMP, udp_encap_dump) static void -send_udp_encap_details (const udp_encap_t * ue, - unix_shared_memory_queue_t * q, u32 context) +send_udp_encap_details (const udp_encap_t * ue, svm_queue_t * q, u32 context) { vl_api_udp_encap_details_t *mp; fib_table_t *fib_table; @@ -82,7 +81,7 @@ static void vl_api_udp_encap_dump_t_handler (vl_api_udp_encap_dump_t * mp, vlib_main_t * vm) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; udp_encap_t *ue; q = vl_api_client_index_to_input_queue (mp->client_index); @@ -94,12 +93,12 @@ vl_api_udp_encap_dump_t_handler (vl_api_udp_encap_dump_t * mp, ({ send_udp_encap_details(ue, q, mp->context); })); - /* *INDENT-OFF* */ + /* *INDENT-ON* */ } static void vl_api_udp_encap_add_del_t_handler (vl_api_udp_encap_add_del_t * mp, - vlib_main_t * vm) + vlib_main_t * vm) { vl_api_udp_encap_add_del_reply_t *rmp; ip46_address_t src_ip, dst_ip; @@ -107,11 +106,11 @@ vl_api_udp_encap_add_del_t_handler (vl_api_udp_encap_add_del_t * mp, fib_protocol_t fproto; int rv = 0; - ue_id = ntohl(mp->id); - table_id = ntohl(mp->table_id); + ue_id = ntohl (mp->id); + table_id = ntohl (mp->table_id); fproto = (mp->is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); - fib_index = fib_table_find(fproto, table_id); + fib_index = fib_table_find (fproto, table_id); if (~0 == fib_index) { @@ -121,29 +120,28 @@ vl_api_udp_encap_add_del_t_handler (vl_api_udp_encap_add_del_t * mp, if (FIB_PROTOCOL_IP4 == fproto) { - clib_memcpy(&src_ip.ip4, mp->src_ip, 4); - clib_memcpy(&dst_ip.ip4, mp->dst_ip, 4); + clib_memcpy (&src_ip.ip4, mp->src_ip, 4); + clib_memcpy (&dst_ip.ip4, mp->dst_ip, 4); } else { - clib_memcpy(&src_ip.ip6, mp->src_ip, 16); - clib_memcpy(&dst_ip.ip6, mp->dst_ip, 16); + clib_memcpy (&src_ip.ip6, mp->src_ip, 16); + clib_memcpy (&dst_ip.ip6, mp->dst_ip, 16); } if (mp->is_add) { - udp_encap_add_and_lock(ue_id, fproto, fib_index, - &src_ip, &dst_ip, - ntohs(mp->src_port), - ntohs(mp->dst_port), - UDP_ENCAP_FIXUP_NONE); + udp_encap_add_and_lock (ue_id, fproto, fib_index, + &src_ip, &dst_ip, + ntohs (mp->src_port), + ntohs (mp->dst_port), UDP_ENCAP_FIXUP_NONE); } else { - udp_encap_unlock(ue_id); + udp_encap_unlock (ue_id); } - done: +done: REPLY_MACRO (VL_API_UDP_ENCAP_ADD_DEL_REPLY); } diff --git a/src/vnet/unix/tap_api.c b/src/vnet/unix/tap_api.c index 3a64e1009cf..23755722678 100644 --- a/src/vnet/unix/tap_api.c +++ b/src/vnet/unix/tap_api.c @@ -60,8 +60,7 @@ _(SW_INTERFACE_TAP_DUMP, sw_interface_tap_dump) */ static void send_sw_interface_event_deleted (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, - u32 sw_if_index) + svm_queue_t * q, u32 sw_if_index) { vl_api_sw_interface_event_t *mp; @@ -83,7 +82,7 @@ vl_api_tap_connect_t_handler (vl_api_tap_connect_t * mp) int rv; vl_api_tap_connect_reply_t *rmp; vnet_main_t *vnm = vnet_get_main (); - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 sw_if_index = (u32) ~ 0; u8 *tag; vnet_tap_connect_args_t _a, *ap = &_a; @@ -137,7 +136,7 @@ vl_api_tap_modify_t_handler (vl_api_tap_modify_t * mp) { int rv; vl_api_tap_modify_reply_t *rmp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 sw_if_index = (u32) ~ 0; vlib_main_t *vm = vlib_get_main (); vnet_tap_connect_args_t _a, *ap = &_a; @@ -174,7 +173,7 @@ vl_api_tap_delete_t_handler (vl_api_tap_delete_t * mp) int rv; vpe_api_main_t *vam = &vpe_api_main; vl_api_tap_delete_reply_t *rmp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; u32 sw_if_index = ntohl (mp->sw_if_index); rv = vnet_tap_delete (vm, sw_if_index); @@ -201,7 +200,7 @@ vl_api_tap_delete_t_handler (vl_api_tap_delete_t * mp) static void send_sw_interface_tap_details (vpe_api_main_t * am, - unix_shared_memory_queue_t * q, + svm_queue_t * q, tapcli_interface_details_t * tap_if, u32 context) { @@ -222,7 +221,7 @@ vl_api_sw_interface_tap_dump_t_handler (vl_api_sw_interface_tap_dump_t * mp) { int rv = 0; vpe_api_main_t *am = &vpe_api_main; - unix_shared_memory_queue_t *q; + svm_queue_t *q; tapcli_interface_details_t *tapifs = NULL; tapcli_interface_details_t *tap_if = NULL; diff --git a/src/vnet/vxlan-gpe/vxlan_gpe_api.c b/src/vnet/vxlan-gpe/vxlan_gpe_api.c index 8e2684187a7..b3e300ecc55 100644 --- a/src/vnet/vxlan-gpe/vxlan_gpe_api.c +++ b/src/vnet/vxlan-gpe/vxlan_gpe_api.c @@ -144,7 +144,7 @@ out: } static void send_vxlan_gpe_tunnel_details - (vxlan_gpe_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (vxlan_gpe_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_vxlan_gpe_tunnel_details_t *rmp; ip4_main_t *im4 = &ip4_main; @@ -181,7 +181,7 @@ static void send_vxlan_gpe_tunnel_details static void vl_api_vxlan_gpe_tunnel_dump_t_handler (vl_api_vxlan_gpe_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vxlan_gpe_main_t *vgm = &vxlan_gpe_main; vxlan_gpe_tunnel_t *t; u32 sw_if_index; diff --git a/src/vnet/vxlan/vxlan_api.c b/src/vnet/vxlan/vxlan_api.c index a2d412322fb..20034f74f0e 100644 --- a/src/vnet/vxlan/vxlan_api.c +++ b/src/vnet/vxlan/vxlan_api.c @@ -116,7 +116,7 @@ out: } static void send_vxlan_tunnel_details - (vxlan_tunnel_t * t, unix_shared_memory_queue_t * q, u32 context) + (vxlan_tunnel_t * t, svm_queue_t * q, u32 context) { vl_api_vxlan_tunnel_details_t *rmp; ip4_main_t *im4 = &ip4_main; @@ -151,7 +151,7 @@ static void send_vxlan_tunnel_details static void vl_api_vxlan_tunnel_dump_t_handler (vl_api_vxlan_tunnel_dump_t * mp) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vxlan_main_t *vxm = &vxlan_main; vxlan_tunnel_t *t; u32 sw_if_index; diff --git a/src/vpp-api/client/client.c b/src/vpp-api/client/client.c index 668461aad6c..f1372230195 100644 --- a/src/vpp-api/client/client.c +++ b/src/vpp-api/client/client.c @@ -132,7 +132,7 @@ vac_api_handler (void *msg) static void * vac_rx_thread_fn (void *arg) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; vl_api_memclnt_keepalive_t *mp; vl_api_memclnt_keepalive_reply_t *rmp; vac_main_t *pm = &vac_main; @@ -143,7 +143,7 @@ vac_rx_thread_fn (void *arg) q = am->vl_input_queue; while (1) - while (!unix_shared_memory_queue_sub(q, (u8 *)&msg, 0)) + while (!svm_queue_sub(q, (u8 *)&msg, 0)) { u16 id = ntohs(*((u16 *)msg)); switch (id) { @@ -381,7 +381,7 @@ unset_timeout (void) int vac_read (char **p, int *l, u16 timeout) { - unix_shared_memory_queue_t *q; + svm_queue_t *q; api_main_t *am = &api_main; vac_main_t *pm = &vac_main; vl_api_memclnt_keepalive_t *mp; @@ -404,7 +404,7 @@ vac_read (char **p, int *l, u16 timeout) q = am->vl_input_queue; again: - rv = unix_shared_memory_queue_sub(q, (u8 *)&msg, 0); + rv = svm_queue_sub(q, (u8 *)&msg, 0); if (rv == 0) { u16 msg_id = ntohs(*((u16 *)msg)); switch (msg_id) { @@ -478,7 +478,7 @@ vac_write (char *p, int l) int rv = -1; api_main_t *am = &api_main; vl_api_header_t *mp = vl_msg_api_alloc(l); - unix_shared_memory_queue_t *q; + svm_queue_t *q; vac_main_t *pm = &vac_main; if (!pm->connected_to_vlib) return -1; @@ -487,7 +487,7 @@ vac_write (char *p, int l) memcpy(mp, p, l); mp->client_index = vac_client_index(); q = am->shmem_hdr->vl_input_queue; - rv = unix_shared_memory_queue_add(q, (u8 *)&mp, 0); + rv = svm_queue_add(q, (u8 *)&mp, 0); if (rv != 0) { clib_warning("vpe_api_write fails: %d\n", rv); /* Clear message */ @@ -499,7 +499,7 @@ vac_write (char *p, int l) int vac_get_msg_index (unsigned char * name) { - return vl_api_get_msg_index (name); + return vl_msg_api_get_msg_index (name); } int diff --git a/src/vpp-api/java/jvpp-acl/jvpp_acl.c b/src/vpp-api/java/jvpp-acl/jvpp_acl.c index 82719aafbc8..22e44f1db5a 100644 --- a/src/vpp-api/java/jvpp-acl/jvpp_acl.c +++ b/src/vpp-api/java/jvpp-acl/jvpp_acl.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_acl_JVppAclImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_acl_JVppAclImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-acl/jvpp_acl.h b/src/vpp-api/java/jvpp-acl/jvpp_acl.h index 726f7298221..d1ec78feb19 100644 --- a/src/vpp-api/java/jvpp-acl/jvpp_acl.h +++ b/src/vpp-api/java/jvpp-acl/jvpp_acl.h @@ -25,7 +25,7 @@ /* Global state for JVPP-acl */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-common/jvpp_common.h b/src/vpp-api/java/jvpp-common/jvpp_common.h index 34502d04ab8..14027a96f78 100644 --- a/src/vpp-api/java/jvpp-common/jvpp_common.h +++ b/src/vpp-api/java/jvpp-common/jvpp_common.h @@ -35,7 +35,7 @@ typedef struct { JavaVM *jvm; /* Convenience */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; u32 my_client_index; uword *messages_hash; } jvpp_main_t; diff --git a/src/vpp-api/java/jvpp-core/jvpp_core.c b/src/vpp-api/java/jvpp-core/jvpp_core.c index b12f63af16f..09d753026d7 100644 --- a/src/vpp-api/java/jvpp-core/jvpp_core.c +++ b/src/vpp-api/java/jvpp-core/jvpp_core.c @@ -30,7 +30,7 @@ // TODO: generate jvpp_plugin_name.c files (or at least reuse plugin's main structure) typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; @@ -50,7 +50,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_core_JVppCoreImpl_init0 (JNIEnv * env, jclass clazz, jobject callback, jlong queue_address, jint my_client_index) { core_main_t * plugin_main = &core_main; plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.c b/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.c index 286a9ceccbe..8e523caa9f8 100644 --- a/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.c +++ b/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_gtpu_JVppGtpuImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_gtpu_JVppGtpuImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = (unix_shared_memory_queue_t *)queue_address; + plugin_main->vl_input_queue = (svm_queue_t *)queue_address; plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.h b/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.h index 447776ce0b8..fa7c8b7c53b 100644 --- a/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.h +++ b/src/vpp-api/java/jvpp-gtpu/jvpp_gtpu.h @@ -25,7 +25,7 @@ /* Global state for JVPP-gtpu */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c index 8d486134cfa..74ae438e136 100644 --- a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c +++ b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioamexport_JVppIoamexportImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_ioamexport_JVppIoamexportImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.h b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.h index 8b243def8e8..596a05400e9 100644 --- a/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.h +++ b/src/vpp-api/java/jvpp-ioamexport/jvpp_ioam_export.h @@ -25,7 +25,7 @@ /* Global state for JVPP-IOAM-EXPORT */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c index 4b9d1a58932..ce1da6979e7 100644 --- a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c +++ b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioampot_JVppIoampotImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_ioampot_JVppIoampotImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.h b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.h index 81e2a1bbbb6..51db3da83b5 100644 --- a/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.h +++ b/src/vpp-api/java/jvpp-ioampot/jvpp_ioam_pot.h @@ -25,7 +25,7 @@ /* Global state for JVPP-IOAM-POT */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c index f917d1c684e..3532d91e3a4 100644 --- a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c +++ b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_ioamtrace_JVppIoamtraceImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_ioamtrace_JVppIoamtraceImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.h b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.h index cb0b27e199c..752b599f4b8 100644 --- a/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.h +++ b/src/vpp-api/java/jvpp-ioamtrace/jvpp_ioam_trace.h @@ -25,7 +25,7 @@ /* Global state for JVPP-IOAM-TRACE */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-nat/jvpp_nat.c b/src/vpp-api/java/jvpp-nat/jvpp_nat.c index 56c74d21141..bdae1e64913 100644 --- a/src/vpp-api/java/jvpp-nat/jvpp_nat.c +++ b/src/vpp-api/java/jvpp-nat/jvpp_nat.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_nat_JVppNatImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_nat_JVppNatImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = uword_to_pointer (queue_address, unix_shared_memory_queue_t *); + plugin_main->vl_input_queue = uword_to_pointer (queue_address, svm_queue_t *); plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-nat/jvpp_nat.h b/src/vpp-api/java/jvpp-nat/jvpp_nat.h index c8f6b683fea..9bff974a976 100644 --- a/src/vpp-api/java/jvpp-nat/jvpp_nat.h +++ b/src/vpp-api/java/jvpp-nat/jvpp_nat.h @@ -25,7 +25,7 @@ /* Global state for JVPP-NAT */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.c b/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.c index d339700ea22..02bd20e6bb4 100644 --- a/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.c +++ b/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.c @@ -47,7 +47,7 @@ JNIEXPORT void JNICALL Java_io_fd_vpp_jvpp_pppoe_JVppPppoeImpl_init0 clib_warning ("Java_io_fd_vpp_jvpp_pppoe_JVppPppoeImpl_init0"); plugin_main->my_client_index = my_client_index; - plugin_main->vl_input_queue = (unix_shared_memory_queue_t *)queue_address; + plugin_main->vl_input_queue = (svm_queue_t *)queue_address; plugin_main->callbackObject = (*env)->NewGlobalRef(env, callback); plugin_main->callbackClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, callback)); diff --git a/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.h b/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.h index 4523ba9cd96..7606a7ef86e 100644 --- a/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.h +++ b/src/vpp-api/java/jvpp-pppoe/jvpp_pppoe.h @@ -25,7 +25,7 @@ /* Global state for JVPP-pppoe */ typedef struct { /* Pointer to shared memory queue */ - unix_shared_memory_queue_t * vl_input_queue; + svm_queue_t * vl_input_queue; /* VPP api client index */ u32 my_client_index; diff --git a/src/vpp-api/vapi/vapi.c b/src/vpp-api/vapi/vapi.c index 658fd7e584c..7aa346bf083 100644 --- a/src/vpp-api/vapi/vapi.c +++ b/src/vpp-api/vapi/vapi.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include /* we need to use control pings for some stuff and because we're forced to put * the code in headers, we need a way to be able to grab the ids of these @@ -336,7 +336,7 @@ vapi_connect (vapi_ctx_t ctx, const char *name, vapi_message_desc_t *m = __vapi_metadata.msgs[i]; u8 scratch[m->name_with_crc_len + 1]; memcpy (scratch, m->name_with_crc, m->name_with_crc_len + 1); - u32 id = vl_api_get_msg_index (scratch); + u32 id = vl_msg_api_get_msg_index (scratch); if (INVALID_MSG_ID != id) { if (id > UINT16_MAX) @@ -425,7 +425,7 @@ vapi_send (vapi_ctx_t ctx, void *msg) goto out; } int tmp; - unix_shared_memory_queue_t *q = api_main.shmem_hdr->vl_input_queue; + svm_queue_t *q = api_main.shmem_hdr->vl_input_queue; #if VAPI_DEBUG unsigned msgid = be16toh (*(u16 *) msg); if (msgid <= ctx->vl_msg_id_max) @@ -446,9 +446,8 @@ vapi_send (vapi_ctx_t ctx, void *msg) VAPI_DBG ("send msg@%p:%u[UNKNOWN]", msg, msgid); } #endif - tmp = unix_shared_memory_queue_add (q, (u8 *) & msg, - VAPI_MODE_BLOCKING == - ctx->mode ? 0 : 1); + tmp = svm_queue_add (q, (u8 *) & msg, + VAPI_MODE_BLOCKING == ctx->mode ? 0 : 1); if (tmp < 0) { rv = VAPI_EAGAIN; @@ -467,7 +466,7 @@ vapi_send2 (vapi_ctx_t ctx, void *msg1, void *msg2) rv = VAPI_EINVAL; goto out; } - unix_shared_memory_queue_t *q = api_main.shmem_hdr->vl_input_queue; + svm_queue_t *q = api_main.shmem_hdr->vl_input_queue; #if VAPI_DEBUG unsigned msgid1 = be16toh (*(u16 *) msg1); unsigned msgid2 = be16toh (*(u16 *) msg2); @@ -491,9 +490,8 @@ vapi_send2 (vapi_ctx_t ctx, void *msg1, void *msg2) } VAPI_DBG ("send two: %u[%s], %u[%s]", msgid1, name1, msgid2, name2); #endif - int tmp = unix_shared_memory_queue_add2 (q, (u8 *) & msg1, (u8 *) & msg2, - VAPI_MODE_BLOCKING == - ctx->mode ? 0 : 1); + int tmp = svm_queue_add2 (q, (u8 *) & msg1, (u8 *) & msg2, + VAPI_MODE_BLOCKING == ctx->mode ? 0 : 1); if (tmp < 0) { rv = VAPI_EAGAIN; @@ -519,9 +517,9 @@ vapi_recv (vapi_ctx_t ctx, void **msg, size_t * msg_size) return VAPI_EINVAL; } - unix_shared_memory_queue_t *q = am->vl_input_queue; + svm_queue_t *q = am->vl_input_queue; VAPI_DBG ("doing shm queue sub"); - int tmp = unix_shared_memory_queue_sub (q, (u8 *) & data, 0); + int tmp = svm_queue_sub (q, (u8 *) & data, 0); if (tmp == 0) { #if VAPI_DEBUG_ALLOC diff --git a/src/vpp/api/api.c b/src/vpp/api/api.c index d2b06ff51c4..70b104234b7 100644 --- a/src/vpp/api/api.c +++ b/src/vpp/api/api.c @@ -72,6 +72,7 @@ #include #undef vl_printfun #include + #define foreach_vpe_api_msg \ _(CONTROL_PING, control_ping) \ _(CLI, cli) \ @@ -84,6 +85,7 @@ _(GET_NEXT_INDEX, get_next_index) \ #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) + typedef enum { RESOLVE_IP4_ADD_DEL_ROUTE = 1, @@ -162,7 +164,7 @@ static void vl_api_cli_t_handler (vl_api_cli_t * mp) { vl_api_cli_reply_t *rp; - unix_shared_memory_queue_t *q; + svm_queue_t *q; vlib_main_t *vm = vlib_get_main (); api_main_t *am = &api_main; unformat_input_t input; @@ -365,6 +367,7 @@ vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp) vlib_main_t *vm = vlib_get_main (); void *oldheap; vl_api_get_node_graph_reply_t *rmp; + vlib_node_t ***node_dups; pthread_mutex_lock (&am->vlib_rp->mutex); oldheap = svm_push_data_heap (am->vlib_rp); @@ -376,9 +379,9 @@ vl_api_get_node_graph_t_handler (vl_api_get_node_graph_t * mp) vec_reset_length (vector); /* $$$$ FIXME */ - vector = vlib_node_serialize (&vm->node_main, vector, - (u32) ~ 0 /* all threads */ , - 1 /* include nexts */ , + node_dups = vlib_node_get_nodes (vm, (u32) ~ 0 /* all threads */ , + 1 /* include stats */ ); + vector = vlib_node_serialize (vm, node_dups, vector, 1 /* include nexts */ , 1 /* include stats */ ); svm_pop_heap (oldheap); @@ -398,7 +401,7 @@ static void vl_api_##nn##_t_handler ( \ { \ vpe_client_registration_t *reg; \ vpe_api_main_t * vam = &vpe_api_main; \ - unix_shared_memory_queue_t * q; \ + svm_queue_t * q; \ \ /* One registration only... */ \ pool_foreach(reg, vam->nn##_registrations, \ @@ -482,7 +485,7 @@ vpe_api_init (vlib_main_t * vm) #undef _ vl_set_memory_region_name ("/vpe-api"); - vl_enable_disable_memory_api (vm, 1 /* enable it */ ); + vl_mem_api_enable_disable (vm, 1 /* enable it */ ); return 0; } diff --git a/src/vpp/api/api_format.c b/src/vpp/api/api_format.c deleted file mode 120000 index cec72cc0d0f..00000000000 --- a/src/vpp/api/api_format.c +++ /dev/null @@ -1 +0,0 @@ -../../vat/api_format.c \ No newline at end of file diff --git a/src/vpp/api/api_format.c b/src/vpp/api/api_format.c new file mode 100644 index 00000000000..4c13e11226f --- /dev/null +++ b/src/vpp/api/api_format.c @@ -0,0 +1,23265 @@ +/* + *------------------------------------------------------------------ + * api_format.c + * + * Copyright (c) 2014-2016 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vat/json_format.h" + +#include +#include + +#define vl_typedefs /* define message structures */ +#include +#undef vl_typedefs + +/* declare message handlers for each api */ + +#define vl_endianfun /* define message structures */ +#include +#undef vl_endianfun + +/* instantiate all the print functions we know about */ +#define vl_print(handle, ...) +#define vl_printfun +#include +#undef vl_printfun + +#define __plugin_msg_base 0 +#include + +#if VPP_API_TEST_BUILTIN == 0 +#include + +u32 +vl (void *p) +{ + return vec_len (p); +} + +int +vat_socket_connect (vat_main_t * vam) +{ + vam->socket_client_main = &socket_client_main; + return vl_socket_client_connect ((char *) vam->socket_name, "vpp_api_test", + 0 /* default socket rx, tx buffer */ ); +} +#else /* vpp built-in case, we don't do sockets... */ +int +vat_socket_connect (vat_main_t * vam) +{ + return 0; +} + +int +vl_socket_client_read (int wait) +{ + return -1; +}; + +int +vl_socket_client_write () +{ + return -1; +}; + +void * +vl_socket_client_msg_alloc (int nbytes) +{ + return 0; +} +#endif + + +f64 +vat_time_now (vat_main_t * vam) +{ +#if VPP_API_TEST_BUILTIN + return vlib_time_now (vam->vlib_main); +#else + return clib_time_now (&vam->clib_time); +#endif +} + +void +errmsg (char *fmt, ...) +{ + vat_main_t *vam = &vat_main; + va_list va; + u8 *s; + + va_start (va, fmt); + s = va_format (0, fmt, &va); + va_end (va); + + vec_add1 (s, 0); + +#if VPP_API_TEST_BUILTIN + vlib_cli_output (vam->vlib_main, (char *) s); +#else + { + if (vam->ifp != stdin) + fformat (vam->ofp, "%s(%d): \n", vam->current_file, + vam->input_line_number); + fformat (vam->ofp, (char *) s); + fflush (vam->ofp); + } +#endif + + vec_free (s); +} + +#if VPP_API_TEST_BUILTIN == 0 +static uword +api_unformat_sw_if_index (unformat_input_t * input, va_list * args) +{ + vat_main_t *vam = va_arg (*args, vat_main_t *); + u32 *result = va_arg (*args, u32 *); + u8 *if_name; + uword *p; + + if (!unformat (input, "%s", &if_name)) + return 0; + + p = hash_get_mem (vam->sw_if_index_by_interface_name, if_name); + if (p == 0) + return 0; + *result = p[0]; + return 1; +} + +/* Parse an IP4 address %d.%d.%d.%d. */ +uword +unformat_ip4_address (unformat_input_t * input, va_list * args) +{ + u8 *result = va_arg (*args, u8 *); + unsigned a[4]; + + if (!unformat (input, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3])) + return 0; + + if (a[0] >= 256 || a[1] >= 256 || a[2] >= 256 || a[3] >= 256) + return 0; + + result[0] = a[0]; + result[1] = a[1]; + result[2] = a[2]; + result[3] = a[3]; + + return 1; +} + +uword +unformat_ethernet_address (unformat_input_t * input, va_list * args) +{ + u8 *result = va_arg (*args, u8 *); + u32 i, a[6]; + + if (!unformat (input, "%_%x:%x:%x:%x:%x:%x%_", + &a[0], &a[1], &a[2], &a[3], &a[4], &a[5])) + return 0; + + /* Check range. */ + for (i = 0; i < 6; i++) + if (a[i] >= (1 << 8)) + return 0; + + for (i = 0; i < 6; i++) + result[i] = a[i]; + + return 1; +} + +/* Returns ethernet type as an int in host byte order. */ +uword +unformat_ethernet_type_host_byte_order (unformat_input_t * input, + va_list * args) +{ + u16 *result = va_arg (*args, u16 *); + int type; + + /* Numeric type. */ + if (unformat (input, "0x%x", &type) || unformat (input, "%d", &type)) + { + if (type >= (1 << 16)) + return 0; + *result = type; + return 1; + } + return 0; +} + +/* Parse an IP6 address. */ +uword +unformat_ip6_address (unformat_input_t * input, va_list * args) +{ + ip6_address_t *result = va_arg (*args, ip6_address_t *); + u16 hex_quads[8]; + uword hex_quad, n_hex_quads, hex_digit, n_hex_digits; + uword c, n_colon, double_colon_index; + + n_hex_quads = hex_quad = n_hex_digits = n_colon = 0; + double_colon_index = ARRAY_LEN (hex_quads); + while ((c = unformat_get_input (input)) != UNFORMAT_END_OF_INPUT) + { + hex_digit = 16; + if (c >= '0' && c <= '9') + hex_digit = c - '0'; + else if (c >= 'a' && c <= 'f') + hex_digit = c + 10 - 'a'; + else if (c >= 'A' && c <= 'F') + hex_digit = c + 10 - 'A'; + else if (c == ':' && n_colon < 2) + n_colon++; + else + { + unformat_put_input (input); + break; + } + + /* Too many hex quads. */ + if (n_hex_quads >= ARRAY_LEN (hex_quads)) + return 0; + + if (hex_digit < 16) + { + hex_quad = (hex_quad << 4) | hex_digit; + + /* Hex quad must fit in 16 bits. */ + if (n_hex_digits >= 4) + return 0; + + n_colon = 0; + n_hex_digits++; + } + + /* Save position of :: */ + if (n_colon == 2) + { + /* More than one :: ? */ + if (double_colon_index < ARRAY_LEN (hex_quads)) + return 0; + double_colon_index = n_hex_quads; + } + + if (n_colon > 0 && n_hex_digits > 0) + { + hex_quads[n_hex_quads++] = hex_quad; + hex_quad = 0; + n_hex_digits = 0; + } + } + + if (n_hex_digits > 0) + hex_quads[n_hex_quads++] = hex_quad; + + { + word i; + + /* Expand :: to appropriate number of zero hex quads. */ + if (double_colon_index < ARRAY_LEN (hex_quads)) + { + word n_zero = ARRAY_LEN (hex_quads) - n_hex_quads; + + for (i = n_hex_quads - 1; i >= (signed) double_colon_index; i--) + hex_quads[n_zero + i] = hex_quads[i]; + + for (i = 0; i < n_zero; i++) + hex_quads[double_colon_index + i] = 0; + + n_hex_quads = ARRAY_LEN (hex_quads); + } + + /* Too few hex quads given. */ + if (n_hex_quads < ARRAY_LEN (hex_quads)) + return 0; + + for (i = 0; i < ARRAY_LEN (hex_quads); i++) + result->as_u16[i] = clib_host_to_net_u16 (hex_quads[i]); + + return 1; + } +} + +uword +unformat_ipsec_policy_action (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0); +#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_POLICY_ACTION_##f; + foreach_ipsec_policy_action +#undef _ + else + return 0; + return 1; +} + +uword +unformat_ipsec_crypto_alg (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0); +#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_CRYPTO_ALG_##f; + foreach_ipsec_crypto_alg +#undef _ + else + return 0; + return 1; +} + +u8 * +format_ipsec_crypto_alg (u8 * s, va_list * args) +{ + u32 i = va_arg (*args, u32); + u8 *t = 0; + + switch (i) + { +#define _(v,f,str) case IPSEC_CRYPTO_ALG_##f: t = (u8 *) str; break; + foreach_ipsec_crypto_alg +#undef _ + default: + return format (s, "unknown"); + } + return format (s, "%s", t); +} + +uword +unformat_ipsec_integ_alg (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0); +#define _(v,f,s) else if (unformat (input, s)) *r = IPSEC_INTEG_ALG_##f; + foreach_ipsec_integ_alg +#undef _ + else + return 0; + return 1; +} + +u8 * +format_ipsec_integ_alg (u8 * s, va_list * args) +{ + u32 i = va_arg (*args, u32); + u8 *t = 0; + + switch (i) + { +#define _(v,f,str) case IPSEC_INTEG_ALG_##f: t = (u8 *) str; break; + foreach_ipsec_integ_alg +#undef _ + default: + return format (s, "unknown"); + } + return format (s, "%s", t); +} + +uword +unformat_ikev2_auth_method (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0); +#define _(v,f,s) else if (unformat (input, s)) *r = IKEV2_AUTH_METHOD_##f; + foreach_ikev2_auth_method +#undef _ + else + return 0; + return 1; +} + +uword +unformat_ikev2_id_type (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (0); +#define _(v,f,s) else if (unformat (input, s)) *r = IKEV2_ID_TYPE_##f; + foreach_ikev2_id_type +#undef _ + else + return 0; + return 1; +} +#else /* VPP_API_TEST_BUILTIN == 1 */ +static uword +api_unformat_sw_if_index (unformat_input_t * input, va_list * args) +{ + vat_main_t *vam __attribute__ ((unused)) = va_arg (*args, vat_main_t *); + vnet_main_t *vnm = vnet_get_main (); + u32 *result = va_arg (*args, u32 *); + u32 sw_if_index; + + if (!unformat (input, "%U", unformat_vnet_sw_interface, vnm, &sw_if_index)) + return 0; + + *result = sw_if_index; + return 1; +} +#endif /* VPP_API_TEST_BUILTIN */ + +static 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; +} + +static 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; +} + +static 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; +} + +static uword +unformat_dscp (unformat_input_t * input, va_list * va) +{ + u8 *r = va_arg (*va, u8 *); + + if (0); +#define _(v,f,str) else if (unformat (input, str)) *r = VNET_DSCP_##f; + foreach_vnet_dscp +#undef _ + else + return 0; + return 1; +} + +static uword +unformat_policer_action_type (unformat_input_t * input, va_list * va) +{ + sse2_qos_pol_action_params_st *a + = va_arg (*va, sse2_qos_pol_action_params_st *); + + if (unformat (input, "drop")) + a->action_type = SSE2_QOS_ACTION_DROP; + else if (unformat (input, "transmit")) + a->action_type = SSE2_QOS_ACTION_TRANSMIT; + else if (unformat (input, "mark-and-transmit %U", unformat_dscp, &a->dscp)) + a->action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT; + else + return 0; + return 1; +} + +static uword +unformat_policer_classify_table_type (unformat_input_t * input, va_list * va) +{ + u32 *r = va_arg (*va, u32 *); + u32 tid; + + if (unformat (input, "ip4")) + tid = POLICER_CLASSIFY_TABLE_IP4; + else if (unformat (input, "ip6")) + tid = POLICER_CLASSIFY_TABLE_IP6; + else if (unformat (input, "l2")) + tid = POLICER_CLASSIFY_TABLE_L2; + else + return 0; + + *r = tid; + return 1; +} + +static uword +unformat_flow_classify_table_type (unformat_input_t * input, va_list * va) +{ + u32 *r = va_arg (*va, u32 *); + u32 tid; + + if (unformat (input, "ip4")) + tid = FLOW_CLASSIFY_TABLE_IP4; + else if (unformat (input, "ip6")) + tid = FLOW_CLASSIFY_TABLE_IP6; + else + return 0; + + *r = tid; + return 1; +} + +static const char *mfib_flag_names[] = MFIB_ENTRY_NAMES_SHORT; +static const char *mfib_flag_long_names[] = MFIB_ENTRY_NAMES_LONG; +static const char *mfib_itf_flag_long_names[] = MFIB_ITF_NAMES_LONG; +static const char *mfib_itf_flag_names[] = MFIB_ITF_NAMES_SHORT; + +#if (VPP_API_TEST_BUILTIN==0) +uword +unformat_mfib_itf_flags (unformat_input_t * input, va_list * args) +{ + mfib_itf_flags_t old, *iflags = va_arg (*args, mfib_itf_flags_t *); + mfib_itf_attribute_t attr; + + old = *iflags; + FOR_EACH_MFIB_ITF_ATTRIBUTE (attr) + { + if (unformat (input, mfib_itf_flag_long_names[attr])) + *iflags |= (1 << attr); + } + FOR_EACH_MFIB_ITF_ATTRIBUTE (attr) + { + if (unformat (input, mfib_itf_flag_names[attr])) + *iflags |= (1 << attr); + } + + return (old == *iflags ? 0 : 1); +} + +uword +unformat_mfib_entry_flags (unformat_input_t * input, va_list * args) +{ + mfib_entry_flags_t old, *eflags = va_arg (*args, mfib_entry_flags_t *); + mfib_entry_attribute_t attr; + + old = *eflags; + FOR_EACH_MFIB_ATTRIBUTE (attr) + { + if (unformat (input, mfib_flag_long_names[attr])) + *eflags |= (1 << attr); + } + FOR_EACH_MFIB_ATTRIBUTE (attr) + { + if (unformat (input, mfib_flag_names[attr])) + *eflags |= (1 << attr); + } + + return (old == *eflags ? 0 : 1); +} + +u8 * +format_ip4_address (u8 * s, va_list * args) +{ + u8 *a = va_arg (*args, u8 *); + return format (s, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]); +} + +u8 * +format_ip6_address (u8 * s, va_list * args) +{ + ip6_address_t *a = va_arg (*args, ip6_address_t *); + u32 i, i_max_n_zero, max_n_zeros, i_first_zero, n_zeros, last_double_colon; + + i_max_n_zero = ARRAY_LEN (a->as_u16); + max_n_zeros = 0; + i_first_zero = i_max_n_zero; + n_zeros = 0; + for (i = 0; i < ARRAY_LEN (a->as_u16); i++) + { + u32 is_zero = a->as_u16[i] == 0; + if (is_zero && i_first_zero >= ARRAY_LEN (a->as_u16)) + { + i_first_zero = i; + n_zeros = 0; + } + n_zeros += is_zero; + if ((!is_zero && n_zeros > max_n_zeros) + || (i + 1 >= ARRAY_LEN (a->as_u16) && n_zeros > max_n_zeros)) + { + i_max_n_zero = i_first_zero; + max_n_zeros = n_zeros; + i_first_zero = ARRAY_LEN (a->as_u16); + n_zeros = 0; + } + } + + last_double_colon = 0; + for (i = 0; i < ARRAY_LEN (a->as_u16); i++) + { + if (i == i_max_n_zero && max_n_zeros > 1) + { + s = format (s, "::"); + i += max_n_zeros - 1; + last_double_colon = 1; + } + else + { + s = format (s, "%s%x", + (last_double_colon || i == 0) ? "" : ":", + clib_net_to_host_u16 (a->as_u16[i])); + last_double_colon = 0; + } + } + + return s; +} + +/* Format an IP46 address. */ +u8 * +format_ip46_address (u8 * s, va_list * args) +{ + ip46_address_t *ip46 = va_arg (*args, ip46_address_t *); + ip46_type_t type = va_arg (*args, ip46_type_t); + int is_ip4 = 1; + + switch (type) + { + case IP46_TYPE_ANY: + is_ip4 = ip46_address_is_ip4 (ip46); + break; + case IP46_TYPE_IP4: + is_ip4 = 1; + break; + case IP46_TYPE_IP6: + is_ip4 = 0; + break; + } + + return is_ip4 ? + format (s, "%U", format_ip4_address, &ip46->ip4) : + format (s, "%U", format_ip6_address, &ip46->ip6); +} + +u8 * +format_ethernet_address (u8 * s, va_list * args) +{ + u8 *a = va_arg (*args, u8 *); + + return format (s, "%02x:%02x:%02x:%02x:%02x:%02x", + a[0], a[1], a[2], a[3], a[4], a[5]); +} +#endif + +static void +increment_v4_address (ip4_address_t * a) +{ + u32 v; + + v = ntohl (a->as_u32) + 1; + a->as_u32 = ntohl (v); +} + +static void +increment_v6_address (ip6_address_t * a) +{ + u64 v0, v1; + + v0 = clib_net_to_host_u64 (a->as_u64[0]); + v1 = clib_net_to_host_u64 (a->as_u64[1]); + + v1 += 1; + if (v1 == 0) + v0 += 1; + a->as_u64[0] = clib_net_to_host_u64 (v0); + a->as_u64[1] = clib_net_to_host_u64 (v1); +} + +static void +increment_mac_address (u8 * mac) +{ + u64 tmp = *((u64 *) mac); + tmp = clib_net_to_host_u64 (tmp); + tmp += 1 << 16; /* skip unused (least significant) octets */ + tmp = clib_host_to_net_u64 (tmp); + + clib_memcpy (mac, &tmp, 6); +} + +static void vl_api_create_loopback_reply_t_handler + (vl_api_create_loopback_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; +} + +static void vl_api_create_loopback_reply_t_handler_json + (vl_api_create_loopback_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_create_loopback_instance_reply_t_handler + (vl_api_create_loopback_instance_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; +} + +static void vl_api_create_loopback_instance_reply_t_handler_json + (vl_api_create_loopback_instance_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_af_packet_create_reply_t_handler + (vl_api_af_packet_create_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; +} + +static void vl_api_af_packet_create_reply_t_handler_json + (vl_api_af_packet_create_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_create_vlan_subif_reply_t_handler + (vl_api_create_vlan_subif_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; +} + +static void vl_api_create_vlan_subif_reply_t_handler_json + (vl_api_create_vlan_subif_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_create_subif_reply_t_handler + (vl_api_create_subif_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; +} + +static void vl_api_create_subif_reply_t_handler_json + (vl_api_create_subif_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_interface_name_renumber_reply_t_handler + (vl_api_interface_name_renumber_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->regenerate_interface_table = 1; + vam->result_ready = 1; +} + +static void vl_api_interface_name_renumber_reply_t_handler_json + (vl_api_interface_name_renumber_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +/* + * Special-case: build the interface table, maintain + * the next loopback sw_if_index vbl. + */ +static void vl_api_sw_interface_details_t_handler + (vl_api_sw_interface_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *s = format (0, "%s%c", mp->interface_name, 0); + + hash_set_mem (vam->sw_if_index_by_interface_name, s, + ntohl (mp->sw_if_index)); + + /* In sub interface case, fill the sub interface table entry */ + if (mp->sw_if_index != mp->sup_sw_if_index) + { + sw_interface_subif_t *sub = NULL; + + vec_add2 (vam->sw_if_subif_table, sub, 1); + + vec_validate (sub->interface_name, strlen ((char *) s) + 1); + strncpy ((char *) sub->interface_name, (char *) s, + vec_len (sub->interface_name)); + sub->sw_if_index = ntohl (mp->sw_if_index); + sub->sub_id = ntohl (mp->sub_id); + + sub->sub_dot1ad = mp->sub_dot1ad; + sub->sub_number_of_tags = mp->sub_number_of_tags; + sub->sub_outer_vlan_id = ntohs (mp->sub_outer_vlan_id); + sub->sub_inner_vlan_id = ntohs (mp->sub_inner_vlan_id); + sub->sub_exact_match = mp->sub_exact_match; + sub->sub_default = mp->sub_default; + sub->sub_outer_vlan_id_any = mp->sub_outer_vlan_id_any; + sub->sub_inner_vlan_id_any = mp->sub_inner_vlan_id_any; + + /* vlan tag rewrite */ + sub->vtr_op = ntohl (mp->vtr_op); + sub->vtr_push_dot1q = ntohl (mp->vtr_push_dot1q); + sub->vtr_tag1 = ntohl (mp->vtr_tag1); + sub->vtr_tag2 = ntohl (mp->vtr_tag2); + } +} + +static void vl_api_sw_interface_details_t_handler_json + (vl_api_sw_interface_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_uint (node, "sup_sw_if_index", + ntohl (mp->sup_sw_if_index)); + vat_json_object_add_uint (node, "l2_address_length", + ntohl (mp->l2_address_length)); + vat_json_object_add_bytes (node, "l2_address", mp->l2_address, + sizeof (mp->l2_address)); + vat_json_object_add_string_copy (node, "interface_name", + mp->interface_name); + vat_json_object_add_uint (node, "admin_up_down", mp->admin_up_down); + vat_json_object_add_uint (node, "link_up_down", mp->link_up_down); + vat_json_object_add_uint (node, "link_duplex", mp->link_duplex); + vat_json_object_add_uint (node, "link_speed", mp->link_speed); + vat_json_object_add_uint (node, "mtu", ntohs (mp->link_mtu)); + vat_json_object_add_uint (node, "sub_id", ntohl (mp->sub_id)); + vat_json_object_add_uint (node, "sub_dot1ad", mp->sub_dot1ad); + vat_json_object_add_uint (node, "sub_number_of_tags", + mp->sub_number_of_tags); + vat_json_object_add_uint (node, "sub_outer_vlan_id", + ntohs (mp->sub_outer_vlan_id)); + vat_json_object_add_uint (node, "sub_inner_vlan_id", + ntohs (mp->sub_inner_vlan_id)); + vat_json_object_add_uint (node, "sub_exact_match", mp->sub_exact_match); + vat_json_object_add_uint (node, "sub_default", mp->sub_default); + vat_json_object_add_uint (node, "sub_outer_vlan_id_any", + mp->sub_outer_vlan_id_any); + vat_json_object_add_uint (node, "sub_inner_vlan_id_any", + mp->sub_inner_vlan_id_any); + vat_json_object_add_uint (node, "vtr_op", ntohl (mp->vtr_op)); + vat_json_object_add_uint (node, "vtr_push_dot1q", + ntohl (mp->vtr_push_dot1q)); + vat_json_object_add_uint (node, "vtr_tag1", ntohl (mp->vtr_tag1)); + vat_json_object_add_uint (node, "vtr_tag2", ntohl (mp->vtr_tag2)); + if (mp->sub_dot1ah) + { + vat_json_object_add_string_copy (node, "pbb_vtr_dmac", + format (0, "%U", + format_ethernet_address, + &mp->b_dmac)); + vat_json_object_add_string_copy (node, "pbb_vtr_smac", + format (0, "%U", + format_ethernet_address, + &mp->b_smac)); + vat_json_object_add_uint (node, "pbb_vtr_b_vlanid", mp->b_vlanid); + vat_json_object_add_uint (node, "pbb_vtr_i_sid", mp->i_sid); + } +} + +#if VPP_API_TEST_BUILTIN == 0 +static void vl_api_sw_interface_event_t_handler + (vl_api_sw_interface_event_t * mp) +{ + vat_main_t *vam = &vat_main; + if (vam->interface_event_display) + errmsg ("interface flags: sw_if_index %d %s %s", + ntohl (mp->sw_if_index), + mp->admin_up_down ? "admin-up" : "admin-down", + mp->link_up_down ? "link-up" : "link-down"); +} +#endif + +static void vl_api_sw_interface_event_t_handler_json + (vl_api_sw_interface_event_t * mp) +{ + /* JSON output not supported */ +} + +static void +vl_api_cli_reply_t_handler (vl_api_cli_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vam->retval = retval; + vam->shmem_result = uword_to_pointer (mp->reply_in_shmem, u8 *); + vam->result_ready = 1; +} + +static void +vl_api_cli_reply_t_handler_json (vl_api_cli_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + api_main_t *am = &api_main; + void *oldheap; + u8 *reply; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "reply_in_shmem", + ntohl (mp->reply_in_shmem)); + /* Toss the shared-memory original... */ + pthread_mutex_lock (&am->vlib_rp->mutex); + oldheap = svm_push_data_heap (am->vlib_rp); + + reply = uword_to_pointer (mp->reply_in_shmem, u8 *); + vec_free (reply); + + svm_pop_heap (oldheap); + pthread_mutex_unlock (&am->vlib_rp->mutex); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_cli_inband_reply_t_handler (vl_api_cli_inband_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + u32 length = ntohl (mp->length); + + vec_reset_length (vam->cmd_reply); + + vam->retval = retval; + if (retval == 0) + { + vec_validate (vam->cmd_reply, length); + clib_memcpy ((char *) (vam->cmd_reply), mp->reply, length); + vam->cmd_reply[length] = 0; + } + vam->result_ready = 1; +} + +static void +vl_api_cli_inband_reply_t_handler_json (vl_api_cli_inband_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vec_reset_length (vam->cmd_reply); + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_string_copy (&node, "reply", mp->reply); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_classify_add_del_table_reply_t_handler + (vl_api_classify_add_del_table_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + if (retval == 0 && + ((mp->new_table_index != 0xFFFFFFFF) || + (mp->skip_n_vectors != 0xFFFFFFFF) || + (mp->match_n_vectors != 0xFFFFFFFF))) + /* + * Note: this is just barely thread-safe, depends on + * the main thread spinning waiting for an answer... + */ + errmsg ("new index %d, skip_n_vectors %d, match_n_vectors %d", + ntohl (mp->new_table_index), + ntohl (mp->skip_n_vectors), ntohl (mp->match_n_vectors)); + vam->result_ready = 1; + } +} + +static void vl_api_classify_add_del_table_reply_t_handler_json + (vl_api_classify_add_del_table_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "new_table_index", + ntohl (mp->new_table_index)); + vat_json_object_add_uint (&node, "skip_n_vectors", + ntohl (mp->skip_n_vectors)); + vat_json_object_add_uint (&node, "match_n_vectors", + ntohl (mp->match_n_vectors)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_get_node_index_reply_t_handler + (vl_api_get_node_index_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + if (retval == 0) + errmsg ("node index %d", ntohl (mp->node_index)); + vam->result_ready = 1; + } +} + +static void vl_api_get_node_index_reply_t_handler_json + (vl_api_get_node_index_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "node_index", ntohl (mp->node_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_get_next_index_reply_t_handler + (vl_api_get_next_index_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + if (retval == 0) + errmsg ("next node index %d", ntohl (mp->next_index)); + vam->result_ready = 1; + } +} + +static void vl_api_get_next_index_reply_t_handler_json + (vl_api_get_next_index_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_add_node_next_reply_t_handler + (vl_api_add_node_next_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + if (retval == 0) + errmsg ("next index %d", ntohl (mp->next_index)); + vam->result_ready = 1; + } +} + +static void vl_api_add_node_next_reply_t_handler_json + (vl_api_add_node_next_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "next_index", ntohl (mp->next_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_show_version_reply_t_handler + (vl_api_show_version_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (retval >= 0) + { + errmsg (" program: %s", mp->program); + errmsg (" version: %s", mp->version); + errmsg (" build date: %s", mp->build_date); + errmsg ("build directory: %s", mp->build_directory); + } + vam->retval = retval; + vam->result_ready = 1; +} + +static void vl_api_show_version_reply_t_handler_json + (vl_api_show_version_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_string_copy (&node, "program", mp->program); + vat_json_object_add_string_copy (&node, "version", mp->version); + vat_json_object_add_string_copy (&node, "build_date", mp->build_date); + vat_json_object_add_string_copy (&node, "build_directory", + mp->build_directory); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_ip4_arp_event_t_handler (vl_api_ip4_arp_event_t * mp) +{ + u32 sw_if_index = ntohl (mp->sw_if_index); + errmsg ("arp %s event: pid %d address %U new mac %U sw_if_index %d\n", + mp->mac_ip ? "mac/ip binding" : "address resolution", + ntohl (mp->pid), format_ip4_address, &mp->address, + format_ethernet_address, mp->new_mac, sw_if_index); +} + +static void +vl_api_ip4_arp_event_t_handler_json (vl_api_ip4_arp_event_t * mp) +{ + /* JSON output not supported */ +} + +static void +vl_api_ip6_nd_event_t_handler (vl_api_ip6_nd_event_t * mp) +{ + u32 sw_if_index = ntohl (mp->sw_if_index); + errmsg ("ip6 nd %s event: pid %d address %U new mac %U sw_if_index %d\n", + mp->mac_ip ? "mac/ip binding" : "address resolution", + ntohl (mp->pid), format_ip6_address, mp->address, + format_ethernet_address, mp->new_mac, sw_if_index); +} + +static void +vl_api_ip6_nd_event_t_handler_json (vl_api_ip6_nd_event_t * mp) +{ + /* JSON output not supported */ +} + +static void +vl_api_l2_macs_event_t_handler (vl_api_l2_macs_event_t * mp) +{ + u32 n_macs = ntohl (mp->n_macs); + errmsg ("L2MAC event recived with pid %d cl-idx %d for %d macs: \n", + ntohl (mp->pid), mp->client_index, n_macs); + int i; + for (i = 0; i < n_macs; i++) + { + vl_api_mac_entry_t *mac = &mp->mac[i]; + errmsg (" [%d] sw_if_index %d mac_addr %U is_del %d \n", + i + 1, ntohl (mac->sw_if_index), + format_ethernet_address, mac->mac_addr, mac->is_del); + if (i == 1000) + break; + } +} + +static void +vl_api_l2_macs_event_t_handler_json (vl_api_l2_macs_event_t * mp) +{ + /* JSON output not supported */ +} + +#define vl_api_bridge_domain_details_t_endian vl_noop_handler +#define vl_api_bridge_domain_details_t_print vl_noop_handler + +/* + * Special-case: build the bridge domain table, maintain + * the next bd id vbl. + */ +static void vl_api_bridge_domain_details_t_handler + (vl_api_bridge_domain_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 n_sw_ifs = ntohl (mp->n_sw_ifs); + int i; + + print (vam->ofp, "\n%-3s %-3s %-3s %-3s %-3s %-3s", + " ID", "LRN", "FWD", "FLD", "BVI", "#IF"); + + print (vam->ofp, "%3d %3d %3d %3d %3d %3d", + ntohl (mp->bd_id), mp->learn, mp->forward, + mp->flood, ntohl (mp->bvi_sw_if_index), n_sw_ifs); + + if (n_sw_ifs) + { + vl_api_bridge_domain_sw_if_t *sw_ifs; + print (vam->ofp, "\n\n%s %s %s", "sw_if_index", "SHG", + "Interface Name"); + + sw_ifs = mp->sw_if_details; + for (i = 0; i < n_sw_ifs; i++) + { + u8 *sw_if_name = 0; + u32 sw_if_index; + hash_pair_t *p; + + sw_if_index = ntohl (sw_ifs->sw_if_index); + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, + ({ + if ((u32) p->value[0] == sw_if_index) + { + sw_if_name = (u8 *)(p->key); + break; + } + })); + /* *INDENT-ON* */ + print (vam->ofp, "%7d %3d %s", sw_if_index, + sw_ifs->shg, sw_if_name ? (char *) sw_if_name : + "sw_if_index not found!"); + + sw_ifs++; + } + } +} + +static void vl_api_bridge_domain_details_t_handler_json + (vl_api_bridge_domain_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node, *array = NULL; + u32 n_sw_ifs = ntohl (mp->n_sw_ifs); + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id)); + vat_json_object_add_uint (node, "flood", mp->flood); + vat_json_object_add_uint (node, "forward", mp->forward); + vat_json_object_add_uint (node, "learn", mp->learn); + vat_json_object_add_uint (node, "bvi_sw_if_index", + ntohl (mp->bvi_sw_if_index)); + vat_json_object_add_uint (node, "n_sw_ifs", n_sw_ifs); + array = vat_json_object_add (node, "sw_if"); + vat_json_init_array (array); + + + + if (n_sw_ifs) + { + vl_api_bridge_domain_sw_if_t *sw_ifs; + int i; + + sw_ifs = mp->sw_if_details; + for (i = 0; i < n_sw_ifs; i++) + { + node = vat_json_array_add (array); + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", + ntohl (sw_ifs->sw_if_index)); + vat_json_object_add_uint (node, "shg", sw_ifs->shg); + sw_ifs++; + } + } +} + +static void vl_api_control_ping_reply_t_handler + (vl_api_control_ping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } + if (vam->socket_client_main) + vam->socket_client_main->control_pings_outstanding--; +} + +static void vl_api_control_ping_reply_t_handler_json + (vl_api_control_ping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (VAT_JSON_NONE != vam->json_tree.type) + { + vat_json_print (vam->ofp, &vam->json_tree); + vat_json_free (&vam->json_tree); + vam->json_tree.type = VAT_JSON_NONE; + } + else + { + /* just print [] */ + vat_json_init_array (&vam->json_tree); + vat_json_print (vam->ofp, &vam->json_tree); + vam->json_tree.type = VAT_JSON_NONE; + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_bridge_domain_set_mac_age_reply_t_handler + (vl_api_bridge_domain_set_mac_age_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_bridge_domain_set_mac_age_reply_t_handler_json + (vl_api_bridge_domain_set_mac_age_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_l2_flags_reply_t_handler (vl_api_l2_flags_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_l2_flags_reply_t_handler_json + (vl_api_l2_flags_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "resulting_feature_bitmap", + ntohl (mp->resulting_feature_bitmap)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_bridge_flags_reply_t_handler + (vl_api_bridge_flags_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_bridge_flags_reply_t_handler_json + (vl_api_bridge_flags_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "resulting_feature_bitmap", + ntohl (mp->resulting_feature_bitmap)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_tap_connect_reply_t_handler + (vl_api_tap_connect_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } + +} + +static void vl_api_tap_connect_reply_t_handler_json + (vl_api_tap_connect_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; + +} + +static void +vl_api_tap_modify_reply_t_handler (vl_api_tap_modify_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_tap_modify_reply_t_handler_json + (vl_api_tap_modify_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_tap_delete_reply_t_handler (vl_api_tap_delete_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_tap_delete_reply_t_handler_json + (vl_api_tap_delete_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_tap_create_v2_reply_t_handler (vl_api_tap_create_v2_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } + +} + +static void vl_api_tap_create_v2_reply_t_handler_json + (vl_api_tap_create_v2_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; + +} + +static void +vl_api_tap_delete_v2_reply_t_handler (vl_api_tap_delete_v2_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_tap_delete_v2_reply_t_handler_json + (vl_api_tap_delete_v2_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_mpls_tunnel_add_del_reply_t_handler + (vl_api_mpls_tunnel_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_mpls_tunnel_add_del_reply_t_handler_json + (vl_api_mpls_tunnel_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "tunnel_sw_if_index", + ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_l2tpv3_create_tunnel_reply_t_handler + (vl_api_l2tpv3_create_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_l2tpv3_create_tunnel_reply_t_handler_json + (vl_api_l2tpv3_create_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_gpe_add_del_fwd_entry_reply_t_handler + (vl_api_gpe_add_del_fwd_entry_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_gpe_add_del_fwd_entry_reply_t_handler_json + (vl_api_gpe_add_del_fwd_entry_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "fwd_entry_index", + clib_net_to_host_u32 (mp->fwd_entry_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +u8 * +format_lisp_transport_protocol (u8 * s, va_list * args) +{ + u32 proto = va_arg (*args, u32); + + switch (proto) + { + case 1: + return format (s, "udp"); + case 2: + return format (s, "api"); + default: + return 0; + } + return 0; +} + +static void vl_api_one_get_transport_protocol_reply_t_handler + (vl_api_one_get_transport_protocol_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + u32 proto = mp->protocol; + print (vam->ofp, "Transport protocol: %U", + format_lisp_transport_protocol, proto); + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_one_get_transport_protocol_reply_t_handler_json + (vl_api_one_get_transport_protocol_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *s; + + s = format (0, "%U", format_lisp_transport_protocol, mp->protocol); + vec_add1 (s, 0); + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_string_copy (&node, "transport-protocol", s); + + vec_free (s); + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_one_add_del_locator_set_reply_t_handler + (vl_api_one_add_del_locator_set_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_one_add_del_locator_set_reply_t_handler_json + (vl_api_one_add_del_locator_set_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "locator_set_index", ntohl (mp->ls_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_vxlan_add_del_tunnel_reply_t_handler + (vl_api_vxlan_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_vxlan_add_del_tunnel_reply_t_handler_json + (vl_api_vxlan_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_geneve_add_del_tunnel_reply_t_handler + (vl_api_geneve_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_geneve_add_del_tunnel_reply_t_handler_json + (vl_api_geneve_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler + (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_vxlan_gpe_add_del_tunnel_reply_t_handler_json + (vl_api_vxlan_gpe_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_gre_add_del_tunnel_reply_t_handler + (vl_api_gre_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_gre_add_del_tunnel_reply_t_handler_json + (vl_api_gre_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_create_vhost_user_if_reply_t_handler + (vl_api_create_vhost_user_if_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_create_vhost_user_if_reply_t_handler_json + (vl_api_create_vhost_user_if_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static clib_error_t * +receive_fd_msg (int socket_fd, int *my_fd) +{ + char msgbuf[16]; + char ctl[CMSG_SPACE (sizeof (int)) + CMSG_SPACE (sizeof (struct ucred))]; + struct msghdr mh = { 0 }; + struct iovec iov[1]; + ssize_t size; + struct ucred *cr = 0; + struct cmsghdr *cmsg; + pid_t pid __attribute__ ((unused)); + uid_t uid __attribute__ ((unused)); + gid_t gid __attribute__ ((unused)); + + iov[0].iov_base = msgbuf; + iov[0].iov_len = 5; + mh.msg_iov = iov; + mh.msg_iovlen = 1; + mh.msg_control = ctl; + mh.msg_controllen = sizeof (ctl); + + memset (ctl, 0, sizeof (ctl)); + + /* receive the incoming message */ + size = recvmsg (socket_fd, &mh, 0); + if (size != 5) + { + return (size == 0) ? clib_error_return (0, "disconnected") : + clib_error_return_unix (0, "recvmsg: malformed message (fd %d)", + socket_fd); + } + + cmsg = CMSG_FIRSTHDR (&mh); + while (cmsg) + { + if (cmsg->cmsg_level == SOL_SOCKET) + { + if (cmsg->cmsg_type == SCM_CREDENTIALS) + { + cr = (struct ucred *) CMSG_DATA (cmsg); + uid = cr->uid; + gid = cr->gid; + pid = cr->pid; + } + else if (cmsg->cmsg_type == SCM_RIGHTS) + { + clib_memcpy (my_fd, CMSG_DATA (cmsg), sizeof (int)); + } + } + cmsg = CMSG_NXTHDR (&mh, cmsg); + } + return 0; +} + +static void vl_api_memfd_segment_create_reply_t_handler + (vl_api_memfd_segment_create_reply_t * mp) +{ + /* Dont bother in the builtin version */ +#if VPP_API_TEST_BUILTIN == 0 + vat_main_t *vam = &vat_main; + api_main_t *am = &api_main; + socket_client_main_t *scm = vam->socket_client_main; + int my_fd = -1; + clib_error_t *error; + memfd_private_t memfd; + i32 retval = ntohl (mp->retval); + + if (retval == 0) + { + error = receive_fd_msg (scm->socket_fd, &my_fd); + if (error) + { + retval = -99; + goto out; + } + + memset (&memfd, 0, sizeof (memfd)); + memfd.fd = my_fd; + + vam->client_index_invalid = 1; + + /* Note: this closes memfd.fd */ + retval = memfd_slave_init (&memfd); + if (retval) + clib_warning ("WARNING: segment map returned %d", retval); + + /* Pivot to the memory client segment that vpp just created */ + + am->vlib_rp = (void *) (memfd.requested_va + MMAP_PAGESIZE); + + am->shmem_hdr = (void *) am->vlib_rp->user_ctx; + + vl_client_install_client_message_handlers (); + + vl_client_connect_to_vlib_no_map ("pvt", + "vpp_api_test(p)", + 32 /* input_queue_length */ ); + vam->vl_input_queue = am->shmem_hdr->vl_input_queue; + + vl_socket_client_enable_disable (0 /* disable socket */ ); + } + +out: + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +#endif +} + +static void vl_api_memfd_segment_create_reply_t_handler_json + (vl_api_memfd_segment_create_reply_t * mp) +{ + clib_warning ("no"); +} + +static void vl_api_dns_resolve_name_reply_t_handler + (vl_api_dns_resolve_name_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + + if (retval == 0) + { + if (mp->ip4_set) + clib_warning ("ip4 address %U", format_ip4_address, + (ip4_address_t *) mp->ip4_address); + if (mp->ip6_set) + clib_warning ("ip6 address %U", format_ip6_address, + (ip6_address_t *) mp->ip6_address); + } + else + clib_warning ("retval %d", retval); + } +} + +static void vl_api_dns_resolve_name_reply_t_handler_json + (vl_api_dns_resolve_name_reply_t * mp) +{ + clib_warning ("not implemented"); +} + +static void vl_api_dns_resolve_ip_reply_t_handler + (vl_api_dns_resolve_ip_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + + if (retval == 0) + { + clib_warning ("canonical name %s", mp->name); + } + else + clib_warning ("retval %d", retval); + } +} + +static void vl_api_dns_resolve_ip_reply_t_handler_json + (vl_api_dns_resolve_ip_reply_t * mp) +{ + clib_warning ("not implemented"); +} + + +static void vl_api_ip_address_details_t_handler + (vl_api_ip_address_details_t * mp) +{ + vat_main_t *vam = &vat_main; + static ip_address_details_t empty_ip_address_details = { {0} }; + ip_address_details_t *address = NULL; + ip_details_t *current_ip_details = NULL; + ip_details_t *details = NULL; + + details = vam->ip_details_by_sw_if_index[vam->is_ipv6]; + + if (!details || vam->current_sw_if_index >= vec_len (details) + || !details[vam->current_sw_if_index].present) + { + errmsg ("ip address details arrived but not stored"); + errmsg ("ip_dump should be called first"); + return; + } + + current_ip_details = vec_elt_at_index (details, vam->current_sw_if_index); + +#define addresses (current_ip_details->addr) + + vec_validate_init_empty (addresses, vec_len (addresses), + empty_ip_address_details); + + address = vec_elt_at_index (addresses, vec_len (addresses) - 1); + + clib_memcpy (&address->ip, &mp->ip, sizeof (address->ip)); + address->prefix_length = mp->prefix_length; +#undef addresses +} + +static void vl_api_ip_address_details_t_handler_json + (vl_api_ip_address_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + if (vam->is_ipv6) + { + clib_memcpy (&ip6, mp->ip, sizeof (ip6)); + vat_json_object_add_ip6 (node, "ip", ip6); + } + else + { + clib_memcpy (&ip4, mp->ip, sizeof (ip4)); + vat_json_object_add_ip4 (node, "ip", ip4); + } + vat_json_object_add_uint (node, "prefix_length", mp->prefix_length); +} + +static void +vl_api_ip_details_t_handler (vl_api_ip_details_t * mp) +{ + vat_main_t *vam = &vat_main; + static ip_details_t empty_ip_details = { 0 }; + ip_details_t *ip = NULL; + u32 sw_if_index = ~0; + + sw_if_index = ntohl (mp->sw_if_index); + + vec_validate_init_empty (vam->ip_details_by_sw_if_index[vam->is_ipv6], + sw_if_index, empty_ip_details); + + ip = vec_elt_at_index (vam->ip_details_by_sw_if_index[vam->is_ipv6], + sw_if_index); + + ip->present = 1; +} + +static void +vl_api_ip_details_t_handler_json (vl_api_ip_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + vat_json_array_add_uint (&vam->json_tree, + clib_net_to_host_u32 (mp->sw_if_index)); +} + +static void vl_api_map_domain_details_t_handler_json + (vl_api_map_domain_details_t * mp) +{ + vat_json_node_t *node = NULL; + vat_main_t *vam = &vat_main; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + vat_json_object_add_uint (node, "domain_index", + clib_net_to_host_u32 (mp->domain_index)); + clib_memcpy (&ip6, mp->ip6_prefix, sizeof (ip6)); + vat_json_object_add_ip6 (node, "ip6_prefix", ip6); + clib_memcpy (&ip4, mp->ip4_prefix, sizeof (ip4)); + vat_json_object_add_ip4 (node, "ip4_prefix", ip4); + clib_memcpy (&ip6, mp->ip6_src, sizeof (ip6)); + vat_json_object_add_ip6 (node, "ip6_src", ip6); + vat_json_object_add_int (node, "ip6_prefix_len", mp->ip6_prefix_len); + vat_json_object_add_int (node, "ip4_prefix_len", mp->ip4_prefix_len); + vat_json_object_add_int (node, "ip6_src_len", mp->ip6_src_len); + vat_json_object_add_int (node, "ea_bits_len", mp->ea_bits_len); + vat_json_object_add_int (node, "psid_offset", mp->psid_offset); + vat_json_object_add_int (node, "psid_length", mp->psid_length); + vat_json_object_add_uint (node, "flags", mp->flags); + vat_json_object_add_uint (node, "mtu", clib_net_to_host_u16 (mp->mtu)); + vat_json_object_add_int (node, "is_translation", mp->is_translation); +} + +static void vl_api_map_domain_details_t_handler + (vl_api_map_domain_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + if (mp->is_translation) + { + print (vam->ofp, + "* %U/%d (ipv4-prefix) %U/%d (ipv6-prefix) %U/%d (ip6-src) index: %u", + format_ip4_address, mp->ip4_prefix, mp->ip4_prefix_len, + format_ip6_address, mp->ip6_prefix, mp->ip6_prefix_len, + format_ip6_address, mp->ip6_src, mp->ip6_src_len, + clib_net_to_host_u32 (mp->domain_index)); + } + else + { + print (vam->ofp, + "* %U/%d (ipv4-prefix) %U/%d (ipv6-prefix) %U (ip6-src) index: %u", + format_ip4_address, mp->ip4_prefix, mp->ip4_prefix_len, + format_ip6_address, mp->ip6_prefix, mp->ip6_prefix_len, + format_ip6_address, mp->ip6_src, + clib_net_to_host_u32 (mp->domain_index)); + } + print (vam->ofp, " ea-len %d psid-offset %d psid-len %d mtu %d %s", + mp->ea_bits_len, mp->psid_offset, mp->psid_length, mp->mtu, + mp->is_translation ? "map-t" : ""); +} + +static void vl_api_map_rule_details_t_handler_json + (vl_api_map_rule_details_t * mp) +{ + struct in6_addr ip6; + vat_json_node_t *node = NULL; + vat_main_t *vam = &vat_main; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + vat_json_object_add_uint (node, "psid", clib_net_to_host_u16 (mp->psid)); + clib_memcpy (&ip6, mp->ip6_dst, sizeof (ip6)); + vat_json_object_add_ip6 (node, "ip6_dst", ip6); +} + +static void +vl_api_map_rule_details_t_handler (vl_api_map_rule_details_t * mp) +{ + vat_main_t *vam = &vat_main; + print (vam->ofp, " %d (psid) %U (ip6-dst)", + clib_net_to_host_u16 (mp->psid), format_ip6_address, mp->ip6_dst); +} + +static void +vl_api_dhcp_compl_event_t_handler (vl_api_dhcp_compl_event_t * mp) +{ + errmsg ("DHCP compl event: pid %d %s hostname %s host_addr %U " + "router_addr %U host_mac %U", + ntohl (mp->pid), mp->is_ipv6 ? "ipv6" : "ipv4", mp->hostname, + format_ip4_address, &mp->host_address, + format_ip4_address, &mp->router_address, + format_ethernet_address, mp->host_mac); +} + +static void vl_api_dhcp_compl_event_t_handler_json + (vl_api_dhcp_compl_event_t * mp) +{ + /* JSON output not supported */ +} + +static void +set_simple_interface_counter (u8 vnet_counter_type, u32 sw_if_index, + u32 counter) +{ + vat_main_t *vam = &vat_main; + static u64 default_counter = 0; + + vec_validate_init_empty (vam->simple_interface_counters, vnet_counter_type, + NULL); + vec_validate_init_empty (vam->simple_interface_counters[vnet_counter_type], + sw_if_index, default_counter); + vam->simple_interface_counters[vnet_counter_type][sw_if_index] = counter; +} + +static void +set_combined_interface_counter (u8 vnet_counter_type, u32 sw_if_index, + interface_counter_t counter) +{ + vat_main_t *vam = &vat_main; + static interface_counter_t default_counter = { 0, }; + + vec_validate_init_empty (vam->combined_interface_counters, + vnet_counter_type, NULL); + vec_validate_init_empty (vam->combined_interface_counters + [vnet_counter_type], sw_if_index, default_counter); + vam->combined_interface_counters[vnet_counter_type][sw_if_index] = counter; +} + +static void vl_api_vnet_interface_simple_counters_t_handler + (vl_api_vnet_interface_simple_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_interface_combined_counters_t_handler + (vl_api_vnet_interface_combined_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_interface_simple_counters_t_handler_json + (vl_api_vnet_interface_simple_counters_t * mp) +{ + u64 *v_packets; + u64 packets; + u32 count; + u32 first_sw_if_index; + int i; + + count = ntohl (mp->count); + first_sw_if_index = ntohl (mp->first_sw_if_index); + + v_packets = (u64 *) & mp->data; + for (i = 0; i < count; i++) + { + packets = clib_net_to_host_u64 (clib_mem_unaligned (v_packets, u64)); + set_simple_interface_counter (mp->vnet_counter_type, + first_sw_if_index + i, packets); + v_packets++; + } +} + +static void vl_api_vnet_interface_combined_counters_t_handler_json + (vl_api_vnet_interface_combined_counters_t * mp) +{ + interface_counter_t counter; + vlib_counter_t *v; + u32 first_sw_if_index; + int i; + u32 count; + + count = ntohl (mp->count); + first_sw_if_index = ntohl (mp->first_sw_if_index); + + v = (vlib_counter_t *) & mp->data; + for (i = 0; i < count; i++) + { + counter.packets = + clib_net_to_host_u64 (clib_mem_unaligned (&v->packets, u64)); + counter.bytes = + clib_net_to_host_u64 (clib_mem_unaligned (&v->bytes, u64)); + set_combined_interface_counter (mp->vnet_counter_type, + first_sw_if_index + i, counter); + v++; + } +} + +static u32 +ip4_fib_counters_get_vrf_index_by_vrf_id (u32 vrf_id) +{ + vat_main_t *vam = &vat_main; + u32 i; + + for (i = 0; i < vec_len (vam->ip4_fib_counters_vrf_id_by_index); i++) + { + if (vam->ip4_fib_counters_vrf_id_by_index[i] == vrf_id) + { + return i; + } + } + return ~0; +} + +static u32 +ip6_fib_counters_get_vrf_index_by_vrf_id (u32 vrf_id) +{ + vat_main_t *vam = &vat_main; + u32 i; + + for (i = 0; i < vec_len (vam->ip6_fib_counters_vrf_id_by_index); i++) + { + if (vam->ip6_fib_counters_vrf_id_by_index[i] == vrf_id) + { + return i; + } + } + return ~0; +} + +static void vl_api_vnet_ip4_fib_counters_t_handler + (vl_api_vnet_ip4_fib_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_ip4_fib_counters_t_handler_json + (vl_api_vnet_ip4_fib_counters_t * mp) +{ + vat_main_t *vam = &vat_main; + vl_api_ip4_fib_counter_t *v; + ip4_fib_counter_t *counter; + struct in_addr ip4; + u32 vrf_id; + u32 vrf_index; + u32 count; + int i; + + vrf_id = ntohl (mp->vrf_id); + vrf_index = ip4_fib_counters_get_vrf_index_by_vrf_id (vrf_id); + if (~0 == vrf_index) + { + vrf_index = vec_len (vam->ip4_fib_counters_vrf_id_by_index); + vec_validate (vam->ip4_fib_counters_vrf_id_by_index, vrf_index); + vam->ip4_fib_counters_vrf_id_by_index[vrf_index] = vrf_id; + vec_validate (vam->ip4_fib_counters, vrf_index); + vam->ip4_fib_counters[vrf_index] = NULL; + } + + vec_free (vam->ip4_fib_counters[vrf_index]); + v = (vl_api_ip4_fib_counter_t *) & mp->c; + count = ntohl (mp->count); + for (i = 0; i < count; i++) + { + vec_validate (vam->ip4_fib_counters[vrf_index], i); + counter = &vam->ip4_fib_counters[vrf_index][i]; + clib_memcpy (&ip4, &v->address, sizeof (ip4)); + counter->address = ip4; + counter->address_length = v->address_length; + counter->packets = clib_net_to_host_u64 (v->packets); + counter->bytes = clib_net_to_host_u64 (v->bytes); + v++; + } +} + +static void vl_api_vnet_ip4_nbr_counters_t_handler + (vl_api_vnet_ip4_nbr_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_ip4_nbr_counters_t_handler_json + (vl_api_vnet_ip4_nbr_counters_t * mp) +{ + vat_main_t *vam = &vat_main; + vl_api_ip4_nbr_counter_t *v; + ip4_nbr_counter_t *counter; + u32 sw_if_index; + u32 count; + int i; + + sw_if_index = ntohl (mp->sw_if_index); + count = ntohl (mp->count); + vec_validate (vam->ip4_nbr_counters, sw_if_index); + + if (mp->begin) + vec_free (vam->ip4_nbr_counters[sw_if_index]); + + v = (vl_api_ip4_nbr_counter_t *) & mp->c; + for (i = 0; i < count; i++) + { + vec_validate (vam->ip4_nbr_counters[sw_if_index], i); + counter = &vam->ip4_nbr_counters[sw_if_index][i]; + counter->address.s_addr = v->address; + counter->packets = clib_net_to_host_u64 (v->packets); + counter->bytes = clib_net_to_host_u64 (v->bytes); + counter->linkt = v->link_type; + v++; + } +} + +static void vl_api_vnet_ip6_fib_counters_t_handler + (vl_api_vnet_ip6_fib_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_ip6_fib_counters_t_handler_json + (vl_api_vnet_ip6_fib_counters_t * mp) +{ + vat_main_t *vam = &vat_main; + vl_api_ip6_fib_counter_t *v; + ip6_fib_counter_t *counter; + struct in6_addr ip6; + u32 vrf_id; + u32 vrf_index; + u32 count; + int i; + + vrf_id = ntohl (mp->vrf_id); + vrf_index = ip6_fib_counters_get_vrf_index_by_vrf_id (vrf_id); + if (~0 == vrf_index) + { + vrf_index = vec_len (vam->ip6_fib_counters_vrf_id_by_index); + vec_validate (vam->ip6_fib_counters_vrf_id_by_index, vrf_index); + vam->ip6_fib_counters_vrf_id_by_index[vrf_index] = vrf_id; + vec_validate (vam->ip6_fib_counters, vrf_index); + vam->ip6_fib_counters[vrf_index] = NULL; + } + + vec_free (vam->ip6_fib_counters[vrf_index]); + v = (vl_api_ip6_fib_counter_t *) & mp->c; + count = ntohl (mp->count); + for (i = 0; i < count; i++) + { + vec_validate (vam->ip6_fib_counters[vrf_index], i); + counter = &vam->ip6_fib_counters[vrf_index][i]; + clib_memcpy (&ip6, &v->address, sizeof (ip6)); + counter->address = ip6; + counter->address_length = v->address_length; + counter->packets = clib_net_to_host_u64 (v->packets); + counter->bytes = clib_net_to_host_u64 (v->bytes); + v++; + } +} + +static void vl_api_vnet_ip6_nbr_counters_t_handler + (vl_api_vnet_ip6_nbr_counters_t * mp) +{ + /* not supported */ +} + +static void vl_api_vnet_ip6_nbr_counters_t_handler_json + (vl_api_vnet_ip6_nbr_counters_t * mp) +{ + vat_main_t *vam = &vat_main; + vl_api_ip6_nbr_counter_t *v; + ip6_nbr_counter_t *counter; + struct in6_addr ip6; + u32 sw_if_index; + u32 count; + int i; + + sw_if_index = ntohl (mp->sw_if_index); + count = ntohl (mp->count); + vec_validate (vam->ip6_nbr_counters, sw_if_index); + + if (mp->begin) + vec_free (vam->ip6_nbr_counters[sw_if_index]); + + v = (vl_api_ip6_nbr_counter_t *) & mp->c; + for (i = 0; i < count; i++) + { + vec_validate (vam->ip6_nbr_counters[sw_if_index], i); + counter = &vam->ip6_nbr_counters[sw_if_index][i]; + clib_memcpy (&ip6, &v->address, sizeof (ip6)); + counter->address = ip6; + counter->packets = clib_net_to_host_u64 (v->packets); + counter->bytes = clib_net_to_host_u64 (v->bytes); + v++; + } +} + +static void vl_api_get_first_msg_id_reply_t_handler + (vl_api_get_first_msg_id_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } + if (retval >= 0) + { + errmsg ("first message id %d", ntohs (mp->first_msg_id)); + } +} + +static void vl_api_get_first_msg_id_reply_t_handler_json + (vl_api_get_first_msg_id_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "first_msg_id", + (uint) ntohs (mp->first_msg_id)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_get_node_graph_reply_t_handler + (vl_api_get_node_graph_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + api_main_t *am = &api_main; + i32 retval = ntohl (mp->retval); + u8 *pvt_copy, *reply; + void *oldheap; + vlib_node_t *node; + int i; + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } + + /* "Should never happen..." */ + if (retval != 0) + return; + + reply = uword_to_pointer (mp->reply_in_shmem, u8 *); + pvt_copy = vec_dup (reply); + + /* Toss the shared-memory original... */ + pthread_mutex_lock (&am->vlib_rp->mutex); + oldheap = svm_push_data_heap (am->vlib_rp); + + vec_free (reply); + + svm_pop_heap (oldheap); + pthread_mutex_unlock (&am->vlib_rp->mutex); + + if (vam->graph_nodes) + { + hash_free (vam->graph_node_index_by_name); + + for (i = 0; i < vec_len (vam->graph_nodes); i++) + { + node = vam->graph_nodes[i]; + vec_free (node->name); + vec_free (node->next_nodes); + vec_free (node); + } + vec_free (vam->graph_nodes); + } + + vam->graph_node_index_by_name = hash_create_string (0, sizeof (uword)); + vam->graph_nodes = vlib_node_unserialize (pvt_copy); + vec_free (pvt_copy); + + for (i = 0; i < vec_len (vam->graph_nodes); i++) + { + node = vam->graph_nodes[i]; + hash_set_mem (vam->graph_node_index_by_name, node->name, i); + } +} + +static void vl_api_get_node_graph_reply_t_handler_json + (vl_api_get_node_graph_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + api_main_t *am = &api_main; + void *oldheap; + vat_json_node_t node; + u8 *reply; + + /* $$$$ make this real? */ + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "reply_in_shmem", mp->reply_in_shmem); + + reply = uword_to_pointer (mp->reply_in_shmem, u8 *); + + /* Toss the shared-memory original... */ + pthread_mutex_lock (&am->vlib_rp->mutex); + oldheap = svm_push_data_heap (am->vlib_rp); + + vec_free (reply); + + svm_pop_heap (oldheap); + pthread_mutex_unlock (&am->vlib_rp->mutex); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_one_locator_details_t_handler (vl_api_one_locator_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *s = 0; + + if (mp->local) + { + s = format (s, "%=16d%=16d%=16d", + ntohl (mp->sw_if_index), mp->priority, mp->weight); + } + else + { + s = format (s, "%=16U%=16d%=16d", + mp->is_ipv6 ? format_ip6_address : + format_ip4_address, + mp->ip_address, mp->priority, mp->weight); + } + + print (vam->ofp, "%v", s); + vec_free (s); +} + +static void +vl_api_one_locator_details_t_handler_json (vl_api_one_locator_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + vat_json_object_add_uint (node, "local", mp->local ? 1 : 0); + vat_json_object_add_uint (node, "priority", mp->priority); + vat_json_object_add_uint (node, "weight", mp->weight); + + if (mp->local) + vat_json_object_add_uint (node, "sw_if_index", + clib_net_to_host_u32 (mp->sw_if_index)); + else + { + if (mp->is_ipv6) + { + clib_memcpy (&ip6, mp->ip_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "address", ip6); + } + else + { + clib_memcpy (&ip4, mp->ip_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "address", ip4); + } + } +} + +static void +vl_api_one_locator_set_details_t_handler (vl_api_one_locator_set_details_t * + mp) +{ + vat_main_t *vam = &vat_main; + u8 *ls_name = 0; + + ls_name = format (0, "%s", mp->ls_name); + + print (vam->ofp, "%=10d%=15v", clib_net_to_host_u32 (mp->ls_index), + ls_name); + vec_free (ls_name); +} + +static void + vl_api_one_locator_set_details_t_handler_json + (vl_api_one_locator_set_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = 0; + u8 *ls_name = 0; + + ls_name = format (0, "%s", mp->ls_name); + vec_add1 (ls_name, 0); + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "ls_name", ls_name); + vat_json_object_add_uint (node, "ls_index", + clib_net_to_host_u32 (mp->ls_index)); + vec_free (ls_name); +} + +typedef struct +{ + u32 spi; + u8 si; +} __attribute__ ((__packed__)) lisp_nsh_api_t; + +uword +unformat_nsh_address (unformat_input_t * input, va_list * args) +{ + lisp_nsh_api_t *nsh = va_arg (*args, lisp_nsh_api_t *); + return unformat (input, "SPI:%d SI:%d", &nsh->spi, &nsh->si); +} + +u8 * +format_nsh_address_vat (u8 * s, va_list * args) +{ + nsh_t *a = va_arg (*args, nsh_t *); + return format (s, "SPI:%d SI:%d", clib_net_to_host_u32 (a->spi), a->si); +} + +static u8 * +format_lisp_flat_eid (u8 * s, va_list * args) +{ + u32 type = va_arg (*args, u32); + u8 *eid = va_arg (*args, u8 *); + u32 eid_len = va_arg (*args, u32); + + switch (type) + { + case 0: + return format (s, "%U/%d", format_ip4_address, eid, eid_len); + case 1: + return format (s, "%U/%d", format_ip6_address, eid, eid_len); + case 2: + return format (s, "%U", format_ethernet_address, eid); + case 3: + return format (s, "%U", format_nsh_address_vat, eid); + } + return 0; +} + +static u8 * +format_lisp_eid_vat (u8 * s, va_list * args) +{ + u32 type = va_arg (*args, u32); + u8 *eid = va_arg (*args, u8 *); + u32 eid_len = va_arg (*args, u32); + u8 *seid = va_arg (*args, u8 *); + u32 seid_len = va_arg (*args, u32); + u32 is_src_dst = va_arg (*args, u32); + + if (is_src_dst) + s = format (s, "%U|", format_lisp_flat_eid, type, seid, seid_len); + + s = format (s, "%U", format_lisp_flat_eid, type, eid, eid_len); + + return s; +} + +static void +vl_api_one_eid_table_details_t_handler (vl_api_one_eid_table_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *s = 0, *eid = 0; + + if (~0 == mp->locator_set_index) + s = format (0, "action: %d", mp->action); + else + s = format (0, "%d", clib_net_to_host_u32 (mp->locator_set_index)); + + eid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, + mp->eid, + mp->eid_prefix_len, + mp->seid, mp->seid_prefix_len, mp->is_src_dst); + vec_add1 (eid, 0); + + print (vam->ofp, "[%d] %-35s%-20s%-30s%-20d%-20d%-10d%-20s", + clib_net_to_host_u32 (mp->vni), + eid, + mp->is_local ? "local" : "remote", + s, clib_net_to_host_u32 (mp->ttl), mp->authoritative, + clib_net_to_host_u16 (mp->key_id), mp->key); + + vec_free (s); + vec_free (eid); +} + +static void +vl_api_one_eid_table_details_t_handler_json (vl_api_one_eid_table_details_t + * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = 0; + u8 *eid = 0; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + if (~0 == mp->locator_set_index) + vat_json_object_add_uint (node, "action", mp->action); + else + vat_json_object_add_uint (node, "locator_set_index", + clib_net_to_host_u32 (mp->locator_set_index)); + + vat_json_object_add_uint (node, "is_local", mp->is_local ? 1 : 0); + if (mp->eid_type == 3) + { + vat_json_node_t *nsh_json = vat_json_object_add (node, "eid"); + vat_json_init_object (nsh_json); + lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) mp->eid; + vat_json_object_add_uint (nsh_json, "spi", + clib_net_to_host_u32 (nsh->spi)); + vat_json_object_add_uint (nsh_json, "si", nsh->si); + } + else + { + eid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, + mp->eid, + mp->eid_prefix_len, + mp->seid, mp->seid_prefix_len, mp->is_src_dst); + vec_add1 (eid, 0); + vat_json_object_add_string_copy (node, "eid", eid); + vec_free (eid); + } + vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); + vat_json_object_add_uint (node, "ttl", clib_net_to_host_u32 (mp->ttl)); + vat_json_object_add_uint (node, "authoritative", (mp->authoritative)); + + if (mp->key_id) + { + vat_json_object_add_uint (node, "key_id", + clib_net_to_host_u16 (mp->key_id)); + vat_json_object_add_string_copy (node, "key", mp->key); + } +} + +static void +vl_api_one_stats_details_t_handler (vl_api_one_stats_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *seid = 0, *deid = 0; + u8 *(*format_ip_address_fcn) (u8 *, va_list *) = 0; + + deid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0); + + seid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0); + + vec_add1 (deid, 0); + vec_add1 (seid, 0); + + if (mp->is_ip4) + format_ip_address_fcn = format_ip4_address; + else + format_ip_address_fcn = format_ip6_address; + + + print (vam->ofp, "([%d] %s %s) (%U %U) %u %u", + clib_net_to_host_u32 (mp->vni), + seid, deid, + format_ip_address_fcn, mp->lloc, + format_ip_address_fcn, mp->rloc, + clib_net_to_host_u32 (mp->pkt_count), + clib_net_to_host_u32 (mp->bytes)); + + vec_free (deid); + vec_free (seid); +} + +static void +vl_api_one_stats_details_t_handler_json (vl_api_one_stats_details_t * mp) +{ + struct in6_addr ip6; + struct in_addr ip4; + vat_main_t *vam = &vat_main; + vat_json_node_t *node = 0; + u8 *deid = 0, *seid = 0; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + deid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->deid, mp->deid_pref_len, 0, 0, 0); + + seid = format (0, "%U", format_lisp_eid_vat, + mp->eid_type, mp->seid, mp->seid_pref_len, 0, 0, 0); + + vec_add1 (deid, 0); + vec_add1 (seid, 0); + + vat_json_object_add_string_copy (node, "seid", seid); + vat_json_object_add_string_copy (node, "deid", deid); + vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); + + if (mp->is_ip4) + { + clib_memcpy (&ip4, mp->lloc, sizeof (ip4)); + vat_json_object_add_ip4 (node, "lloc", ip4); + clib_memcpy (&ip4, mp->rloc, sizeof (ip4)); + vat_json_object_add_ip4 (node, "rloc", ip4); + } + else + { + clib_memcpy (&ip6, mp->lloc, sizeof (ip6)); + vat_json_object_add_ip6 (node, "lloc", ip6); + clib_memcpy (&ip6, mp->rloc, sizeof (ip6)); + vat_json_object_add_ip6 (node, "rloc", ip6); + } + vat_json_object_add_uint (node, "pkt_count", + clib_net_to_host_u32 (mp->pkt_count)); + vat_json_object_add_uint (node, "bytes", clib_net_to_host_u32 (mp->bytes)); + + vec_free (deid); + vec_free (seid); +} + +static void + vl_api_one_eid_table_map_details_t_handler + (vl_api_one_eid_table_map_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + u8 *line = format (0, "%=10d%=10d", + clib_net_to_host_u32 (mp->vni), + clib_net_to_host_u32 (mp->dp_table)); + print (vam->ofp, "%v", line); + vec_free (line); +} + +static void + vl_api_one_eid_table_map_details_t_handler_json + (vl_api_one_eid_table_map_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + vat_json_object_add_uint (node, "dp_table", + clib_net_to_host_u32 (mp->dp_table)); + vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); +} + +static void + vl_api_one_eid_table_vni_details_t_handler + (vl_api_one_eid_table_vni_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + u8 *line = format (0, "%d", clib_net_to_host_u32 (mp->vni)); + print (vam->ofp, "%v", line); + vec_free (line); +} + +static void + vl_api_one_eid_table_vni_details_t_handler_json + (vl_api_one_eid_table_vni_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + vat_json_object_add_uint (node, "vni", clib_net_to_host_u32 (mp->vni)); +} + +static void + vl_api_show_one_map_register_fallback_threshold_reply_t_handler + (vl_api_show_one_map_register_fallback_threshold_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + vl_api_show_one_map_register_fallback_threshold_reply_t_endian (mp); + print (vam->ofp, "fallback threshold value: %d", mp->value); + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_fallback_threshold_reply_t_handler_json + (vl_api_show_one_map_register_fallback_threshold_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + vl_api_show_one_map_register_fallback_threshold_reply_t_endian (mp); + vat_json_init_object (node); + vat_json_object_add_uint (node, "value", mp->value); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_state_reply_t_handler + (vl_api_show_one_map_register_state_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + print (vam->ofp, "%s", mp->is_enabled ? "enabled" : "disabled"); + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_state_reply_t_handler_json + (vl_api_show_one_map_register_state_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + u8 *s = format (0, "%s", mp->is_enabled ? "enabled" : "disabled"); + + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "state", s); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; + vec_free (s); +} + +static void + vl_api_show_one_rloc_probe_state_reply_t_handler + (vl_api_show_one_rloc_probe_state_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + print (vam->ofp, "%s", mp->is_enabled ? "enabled" : "disabled"); +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_rloc_probe_state_reply_t_handler_json + (vl_api_show_one_rloc_probe_state_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + u8 *s = format (0, "%s", mp->is_enabled ? "enabled" : "disabled"); + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "state", s); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; + vec_free (s); +} + +static void + vl_api_show_one_stats_enable_disable_reply_t_handler + (vl_api_show_one_stats_enable_disable_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + print (vam->ofp, "%s", mp->is_en ? "enabled" : "disabled"); +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_stats_enable_disable_reply_t_handler_json + (vl_api_show_one_stats_enable_disable_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t _node, *node = &_node; + int retval = clib_net_to_host_u32 (mp->retval); + + u8 *s = format (0, "%s", mp->is_en ? "enabled" : "disabled"); + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "state", s); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = retval; + vam->result_ready = 1; + vec_free (s); +} + +static void +api_gpe_fwd_entry_net_to_host (vl_api_gpe_fwd_entry_t * e) +{ + e->dp_table = clib_net_to_host_u32 (e->dp_table); + e->fwd_entry_index = clib_net_to_host_u32 (e->fwd_entry_index); + e->vni = clib_net_to_host_u32 (e->vni); +} + +static void + gpe_fwd_entries_get_reply_t_net_to_host + (vl_api_gpe_fwd_entries_get_reply_t * mp) +{ + u32 i; + + mp->count = clib_net_to_host_u32 (mp->count); + for (i = 0; i < mp->count; i++) + { + api_gpe_fwd_entry_net_to_host (&mp->entries[i]); + } +} + +static u8 * +format_gpe_encap_mode (u8 * s, va_list * args) +{ + u32 mode = va_arg (*args, u32); + + switch (mode) + { + case 0: + return format (s, "lisp"); + case 1: + return format (s, "vxlan"); + } + return 0; +} + +static void + vl_api_gpe_get_encap_mode_reply_t_handler + (vl_api_gpe_get_encap_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "gpe mode: %U", format_gpe_encap_mode, mp->encap_mode); + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_gpe_get_encap_mode_reply_t_handler_json + (vl_api_gpe_get_encap_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + u8 *encap_mode = format (0, "%U", format_gpe_encap_mode, mp->encap_mode); + vec_add1 (encap_mode, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "gpe_mode", encap_mode); + + vec_free (encap_mode); + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_gpe_fwd_entry_path_details_t_handler + (vl_api_gpe_fwd_entry_path_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *(*format_ip_address_fcn) (u8 *, va_list *) = 0; + + if (mp->lcl_loc.is_ip4) + format_ip_address_fcn = format_ip4_address; + else + format_ip_address_fcn = format_ip6_address; + + print (vam->ofp, "w:%d %30U %30U", mp->rmt_loc.weight, + format_ip_address_fcn, &mp->lcl_loc, + format_ip_address_fcn, &mp->rmt_loc); +} + +static void +lisp_fill_locator_node (vat_json_node_t * n, vl_api_gpe_locator_t * loc) +{ + struct in6_addr ip6; + struct in_addr ip4; + + if (loc->is_ip4) + { + clib_memcpy (&ip4, loc->addr, sizeof (ip4)); + vat_json_object_add_ip4 (n, "address", ip4); + } + else + { + clib_memcpy (&ip6, loc->addr, sizeof (ip6)); + vat_json_object_add_ip6 (n, "address", ip6); + } + vat_json_object_add_uint (n, "weight", loc->weight); +} + +static void + vl_api_gpe_fwd_entry_path_details_t_handler_json + (vl_api_gpe_fwd_entry_path_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + vat_json_node_t *loc_node; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + loc_node = vat_json_object_add (node, "local_locator"); + vat_json_init_object (loc_node); + lisp_fill_locator_node (loc_node, &mp->lcl_loc); + + loc_node = vat_json_object_add (node, "remote_locator"); + vat_json_init_object (loc_node); + lisp_fill_locator_node (loc_node, &mp->rmt_loc); +} + +static void + vl_api_gpe_fwd_entries_get_reply_t_handler + (vl_api_gpe_fwd_entries_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_gpe_fwd_entry_t *e; + + if (retval) + goto end; + + gpe_fwd_entries_get_reply_t_net_to_host (mp); + + for (i = 0; i < mp->count; i++) + { + e = &mp->entries[i]; + print (vam->ofp, "%10d %10d %U %40U", e->fwd_entry_index, e->dp_table, + format_lisp_flat_eid, e->eid_type, e->leid, e->leid_prefix_len, + format_lisp_flat_eid, e->eid_type, e->reid, e->reid_prefix_len); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_gpe_fwd_entries_get_reply_t_handler_json + (vl_api_gpe_fwd_entries_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_gpe_fwd_entry_t *fwd; + + if (retval) + goto end; + + gpe_fwd_entries_get_reply_t_net_to_host (mp); + vat_json_init_array (&root); + + for (i = 0; i < mp->count; i++) + { + e = vat_json_array_add (&root); + fwd = &mp->entries[i]; + + vat_json_init_object (e); + vat_json_object_add_int (e, "fwd_entry_index", fwd->fwd_entry_index); + vat_json_object_add_int (e, "dp_table", fwd->dp_table); + vat_json_object_add_int (e, "vni", fwd->vni); + vat_json_object_add_int (e, "action", fwd->action); + + s = format (0, "%U", format_lisp_flat_eid, fwd->eid_type, fwd->leid, + fwd->leid_prefix_len); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "leid", s); + vec_free (s); + + s = format (0, "%U", format_lisp_flat_eid, fwd->eid_type, fwd->reid, + fwd->reid_prefix_len); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "reid", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_gpe_native_fwd_rpaths_get_reply_t_handler + (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_gpe_native_fwd_rpath_t *r; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + r = &mp->entries[i]; + print (vam->ofp, "fib_index: %d sw_if_index %d nh %U", + clib_net_to_host_u32 (r->fib_index), + clib_net_to_host_u32 (r->nh_sw_if_index), + r->is_ip4 ? format_ip4_address : format_ip6_address, r->nh_addr); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_gpe_native_fwd_rpaths_get_reply_t_handler_json + (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root, *e; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_gpe_native_fwd_rpath_t *r; + u8 *s; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + vat_json_init_object (e); + r = &mp->entries[i]; + s = + format (0, "%U", r->is_ip4 ? format_ip4_address : format_ip6_address, + r->nh_addr); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "ip4", s); + vec_free (s); + + vat_json_object_add_uint (e, "fib_index", + clib_net_to_host_u32 (r->fib_index)); + vat_json_object_add_uint (e, "nh_sw_if_index", + clib_net_to_host_u32 (r->nh_sw_if_index)); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_gpe_fwd_entry_vnis_get_reply_t_handler + (vl_api_gpe_fwd_entry_vnis_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + print (vam->ofp, "%d", clib_net_to_host_u32 (mp->vnis[i])); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_gpe_fwd_entry_vnis_get_reply_t_handler_json + (vl_api_gpe_fwd_entry_vnis_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + vat_json_array_add_uint (&root, clib_net_to_host_u32 (mp->vnis[i])); + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_ndp_entries_get_reply_t_handler + (vl_api_one_ndp_entries_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + print (vam->ofp, "%U -> %U", format_ip6_address, &mp->entries[i].ip6, + format_ethernet_address, mp->entries[i].mac); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_ndp_entries_get_reply_t_handler_json + (vl_api_one_ndp_entries_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_ndp_entry_t *arp_entry; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + arp_entry = &mp->entries[i]; + + vat_json_init_object (e); + s = format (0, "%U", format_ethernet_address, arp_entry->mac); + vec_add1 (s, 0); + + vat_json_object_add_string_copy (e, "mac", s); + vec_free (s); + + s = format (0, "%U", format_ip6_address, &arp_entry->ip6); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "ip6", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_entries_get_reply_t_handler + (vl_api_one_l2_arp_entries_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + print (vam->ofp, "%U -> %U", format_ip4_address, &mp->entries[i].ip4, + format_ethernet_address, mp->entries[i].mac); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_entries_get_reply_t_handler_json + (vl_api_one_l2_arp_entries_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_l2_arp_entry_t *arp_entry; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + arp_entry = &mp->entries[i]; + + vat_json_init_object (e); + s = format (0, "%U", format_ethernet_address, arp_entry->mac); + vec_add1 (s, 0); + + vat_json_object_add_string_copy (e, "mac", s); + vec_free (s); + + s = format (0, "%U", format_ip4_address, &arp_entry->ip4); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "ip4", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void +vl_api_one_ndp_bd_get_reply_t_handler (vl_api_one_ndp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + print (vam->ofp, "%d", clib_net_to_host_u32 (mp->bridge_domains[i])); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_ndp_bd_get_reply_t_handler_json + (vl_api_one_ndp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + vat_json_array_add_uint (&root, + clib_net_to_host_u32 (mp->bridge_domains[i])); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_bd_get_reply_t_handler + (vl_api_one_l2_arp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + print (vam->ofp, "%d", clib_net_to_host_u32 (mp->bridge_domains[i])); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_l2_arp_bd_get_reply_t_handler_json + (vl_api_one_l2_arp_bd_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + vat_json_array_add_uint (&root, + clib_net_to_host_u32 (mp->bridge_domains[i])); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_adjacencies_get_reply_t_handler + (vl_api_one_adjacencies_get_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_adjacency_t *a; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + + for (i = 0; i < n; i++) + { + a = &mp->adjacencies[i]; + print (vam->ofp, "%U %40U", + format_lisp_flat_eid, a->eid_type, a->leid, a->leid_prefix_len, + format_lisp_flat_eid, a->eid_type, a->reid, a->reid_prefix_len); + } + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_adjacencies_get_reply_t_handler_json + (vl_api_one_adjacencies_get_reply_t * mp) +{ + u8 *s = 0; + vat_main_t *vam = &vat_main; + vat_json_node_t *e = 0, root; + u32 i, n; + int retval = clib_net_to_host_u32 (mp->retval); + vl_api_one_adjacency_t *a; + + if (retval) + goto end; + + n = clib_net_to_host_u32 (mp->count); + vat_json_init_array (&root); + + for (i = 0; i < n; i++) + { + e = vat_json_array_add (&root); + a = &mp->adjacencies[i]; + + vat_json_init_object (e); + s = format (0, "%U", format_lisp_flat_eid, a->eid_type, a->leid, + a->leid_prefix_len); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "leid", s); + vec_free (s); + + s = format (0, "%U", format_lisp_flat_eid, a->eid_type, a->reid, + a->reid_prefix_len); + vec_add1 (s, 0); + vat_json_object_add_string_copy (e, "reid", s); + vec_free (s); + } + + vat_json_print (vam->ofp, &root); + vat_json_free (&root); + +end: + vam->retval = retval; + vam->result_ready = 1; +} + +static void +vl_api_one_map_server_details_t_handler (vl_api_one_map_server_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%=20U", + mp->is_ipv6 ? format_ip6_address : format_ip4_address, + mp->ip_address); +} + +static void + vl_api_one_map_server_details_t_handler_json + (vl_api_one_map_server_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + if (mp->is_ipv6) + { + clib_memcpy (&ip6, mp->ip_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "map-server", ip6); + } + else + { + clib_memcpy (&ip4, mp->ip_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "map-server", ip4); + } +} + +static void +vl_api_one_map_resolver_details_t_handler (vl_api_one_map_resolver_details_t + * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%=20U", + mp->is_ipv6 ? format_ip6_address : format_ip4_address, + mp->ip_address); +} + +static void + vl_api_one_map_resolver_details_t_handler_json + (vl_api_one_map_resolver_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + if (mp->is_ipv6) + { + clib_memcpy (&ip6, mp->ip_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "map resolver", ip6); + } + else + { + clib_memcpy (&ip4, mp->ip_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "map resolver", ip4); + } +} + +static void +vl_api_show_one_status_reply_t_handler (vl_api_show_one_status_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "feature: %s\ngpe: %s", + mp->feature_status ? "enabled" : "disabled", + mp->gpe_status ? "enabled" : "disabled"); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_status_reply_t_handler_json + (vl_api_show_one_status_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *gpe_status = NULL; + u8 *feature_status = NULL; + + gpe_status = format (0, "%s", mp->gpe_status ? "enabled" : "disabled"); + feature_status = format (0, "%s", + mp->feature_status ? "enabled" : "disabled"); + vec_add1 (gpe_status, 0); + vec_add1 (feature_status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "gpe_status", gpe_status); + vat_json_object_add_string_copy (&node, "feature_status", feature_status); + + vec_free (gpe_status); + vec_free (feature_status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_one_get_map_request_itr_rlocs_reply_t_handler + (vl_api_one_get_map_request_itr_rlocs_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (retval >= 0) + { + print (vam->ofp, "%=20s", mp->locator_set_name); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_get_map_request_itr_rlocs_reply_t_handler_json + (vl_api_one_get_map_request_itr_rlocs_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "itr-rlocs", mp->locator_set_name); + + vat_json_print (vam->ofp, node); + vat_json_free (node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static u8 * +format_lisp_map_request_mode (u8 * s, va_list * args) +{ + u32 mode = va_arg (*args, u32); + + switch (mode) + { + case 0: + return format (0, "dst-only"); + case 1: + return format (0, "src-dst"); + } + return 0; +} + +static void + vl_api_show_one_map_request_mode_reply_t_handler + (vl_api_show_one_map_request_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + u32 mode = mp->mode; + print (vam->ofp, "map_request_mode: %U", + format_lisp_map_request_mode, mode); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_request_mode_reply_t_handler_json + (vl_api_show_one_map_request_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *s = 0; + u32 mode; + + mode = mp->mode; + s = format (0, "%U", format_lisp_map_request_mode, mode); + vec_add1 (s, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "map_request_mode", s); + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vec_free (s); + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_one_show_xtr_mode_reply_t_handler + (vl_api_one_show_xtr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%s\n", mp->is_en ? "enabled" : "disabled"); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_show_xtr_mode_reply_t_handler_json + (vl_api_one_show_xtr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->is_en ? "enabled" : "disabled"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "status", status); + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_one_show_pitr_mode_reply_t_handler + (vl_api_one_show_pitr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%s\n", mp->is_en ? "enabled" : "disabled"); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_show_pitr_mode_reply_t_handler_json + (vl_api_one_show_pitr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->is_en ? "enabled" : "disabled"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "status", status); + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_one_show_petr_mode_reply_t_handler + (vl_api_one_show_petr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%s\n", mp->is_en ? "enabled" : "disabled"); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_one_show_petr_mode_reply_t_handler_json + (vl_api_one_show_petr_mode_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->is_en ? "enabled" : "disabled"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "status", status); + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_show_one_use_petr_reply_t_handler + (vl_api_show_one_use_petr_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%s\n", mp->status ? "enabled" : "disabled"); + if (mp->status) + { + print (vam->ofp, "Proxy-ETR address; %U", + mp->is_ip4 ? format_ip4_address : format_ip6_address, + mp->address); + } + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_use_petr_reply_t_handler_json + (vl_api_show_one_use_petr_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + struct in_addr ip4; + struct in6_addr ip6; + + status = format (0, "%s", mp->status ? "enabled" : "disabled"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "status", status); + if (mp->status) + { + if (mp->is_ip4) + { + clib_memcpy (&ip6, mp->address, sizeof (ip6)); + vat_json_object_add_ip6 (&node, "address", ip6); + } + else + { + clib_memcpy (&ip4, mp->address, sizeof (ip4)); + vat_json_object_add_ip4 (&node, "address", ip4); + } + } + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_show_one_nsh_mapping_reply_t_handler + (vl_api_show_one_nsh_mapping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%-20s%-16s", + mp->is_set ? "set" : "not-set", + mp->is_set ? (char *) mp->locator_set_name : ""); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_nsh_mapping_reply_t_handler_json + (vl_api_show_one_nsh_mapping_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->is_set ? "yes" : "no"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "is_set", status); + if (mp->is_set) + { + vat_json_object_add_string_copy (&node, "locator_set", + mp->locator_set_name); + } + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_ttl_reply_t_handler + (vl_api_show_one_map_register_ttl_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + vl_api_show_one_map_register_ttl_reply_t_endian (mp); + + if (0 <= retval) + { + print (vam->ofp, "ttl: %u", mp->ttl); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_show_one_map_register_ttl_reply_t_handler_json + (vl_api_show_one_map_register_ttl_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vl_api_show_one_map_register_ttl_reply_t_endian (mp); + vat_json_init_object (&node); + vat_json_object_add_uint (&node, "ttl", mp->ttl); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_show_one_pitr_reply_t_handler (vl_api_show_one_pitr_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (0 <= retval) + { + print (vam->ofp, "%-20s%-16s", + mp->status ? "enabled" : "disabled", + mp->status ? (char *) mp->locator_set_name : ""); + } + + vam->retval = retval; + vam->result_ready = 1; +} + +static void +vl_api_show_one_pitr_reply_t_handler_json (vl_api_show_one_pitr_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + u8 *status = 0; + + status = format (0, "%s", mp->status ? "enabled" : "disabled"); + vec_add1 (status, 0); + + vat_json_init_object (&node); + vat_json_object_add_string_copy (&node, "status", status); + if (mp->status) + { + vat_json_object_add_string_copy (&node, "locator_set", + mp->locator_set_name); + } + + vec_free (status); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static u8 * +format_policer_type (u8 * s, va_list * va) +{ + u32 i = va_arg (*va, u32); + + if (i == SSE2_QOS_POLICER_TYPE_1R2C) + s = format (s, "1r2c"); + else if (i == SSE2_QOS_POLICER_TYPE_1R3C_RFC_2697) + s = format (s, "1r3c"); + else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_2698) + s = format (s, "2r3c-2698"); + else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_4115) + s = format (s, "2r3c-4115"); + else if (i == SSE2_QOS_POLICER_TYPE_2R3C_RFC_MEF5CF1) + s = format (s, "2r3c-mef5cf1"); + else + s = format (s, "ILLEGAL"); + return s; +} + +static u8 * +format_policer_rate_type (u8 * s, va_list * va) +{ + u32 i = va_arg (*va, u32); + + if (i == SSE2_QOS_RATE_KBPS) + s = format (s, "kbps"); + else if (i == SSE2_QOS_RATE_PPS) + s = format (s, "pps"); + else + s = format (s, "ILLEGAL"); + return s; +} + +static u8 * +format_policer_round_type (u8 * s, va_list * va) +{ + u32 i = va_arg (*va, u32); + + if (i == SSE2_QOS_ROUND_TO_CLOSEST) + s = format (s, "closest"); + else if (i == SSE2_QOS_ROUND_TO_UP) + s = format (s, "up"); + else if (i == SSE2_QOS_ROUND_TO_DOWN) + s = format (s, "down"); + else + s = format (s, "ILLEGAL"); + return s; +} + +static u8 * +format_policer_action_type (u8 * s, va_list * va) +{ + u32 i = va_arg (*va, u32); + + if (i == SSE2_QOS_ACTION_DROP) + s = format (s, "drop"); + else if (i == SSE2_QOS_ACTION_TRANSMIT) + s = format (s, "transmit"); + else if (i == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + s = format (s, "mark-and-transmit"); + else + s = format (s, "ILLEGAL"); + return s; +} + +static u8 * +format_dscp (u8 * s, va_list * va) +{ + u32 i = va_arg (*va, u32); + char *t = 0; + + switch (i) + { +#define _(v,f,str) case VNET_DSCP_##f: t = str; break; + foreach_vnet_dscp +#undef _ + default: + return format (s, "ILLEGAL"); + } + s = format (s, "%s", t); + return s; +} + +static void +vl_api_policer_details_t_handler (vl_api_policer_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u8 *conform_dscp_str, *exceed_dscp_str, *violate_dscp_str; + + if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + conform_dscp_str = format (0, "%U", format_dscp, mp->conform_dscp); + else + conform_dscp_str = format (0, ""); + + if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + exceed_dscp_str = format (0, "%U", format_dscp, mp->exceed_dscp); + else + exceed_dscp_str = format (0, ""); + + if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + violate_dscp_str = format (0, "%U", format_dscp, mp->violate_dscp); + else + violate_dscp_str = format (0, ""); + + print (vam->ofp, "Name \"%s\", type %U, cir %u, eir %u, cb %u, eb %u, " + "rate type %U, round type %U, %s rate, %s color-aware, " + "cir %u tok/period, pir %u tok/period, scale %u, cur lim %u, " + "cur bkt %u, ext lim %u, ext bkt %u, last update %llu" + "conform action %U%s, exceed action %U%s, violate action %U%s", + mp->name, + format_policer_type, mp->type, + ntohl (mp->cir), + ntohl (mp->eir), + clib_net_to_host_u64 (mp->cb), + clib_net_to_host_u64 (mp->eb), + format_policer_rate_type, mp->rate_type, + format_policer_round_type, mp->round_type, + mp->single_rate ? "single" : "dual", + mp->color_aware ? "is" : "not", + ntohl (mp->cir_tokens_per_period), + ntohl (mp->pir_tokens_per_period), + ntohl (mp->scale), + ntohl (mp->current_limit), + ntohl (mp->current_bucket), + ntohl (mp->extended_limit), + ntohl (mp->extended_bucket), + clib_net_to_host_u64 (mp->last_update_time), + format_policer_action_type, mp->conform_action_type, + conform_dscp_str, + format_policer_action_type, mp->exceed_action_type, + exceed_dscp_str, + format_policer_action_type, mp->violate_action_type, + violate_dscp_str); + + vec_free (conform_dscp_str); + vec_free (exceed_dscp_str); + vec_free (violate_dscp_str); +} + +static void vl_api_policer_details_t_handler_json + (vl_api_policer_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node; + u8 *rate_type_str, *round_type_str, *type_str; + u8 *conform_action_str, *exceed_action_str, *violate_action_str; + + rate_type_str = format (0, "%U", format_policer_rate_type, mp->rate_type); + round_type_str = + format (0, "%U", format_policer_round_type, mp->round_type); + type_str = format (0, "%U", format_policer_type, mp->type); + conform_action_str = format (0, "%U", format_policer_action_type, + mp->conform_action_type); + exceed_action_str = format (0, "%U", format_policer_action_type, + mp->exceed_action_type); + violate_action_str = format (0, "%U", format_policer_action_type, + mp->violate_action_type); + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "name", mp->name); + vat_json_object_add_uint (node, "cir", ntohl (mp->cir)); + vat_json_object_add_uint (node, "eir", ntohl (mp->eir)); + vat_json_object_add_uint (node, "cb", clib_net_to_host_u64 (mp->cb)); + vat_json_object_add_uint (node, "eb", clib_net_to_host_u64 (mp->eb)); + vat_json_object_add_string_copy (node, "rate_type", rate_type_str); + vat_json_object_add_string_copy (node, "round_type", round_type_str); + vat_json_object_add_string_copy (node, "type", type_str); + vat_json_object_add_uint (node, "single_rate", mp->single_rate); + vat_json_object_add_uint (node, "color_aware", mp->color_aware); + vat_json_object_add_uint (node, "scale", ntohl (mp->scale)); + vat_json_object_add_uint (node, "cir_tokens_per_period", + ntohl (mp->cir_tokens_per_period)); + vat_json_object_add_uint (node, "eir_tokens_per_period", + ntohl (mp->pir_tokens_per_period)); + vat_json_object_add_uint (node, "current_limit", ntohl (mp->current_limit)); + vat_json_object_add_uint (node, "current_bucket", + ntohl (mp->current_bucket)); + vat_json_object_add_uint (node, "extended_limit", + ntohl (mp->extended_limit)); + vat_json_object_add_uint (node, "extended_bucket", + ntohl (mp->extended_bucket)); + vat_json_object_add_uint (node, "last_update_time", + ntohl (mp->last_update_time)); + vat_json_object_add_string_copy (node, "conform_action", + conform_action_str); + if (mp->conform_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + { + u8 *dscp_str = format (0, "%U", format_dscp, mp->conform_dscp); + vat_json_object_add_string_copy (node, "conform_dscp", dscp_str); + vec_free (dscp_str); + } + vat_json_object_add_string_copy (node, "exceed_action", exceed_action_str); + if (mp->exceed_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + { + u8 *dscp_str = format (0, "%U", format_dscp, mp->exceed_dscp); + vat_json_object_add_string_copy (node, "exceed_dscp", dscp_str); + vec_free (dscp_str); + } + vat_json_object_add_string_copy (node, "violate_action", + violate_action_str); + if (mp->violate_action_type == SSE2_QOS_ACTION_MARK_AND_TRANSMIT) + { + u8 *dscp_str = format (0, "%U", format_dscp, mp->violate_dscp); + vat_json_object_add_string_copy (node, "violate_dscp", dscp_str); + vec_free (dscp_str); + } + + vec_free (rate_type_str); + vec_free (round_type_str); + vec_free (type_str); + vec_free (conform_action_str); + vec_free (exceed_action_str); + vec_free (violate_action_str); +} + +static void +vl_api_classify_table_ids_reply_t_handler (vl_api_classify_table_ids_reply_t * + mp) +{ + vat_main_t *vam = &vat_main; + int i, count = ntohl (mp->count); + + if (count > 0) + print (vam->ofp, "classify table ids (%d) : ", count); + for (i = 0; i < count; i++) + { + print (vam->ofp, "%d", ntohl (mp->ids[i])); + print (vam->ofp, (i < count - 1) ? "," : ""); + } + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_classify_table_ids_reply_t_handler_json + (vl_api_classify_table_ids_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + int i, count = ntohl (mp->count); + + if (count > 0) + { + vat_json_node_t node; + + vat_json_init_object (&node); + for (i = 0; i < count; i++) + { + vat_json_object_add_uint (&node, "table_id", ntohl (mp->ids[i])); + } + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + } + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_classify_table_by_interface_reply_t_handler + (vl_api_classify_table_by_interface_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 table_id; + + table_id = ntohl (mp->l2_table_id); + if (table_id != ~0) + print (vam->ofp, "l2 table id : %d", table_id); + else + print (vam->ofp, "l2 table id : No input ACL tables configured"); + table_id = ntohl (mp->ip4_table_id); + if (table_id != ~0) + print (vam->ofp, "ip4 table id : %d", table_id); + else + print (vam->ofp, "ip4 table id : No input ACL tables configured"); + table_id = ntohl (mp->ip6_table_id); + if (table_id != ~0) + print (vam->ofp, "ip6 table id : %d", table_id); + else + print (vam->ofp, "ip6 table id : No input ACL tables configured"); + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void + vl_api_classify_table_by_interface_reply_t_handler_json + (vl_api_classify_table_by_interface_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + + vat_json_object_add_int (&node, "l2_table_id", ntohl (mp->l2_table_id)); + vat_json_object_add_int (&node, "ip4_table_id", ntohl (mp->ip4_table_id)); + vat_json_object_add_int (&node, "ip6_table_id", ntohl (mp->ip6_table_id)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_policer_add_del_reply_t_handler + (vl_api_policer_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + if (retval == 0 && mp->policer_index != 0xFFFFFFFF) + /* + * Note: this is just barely thread-safe, depends on + * the main thread spinning waiting for an answer... + */ + errmsg ("policer index %d", ntohl (mp->policer_index)); + } +} + +static void vl_api_policer_add_del_reply_t_handler_json + (vl_api_policer_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "policer_index", + ntohl (mp->policer_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +/* Format hex dump. */ +u8 * +format_hex_bytes (u8 * s, va_list * va) +{ + u8 *bytes = va_arg (*va, u8 *); + int n_bytes = va_arg (*va, int); + uword i; + + /* Print short or long form depending on byte count. */ + uword short_form = n_bytes <= 32; + u32 indent = format_get_indent (s); + + if (n_bytes == 0) + return s; + + for (i = 0; i < n_bytes; i++) + { + if (!short_form && (i % 32) == 0) + s = format (s, "%08x: ", i); + s = format (s, "%02x", bytes[i]); + if (!short_form && ((i + 1) % 32) == 0 && (i + 1) < n_bytes) + s = format (s, "\n%U", format_white_space, indent); + } + + return s; +} + +static void +vl_api_classify_table_info_reply_t_handler (vl_api_classify_table_info_reply_t + * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (retval == 0) + { + print (vam->ofp, "classify table info :"); + print (vam->ofp, "sessions: %d nexttbl: %d nextnode: %d", + ntohl (mp->active_sessions), ntohl (mp->next_table_index), + ntohl (mp->miss_next_index)); + print (vam->ofp, "nbuckets: %d skip: %d match: %d", + ntohl (mp->nbuckets), ntohl (mp->skip_n_vectors), + ntohl (mp->match_n_vectors)); + print (vam->ofp, "mask: %U", format_hex_bytes, mp->mask, + ntohl (mp->mask_length)); + } + vam->retval = retval; + vam->result_ready = 1; +} + +static void + vl_api_classify_table_info_reply_t_handler_json + (vl_api_classify_table_info_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + i32 retval = ntohl (mp->retval); + if (retval == 0) + { + vat_json_init_object (&node); + + vat_json_object_add_int (&node, "sessions", + ntohl (mp->active_sessions)); + vat_json_object_add_int (&node, "nexttbl", + ntohl (mp->next_table_index)); + vat_json_object_add_int (&node, "nextnode", + ntohl (mp->miss_next_index)); + vat_json_object_add_int (&node, "nbuckets", ntohl (mp->nbuckets)); + vat_json_object_add_int (&node, "skip", ntohl (mp->skip_n_vectors)); + vat_json_object_add_int (&node, "match", ntohl (mp->match_n_vectors)); + u8 *s = format (0, "%U%c", format_hex_bytes, mp->mask, + ntohl (mp->mask_length), 0); + vat_json_object_add_string_copy (&node, "mask", s); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + } + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void +vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * + mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "next_index: %d advance: %d opaque: %d ", + ntohl (mp->hit_next_index), ntohl (mp->advance), + ntohl (mp->opaque_index)); + print (vam->ofp, "mask: %U", format_hex_bytes, mp->match, + ntohl (mp->match_length)); +} + +static void + vl_api_classify_session_details_t_handler_json + (vl_api_classify_session_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_int (node, "next_index", ntohl (mp->hit_next_index)); + vat_json_object_add_int (node, "advance", ntohl (mp->advance)); + vat_json_object_add_int (node, "opaque", ntohl (mp->opaque_index)); + u8 *s = + format (0, "%U%c", format_hex_bytes, mp->match, ntohl (mp->match_length), + 0); + vat_json_object_add_string_copy (node, "match", s); +} + +static void vl_api_pg_create_interface_reply_t_handler + (vl_api_pg_create_interface_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_pg_create_interface_reply_t_handler_json + (vl_api_pg_create_interface_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + i32 retval = ntohl (mp->retval); + if (retval == 0) + { + vat_json_init_object (&node); + + vat_json_object_add_int (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + } + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_policer_classify_details_t_handler + (vl_api_policer_classify_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index), + ntohl (mp->table_index)); +} + +static void vl_api_policer_classify_details_t_handler_json + (vl_api_policer_classify_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index)); +} + +static void vl_api_ipsec_gre_add_del_tunnel_reply_t_handler + (vl_api_ipsec_gre_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->sw_if_index = ntohl (mp->sw_if_index); + vam->result_ready = 1; + } +} + +static void vl_api_ipsec_gre_add_del_tunnel_reply_t_handler_json + (vl_api_ipsec_gre_add_del_tunnel_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "sw_if_index", ntohl (mp->sw_if_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static void vl_api_flow_classify_details_t_handler + (vl_api_flow_classify_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%10d%20d", ntohl (mp->sw_if_index), + ntohl (mp->table_index)); +} + +static void vl_api_flow_classify_details_t_handler_json + (vl_api_flow_classify_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_uint (node, "table_index", ntohl (mp->table_index)); +} + +#define vl_api_vnet_interface_simple_counters_t_endian vl_noop_handler +#define vl_api_vnet_interface_simple_counters_t_print vl_noop_handler +#define vl_api_vnet_interface_combined_counters_t_endian vl_noop_handler +#define vl_api_vnet_interface_combined_counters_t_print vl_noop_handler +#define vl_api_vnet_ip4_fib_counters_t_endian vl_noop_handler +#define vl_api_vnet_ip4_fib_counters_t_print vl_noop_handler +#define vl_api_vnet_ip6_fib_counters_t_endian vl_noop_handler +#define vl_api_vnet_ip6_fib_counters_t_print vl_noop_handler +#define vl_api_vnet_ip4_nbr_counters_t_endian vl_noop_handler +#define vl_api_vnet_ip4_nbr_counters_t_print vl_noop_handler +#define vl_api_vnet_ip6_nbr_counters_t_endian vl_noop_handler +#define vl_api_vnet_ip6_nbr_counters_t_print vl_noop_handler +#define vl_api_one_adjacencies_get_reply_t_endian vl_noop_handler +#define vl_api_one_adjacencies_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_bd_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_entries_get_reply_t_endian vl_noop_handler +#define vl_api_one_l2_arp_entries_get_reply_t_print vl_noop_handler +#define vl_api_one_l2_arp_bd_get_reply_t_endian vl_noop_handler +#define vl_api_one_ndp_bd_get_reply_t_endian vl_noop_handler +#define vl_api_one_ndp_bd_get_reply_t_print vl_noop_handler +#define vl_api_one_ndp_entries_get_reply_t_print vl_noop_handler +#define vl_api_one_ndp_entries_get_reply_t_endian vl_noop_handler + +/* + * Generate boilerplate reply handlers, which + * dig the return value out of the xxx_reply_t API message, + * stick it into vam->retval, and set vam->result_ready + * + * Could also do this by pointing N message decode slots at + * a single function, but that could break in subtle ways. + */ + +#define foreach_standard_reply_retval_handler \ +_(sw_interface_set_flags_reply) \ +_(sw_interface_add_del_address_reply) \ +_(sw_interface_set_rx_mode_reply) \ +_(sw_interface_set_table_reply) \ +_(sw_interface_set_mpls_enable_reply) \ +_(sw_interface_set_vpath_reply) \ +_(sw_interface_set_vxlan_bypass_reply) \ +_(sw_interface_set_geneve_bypass_reply) \ +_(sw_interface_set_vxlan_gpe_bypass_reply) \ +_(sw_interface_set_l2_bridge_reply) \ +_(bridge_domain_add_del_reply) \ +_(sw_interface_set_l2_xconnect_reply) \ +_(l2fib_add_del_reply) \ +_(l2fib_flush_int_reply) \ +_(l2fib_flush_bd_reply) \ +_(ip_add_del_route_reply) \ +_(ip_table_add_del_reply) \ +_(ip_mroute_add_del_reply) \ +_(mpls_route_add_del_reply) \ +_(mpls_table_add_del_reply) \ +_(mpls_ip_bind_unbind_reply) \ +_(bier_route_add_del_reply) \ +_(bier_table_add_del_reply) \ +_(proxy_arp_add_del_reply) \ +_(proxy_arp_intfc_enable_disable_reply) \ +_(sw_interface_set_unnumbered_reply) \ +_(ip_neighbor_add_del_reply) \ +_(oam_add_del_reply) \ +_(reset_fib_reply) \ +_(dhcp_proxy_config_reply) \ +_(dhcp_proxy_set_vss_reply) \ +_(dhcp_client_config_reply) \ +_(set_ip_flow_hash_reply) \ +_(sw_interface_ip6_enable_disable_reply) \ +_(sw_interface_ip6_set_link_local_address_reply) \ +_(ip6nd_proxy_add_del_reply) \ +_(sw_interface_ip6nd_ra_prefix_reply) \ +_(sw_interface_ip6nd_ra_config_reply) \ +_(set_arp_neighbor_limit_reply) \ +_(l2_patch_add_del_reply) \ +_(sr_policy_add_reply) \ +_(sr_policy_mod_reply) \ +_(sr_policy_del_reply) \ +_(sr_localsid_add_del_reply) \ +_(sr_steering_add_del_reply) \ +_(classify_add_del_session_reply) \ +_(classify_set_interface_ip_table_reply) \ +_(classify_set_interface_l2_tables_reply) \ +_(l2tpv3_set_tunnel_cookies_reply) \ +_(l2tpv3_interface_enable_disable_reply) \ +_(l2tpv3_set_lookup_key_reply) \ +_(l2_fib_clear_table_reply) \ +_(l2_interface_efp_filter_reply) \ +_(l2_interface_vlan_tag_rewrite_reply) \ +_(modify_vhost_user_if_reply) \ +_(delete_vhost_user_if_reply) \ +_(want_ip4_arp_events_reply) \ +_(want_ip6_nd_events_reply) \ +_(want_l2_macs_events_reply) \ +_(input_acl_set_interface_reply) \ +_(ipsec_spd_add_del_reply) \ +_(ipsec_interface_add_del_spd_reply) \ +_(ipsec_spd_add_del_entry_reply) \ +_(ipsec_sad_add_del_entry_reply) \ +_(ipsec_sa_set_key_reply) \ +_(ipsec_tunnel_if_add_del_reply) \ +_(ipsec_tunnel_if_set_key_reply) \ +_(ipsec_tunnel_if_set_sa_reply) \ +_(ikev2_profile_add_del_reply) \ +_(ikev2_profile_set_auth_reply) \ +_(ikev2_profile_set_id_reply) \ +_(ikev2_profile_set_ts_reply) \ +_(ikev2_set_local_key_reply) \ +_(ikev2_set_responder_reply) \ +_(ikev2_set_ike_transforms_reply) \ +_(ikev2_set_esp_transforms_reply) \ +_(ikev2_set_sa_lifetime_reply) \ +_(ikev2_initiate_sa_init_reply) \ +_(ikev2_initiate_del_ike_sa_reply) \ +_(ikev2_initiate_del_child_sa_reply) \ +_(ikev2_initiate_rekey_child_sa_reply) \ +_(delete_loopback_reply) \ +_(bd_ip_mac_add_del_reply) \ +_(map_del_domain_reply) \ +_(map_add_del_rule_reply) \ +_(want_interface_events_reply) \ +_(want_stats_reply) \ +_(cop_interface_enable_disable_reply) \ +_(cop_whitelist_enable_disable_reply) \ +_(sw_interface_clear_stats_reply) \ +_(ioam_enable_reply) \ +_(ioam_disable_reply) \ +_(one_add_del_locator_reply) \ +_(one_add_del_local_eid_reply) \ +_(one_add_del_remote_mapping_reply) \ +_(one_add_del_adjacency_reply) \ +_(one_add_del_map_resolver_reply) \ +_(one_add_del_map_server_reply) \ +_(one_enable_disable_reply) \ +_(one_rloc_probe_enable_disable_reply) \ +_(one_map_register_enable_disable_reply) \ +_(one_map_register_set_ttl_reply) \ +_(one_set_transport_protocol_reply) \ +_(one_map_register_fallback_threshold_reply) \ +_(one_pitr_set_locator_set_reply) \ +_(one_map_request_mode_reply) \ +_(one_add_del_map_request_itr_rlocs_reply) \ +_(one_eid_table_add_del_map_reply) \ +_(one_use_petr_reply) \ +_(one_stats_enable_disable_reply) \ +_(one_add_del_l2_arp_entry_reply) \ +_(one_add_del_ndp_entry_reply) \ +_(one_stats_flush_reply) \ +_(one_enable_disable_xtr_mode_reply) \ +_(one_enable_disable_pitr_mode_reply) \ +_(one_enable_disable_petr_mode_reply) \ +_(gpe_enable_disable_reply) \ +_(gpe_set_encap_mode_reply) \ +_(gpe_add_del_iface_reply) \ +_(gpe_add_del_native_fwd_rpath_reply) \ +_(af_packet_delete_reply) \ +_(policer_classify_set_interface_reply) \ +_(netmap_create_reply) \ +_(netmap_delete_reply) \ +_(set_ipfix_exporter_reply) \ +_(set_ipfix_classify_stream_reply) \ +_(ipfix_classify_table_add_del_reply) \ +_(flow_classify_set_interface_reply) \ +_(sw_interface_span_enable_disable_reply) \ +_(pg_capture_reply) \ +_(pg_enable_disable_reply) \ +_(ip_source_and_port_range_check_add_del_reply) \ +_(ip_source_and_port_range_check_interface_add_del_reply)\ +_(delete_subif_reply) \ +_(l2_interface_pbb_tag_rewrite_reply) \ +_(punt_reply) \ +_(feature_enable_disable_reply) \ +_(sw_interface_tag_add_del_reply) \ +_(sw_interface_set_mtu_reply) \ +_(p2p_ethernet_add_reply) \ +_(p2p_ethernet_del_reply) \ +_(lldp_config_reply) \ +_(sw_interface_set_lldp_reply) \ +_(tcp_configure_src_addresses_reply) \ +_(dns_enable_disable_reply) \ +_(dns_name_server_add_del_reply) \ +_(session_rule_add_del_reply) \ +_(ip_container_proxy_add_del_reply) + +#define _(n) \ + static void vl_api_##n##_t_handler \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = &vat_main; \ + i32 retval = ntohl(mp->retval); \ + if (vam->async_mode) { \ + vam->async_errors += (retval < 0); \ + } else { \ + vam->retval = retval; \ + vam->result_ready = 1; \ + } \ + } +foreach_standard_reply_retval_handler; +#undef _ + +#define _(n) \ + static void vl_api_##n##_t_handler_json \ + (vl_api_##n##_t * mp) \ + { \ + vat_main_t * vam = &vat_main; \ + vat_json_node_t node; \ + vat_json_init_object(&node); \ + vat_json_object_add_int(&node, "retval", ntohl(mp->retval)); \ + vat_json_print(vam->ofp, &node); \ + vam->retval = ntohl(mp->retval); \ + vam->result_ready = 1; \ + } +foreach_standard_reply_retval_handler; +#undef _ + +/* + * Table of message reply handlers, must include boilerplate handlers + * we just generated + */ + +#define foreach_vpe_api_reply_msg \ +_(CREATE_LOOPBACK_REPLY, create_loopback_reply) \ +_(CREATE_LOOPBACK_INSTANCE_REPLY, create_loopback_instance_reply) \ +_(SW_INTERFACE_DETAILS, sw_interface_details) \ +_(SW_INTERFACE_SET_FLAGS_REPLY, sw_interface_set_flags_reply) \ +_(CONTROL_PING_REPLY, control_ping_reply) \ +_(CLI_REPLY, cli_reply) \ +_(CLI_INBAND_REPLY, cli_inband_reply) \ +_(SW_INTERFACE_ADD_DEL_ADDRESS_REPLY, \ + sw_interface_add_del_address_reply) \ +_(SW_INTERFACE_SET_RX_MODE_REPLY, sw_interface_set_rx_mode_reply) \ +_(SW_INTERFACE_SET_TABLE_REPLY, sw_interface_set_table_reply) \ +_(SW_INTERFACE_SET_MPLS_ENABLE_REPLY, sw_interface_set_mpls_enable_reply) \ +_(SW_INTERFACE_SET_VPATH_REPLY, sw_interface_set_vpath_reply) \ +_(SW_INTERFACE_SET_VXLAN_BYPASS_REPLY, sw_interface_set_vxlan_bypass_reply) \ +_(SW_INTERFACE_SET_GENEVE_BYPASS_REPLY, sw_interface_set_geneve_bypass_reply) \ +_(SW_INTERFACE_SET_VXLAN_GPE_BYPASS_REPLY, sw_interface_set_vxlan_gpe_bypass_reply) \ +_(SW_INTERFACE_SET_L2_XCONNECT_REPLY, \ + sw_interface_set_l2_xconnect_reply) \ +_(SW_INTERFACE_SET_L2_BRIDGE_REPLY, \ + sw_interface_set_l2_bridge_reply) \ +_(BRIDGE_DOMAIN_ADD_DEL_REPLY, bridge_domain_add_del_reply) \ +_(BRIDGE_DOMAIN_DETAILS, bridge_domain_details) \ +_(BRIDGE_DOMAIN_SET_MAC_AGE_REPLY, bridge_domain_set_mac_age_reply) \ +_(L2FIB_ADD_DEL_REPLY, l2fib_add_del_reply) \ +_(L2FIB_FLUSH_INT_REPLY, l2fib_flush_int_reply) \ +_(L2FIB_FLUSH_BD_REPLY, l2fib_flush_bd_reply) \ +_(L2_FLAGS_REPLY, l2_flags_reply) \ +_(BRIDGE_FLAGS_REPLY, bridge_flags_reply) \ +_(TAP_CONNECT_REPLY, tap_connect_reply) \ +_(TAP_MODIFY_REPLY, tap_modify_reply) \ +_(TAP_DELETE_REPLY, tap_delete_reply) \ +_(SW_INTERFACE_TAP_DETAILS, sw_interface_tap_details) \ +_(TAP_CREATE_V2_REPLY, tap_create_v2_reply) \ +_(TAP_DELETE_V2_REPLY, tap_delete_v2_reply) \ +_(SW_INTERFACE_TAP_V2_DETAILS, sw_interface_tap_v2_details) \ +_(IP_ADD_DEL_ROUTE_REPLY, ip_add_del_route_reply) \ +_(IP_TABLE_ADD_DEL_REPLY, ip_table_add_del_reply) \ +_(IP_MROUTE_ADD_DEL_REPLY, ip_mroute_add_del_reply) \ +_(MPLS_TABLE_ADD_DEL_REPLY, mpls_table_add_del_reply) \ +_(MPLS_ROUTE_ADD_DEL_REPLY, mpls_route_add_del_reply) \ +_(MPLS_IP_BIND_UNBIND_REPLY, mpls_ip_bind_unbind_reply) \ +_(BIER_ROUTE_ADD_DEL_REPLY, bier_route_add_del_reply) \ +_(BIER_TABLE_ADD_DEL_REPLY, bier_table_add_del_reply) \ +_(PROXY_ARP_ADD_DEL_REPLY, proxy_arp_add_del_reply) \ +_(PROXY_ARP_INTFC_ENABLE_DISABLE_REPLY, \ + proxy_arp_intfc_enable_disable_reply) \ +_(MPLS_TUNNEL_ADD_DEL_REPLY, mpls_tunnel_add_del_reply) \ +_(SW_INTERFACE_SET_UNNUMBERED_REPLY, \ + sw_interface_set_unnumbered_reply) \ +_(IP_NEIGHBOR_ADD_DEL_REPLY, ip_neighbor_add_del_reply) \ +_(CREATE_VLAN_SUBIF_REPLY, create_vlan_subif_reply) \ +_(CREATE_SUBIF_REPLY, create_subif_reply) \ +_(OAM_ADD_DEL_REPLY, oam_add_del_reply) \ +_(RESET_FIB_REPLY, reset_fib_reply) \ +_(DHCP_PROXY_CONFIG_REPLY, dhcp_proxy_config_reply) \ +_(DHCP_PROXY_SET_VSS_REPLY, dhcp_proxy_set_vss_reply) \ +_(DHCP_PROXY_DETAILS, dhcp_proxy_details) \ +_(DHCP_CLIENT_CONFIG_REPLY, dhcp_client_config_reply) \ +_(SET_IP_FLOW_HASH_REPLY, set_ip_flow_hash_reply) \ +_(SW_INTERFACE_IP6_ENABLE_DISABLE_REPLY, \ + sw_interface_ip6_enable_disable_reply) \ +_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS_REPLY, \ + sw_interface_ip6_set_link_local_address_reply) \ +_(IP6ND_PROXY_ADD_DEL_REPLY, ip6nd_proxy_add_del_reply) \ +_(IP6ND_PROXY_DETAILS, ip6nd_proxy_details) \ +_(SW_INTERFACE_IP6ND_RA_PREFIX_REPLY, \ + sw_interface_ip6nd_ra_prefix_reply) \ +_(SW_INTERFACE_IP6ND_RA_CONFIG_REPLY, \ + sw_interface_ip6nd_ra_config_reply) \ +_(SET_ARP_NEIGHBOR_LIMIT_REPLY, set_arp_neighbor_limit_reply) \ +_(L2_PATCH_ADD_DEL_REPLY, l2_patch_add_del_reply) \ +_(SR_POLICY_ADD_REPLY, sr_policy_add_reply) \ +_(SR_POLICY_MOD_REPLY, sr_policy_mod_reply) \ +_(SR_POLICY_DEL_REPLY, sr_policy_del_reply) \ +_(SR_LOCALSID_ADD_DEL_REPLY, sr_localsid_add_del_reply) \ +_(SR_STEERING_ADD_DEL_REPLY, sr_steering_add_del_reply) \ +_(CLASSIFY_ADD_DEL_TABLE_REPLY, classify_add_del_table_reply) \ +_(CLASSIFY_ADD_DEL_SESSION_REPLY, classify_add_del_session_reply) \ +_(CLASSIFY_SET_INTERFACE_IP_TABLE_REPLY, \ +classify_set_interface_ip_table_reply) \ +_(CLASSIFY_SET_INTERFACE_L2_TABLES_REPLY, \ + classify_set_interface_l2_tables_reply) \ +_(GET_NODE_INDEX_REPLY, get_node_index_reply) \ +_(ADD_NODE_NEXT_REPLY, add_node_next_reply) \ +_(L2TPV3_CREATE_TUNNEL_REPLY, l2tpv3_create_tunnel_reply) \ +_(L2TPV3_SET_TUNNEL_COOKIES_REPLY, l2tpv3_set_tunnel_cookies_reply) \ +_(L2TPV3_INTERFACE_ENABLE_DISABLE_REPLY, \ + l2tpv3_interface_enable_disable_reply) \ +_(L2TPV3_SET_LOOKUP_KEY_REPLY, l2tpv3_set_lookup_key_reply) \ +_(SW_IF_L2TPV3_TUNNEL_DETAILS, sw_if_l2tpv3_tunnel_details) \ +_(VXLAN_ADD_DEL_TUNNEL_REPLY, vxlan_add_del_tunnel_reply) \ +_(GENEVE_ADD_DEL_TUNNEL_REPLY, geneve_add_del_tunnel_reply) \ +_(VXLAN_TUNNEL_DETAILS, vxlan_tunnel_details) \ +_(GENEVE_TUNNEL_DETAILS, geneve_tunnel_details) \ +_(GRE_ADD_DEL_TUNNEL_REPLY, gre_add_del_tunnel_reply) \ +_(GRE_TUNNEL_DETAILS, gre_tunnel_details) \ +_(L2_FIB_CLEAR_TABLE_REPLY, l2_fib_clear_table_reply) \ +_(L2_INTERFACE_EFP_FILTER_REPLY, l2_interface_efp_filter_reply) \ +_(L2_INTERFACE_VLAN_TAG_REWRITE_REPLY, l2_interface_vlan_tag_rewrite_reply) \ +_(SW_INTERFACE_VHOST_USER_DETAILS, sw_interface_vhost_user_details) \ +_(CREATE_VHOST_USER_IF_REPLY, create_vhost_user_if_reply) \ +_(MODIFY_VHOST_USER_IF_REPLY, modify_vhost_user_if_reply) \ +_(DELETE_VHOST_USER_IF_REPLY, delete_vhost_user_if_reply) \ +_(SHOW_VERSION_REPLY, show_version_reply) \ +_(L2_FIB_TABLE_DETAILS, l2_fib_table_details) \ +_(VXLAN_GPE_ADD_DEL_TUNNEL_REPLY, vxlan_gpe_add_del_tunnel_reply) \ +_(VXLAN_GPE_TUNNEL_DETAILS, vxlan_gpe_tunnel_details) \ +_(INTERFACE_NAME_RENUMBER_REPLY, interface_name_renumber_reply) \ +_(WANT_IP4_ARP_EVENTS_REPLY, want_ip4_arp_events_reply) \ +_(IP4_ARP_EVENT, ip4_arp_event) \ +_(WANT_IP6_ND_EVENTS_REPLY, want_ip6_nd_events_reply) \ +_(IP6_ND_EVENT, ip6_nd_event) \ +_(WANT_L2_MACS_EVENTS_REPLY, want_l2_macs_events_reply) \ +_(L2_MACS_EVENT, l2_macs_event) \ +_(INPUT_ACL_SET_INTERFACE_REPLY, input_acl_set_interface_reply) \ +_(IP_ADDRESS_DETAILS, ip_address_details) \ +_(IP_DETAILS, ip_details) \ +_(IPSEC_SPD_ADD_DEL_REPLY, ipsec_spd_add_del_reply) \ +_(IPSEC_INTERFACE_ADD_DEL_SPD_REPLY, ipsec_interface_add_del_spd_reply) \ +_(IPSEC_SPD_ADD_DEL_ENTRY_REPLY, ipsec_spd_add_del_entry_reply) \ +_(IPSEC_SAD_ADD_DEL_ENTRY_REPLY, ipsec_sad_add_del_entry_reply) \ +_(IPSEC_SA_DETAILS, ipsec_sa_details) \ +_(IPSEC_SA_SET_KEY_REPLY, ipsec_sa_set_key_reply) \ +_(IPSEC_TUNNEL_IF_ADD_DEL_REPLY, ipsec_tunnel_if_add_del_reply) \ +_(IPSEC_TUNNEL_IF_SET_KEY_REPLY, ipsec_tunnel_if_set_key_reply) \ +_(IPSEC_TUNNEL_IF_SET_SA_REPLY, ipsec_tunnel_if_set_sa_reply) \ +_(IKEV2_PROFILE_ADD_DEL_REPLY, ikev2_profile_add_del_reply) \ +_(IKEV2_PROFILE_SET_AUTH_REPLY, ikev2_profile_set_auth_reply) \ +_(IKEV2_PROFILE_SET_ID_REPLY, ikev2_profile_set_id_reply) \ +_(IKEV2_PROFILE_SET_TS_REPLY, ikev2_profile_set_ts_reply) \ +_(IKEV2_SET_LOCAL_KEY_REPLY, ikev2_set_local_key_reply) \ +_(IKEV2_SET_RESPONDER_REPLY, ikev2_set_responder_reply) \ +_(IKEV2_SET_IKE_TRANSFORMS_REPLY, ikev2_set_ike_transforms_reply) \ +_(IKEV2_SET_ESP_TRANSFORMS_REPLY, ikev2_set_esp_transforms_reply) \ +_(IKEV2_SET_SA_LIFETIME_REPLY, ikev2_set_sa_lifetime_reply) \ +_(IKEV2_INITIATE_SA_INIT_REPLY, ikev2_initiate_sa_init_reply) \ +_(IKEV2_INITIATE_DEL_IKE_SA_REPLY, ikev2_initiate_del_ike_sa_reply) \ +_(IKEV2_INITIATE_DEL_CHILD_SA_REPLY, ikev2_initiate_del_child_sa_reply) \ +_(IKEV2_INITIATE_REKEY_CHILD_SA_REPLY, ikev2_initiate_rekey_child_sa_reply) \ +_(DELETE_LOOPBACK_REPLY, delete_loopback_reply) \ +_(BD_IP_MAC_ADD_DEL_REPLY, bd_ip_mac_add_del_reply) \ +_(DHCP_COMPL_EVENT, dhcp_compl_event) \ +_(MAP_ADD_DOMAIN_REPLY, map_add_domain_reply) \ +_(MAP_DEL_DOMAIN_REPLY, map_del_domain_reply) \ +_(MAP_ADD_DEL_RULE_REPLY, map_add_del_rule_reply) \ +_(MAP_DOMAIN_DETAILS, map_domain_details) \ +_(MAP_RULE_DETAILS, map_rule_details) \ +_(WANT_INTERFACE_EVENTS_REPLY, want_interface_events_reply) \ +_(WANT_STATS_REPLY, want_stats_reply) \ +_(GET_FIRST_MSG_ID_REPLY, get_first_msg_id_reply) \ +_(COP_INTERFACE_ENABLE_DISABLE_REPLY, cop_interface_enable_disable_reply) \ +_(COP_WHITELIST_ENABLE_DISABLE_REPLY, cop_whitelist_enable_disable_reply) \ +_(GET_NODE_GRAPH_REPLY, get_node_graph_reply) \ +_(SW_INTERFACE_CLEAR_STATS_REPLY, sw_interface_clear_stats_reply) \ +_(IOAM_ENABLE_REPLY, ioam_enable_reply) \ +_(IOAM_DISABLE_REPLY, ioam_disable_reply) \ +_(ONE_ADD_DEL_LOCATOR_SET_REPLY, one_add_del_locator_set_reply) \ +_(ONE_ADD_DEL_LOCATOR_REPLY, one_add_del_locator_reply) \ +_(ONE_ADD_DEL_LOCAL_EID_REPLY, one_add_del_local_eid_reply) \ +_(ONE_ADD_DEL_REMOTE_MAPPING_REPLY, one_add_del_remote_mapping_reply) \ +_(ONE_ADD_DEL_ADJACENCY_REPLY, one_add_del_adjacency_reply) \ +_(ONE_ADD_DEL_MAP_RESOLVER_REPLY, one_add_del_map_resolver_reply) \ +_(ONE_ADD_DEL_MAP_SERVER_REPLY, one_add_del_map_server_reply) \ +_(ONE_ENABLE_DISABLE_REPLY, one_enable_disable_reply) \ +_(ONE_MAP_REGISTER_ENABLE_DISABLE_REPLY, \ + one_map_register_enable_disable_reply) \ +_(ONE_MAP_REGISTER_SET_TTL_REPLY, one_map_register_set_ttl_reply) \ +_(ONE_SET_TRANSPORT_PROTOCOL_REPLY, one_set_transport_protocol_reply) \ +_(ONE_GET_TRANSPORT_PROTOCOL_REPLY, one_get_transport_protocol_reply) \ +_(ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, \ + one_map_register_fallback_threshold_reply) \ +_(ONE_RLOC_PROBE_ENABLE_DISABLE_REPLY, \ + one_rloc_probe_enable_disable_reply) \ +_(ONE_PITR_SET_LOCATOR_SET_REPLY, one_pitr_set_locator_set_reply) \ +_(ONE_USE_PETR_REPLY, one_use_petr_reply) \ +_(ONE_MAP_REQUEST_MODE_REPLY, one_map_request_mode_reply) \ +_(ONE_EID_TABLE_ADD_DEL_MAP_REPLY, one_eid_table_add_del_map_reply) \ +_(ONE_LOCATOR_SET_DETAILS, one_locator_set_details) \ +_(ONE_LOCATOR_DETAILS, one_locator_details) \ +_(ONE_EID_TABLE_DETAILS, one_eid_table_details) \ +_(ONE_EID_TABLE_MAP_DETAILS, one_eid_table_map_details) \ +_(ONE_EID_TABLE_VNI_DETAILS, one_eid_table_vni_details) \ +_(ONE_MAP_RESOLVER_DETAILS, one_map_resolver_details) \ +_(ONE_MAP_SERVER_DETAILS, one_map_server_details) \ +_(ONE_ADJACENCIES_GET_REPLY, one_adjacencies_get_reply) \ +_(ONE_STATS_DETAILS, one_stats_details) \ +_(ONE_STATS_FLUSH_REPLY, one_stats_flush_reply) \ +_(ONE_STATS_ENABLE_DISABLE_REPLY, one_stats_enable_disable_reply) \ +_(SHOW_ONE_STATS_ENABLE_DISABLE_REPLY, \ + show_one_stats_enable_disable_reply) \ +_(ONE_ADD_DEL_NDP_ENTRY_REPLY, one_add_del_ndp_entry_reply) \ +_(ONE_NDP_BD_GET_REPLY, one_ndp_bd_get_reply) \ +_(ONE_NDP_ENTRIES_GET_REPLY, one_ndp_entries_get_reply) \ +_(ONE_ADD_DEL_L2_ARP_ENTRY_REPLY, one_add_del_l2_arp_entry_reply) \ +_(ONE_L2_ARP_BD_GET_REPLY, one_l2_arp_bd_get_reply) \ +_(ONE_L2_ARP_ENTRIES_GET_REPLY, one_l2_arp_entries_get_reply) \ +_(ONE_ENABLE_DISABLE_XTR_MODE_REPLY, one_enable_disable_xtr_mode_reply) \ +_(ONE_ENABLE_DISABLE_PITR_MODE_REPLY, \ + one_enable_disable_pitr_mode_reply) \ +_(ONE_ENABLE_DISABLE_PETR_MODE_REPLY, \ + one_enable_disable_petr_mode_reply) \ +_(ONE_SHOW_XTR_MODE_REPLY, one_show_xtr_mode_reply) \ +_(ONE_SHOW_PITR_MODE_REPLY, one_show_pitr_mode_reply) \ +_(ONE_SHOW_PETR_MODE_REPLY, one_show_petr_mode_reply) \ +_(GPE_SET_ENCAP_MODE_REPLY, gpe_set_encap_mode_reply) \ +_(GPE_GET_ENCAP_MODE_REPLY, gpe_get_encap_mode_reply) \ +_(GPE_ADD_DEL_IFACE_REPLY, gpe_add_del_iface_reply) \ +_(GPE_ENABLE_DISABLE_REPLY, gpe_enable_disable_reply) \ +_(GPE_ADD_DEL_FWD_ENTRY_REPLY, gpe_add_del_fwd_entry_reply) \ +_(GPE_FWD_ENTRY_VNIS_GET_REPLY, gpe_fwd_entry_vnis_get_reply) \ +_(GPE_FWD_ENTRIES_GET_REPLY, gpe_fwd_entries_get_reply) \ +_(GPE_NATIVE_FWD_RPATHS_GET_REPLY, gpe_native_fwd_rpaths_get_reply) \ +_(GPE_ADD_DEL_NATIVE_FWD_RPATH_REPLY, \ + gpe_add_del_native_fwd_rpath_reply) \ +_(GPE_FWD_ENTRY_PATH_DETAILS, \ + gpe_fwd_entry_path_details) \ +_(SHOW_ONE_STATUS_REPLY, show_one_status_reply) \ +_(ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY, \ + one_add_del_map_request_itr_rlocs_reply) \ +_(ONE_GET_MAP_REQUEST_ITR_RLOCS_REPLY, \ + one_get_map_request_itr_rlocs_reply) \ +_(SHOW_ONE_NSH_MAPPING_REPLY, show_one_nsh_mapping_reply) \ +_(SHOW_ONE_PITR_REPLY, show_one_pitr_reply) \ +_(SHOW_ONE_USE_PETR_REPLY, show_one_use_petr_reply) \ +_(SHOW_ONE_MAP_REQUEST_MODE_REPLY, show_one_map_request_mode_reply) \ +_(SHOW_ONE_RLOC_PROBE_STATE_REPLY, show_one_rloc_probe_state_reply) \ +_(SHOW_ONE_MAP_REGISTER_STATE_REPLY, \ + show_one_map_register_state_reply) \ +_(SHOW_ONE_MAP_REGISTER_TTL_REPLY, show_one_map_register_ttl_reply) \ +_(SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD_REPLY, \ + show_one_map_register_fallback_threshold_reply) \ +_(AF_PACKET_CREATE_REPLY, af_packet_create_reply) \ +_(AF_PACKET_DELETE_REPLY, af_packet_delete_reply) \ +_(POLICER_ADD_DEL_REPLY, policer_add_del_reply) \ +_(POLICER_DETAILS, policer_details) \ +_(POLICER_CLASSIFY_SET_INTERFACE_REPLY, policer_classify_set_interface_reply) \ +_(POLICER_CLASSIFY_DETAILS, policer_classify_details) \ +_(NETMAP_CREATE_REPLY, netmap_create_reply) \ +_(NETMAP_DELETE_REPLY, netmap_delete_reply) \ +_(MPLS_TUNNEL_DETAILS, mpls_tunnel_details) \ +_(MPLS_FIB_DETAILS, mpls_fib_details) \ +_(CLASSIFY_TABLE_IDS_REPLY, classify_table_ids_reply) \ +_(CLASSIFY_TABLE_BY_INTERFACE_REPLY, classify_table_by_interface_reply) \ +_(CLASSIFY_TABLE_INFO_REPLY, classify_table_info_reply) \ +_(CLASSIFY_SESSION_DETAILS, classify_session_details) \ +_(SET_IPFIX_EXPORTER_REPLY, set_ipfix_exporter_reply) \ +_(IPFIX_EXPORTER_DETAILS, ipfix_exporter_details) \ +_(SET_IPFIX_CLASSIFY_STREAM_REPLY, set_ipfix_classify_stream_reply) \ +_(IPFIX_CLASSIFY_STREAM_DETAILS, ipfix_classify_stream_details) \ +_(IPFIX_CLASSIFY_TABLE_ADD_DEL_REPLY, ipfix_classify_table_add_del_reply) \ +_(IPFIX_CLASSIFY_TABLE_DETAILS, ipfix_classify_table_details) \ +_(FLOW_CLASSIFY_SET_INTERFACE_REPLY, flow_classify_set_interface_reply) \ +_(FLOW_CLASSIFY_DETAILS, flow_classify_details) \ +_(SW_INTERFACE_SPAN_ENABLE_DISABLE_REPLY, sw_interface_span_enable_disable_reply) \ +_(SW_INTERFACE_SPAN_DETAILS, sw_interface_span_details) \ +_(GET_NEXT_INDEX_REPLY, get_next_index_reply) \ +_(PG_CREATE_INTERFACE_REPLY, pg_create_interface_reply) \ +_(PG_CAPTURE_REPLY, pg_capture_reply) \ +_(PG_ENABLE_DISABLE_REPLY, pg_enable_disable_reply) \ +_(IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL_REPLY, \ + ip_source_and_port_range_check_add_del_reply) \ +_(IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL_REPLY, \ + ip_source_and_port_range_check_interface_add_del_reply) \ +_(IPSEC_GRE_ADD_DEL_TUNNEL_REPLY, ipsec_gre_add_del_tunnel_reply) \ +_(IPSEC_GRE_TUNNEL_DETAILS, ipsec_gre_tunnel_details) \ +_(DELETE_SUBIF_REPLY, delete_subif_reply) \ +_(L2_INTERFACE_PBB_TAG_REWRITE_REPLY, l2_interface_pbb_tag_rewrite_reply) \ +_(PUNT_REPLY, punt_reply) \ +_(IP_FIB_DETAILS, ip_fib_details) \ +_(IP6_FIB_DETAILS, ip6_fib_details) \ +_(FEATURE_ENABLE_DISABLE_REPLY, feature_enable_disable_reply) \ +_(SW_INTERFACE_TAG_ADD_DEL_REPLY, sw_interface_tag_add_del_reply) \ +_(L2_XCONNECT_DETAILS, l2_xconnect_details) \ +_(SW_INTERFACE_SET_MTU_REPLY, sw_interface_set_mtu_reply) \ +_(IP_NEIGHBOR_DETAILS, ip_neighbor_details) \ +_(SW_INTERFACE_GET_TABLE_REPLY, sw_interface_get_table_reply) \ +_(P2P_ETHERNET_ADD_REPLY, p2p_ethernet_add_reply) \ +_(P2P_ETHERNET_DEL_REPLY, p2p_ethernet_del_reply) \ +_(LLDP_CONFIG_REPLY, lldp_config_reply) \ +_(SW_INTERFACE_SET_LLDP_REPLY, sw_interface_set_lldp_reply) \ +_(TCP_CONFIGURE_SRC_ADDRESSES_REPLY, tcp_configure_src_addresses_reply) \ +_(APP_NAMESPACE_ADD_DEL_REPLY, app_namespace_add_del_reply) \ +_(DNS_ENABLE_DISABLE_REPLY, dns_enable_disable_reply) \ +_(DNS_NAME_SERVER_ADD_DEL_REPLY, dns_name_server_add_del_reply) \ +_(DNS_RESOLVE_NAME_REPLY, dns_resolve_name_reply) \ +_(DNS_RESOLVE_IP_REPLY, dns_resolve_ip_reply) \ +_(SESSION_RULE_ADD_DEL_REPLY, session_rule_add_del_reply) \ +_(SESSION_RULES_DETAILS, session_rules_details) \ +_(IP_CONTAINER_PROXY_ADD_DEL_REPLY, ip_container_proxy_add_del_reply) \ + +#define foreach_standalone_reply_msg \ +_(SW_INTERFACE_EVENT, sw_interface_event) \ +_(VNET_INTERFACE_SIMPLE_COUNTERS, vnet_interface_simple_counters) \ +_(VNET_INTERFACE_COMBINED_COUNTERS, vnet_interface_combined_counters) \ +_(VNET_IP4_FIB_COUNTERS, vnet_ip4_fib_counters) \ +_(VNET_IP6_FIB_COUNTERS, vnet_ip6_fib_counters) \ +_(VNET_IP4_NBR_COUNTERS, vnet_ip4_nbr_counters) \ +_(VNET_IP6_NBR_COUNTERS, vnet_ip6_nbr_counters) \ +_(MEMFD_SEGMENT_CREATE_REPLY, memfd_segment_create_reply) \ + +typedef struct +{ + u8 *name; + u32 value; +} name_sort_t; + + +#define STR_VTR_OP_CASE(op) \ + case L2_VTR_ ## op: \ + return "" # op; + +static const char * +str_vtr_op (u32 vtr_op) +{ + switch (vtr_op) + { + STR_VTR_OP_CASE (DISABLED); + STR_VTR_OP_CASE (PUSH_1); + STR_VTR_OP_CASE (PUSH_2); + STR_VTR_OP_CASE (POP_1); + STR_VTR_OP_CASE (POP_2); + STR_VTR_OP_CASE (TRANSLATE_1_1); + STR_VTR_OP_CASE (TRANSLATE_1_2); + STR_VTR_OP_CASE (TRANSLATE_2_1); + STR_VTR_OP_CASE (TRANSLATE_2_2); + } + + return "UNKNOWN"; +} + +static int +dump_sub_interface_table (vat_main_t * vam) +{ + const sw_interface_subif_t *sub = NULL; + + if (vam->json_output) + { + clib_warning + ("JSON output supported only for VPE API calls and dump_stats_table"); + return -99; + } + + print (vam->ofp, + "%-30s%-12s%-11s%-7s%-5s%-9s%-9s%-6s%-8s%-10s%-10s", + "Interface", "sw_if_index", + "sub id", "dot1ad", "tags", "outer id", + "inner id", "exact", "default", "outer any", "inner any"); + + vec_foreach (sub, vam->sw_if_subif_table) + { + print (vam->ofp, + "%-30s%-12d%-11d%-7s%-5d%-9d%-9d%-6d%-8d%-10d%-10d", + sub->interface_name, + sub->sw_if_index, + sub->sub_id, sub->sub_dot1ad ? "dot1ad" : "dot1q", + sub->sub_number_of_tags, sub->sub_outer_vlan_id, + sub->sub_inner_vlan_id, sub->sub_exact_match, sub->sub_default, + sub->sub_outer_vlan_id_any, sub->sub_inner_vlan_id_any); + if (sub->vtr_op != L2_VTR_DISABLED) + { + print (vam->ofp, + " vlan-tag-rewrite - op: %-14s [ dot1q: %d " + "tag1: %d tag2: %d ]", + str_vtr_op (sub->vtr_op), sub->vtr_push_dot1q, + sub->vtr_tag1, sub->vtr_tag2); + } + } + + return 0; +} + +static int +name_sort_cmp (void *a1, void *a2) +{ + name_sort_t *n1 = a1; + name_sort_t *n2 = a2; + + return strcmp ((char *) n1->name, (char *) n2->name); +} + +static int +dump_interface_table (vat_main_t * vam) +{ + hash_pair_t *p; + name_sort_t *nses = 0, *ns; + + if (vam->json_output) + { + clib_warning + ("JSON output supported only for VPE API calls and dump_stats_table"); + return -99; + } + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, + ({ + vec_add2 (nses, ns, 1); + ns->name = (u8 *)(p->key); + ns->value = (u32) p->value[0]; + })); + /* *INDENT-ON* */ + + vec_sort_with_function (nses, name_sort_cmp); + + print (vam->ofp, "%-25s%-15s", "Interface", "sw_if_index"); + vec_foreach (ns, nses) + { + print (vam->ofp, "%-25s%-15d", ns->name, ns->value); + } + vec_free (nses); + return 0; +} + +static int +dump_ip_table (vat_main_t * vam, int is_ipv6) +{ + const ip_details_t *det = NULL; + const ip_address_details_t *address = NULL; + u32 i = ~0; + + print (vam->ofp, "%-12s", "sw_if_index"); + + vec_foreach (det, vam->ip_details_by_sw_if_index[is_ipv6]) + { + i++; + if (!det->present) + { + continue; + } + print (vam->ofp, "%-12d", i); + print (vam->ofp, " %-30s%-13s", "Address", "Prefix length"); + if (!det->addr) + { + continue; + } + vec_foreach (address, det->addr) + { + print (vam->ofp, + " %-30U%-13d", + is_ipv6 ? format_ip6_address : format_ip4_address, + address->ip, address->prefix_length); + } + } + + return 0; +} + +static int +dump_ipv4_table (vat_main_t * vam) +{ + if (vam->json_output) + { + clib_warning + ("JSON output supported only for VPE API calls and dump_stats_table"); + return -99; + } + + return dump_ip_table (vam, 0); +} + +static int +dump_ipv6_table (vat_main_t * vam) +{ + if (vam->json_output) + { + clib_warning + ("JSON output supported only for VPE API calls and dump_stats_table"); + return -99; + } + + return dump_ip_table (vam, 1); +} + +static char * +counter_type_to_str (u8 counter_type, u8 is_combined) +{ + if (!is_combined) + { + switch (counter_type) + { + case VNET_INTERFACE_COUNTER_DROP: + return "drop"; + case VNET_INTERFACE_COUNTER_PUNT: + return "punt"; + case VNET_INTERFACE_COUNTER_IP4: + return "ip4"; + case VNET_INTERFACE_COUNTER_IP6: + return "ip6"; + case VNET_INTERFACE_COUNTER_RX_NO_BUF: + return "rx-no-buf"; + case VNET_INTERFACE_COUNTER_RX_MISS: + return "rx-miss"; + case VNET_INTERFACE_COUNTER_RX_ERROR: + return "rx-error"; + case VNET_INTERFACE_COUNTER_TX_ERROR: + return "tx-error"; + default: + return "INVALID-COUNTER-TYPE"; + } + } + else + { + switch (counter_type) + { + case VNET_INTERFACE_COUNTER_RX: + return "rx"; + case VNET_INTERFACE_COUNTER_TX: + return "tx"; + default: + return "INVALID-COUNTER-TYPE"; + } + } +} + +static int +dump_stats_table (vat_main_t * vam) +{ + vat_json_node_t node; + vat_json_node_t *msg_array; + vat_json_node_t *msg; + vat_json_node_t *counter_array; + vat_json_node_t *counter; + interface_counter_t c; + u64 packets; + ip4_fib_counter_t *c4; + ip6_fib_counter_t *c6; + ip4_nbr_counter_t *n4; + ip6_nbr_counter_t *n6; + int i, j; + + if (!vam->json_output) + { + clib_warning ("dump_stats_table supported only in JSON format"); + return -99; + } + + vat_json_init_object (&node); + + /* interface counters */ + msg_array = vat_json_object_add (&node, "interface_counters"); + vat_json_init_array (msg_array); + for (i = 0; i < vec_len (vam->simple_interface_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_string_copy (msg, "vnet_counter_type", + (u8 *) counter_type_to_str (i, 0)); + vat_json_object_add_int (msg, "is_combined", 0); + counter_array = vat_json_object_add (msg, "data"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->simple_interface_counters[i]); j++) + { + packets = vam->simple_interface_counters[i][j]; + vat_json_array_add_uint (counter_array, packets); + } + } + for (i = 0; i < vec_len (vam->combined_interface_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_string_copy (msg, "vnet_counter_type", + (u8 *) counter_type_to_str (i, 1)); + vat_json_object_add_int (msg, "is_combined", 1); + counter_array = vat_json_object_add (msg, "data"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->combined_interface_counters[i]); j++) + { + c = vam->combined_interface_counters[i][j]; + counter = vat_json_array_add (counter_array); + vat_json_init_object (counter); + vat_json_object_add_uint (counter, "packets", c.packets); + vat_json_object_add_uint (counter, "bytes", c.bytes); + } + } + + /* ip4 fib counters */ + msg_array = vat_json_object_add (&node, "ip4_fib_counters"); + vat_json_init_array (msg_array); + for (i = 0; i < vec_len (vam->ip4_fib_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_uint (msg, "vrf_id", + vam->ip4_fib_counters_vrf_id_by_index[i]); + counter_array = vat_json_object_add (msg, "c"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->ip4_fib_counters[i]); j++) + { + counter = vat_json_array_add (counter_array); + vat_json_init_object (counter); + c4 = &vam->ip4_fib_counters[i][j]; + vat_json_object_add_ip4 (counter, "address", c4->address); + vat_json_object_add_uint (counter, "address_length", + c4->address_length); + vat_json_object_add_uint (counter, "packets", c4->packets); + vat_json_object_add_uint (counter, "bytes", c4->bytes); + } + } + + /* ip6 fib counters */ + msg_array = vat_json_object_add (&node, "ip6_fib_counters"); + vat_json_init_array (msg_array); + for (i = 0; i < vec_len (vam->ip6_fib_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_uint (msg, "vrf_id", + vam->ip6_fib_counters_vrf_id_by_index[i]); + counter_array = vat_json_object_add (msg, "c"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->ip6_fib_counters[i]); j++) + { + counter = vat_json_array_add (counter_array); + vat_json_init_object (counter); + c6 = &vam->ip6_fib_counters[i][j]; + vat_json_object_add_ip6 (counter, "address", c6->address); + vat_json_object_add_uint (counter, "address_length", + c6->address_length); + vat_json_object_add_uint (counter, "packets", c6->packets); + vat_json_object_add_uint (counter, "bytes", c6->bytes); + } + } + + /* ip4 nbr counters */ + msg_array = vat_json_object_add (&node, "ip4_nbr_counters"); + vat_json_init_array (msg_array); + for (i = 0; i < vec_len (vam->ip4_nbr_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_uint (msg, "sw_if_index", i); + counter_array = vat_json_object_add (msg, "c"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->ip4_nbr_counters[i]); j++) + { + counter = vat_json_array_add (counter_array); + vat_json_init_object (counter); + n4 = &vam->ip4_nbr_counters[i][j]; + vat_json_object_add_ip4 (counter, "address", n4->address); + vat_json_object_add_uint (counter, "link-type", n4->linkt); + vat_json_object_add_uint (counter, "packets", n4->packets); + vat_json_object_add_uint (counter, "bytes", n4->bytes); + } + } + + /* ip6 nbr counters */ + msg_array = vat_json_object_add (&node, "ip6_nbr_counters"); + vat_json_init_array (msg_array); + for (i = 0; i < vec_len (vam->ip6_nbr_counters); i++) + { + msg = vat_json_array_add (msg_array); + vat_json_init_object (msg); + vat_json_object_add_uint (msg, "sw_if_index", i); + counter_array = vat_json_object_add (msg, "c"); + vat_json_init_array (counter_array); + for (j = 0; j < vec_len (vam->ip6_nbr_counters[i]); j++) + { + counter = vat_json_array_add (counter_array); + vat_json_init_object (counter); + n6 = &vam->ip6_nbr_counters[i][j]; + vat_json_object_add_ip6 (counter, "address", n6->address); + vat_json_object_add_uint (counter, "packets", n6->packets); + vat_json_object_add_uint (counter, "bytes", n6->bytes); + } + } + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + return 0; +} + +/* + * Pass CLI buffers directly in the CLI_INBAND API message, + * instead of an additional shared memory area. + */ +static int +exec_inband (vat_main_t * vam) +{ + vl_api_cli_inband_t *mp; + unformat_input_t *i = vam->input; + int ret; + + if (vec_len (i->buffer) == 0) + return -1; + + if (vam->exec_mode == 0 && unformat (i, "mode")) + { + vam->exec_mode = 1; + return 0; + } + if (vam->exec_mode == 1 && (unformat (i, "exit") || unformat (i, "quit"))) + { + vam->exec_mode = 0; + return 0; + } + + /* + * In order for the CLI command to work, it + * must be a vector ending in \n, not a C-string ending + * in \n\0. + */ + u32 len = vec_len (vam->input->buffer); + M2 (CLI_INBAND, mp, len); + clib_memcpy (mp->cmd, vam->input->buffer, len); + mp->length = htonl (len); + + S (mp); + W (ret); + /* json responses may or may not include a useful reply... */ + if (vec_len (vam->cmd_reply)) + print (vam->ofp, "%v", (char *) (vam->cmd_reply)); + return ret; +} + +int +exec (vat_main_t * vam) +{ + return exec_inband (vam); +} + +static int +api_create_loopback (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_create_loopback_t *mp; + vl_api_create_loopback_instance_t *mp_lbi; + u8 mac_address[6]; + u8 mac_set = 0; + u8 is_specified = 0; + u32 user_instance = 0; + int ret; + + memset (mac_address, 0, sizeof (mac_address)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) + mac_set = 1; + if (unformat (i, "instance %d", &user_instance)) + is_specified = 1; + else + break; + } + + if (is_specified) + { + M (CREATE_LOOPBACK_INSTANCE, mp_lbi); + mp_lbi->is_specified = is_specified; + if (is_specified) + mp_lbi->user_instance = htonl (user_instance); + if (mac_set) + clib_memcpy (mp_lbi->mac_address, mac_address, sizeof (mac_address)); + S (mp_lbi); + } + else + { + /* Construct the API message */ + M (CREATE_LOOPBACK, mp); + if (mac_set) + clib_memcpy (mp->mac_address, mac_address, sizeof (mac_address)); + S (mp); + } + + W (ret); + return ret; +} + +static int +api_delete_loopback (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_delete_loopback_t *mp; + u32 sw_if_index = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (DELETE_LOOPBACK, mp); + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +static int +api_want_stats (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_want_stats_t *mp; + int enable = -1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (enable == -1) + { + errmsg ("missing enable|disable"); + return -99; + } + + M (WANT_STATS, mp); + mp->enable_disable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_want_interface_events (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_want_interface_events_t *mp; + int enable = -1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (enable == -1) + { + errmsg ("missing enable|disable"); + return -99; + } + + M (WANT_INTERFACE_EVENTS, mp); + mp->enable_disable = enable; + + vam->interface_event_display = enable; + + S (mp); + W (ret); + return ret; +} + + +/* Note: non-static, called once to set up the initial intfc table */ +int +api_sw_interface_dump (vat_main_t * vam) +{ + vl_api_sw_interface_dump_t *mp; + vl_api_control_ping_t *mp_ping; + hash_pair_t *p; + name_sort_t *nses = 0, *ns; + sw_interface_subif_t *sub = NULL; + int ret; + + /* Toss the old name table */ + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, + ({ + vec_add2 (nses, ns, 1); + ns->name = (u8 *)(p->key); + ns->value = (u32) p->value[0]; + })); + /* *INDENT-ON* */ + + hash_free (vam->sw_if_index_by_interface_name); + + vec_foreach (ns, nses) vec_free (ns->name); + + vec_free (nses); + + vec_foreach (sub, vam->sw_if_subif_table) + { + vec_free (sub->interface_name); + } + vec_free (vam->sw_if_subif_table); + + /* recreate the interface name hash table */ + vam->sw_if_index_by_interface_name = hash_create_string (0, sizeof (uword)); + + /* Get list of ethernets */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "Ether", sizeof (mp->name_filter) - 1); + S (mp); + + /* and local / loopback interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "lo", sizeof (mp->name_filter) - 1); + S (mp); + + /* and packet-generator interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "pg", sizeof (mp->name_filter) - 1); + S (mp); + + /* and vxlan-gpe tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "vxlan_gpe", + sizeof (mp->name_filter) - 1); + S (mp); + + /* and vxlan tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "vxlan", sizeof (mp->name_filter) - 1); + S (mp); + + /* and geneve tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "geneve", sizeof (mp->name_filter) - 1); + S (mp); + + /* and host (af_packet) interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "host", sizeof (mp->name_filter) - 1); + S (mp); + + /* and l2tpv3 tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "l2tpv3_tunnel", + sizeof (mp->name_filter) - 1); + S (mp); + + /* and GRE tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "gre", sizeof (mp->name_filter) - 1); + S (mp); + + /* and LISP-GPE interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "lisp_gpe", + sizeof (mp->name_filter) - 1); + S (mp); + + /* and IPSEC tunnel interfaces */ + M (SW_INTERFACE_DUMP, mp); + mp->name_filter_valid = 1; + strncpy ((char *) mp->name_filter, "ipsec", sizeof (mp->name_filter) - 1); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_sw_interface_set_flags (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_flags_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 admin_up = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "admin-up")) + admin_up = 1; + else if (unformat (i, "admin-down")) + admin_up = 0; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_FLAGS, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->admin_up_down = admin_up; + + /* send it... */ + S (mp); + + /* Wait for a reply, return the good/bad news... */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_rx_mode (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_rx_mode_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + u8 queue_id_valid = 0; + u32 queue_id; + vnet_hw_interface_rx_mode mode = VNET_HW_INTERFACE_RX_MODE_UNKNOWN; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "queue %d", &queue_id)) + queue_id_valid = 1; + else if (unformat (i, "polling")) + mode = VNET_HW_INTERFACE_RX_MODE_POLLING; + else if (unformat (i, "interrupt")) + mode = VNET_HW_INTERFACE_RX_MODE_INTERRUPT; + else if (unformat (i, "adaptive")) + mode = VNET_HW_INTERFACE_RX_MODE_ADAPTIVE; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (mode == VNET_HW_INTERFACE_RX_MODE_UNKNOWN) + { + errmsg ("missing rx-mode"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_RX_MODE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->mode = mode; + mp->queue_id_valid = queue_id_valid; + mp->queue_id = queue_id_valid ? ntohl (queue_id) : ~0; + + /* send it... */ + S (mp); + + /* Wait for a reply, return the good/bad news... */ + W (ret); + return ret; +} + +static int +api_sw_interface_clear_stats (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_clear_stats_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + /* Construct the API message */ + M (SW_INTERFACE_CLEAR_STATS, mp); + + if (sw_if_index_set == 1) + mp->sw_if_index = ntohl (sw_if_index); + else + mp->sw_if_index = ~0; + + /* send it... */ + S (mp); + + /* Wait for a reply, return the good/bad news... */ + W (ret); + return ret; +} + +static int +api_sw_interface_add_del_address (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_add_del_address_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 is_add = 1, del_all = 0; + u32 address_length = 0; + u8 v4_address_set = 0; + u8 v6_address_set = 0; + ip4_address_t v4address; + ip6_address_t v6address; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del-all")) + del_all = 1; + else if (unformat (i, "del")) + is_add = 0; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "%U/%d", + unformat_ip4_address, &v4address, &address_length)) + v4_address_set = 1; + else if (unformat (i, "%U/%d", + unformat_ip6_address, &v6address, &address_length)) + v6_address_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (v4_address_set && v6_address_set) + { + errmsg ("both v4 and v6 addresses set"); + return -99; + } + if (!v4_address_set && !v6_address_set && !del_all) + { + errmsg ("no addresses set"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_ADD_DEL_ADDRESS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = is_add; + mp->del_all = del_all; + if (v6_address_set) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->address, &v6address, sizeof (v6address)); + } + else + { + clib_memcpy (mp->address, &v4address, sizeof (v4address)); + } + mp->address_length = address_length; + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_mpls_enable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_mpls_enable_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 enable = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "disable")) + enable = 0; + else if (unformat (i, "dis")) + enable = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_MPLS_ENABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = enable; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_table (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_table_t *mp; + u32 sw_if_index, vrf_id = 0; + u8 sw_if_index_set = 0; + u8 is_ipv6 = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "vrf %d", &vrf_id)) + ; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_TABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_ipv6 = is_ipv6; + mp->vrf_id = ntohl (vrf_id); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static void vl_api_sw_interface_get_table_reply_t_handler + (vl_api_sw_interface_get_table_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%d", ntohl (mp->vrf_id)); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; + +} + +static void vl_api_sw_interface_get_table_reply_t_handler_json + (vl_api_sw_interface_get_table_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static int +api_sw_interface_get_table (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_get_table_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 is_ipv6 = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (SW_INTERFACE_GET_TABLE, mp); + mp->sw_if_index = htonl (sw_if_index); + mp->is_ipv6 = is_ipv6; + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_vpath (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_vpath_t *mp; + u32 sw_if_index = 0; + u8 sw_if_index_set = 0; + u8 is_enable = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + is_enable = 1; + else if (unformat (i, "disable")) + is_enable = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_VPATH, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = is_enable; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_vxlan_bypass (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_vxlan_bypass_t *mp; + u32 sw_if_index = 0; + u8 sw_if_index_set = 0; + u8 is_enable = 1; + u8 is_ipv6 = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + is_enable = 1; + else if (unformat (i, "disable")) + is_enable = 0; + else if (unformat (i, "ip4")) + is_ipv6 = 0; + else if (unformat (i, "ip6")) + is_ipv6 = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_VXLAN_BYPASS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = is_enable; + mp->is_ipv6 = is_ipv6; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_geneve_bypass (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_geneve_bypass_t *mp; + u32 sw_if_index = 0; + u8 sw_if_index_set = 0; + u8 is_enable = 1; + u8 is_ipv6 = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + is_enable = 1; + else if (unformat (i, "disable")) + is_enable = 0; + else if (unformat (i, "ip4")) + is_ipv6 = 0; + else if (unformat (i, "ip6")) + is_ipv6 = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_GENEVE_BYPASS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = is_enable; + mp->is_ipv6 = is_ipv6; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_sw_interface_set_l2_xconnect (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_l2_xconnect_t *mp; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 tx_sw_if_index; + u8 tx_sw_if_index_set = 0; + u8 enable = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index)) + tx_sw_if_index_set = 1; + else if (unformat (i, "rx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, + &rx_sw_if_index)) + rx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "tx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, + &tx_sw_if_index)) + tx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or rx_sw_if_index"); + return -99; + } + + if (enable && (tx_sw_if_index_set == 0)) + { + errmsg ("missing tx interface name or tx_sw_if_index"); + return -99; + } + + M (SW_INTERFACE_SET_L2_XCONNECT, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->tx_sw_if_index = ntohl (tx_sw_if_index); + mp->enable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_l2_bridge (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_l2_bridge_t *mp; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 bd_id; + u8 bd_id_set = 0; + u8 bvi = 0; + u32 shg = 0; + u8 enable = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else + if (unformat + (i, "%U", api_unformat_sw_if_index, vam, &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "shg %d", &shg)) + ; + else if (unformat (i, "bvi")) + bvi = 1; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or sw_if_index"); + return -99; + } + + if (enable && (bd_id_set == 0)) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (SW_INTERFACE_SET_L2_BRIDGE, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->bd_id = ntohl (bd_id); + mp->shg = (u8) shg; + mp->bvi = bvi; + mp->enable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_bridge_domain_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 bd_id = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else + break; + } + + M (BRIDGE_DOMAIN_DUMP, mp); + mp->bd_id = ntohl (bd_id); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_bridge_domain_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_add_del_t *mp; + u32 bd_id = ~0; + u8 is_add = 1; + u32 flood = 1, forward = 1, learn = 1, uu_flood = 1, arp_term = 0; + u8 *bd_tag = NULL; + u32 mac_age = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + ; + else if (unformat (i, "flood %d", &flood)) + ; + else if (unformat (i, "uu-flood %d", &uu_flood)) + ; + else if (unformat (i, "forward %d", &forward)) + ; + else if (unformat (i, "learn %d", &learn)) + ; + else if (unformat (i, "arp-term %d", &arp_term)) + ; + else if (unformat (i, "mac-age %d", &mac_age)) + ; + else if (unformat (i, "bd-tag %s", &bd_tag)) + ; + else if (unformat (i, "del")) + { + is_add = 0; + flood = uu_flood = forward = learn = 0; + } + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + ret = -99; + goto done; + } + + if (mac_age > 255) + { + errmsg ("mac age must be less than 256 "); + ret = -99; + goto done; + } + + if ((bd_tag) && (vec_len (bd_tag) > 63)) + { + errmsg ("bd-tag cannot be longer than 63"); + ret = -99; + goto done; + } + + M (BRIDGE_DOMAIN_ADD_DEL, mp); + + mp->bd_id = ntohl (bd_id); + mp->flood = flood; + mp->uu_flood = uu_flood; + mp->forward = forward; + mp->learn = learn; + mp->arp_term = arp_term; + mp->is_add = is_add; + mp->mac_age = (u8) mac_age; + if (bd_tag) + { + clib_memcpy (mp->bd_tag, bd_tag, vec_len (bd_tag)); + mp->bd_tag[vec_len (bd_tag)] = 0; + } + S (mp); + W (ret); + +done: + vec_free (bd_tag); + return ret; +} + +static int +api_l2fib_flush_bd (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2fib_flush_bd_t *mp; + u32 bd_id = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)); + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (L2FIB_FLUSH_BD, mp); + + mp->bd_id = htonl (bd_id); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2fib_flush_int (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2fib_flush_int_t *mp; + u32 sw_if_index = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)); + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)); + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2FIB_FLUSH_INT, mp); + + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2fib_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2fib_add_del_t *mp; + f64 timeout; + u8 mac[6] = { 0 }; + u8 mac_set = 0; + u32 bd_id; + u8 bd_id_set = 0; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + u8 is_add = 1; + u8 static_mac = 0; + u8 filter_mac = 0; + u8 bvi_mac = 0; + int count = 1; + f64 before = 0; + int j; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "static")) + static_mac = 1; + else if (unformat (i, "filter")) + { + filter_mac = 1; + static_mac = 1; + } + else if (unformat (i, "bvi")) + { + bvi_mac = 1; + static_mac = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "count %d", &count)) + ; + else + break; + } + + if (mac_set == 0) + { + errmsg ("missing mac address"); + return -99; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + if (is_add && sw_if_index_set == 0 && filter_mac == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (count > 1) + { + /* Turn on async mode */ + vam->async_mode = 1; + vam->async_errors = 0; + before = vat_time_now (vam); + } + + for (j = 0; j < count; j++) + { + M (L2FIB_ADD_DEL, mp); + + clib_memcpy (mp->mac, mac, 6); + mp->bd_id = ntohl (bd_id); + mp->is_add = is_add; + + if (is_add) + { + mp->sw_if_index = ntohl (sw_if_index); + mp->static_mac = static_mac; + mp->filter_mac = filter_mac; + mp->bvi_mac = bvi_mac; + } + increment_mac_address (mac); + /* send it... */ + S (mp); + } + + if (count > 1) + { + vl_api_control_ping_t *mp_ping; + f64 after; + + /* Shut off async mode */ + vam->async_mode = 0; + + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + timeout = vat_time_now (vam) + 1.0; + while (vat_time_now (vam) < timeout) + if (vam->result_ready == 1) + goto out; + vam->retval = -99; + + out: + if (vam->retval == -99) + errmsg ("timeout"); + + if (vam->async_errors > 0) + { + errmsg ("%d asynchronous errors", vam->async_errors); + vam->retval = -98; + } + vam->async_errors = 0; + after = vat_time_now (vam); + + print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", + count, after - before, count / (after - before)); + } + else + { + int ret; + + /* Wait for a reply... */ + W (ret); + return ret; + } + /* Return the good/bad news */ + return (vam->retval); +} + +static int +api_bridge_domain_set_mac_age (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_domain_set_mac_age_t *mp; + u32 bd_id = ~0; + u32 mac_age = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)); + else if (unformat (i, "mac-age %d", &mac_age)); + else + break; + } + + if (bd_id == ~0) + { + errmsg ("missing bridge domain"); + return -99; + } + + if (mac_age > 255) + { + errmsg ("mac age must be less than 256 "); + return -99; + } + + M (BRIDGE_DOMAIN_SET_MAC_AGE, mp); + + mp->bd_id = htonl (bd_id); + mp->mac_age = (u8) mac_age; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2_flags (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_flags_t *mp; + u32 sw_if_index; + u32 flags = 0; + u8 sw_if_index_set = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "learn")) + flags |= L2_LEARN; + else if (unformat (i, "forward")) + flags |= L2_FWD; + else if (unformat (i, "flood")) + flags |= L2_FLOOD; + else if (unformat (i, "uu-flood")) + flags |= L2_UU_FLOOD; + else if (unformat (i, "arp-term")) + flags |= L2_ARP_TERM; + else if (unformat (i, "off")) + is_set = 0; + else if (unformat (i, "disable")) + is_set = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2_FLAGS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->feature_bitmap = ntohl (flags); + mp->is_set = is_set; + + S (mp); + W (ret); + return ret; +} + +static int +api_bridge_flags (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bridge_flags_t *mp; + u32 bd_id; + u8 bd_id_set = 0; + u8 is_set = 1; + u32 flags = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else if (unformat (i, "learn")) + flags |= L2_LEARN; + else if (unformat (i, "forward")) + flags |= L2_FWD; + else if (unformat (i, "flood")) + flags |= L2_FLOOD; + else if (unformat (i, "uu-flood")) + flags |= L2_UU_FLOOD; + else if (unformat (i, "arp-term")) + flags |= L2_ARP_TERM; + else if (unformat (i, "off")) + is_set = 0; + else if (unformat (i, "disable")) + is_set = 0; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + M (BRIDGE_FLAGS, mp); + + mp->bd_id = ntohl (bd_id); + mp->feature_bitmap = ntohl (flags); + mp->is_set = is_set; + + S (mp); + W (ret); + return ret; +} + +static int +api_bd_ip_mac_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bd_ip_mac_add_del_t *mp; + u32 bd_id; + u8 is_ipv6 = 0; + u8 is_add = 1; + u8 bd_id_set = 0; + u8 ip_set = 0; + u8 mac_set = 0; + ip4_address_t v4addr; + ip6_address_t v6addr; + u8 macaddr[6]; + int ret; + + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + { + bd_id_set++; + } + else if (unformat (i, "%U", unformat_ip4_address, &v4addr)) + { + ip_set++; + } + else if (unformat (i, "%U", unformat_ip6_address, &v6addr)) + { + ip_set++; + is_ipv6++; + } + else if (unformat (i, "%U", unformat_ethernet_address, macaddr)) + { + mac_set++; + } + else if (unformat (i, "del")) + is_add = 0; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + else if (ip_set == 0) + { + errmsg ("missing IP address"); + return -99; + } + else if (mac_set == 0) + { + errmsg ("missing MAC address"); + return -99; + } + + M (BD_IP_MAC_ADD_DEL, mp); + + mp->bd_id = ntohl (bd_id); + mp->is_ipv6 = is_ipv6; + mp->is_add = is_add; + if (is_ipv6) + clib_memcpy (mp->ip_address, &v6addr, sizeof (v6addr)); + else + clib_memcpy (mp->ip_address, &v4addr, sizeof (v4addr)); + clib_memcpy (mp->mac_address, macaddr, 6); + S (mp); + W (ret); + return ret; +} + +static int +api_tap_connect (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_tap_connect_t *mp; + u8 mac_address[6]; + u8 random_mac = 1; + u8 name_set = 0; + u8 *tap_name; + u8 *tag = 0; + ip4_address_t ip4_address; + u32 ip4_mask_width; + int ip4_address_set = 0; + ip6_address_t ip6_address; + u32 ip6_mask_width; + int ip6_address_set = 0; + int ret; + + memset (mac_address, 0, sizeof (mac_address)); + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) + { + random_mac = 0; + } + else if (unformat (i, "random-mac")) + random_mac = 1; + else if (unformat (i, "tapname %s", &tap_name)) + name_set = 1; + else if (unformat (i, "tag %s", &tag)) + ; + else if (unformat (i, "address %U/%d", + unformat_ip4_address, &ip4_address, &ip4_mask_width)) + ip4_address_set = 1; + else if (unformat (i, "address %U/%d", + unformat_ip6_address, &ip6_address, &ip6_mask_width)) + ip6_address_set = 1; + else + break; + } + + if (name_set == 0) + { + errmsg ("missing tap name"); + return -99; + } + if (vec_len (tap_name) > 63) + { + errmsg ("tap name too long"); + return -99; + } + vec_add1 (tap_name, 0); + + if (vec_len (tag) > 63) + { + errmsg ("tag too long"); + return -99; + } + + /* Construct the API message */ + M (TAP_CONNECT, mp); + + mp->use_random_mac = random_mac; + clib_memcpy (mp->mac_address, mac_address, 6); + clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name)); + if (tag) + clib_memcpy (mp->tag, tag, vec_len (tag)); + + if (ip4_address_set) + { + mp->ip4_address_set = 1; + clib_memcpy (mp->ip4_address, &ip4_address, sizeof (mp->ip4_address)); + mp->ip4_mask_width = ip4_mask_width; + } + if (ip6_address_set) + { + mp->ip6_address_set = 1; + clib_memcpy (mp->ip6_address, &ip6_address, sizeof (mp->ip6_address)); + mp->ip6_mask_width = ip6_mask_width; + } + + vec_free (tap_name); + vec_free (tag); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_tap_modify (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_tap_modify_t *mp; + u8 mac_address[6]; + u8 random_mac = 1; + u8 name_set = 0; + u8 *tap_name; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + int ret; + + memset (mac_address, 0, sizeof (mac_address)); + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) + { + random_mac = 0; + } + else if (unformat (i, "random-mac")) + random_mac = 1; + else if (unformat (i, "tapname %s", &tap_name)) + name_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing vpp interface name"); + return -99; + } + if (name_set == 0) + { + errmsg ("missing tap name"); + return -99; + } + if (vec_len (tap_name) > 63) + { + errmsg ("tap name too long"); + } + vec_add1 (tap_name, 0); + + /* Construct the API message */ + M (TAP_MODIFY, mp); + + mp->use_random_mac = random_mac; + mp->sw_if_index = ntohl (sw_if_index); + clib_memcpy (mp->mac_address, mac_address, 6); + clib_memcpy (mp->tap_name, tap_name, vec_len (tap_name)); + vec_free (tap_name); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_tap_delete (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_tap_delete_t *mp; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing vpp interface name"); + return -99; + } + + /* Construct the API message */ + M (TAP_DELETE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_tap_create_v2 (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_tap_create_v2_t *mp; + u8 mac_address[6]; + u8 random_mac = 1; + u32 id = ~0; + u8 *host_if_name = 0; + u8 *host_ns = 0; + u8 host_mac_addr[6]; + u8 host_mac_addr_set = 0; + u8 *host_bridge = 0; + ip4_address_t host_ip4_addr; + u32 host_ip4_prefix_len = 0; + ip6_address_t host_ip6_addr; + u32 host_ip6_prefix_len = 0; + int ret; + int rx_ring_sz = 0, tx_ring_sz = 0; + + memset (mac_address, 0, sizeof (mac_address)); + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "hw-addr %U", unformat_ethernet_address, mac_address)) + { + random_mac = 0; + } + else if (unformat (i, "id %s", &id)) + ; + else if (unformat (i, "host-if-name %s", &host_if_name)) + ; + else if (unformat (i, "host-ns %s", &host_ns)) + ; + else if (unformat (i, "host-mac-addr %U", unformat_ethernet_address, + host_mac_addr)) + host_mac_addr_set = 1; + else if (unformat (i, "host-bridge %s", &host_bridge)) + ; + else if (unformat (i, "host-ip4-addr %U/%d", unformat_ip4_address, + &host_ip4_addr, &host_ip4_prefix_len)) + ; + else if (unformat (i, "host-ip6-addr %U/%d", unformat_ip6_address, + &host_ip6_addr, &host_ip6_prefix_len)) + ; + else if (unformat (i, "rx-ring-size %d", &rx_ring_sz)) + ; + else if (unformat (i, "tx-ring-size %d", &tx_ring_sz)) + ; + else + break; + } + + if (vec_len (host_if_name) > 63) + { + errmsg ("tap name too long. "); + return -99; + } + if (vec_len (host_ns) > 63) + { + errmsg ("host name space too long. "); + return -99; + } + if (vec_len (host_bridge) > 63) + { + errmsg ("host bridge name too long. "); + return -99; + } + if (host_ip4_prefix_len > 32) + { + errmsg ("host ip4 prefix length not valid. "); + return -99; + } + if (host_ip6_prefix_len > 128) + { + errmsg ("host ip6 prefix length not valid. "); + return -99; + } + if (!is_pow2 (rx_ring_sz)) + { + errmsg ("rx ring size must be power of 2. "); + return -99; + } + if (rx_ring_sz > 32768) + { + errmsg ("rx ring size must be 32768 or lower. "); + return -99; + } + if (!is_pow2 (tx_ring_sz)) + { + errmsg ("tx ring size must be power of 2. "); + return -99; + } + if (tx_ring_sz > 32768) + { + errmsg ("tx ring size must be 32768 or lower. "); + return -99; + } + + /* Construct the API message */ + M (TAP_CREATE_V2, mp); + + mp->use_random_mac = random_mac; + + mp->id = id; + mp->host_namespace_set = host_ns != 0; + mp->host_bridge_set = host_bridge != 0; + mp->host_ip4_addr_set = host_ip4_prefix_len != 0; + mp->host_ip6_addr_set = host_ip6_prefix_len != 0; + mp->rx_ring_sz = rx_ring_sz; + mp->tx_ring_sz = tx_ring_sz; + + if (random_mac) + clib_memcpy (mp->mac_address, mac_address, 6); + if (host_mac_addr_set) + clib_memcpy (mp->host_mac_addr, host_mac_addr, 6); + if (host_if_name) + clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name)); + if (host_ns) + clib_memcpy (mp->host_namespace, host_ns, vec_len (host_ns)); + if (host_bridge) + clib_memcpy (mp->host_bridge, host_bridge, vec_len (host_bridge)); + if (host_ip4_prefix_len) + clib_memcpy (mp->host_ip4_addr, &host_ip4_addr, 4); + if (host_ip4_prefix_len) + clib_memcpy (mp->host_ip6_addr, &host_ip6_addr, 16); + + + vec_free (host_ns); + vec_free (host_if_name); + vec_free (host_bridge); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_tap_delete_v2 (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_tap_delete_v2_t *mp; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing vpp interface name. "); + return -99; + } + + /* Construct the API message */ + M (TAP_DELETE_V2, mp); + + mp->sw_if_index = ntohl (sw_if_index); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_ip_table_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_table_add_del_t *mp; + u32 table_id = ~0; + u8 is_ipv6 = 0; + u8 is_add = 1; + int ret = 0; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "ipv6")) + is_ipv6 = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "table %d", &table_id)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (~0 == table_id) + { + errmsg ("missing table-ID"); + return -99; + } + + /* Construct the API message */ + M (IP_TABLE_ADD_DEL, mp); + + mp->table_id = ntohl (table_id); + mp->is_ipv6 = is_ipv6; + mp->is_add = is_add; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static int +api_ip_add_del_route (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_add_del_route_t *mp; + u32 sw_if_index = ~0, vrf_id = 0; + u8 is_ipv6 = 0; + u8 is_local = 0, is_drop = 0; + u8 is_unreach = 0, is_prohibit = 0; + u8 is_add = 1; + u32 next_hop_weight = 1; + u8 is_multipath = 0; + u8 address_set = 0; + u8 address_length_set = 0; + u32 next_hop_table_id = 0; + u32 resolve_attempts = 0; + u32 dst_address_length = 0; + u8 next_hop_set = 0; + ip4_address_t v4_dst_address, v4_next_hop_address; + ip6_address_t v6_dst_address, v6_next_hop_address; + int count = 1; + int j; + f64 before = 0; + u32 random_add_del = 0; + u32 *random_vector = 0; + uword *random_hash; + u32 random_seed = 0xdeaddabe; + u32 classify_table_index = ~0; + u8 is_classify = 0; + u8 resolve_host = 0, resolve_attached = 0; + mpls_label_t *next_hop_out_label_stack = NULL; + mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID; + mpls_label_t next_hop_via_label = MPLS_LABEL_INVALID; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "%U", unformat_ip4_address, &v4_dst_address)) + { + address_set = 1; + is_ipv6 = 0; + } + else if (unformat (i, "%U", unformat_ip6_address, &v6_dst_address)) + { + address_set = 1; + is_ipv6 = 1; + } + else if (unformat (i, "/%d", &dst_address_length)) + { + address_length_set = 1; + } + + else if (is_ipv6 == 0 && unformat (i, "via %U", unformat_ip4_address, + &v4_next_hop_address)) + { + next_hop_set = 1; + } + else if (is_ipv6 == 1 && unformat (i, "via %U", unformat_ip6_address, + &v6_next_hop_address)) + { + next_hop_set = 1; + } + else if (unformat (i, "resolve-attempts %d", &resolve_attempts)) + ; + else if (unformat (i, "weight %d", &next_hop_weight)) + ; + else if (unformat (i, "drop")) + { + is_drop = 1; + } + else if (unformat (i, "null-send-unreach")) + { + is_unreach = 1; + } + else if (unformat (i, "null-send-prohibit")) + { + is_prohibit = 1; + } + else if (unformat (i, "local")) + { + is_local = 1; + } + else if (unformat (i, "classify %d", &classify_table_index)) + { + is_classify = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "resolve-via-host")) + resolve_host = 1; + else if (unformat (i, "resolve-via-attached")) + resolve_attached = 1; + else if (unformat (i, "multipath")) + is_multipath = 1; + else if (unformat (i, "vrf %d", &vrf_id)) + ; + else if (unformat (i, "count %d", &count)) + ; + else if (unformat (i, "lookup-in-vrf %d", &next_hop_table_id)) + ; + else if (unformat (i, "next-hop-table %d", &next_hop_table_id)) + ; + else if (unformat (i, "out-label %d", &next_hop_out_label)) + vec_add1 (next_hop_out_label_stack, ntohl (next_hop_out_label)); + else if (unformat (i, "via-label %d", &next_hop_via_label)) + ; + else if (unformat (i, "random")) + random_add_del = 1; + else if (unformat (i, "seed %d", &random_seed)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!next_hop_set && !is_drop && !is_local && + !is_classify && !is_unreach && !is_prohibit && + MPLS_LABEL_INVALID == next_hop_via_label) + { + errmsg + ("next hop / local / drop / unreach / prohibit / classify not set"); + return -99; + } + + if (next_hop_set && MPLS_LABEL_INVALID != next_hop_via_label) + { + errmsg ("next hop and next-hop via label set"); + return -99; + } + if (address_set == 0) + { + errmsg ("missing addresses"); + return -99; + } + + if (address_length_set == 0) + { + errmsg ("missing address length"); + return -99; + } + + /* Generate a pile of unique, random routes */ + if (random_add_del) + { + u32 this_random_address; + random_hash = hash_create (count, sizeof (uword)); + + hash_set (random_hash, v4_next_hop_address.as_u32, 1); + for (j = 0; j <= count; j++) + { + do + { + this_random_address = random_u32 (&random_seed); + this_random_address = + clib_host_to_net_u32 (this_random_address); + } + while (hash_get (random_hash, this_random_address)); + vec_add1 (random_vector, this_random_address); + hash_set (random_hash, this_random_address, 1); + } + hash_free (random_hash); + v4_dst_address.as_u32 = random_vector[0]; + } + + if (count > 1) + { + /* Turn on async mode */ + vam->async_mode = 1; + vam->async_errors = 0; + before = vat_time_now (vam); + } + + for (j = 0; j < count; j++) + { + /* Construct the API message */ + M2 (IP_ADD_DEL_ROUTE, mp, + sizeof (mpls_label_t) * vec_len (next_hop_out_label_stack)); + + mp->next_hop_sw_if_index = ntohl (sw_if_index); + mp->table_id = ntohl (vrf_id); + + mp->is_add = is_add; + mp->is_drop = is_drop; + mp->is_unreach = is_unreach; + mp->is_prohibit = is_prohibit; + mp->is_ipv6 = is_ipv6; + mp->is_local = is_local; + mp->is_classify = is_classify; + mp->is_multipath = is_multipath; + mp->is_resolve_host = resolve_host; + mp->is_resolve_attached = resolve_attached; + mp->next_hop_weight = next_hop_weight; + mp->dst_address_length = dst_address_length; + mp->next_hop_table_id = ntohl (next_hop_table_id); + mp->classify_table_index = ntohl (classify_table_index); + mp->next_hop_via_label = ntohl (next_hop_via_label); + mp->next_hop_n_out_labels = vec_len (next_hop_out_label_stack); + if (0 != mp->next_hop_n_out_labels) + { + memcpy (mp->next_hop_out_label_stack, + next_hop_out_label_stack, + vec_len (next_hop_out_label_stack) * sizeof (mpls_label_t)); + vec_free (next_hop_out_label_stack); + } + + if (is_ipv6) + { + clib_memcpy (mp->dst_address, &v6_dst_address, + sizeof (v6_dst_address)); + if (next_hop_set) + clib_memcpy (mp->next_hop_address, &v6_next_hop_address, + sizeof (v6_next_hop_address)); + increment_v6_address (&v6_dst_address); + } + else + { + clib_memcpy (mp->dst_address, &v4_dst_address, + sizeof (v4_dst_address)); + if (next_hop_set) + clib_memcpy (mp->next_hop_address, &v4_next_hop_address, + sizeof (v4_next_hop_address)); + if (random_add_del) + v4_dst_address.as_u32 = random_vector[j + 1]; + else + increment_v4_address (&v4_dst_address); + } + /* send it... */ + S (mp); + /* If we receive SIGTERM, stop now... */ + if (vam->do_exit) + break; + } + + /* When testing multiple add/del ops, use a control-ping to sync */ + if (count > 1) + { + vl_api_control_ping_t *mp_ping; + f64 after; + f64 timeout; + + /* Shut off async mode */ + vam->async_mode = 0; + + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + timeout = vat_time_now (vam) + 1.0; + while (vat_time_now (vam) < timeout) + if (vam->result_ready == 1) + goto out; + vam->retval = -99; + + out: + if (vam->retval == -99) + errmsg ("timeout"); + + if (vam->async_errors > 0) + { + errmsg ("%d asynchronous errors", vam->async_errors); + vam->retval = -98; + } + vam->async_errors = 0; + after = vat_time_now (vam); + + /* slim chance, but we might have eaten SIGTERM on the first iteration */ + if (j > 0) + count = j; + + print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", + count, after - before, count / (after - before)); + } + else + { + int ret; + + /* Wait for a reply... */ + W (ret); + return ret; + } + + /* Return the good/bad news */ + return (vam->retval); +} + +static int +api_ip_mroute_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_mroute_add_del_t *mp; + u32 sw_if_index = ~0, vrf_id = 0; + u8 is_ipv6 = 0; + u8 is_local = 0; + u8 is_add = 1; + u8 address_set = 0; + u32 grp_address_length = 0; + ip4_address_t v4_grp_address, v4_src_address; + ip6_address_t v6_grp_address, v6_src_address; + mfib_itf_flags_t iflags = 0; + mfib_entry_flags_t eflags = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "%U %U", + unformat_ip4_address, &v4_src_address, + unformat_ip4_address, &v4_grp_address)) + { + grp_address_length = 64; + address_set = 1; + is_ipv6 = 0; + } + else if (unformat (i, "%U %U", + unformat_ip6_address, &v6_src_address, + unformat_ip6_address, &v6_grp_address)) + { + grp_address_length = 256; + address_set = 1; + is_ipv6 = 1; + } + else if (unformat (i, "%U", unformat_ip4_address, &v4_grp_address)) + { + memset (&v4_src_address, 0, sizeof (v4_src_address)); + grp_address_length = 32; + address_set = 1; + is_ipv6 = 0; + } + else if (unformat (i, "%U", unformat_ip6_address, &v6_grp_address)) + { + memset (&v6_src_address, 0, sizeof (v6_src_address)); + grp_address_length = 128; + address_set = 1; + is_ipv6 = 1; + } + else if (unformat (i, "/%d", &grp_address_length)) + ; + else if (unformat (i, "local")) + { + is_local = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "vrf %d", &vrf_id)) + ; + else if (unformat (i, "%U", unformat_mfib_itf_flags, &iflags)) + ; + else if (unformat (i, "%U", unformat_mfib_entry_flags, &eflags)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (address_set == 0) + { + errmsg ("missing addresses\n"); + return -99; + } + + /* Construct the API message */ + M (IP_MROUTE_ADD_DEL, mp); + + mp->next_hop_sw_if_index = ntohl (sw_if_index); + mp->table_id = ntohl (vrf_id); + + mp->is_add = is_add; + mp->is_ipv6 = is_ipv6; + mp->is_local = is_local; + mp->itf_flags = ntohl (iflags); + mp->entry_flags = ntohl (eflags); + mp->grp_address_length = grp_address_length; + mp->grp_address_length = ntohs (mp->grp_address_length); + + if (is_ipv6) + { + clib_memcpy (mp->grp_address, &v6_grp_address, sizeof (v6_grp_address)); + clib_memcpy (mp->src_address, &v6_src_address, sizeof (v6_src_address)); + } + else + { + clib_memcpy (mp->grp_address, &v4_grp_address, sizeof (v4_grp_address)); + clib_memcpy (mp->src_address, &v4_src_address, sizeof (v4_src_address)); + + } + + /* send it... */ + S (mp); + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_mpls_table_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_mpls_table_add_del_t *mp; + u32 table_id = ~0; + u8 is_add = 1; + int ret = 0; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "table %d", &table_id)) + ; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + is_add = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (~0 == table_id) + { + errmsg ("missing table-ID"); + return -99; + } + + /* Construct the API message */ + M (MPLS_TABLE_ADD_DEL, mp); + + mp->mt_table_id = ntohl (table_id); + mp->mt_is_add = is_add; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return ret; +} + +static int +api_mpls_route_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_mpls_route_add_del_t *mp; + u32 sw_if_index = ~0, table_id = 0; + u8 is_add = 1; + u32 next_hop_weight = 1; + u8 is_multipath = 0; + u32 next_hop_table_id = 0; + u8 next_hop_set = 0; + ip4_address_t v4_next_hop_address = { + .as_u32 = 0, + }; + ip6_address_t v6_next_hop_address = { {0} }; + int count = 1; + int j; + f64 before = 0; + u32 classify_table_index = ~0; + u8 is_classify = 0; + u8 resolve_host = 0, resolve_attached = 0; + mpls_label_t next_hop_via_label = MPLS_LABEL_INVALID; + mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID; + mpls_label_t *next_hop_out_label_stack = NULL; + mpls_label_t local_label = MPLS_LABEL_INVALID; + u8 is_eos = 0; + dpo_proto_t next_hop_proto = DPO_PROTO_IP4; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "%d", &local_label)) + ; + else if (unformat (i, "eos")) + is_eos = 1; + else if (unformat (i, "non-eos")) + is_eos = 0; + else if (unformat (i, "via %U", unformat_ip4_address, + &v4_next_hop_address)) + { + next_hop_set = 1; + next_hop_proto = DPO_PROTO_IP4; + } + else if (unformat (i, "via %U", unformat_ip6_address, + &v6_next_hop_address)) + { + next_hop_set = 1; + next_hop_proto = DPO_PROTO_IP6; + } + else if (unformat (i, "weight %d", &next_hop_weight)) + ; + else if (unformat (i, "classify %d", &classify_table_index)) + { + is_classify = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "resolve-via-host")) + resolve_host = 1; + else if (unformat (i, "resolve-via-attached")) + resolve_attached = 1; + else if (unformat (i, "multipath")) + is_multipath = 1; + else if (unformat (i, "count %d", &count)) + ; + else if (unformat (i, "lookup-in-ip4-table %d", &next_hop_table_id)) + { + next_hop_set = 1; + next_hop_proto = DPO_PROTO_IP4; + } + else if (unformat (i, "lookup-in-ip6-table %d", &next_hop_table_id)) + { + next_hop_set = 1; + next_hop_proto = DPO_PROTO_IP6; + } + else if (unformat (i, "next-hop-table %d", &next_hop_table_id)) + ; + else if (unformat (i, "via-label %d", &next_hop_via_label)) + ; + else if (unformat (i, "out-label %d", &next_hop_out_label)) + vec_add1 (next_hop_out_label_stack, ntohl (next_hop_out_label)); + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!next_hop_set && !is_classify) + { + errmsg ("next hop / classify not set"); + return -99; + } + + if (MPLS_LABEL_INVALID == local_label) + { + errmsg ("missing label"); + return -99; + } + + if (count > 1) + { + /* Turn on async mode */ + vam->async_mode = 1; + vam->async_errors = 0; + before = vat_time_now (vam); + } + + for (j = 0; j < count; j++) + { + /* Construct the API message */ + M2 (MPLS_ROUTE_ADD_DEL, mp, + sizeof (mpls_label_t) * vec_len (next_hop_out_label_stack)); + + mp->mr_next_hop_sw_if_index = ntohl (sw_if_index); + mp->mr_table_id = ntohl (table_id); + + mp->mr_is_add = is_add; + mp->mr_next_hop_proto = next_hop_proto; + mp->mr_is_classify = is_classify; + mp->mr_is_multipath = is_multipath; + mp->mr_is_resolve_host = resolve_host; + mp->mr_is_resolve_attached = resolve_attached; + mp->mr_next_hop_weight = next_hop_weight; + mp->mr_next_hop_table_id = ntohl (next_hop_table_id); + mp->mr_classify_table_index = ntohl (classify_table_index); + mp->mr_next_hop_via_label = ntohl (next_hop_via_label); + mp->mr_label = ntohl (local_label); + mp->mr_eos = is_eos; + + mp->mr_next_hop_n_out_labels = vec_len (next_hop_out_label_stack); + if (0 != mp->mr_next_hop_n_out_labels) + { + memcpy (mp->mr_next_hop_out_label_stack, + next_hop_out_label_stack, + vec_len (next_hop_out_label_stack) * sizeof (mpls_label_t)); + vec_free (next_hop_out_label_stack); + } + + if (next_hop_set) + { + if (DPO_PROTO_IP4 == next_hop_proto) + { + clib_memcpy (mp->mr_next_hop, + &v4_next_hop_address, + sizeof (v4_next_hop_address)); + } + else if (DPO_PROTO_IP6 == next_hop_proto) + + { + clib_memcpy (mp->mr_next_hop, + &v6_next_hop_address, + sizeof (v6_next_hop_address)); + } + } + local_label++; + + /* send it... */ + S (mp); + /* If we receive SIGTERM, stop now... */ + if (vam->do_exit) + break; + } + + /* When testing multiple add/del ops, use a control-ping to sync */ + if (count > 1) + { + vl_api_control_ping_t *mp_ping; + f64 after; + f64 timeout; + + /* Shut off async mode */ + vam->async_mode = 0; + + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + timeout = vat_time_now (vam) + 1.0; + while (vat_time_now (vam) < timeout) + if (vam->result_ready == 1) + goto out; + vam->retval = -99; + + out: + if (vam->retval == -99) + errmsg ("timeout"); + + if (vam->async_errors > 0) + { + errmsg ("%d asynchronous errors", vam->async_errors); + vam->retval = -98; + } + vam->async_errors = 0; + after = vat_time_now (vam); + + /* slim chance, but we might have eaten SIGTERM on the first iteration */ + if (j > 0) + count = j; + + print (vam->ofp, "%d routes in %.6f secs, %.2f routes/sec", + count, after - before, count / (after - before)); + } + else + { + int ret; + + /* Wait for a reply... */ + W (ret); + return ret; + } + + /* Return the good/bad news */ + return (vam->retval); +} + +static int +api_mpls_ip_bind_unbind (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_mpls_ip_bind_unbind_t *mp; + u32 ip_table_id = 0; + u8 is_bind = 1; + u8 is_ip4 = 1; + ip4_address_t v4_address; + ip6_address_t v6_address; + u32 address_length; + u8 address_set = 0; + mpls_label_t local_label = MPLS_LABEL_INVALID; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U/%d", unformat_ip4_address, + &v4_address, &address_length)) + { + is_ip4 = 1; + address_set = 1; + } + else if (unformat (i, "%U/%d", unformat_ip6_address, + &v6_address, &address_length)) + { + is_ip4 = 0; + address_set = 1; + } + else if (unformat (i, "%d", &local_label)) + ; + else if (unformat (i, "table-id %d", &ip_table_id)) + ; + else if (unformat (i, "unbind")) + is_bind = 0; + else if (unformat (i, "bind")) + is_bind = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!address_set) + { + errmsg ("IP addres not set"); + return -99; + } + + if (MPLS_LABEL_INVALID == local_label) + { + errmsg ("missing label"); + return -99; + } + + /* Construct the API message */ + M (MPLS_IP_BIND_UNBIND, mp); + + mp->mb_is_bind = is_bind; + mp->mb_is_ip4 = is_ip4; + mp->mb_ip_table_id = ntohl (ip_table_id); + mp->mb_mpls_table_id = 0; + mp->mb_label = ntohl (local_label); + mp->mb_address_length = address_length; + + if (is_ip4) + clib_memcpy (mp->mb_address, &v4_address, sizeof (v4_address)); + else + clib_memcpy (mp->mb_address, &v6_address, sizeof (v6_address)); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_bier_table_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bier_table_add_del_t *mp; + u8 is_add = 1; + u32 set = 0, sub_domain = 0, hdr_len = 3; + mpls_label_t local_label = MPLS_LABEL_INVALID; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sub-domain %d", &sub_domain)) + ; + else if (unformat (i, "set %d", &set)) + ; + else if (unformat (i, "label %d", &local_label)) + ; + else if (unformat (i, "hdr-len %d", &hdr_len)) + ; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (MPLS_LABEL_INVALID == local_label) + { + errmsg ("missing label\n"); + return -99; + } + + /* Construct the API message */ + M (BIER_TABLE_ADD_DEL, mp); + + mp->bt_is_add = is_add; + mp->bt_label = ntohl (local_label); + mp->bt_tbl_id.bt_set = set; + mp->bt_tbl_id.bt_sub_domain = sub_domain; + mp->bt_tbl_id.bt_hdr_len_id = hdr_len; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return (ret); +} + +static int +api_bier_route_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_bier_route_add_del_t *mp; + u8 is_add = 1; + u32 set = 0, sub_domain = 0, hdr_len = 3, bp = 0; + ip4_address_t v4_next_hop_address; + ip6_address_t v6_next_hop_address; + u8 next_hop_set = 0; + u8 next_hop_proto_is_ip4 = 1; + mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_ip4_address, &v4_next_hop_address)) + { + next_hop_proto_is_ip4 = 1; + next_hop_set = 1; + } + else if (unformat (i, "%U", unformat_ip6_address, &v6_next_hop_address)) + { + next_hop_proto_is_ip4 = 0; + next_hop_set = 1; + } + if (unformat (i, "sub-domain %d", &sub_domain)) + ; + else if (unformat (i, "set %d", &set)) + ; + else if (unformat (i, "hdr-len %d", &hdr_len)) + ; + else if (unformat (i, "bp %d", &bp)) + ; + else if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "out-label %d", &next_hop_out_label)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!next_hop_set || (MPLS_LABEL_INVALID == next_hop_out_label)) + { + errmsg ("next hop / label set\n"); + return -99; + } + if (0 == bp) + { + errmsg ("bit=position not set\n"); + return -99; + } + + /* Construct the API message */ + M2 (BIER_ROUTE_ADD_DEL, mp, sizeof (vl_api_fib_path3_t)); + + mp->br_is_add = is_add; + mp->br_tbl_id.bt_set = set; + mp->br_tbl_id.bt_sub_domain = sub_domain; + mp->br_tbl_id.bt_hdr_len_id = hdr_len; + mp->br_bp = ntohs (bp); + mp->br_n_paths = 1; + mp->br_paths[0].n_labels = 1; + mp->br_paths[0].label_stack[0] = ntohl (next_hop_out_label); + mp->br_paths[0].afi = (next_hop_proto_is_ip4 ? 0 : 1); + + if (next_hop_proto_is_ip4) + { + clib_memcpy (mp->br_paths[0].next_hop, + &v4_next_hop_address, sizeof (v4_next_hop_address)); + } + else + { + clib_memcpy (mp->br_paths[0].next_hop, + &v6_next_hop_address, sizeof (v6_next_hop_address)); + } + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + + return (ret); +} + +static int +api_proxy_arp_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_proxy_arp_add_del_t *mp; + u32 vrf_id = 0; + u8 is_add = 1; + ip4_address_t lo, hi; + u8 range_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vrf %d", &vrf_id)) + ; + else if (unformat (i, "%U - %U", unformat_ip4_address, &lo, + unformat_ip4_address, &hi)) + range_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (range_set == 0) + { + errmsg ("address range not set"); + return -99; + } + + M (PROXY_ARP_ADD_DEL, mp); + + mp->vrf_id = ntohl (vrf_id); + mp->is_add = is_add; + clib_memcpy (mp->low_address, &lo, sizeof (mp->low_address)); + clib_memcpy (mp->hi_address, &hi, sizeof (mp->hi_address)); + + S (mp); + W (ret); + return ret; +} + +static int +api_proxy_arp_intfc_enable_disable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_proxy_arp_intfc_enable_disable_t *mp; + u32 sw_if_index; + u8 enable = 1; + u8 sw_if_index_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (PROXY_ARP_INTFC_ENABLE_DISABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_mpls_tunnel_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_mpls_tunnel_add_del_t *mp; + + u8 is_add = 1; + u8 l2_only = 0; + u32 sw_if_index = ~0; + u32 next_hop_sw_if_index = ~0; + u32 next_hop_proto_is_ip4 = 1; + + u32 next_hop_table_id = 0; + ip4_address_t v4_next_hop_address = { + .as_u32 = 0, + }; + ip6_address_t v6_next_hop_address = { {0} }; + mpls_label_t next_hop_out_label = MPLS_LABEL_INVALID, *labels = NULL; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "del sw_if_index %d", &sw_if_index)) + is_add = 0; + else if (unformat (i, "sw_if_index %d", &next_hop_sw_if_index)) + ; + else if (unformat (i, "via %U", + unformat_ip4_address, &v4_next_hop_address)) + { + next_hop_proto_is_ip4 = 1; + } + else if (unformat (i, "via %U", + unformat_ip6_address, &v6_next_hop_address)) + { + next_hop_proto_is_ip4 = 0; + } + else if (unformat (i, "l2-only")) + l2_only = 1; + else if (unformat (i, "next-hop-table %d", &next_hop_table_id)) + ; + else if (unformat (i, "out-label %d", &next_hop_out_label)) + vec_add1 (labels, ntohl (next_hop_out_label)); + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M2 (MPLS_TUNNEL_ADD_DEL, mp, sizeof (mpls_label_t) * vec_len (labels)); + + mp->mt_next_hop_sw_if_index = ntohl (next_hop_sw_if_index); + mp->mt_sw_if_index = ntohl (sw_if_index); + mp->mt_is_add = is_add; + mp->mt_l2_only = l2_only; + mp->mt_next_hop_table_id = ntohl (next_hop_table_id); + mp->mt_next_hop_proto_is_ip4 = next_hop_proto_is_ip4; + + mp->mt_next_hop_n_out_labels = vec_len (labels); + + if (0 != mp->mt_next_hop_n_out_labels) + { + clib_memcpy (mp->mt_next_hop_out_label_stack, labels, + sizeof (mpls_label_t) * mp->mt_next_hop_n_out_labels); + vec_free (labels); + } + + if (next_hop_proto_is_ip4) + { + clib_memcpy (mp->mt_next_hop, + &v4_next_hop_address, sizeof (v4_next_hop_address)); + } + else + { + clib_memcpy (mp->mt_next_hop, + &v6_next_hop_address, sizeof (v6_next_hop_address)); + } + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_unnumbered (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_unnumbered_t *mp; + u32 sw_if_index; + u32 unnum_sw_index = ~0; + u8 is_add = 1; + u8 sw_if_index_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "unnum_if_index %d", &unnum_sw_index)) + ; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (SW_INTERFACE_SET_UNNUMBERED, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->unnumbered_sw_if_index = ntohl (unnum_sw_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_ip_neighbor_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_neighbor_add_del_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 is_add = 1; + u8 is_static = 0; + u8 is_no_fib_entry = 0; + u8 mac_address[6]; + u8 mac_set = 0; + u8 v4_address_set = 0; + u8 v6_address_set = 0; + ip4_address_t v4address; + ip6_address_t v6address; + int ret; + + memset (mac_address, 0, sizeof (mac_address)); + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mac %U", unformat_ethernet_address, mac_address)) + { + mac_set = 1; + } + else if (unformat (i, "del")) + is_add = 0; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "is_static")) + is_static = 1; + else if (unformat (i, "no-fib-entry")) + is_no_fib_entry = 1; + else if (unformat (i, "dst %U", unformat_ip4_address, &v4address)) + v4_address_set = 1; + else if (unformat (i, "dst %U", unformat_ip6_address, &v6address)) + v6_address_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (v4_address_set && v6_address_set) + { + errmsg ("both v4 and v6 addresses set"); + return -99; + } + if (!v4_address_set && !v6_address_set) + { + errmsg ("no address set"); + return -99; + } + + /* Construct the API message */ + M (IP_NEIGHBOR_ADD_DEL, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = is_add; + mp->is_static = is_static; + mp->is_no_adj_fib = is_no_fib_entry; + if (mac_set) + clib_memcpy (mp->mac_address, mac_address, 6); + if (v6_address_set) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->dst_address, &v6address, sizeof (v6address)); + } + else + { + /* mp->is_ipv6 = 0; via memset in M macro above */ + clib_memcpy (mp->dst_address, &v4address, sizeof (v4address)); + } + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_create_vlan_subif (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_create_vlan_subif_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u32 vlan_id; + u8 vlan_id_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "vlan %d", &vlan_id)) + vlan_id_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (vlan_id_set == 0) + { + errmsg ("missing vlan_id"); + return -99; + } + M (CREATE_VLAN_SUBIF, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->vlan_id = ntohl (vlan_id); + + S (mp); + W (ret); + return ret; +} + +#define foreach_create_subif_bit \ +_(no_tags) \ +_(one_tag) \ +_(two_tags) \ +_(dot1ad) \ +_(exact_match) \ +_(default_sub) \ +_(outer_vlan_id_any) \ +_(inner_vlan_id_any) + +static int +api_create_subif (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_create_subif_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u32 sub_id; + u8 sub_id_set = 0; + u32 no_tags = 0; + u32 one_tag = 0; + u32 two_tags = 0; + u32 dot1ad = 0; + u32 exact_match = 0; + u32 default_sub = 0; + u32 outer_vlan_id_any = 0; + u32 inner_vlan_id_any = 0; + u32 tmp; + u16 outer_vlan_id = 0; + u16 inner_vlan_id = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sub_id %d", &sub_id)) + sub_id_set = 1; + else if (unformat (i, "outer_vlan_id %d", &tmp)) + outer_vlan_id = tmp; + else if (unformat (i, "inner_vlan_id %d", &tmp)) + inner_vlan_id = tmp; + +#define _(a) else if (unformat (i, #a)) a = 1 ; + foreach_create_subif_bit +#undef _ + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (sub_id_set == 0) + { + errmsg ("missing sub_id"); + return -99; + } + M (CREATE_SUBIF, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->sub_id = ntohl (sub_id); + +#define _(a) mp->a = a; + foreach_create_subif_bit; +#undef _ + + mp->outer_vlan_id = ntohs (outer_vlan_id); + mp->inner_vlan_id = ntohs (inner_vlan_id); + + S (mp); + W (ret); + return ret; +} + +static int +api_oam_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_oam_add_del_t *mp; + u32 vrf_id = 0; + u8 is_add = 1; + ip4_address_t src, dst; + u8 src_set = 0; + u8 dst_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vrf %d", &vrf_id)) + ; + else if (unformat (i, "src %U", unformat_ip4_address, &src)) + src_set = 1; + else if (unformat (i, "dst %U", unformat_ip4_address, &dst)) + dst_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (src_set == 0) + { + errmsg ("missing src addr"); + return -99; + } + + if (dst_set == 0) + { + errmsg ("missing dst addr"); + return -99; + } + + M (OAM_ADD_DEL, mp); + + mp->vrf_id = ntohl (vrf_id); + mp->is_add = is_add; + clib_memcpy (mp->src_address, &src, sizeof (mp->src_address)); + clib_memcpy (mp->dst_address, &dst, sizeof (mp->dst_address)); + + S (mp); + W (ret); + return ret; +} + +static int +api_reset_fib (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_reset_fib_t *mp; + u32 vrf_id = 0; + u8 is_ipv6 = 0; + u8 vrf_id_set = 0; + + int ret; + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vrf %d", &vrf_id)) + vrf_id_set = 1; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (vrf_id_set == 0) + { + errmsg ("missing vrf id"); + return -99; + } + + M (RESET_FIB, mp); + + mp->vrf_id = ntohl (vrf_id); + mp->is_ipv6 = is_ipv6; + + S (mp); + W (ret); + return ret; +} + +static int +api_dhcp_proxy_config (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_dhcp_proxy_config_t *mp; + u32 rx_vrf_id = 0; + u32 server_vrf_id = 0; + u8 is_add = 1; + u8 v4_address_set = 0; + u8 v6_address_set = 0; + ip4_address_t v4address; + ip6_address_t v6address; + u8 v4_src_address_set = 0; + u8 v6_src_address_set = 0; + ip4_address_t v4srcaddress; + ip6_address_t v6srcaddress; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "rx_vrf_id %d", &rx_vrf_id)) + ; + else if (unformat (i, "server_vrf_id %d", &server_vrf_id)) + ; + else if (unformat (i, "svr %U", unformat_ip4_address, &v4address)) + v4_address_set = 1; + else if (unformat (i, "svr %U", unformat_ip6_address, &v6address)) + v6_address_set = 1; + else if (unformat (i, "src %U", unformat_ip4_address, &v4srcaddress)) + v4_src_address_set = 1; + else if (unformat (i, "src %U", unformat_ip6_address, &v6srcaddress)) + v6_src_address_set = 1; + else + break; + } + + if (v4_address_set && v6_address_set) + { + errmsg ("both v4 and v6 server addresses set"); + return -99; + } + if (!v4_address_set && !v6_address_set) + { + errmsg ("no server addresses set"); + return -99; + } + + if (v4_src_address_set && v6_src_address_set) + { + errmsg ("both v4 and v6 src addresses set"); + return -99; + } + if (!v4_src_address_set && !v6_src_address_set) + { + errmsg ("no src addresses set"); + return -99; + } + + if (!(v4_src_address_set && v4_address_set) && + !(v6_src_address_set && v6_address_set)) + { + errmsg ("no matching server and src addresses set"); + return -99; + } + + /* Construct the API message */ + M (DHCP_PROXY_CONFIG, mp); + + mp->is_add = is_add; + mp->rx_vrf_id = ntohl (rx_vrf_id); + mp->server_vrf_id = ntohl (server_vrf_id); + if (v6_address_set) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->dhcp_server, &v6address, sizeof (v6address)); + clib_memcpy (mp->dhcp_src_address, &v6srcaddress, sizeof (v6address)); + } + else + { + clib_memcpy (mp->dhcp_server, &v4address, sizeof (v4address)); + clib_memcpy (mp->dhcp_src_address, &v4srcaddress, sizeof (v4address)); + } + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +#define vl_api_dhcp_proxy_details_t_endian vl_noop_handler +#define vl_api_dhcp_proxy_details_t_print vl_noop_handler + +static void +vl_api_dhcp_proxy_details_t_handler (vl_api_dhcp_proxy_details_t * mp) +{ + vat_main_t *vam = &vat_main; + u32 i, count = mp->count; + vl_api_dhcp_server_t *s; + + if (mp->is_ipv6) + print (vam->ofp, + "RX Table-ID %d, Source Address %U, VSS Type %d, " + "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d", + ntohl (mp->rx_vrf_id), + format_ip6_address, mp->dhcp_src_address, + mp->vss_type, mp->vss_vpn_ascii_id, + ntohl (mp->vss_oui), ntohl (mp->vss_fib_id)); + else + print (vam->ofp, + "RX Table-ID %d, Source Address %U, VSS Type %d, " + "VSS VPN-ID '%s', VSS FIB-ID %d, VSS OUI %d", + ntohl (mp->rx_vrf_id), + format_ip4_address, mp->dhcp_src_address, + mp->vss_type, mp->vss_vpn_ascii_id, + ntohl (mp->vss_oui), ntohl (mp->vss_fib_id)); + + for (i = 0; i < count; i++) + { + s = &mp->servers[i]; + + if (mp->is_ipv6) + print (vam->ofp, + " Server Table-ID %d, Server Address %U", + ntohl (s->server_vrf_id), format_ip6_address, s->dhcp_server); + else + print (vam->ofp, + " Server Table-ID %d, Server Address %U", + ntohl (s->server_vrf_id), format_ip4_address, s->dhcp_server); + } +} + +static void vl_api_dhcp_proxy_details_t_handler_json + (vl_api_dhcp_proxy_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + u32 i, count = mp->count; + struct in_addr ip4; + struct in6_addr ip6; + vl_api_dhcp_server_t *s; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "rx-table-id", ntohl (mp->rx_vrf_id)); + vat_json_object_add_bytes (node, "vss-type", &mp->vss_type, + sizeof (mp->vss_type)); + vat_json_object_add_string_copy (node, "vss-vpn-ascii-id", + mp->vss_vpn_ascii_id); + vat_json_object_add_uint (node, "vss-fib-id", ntohl (mp->vss_fib_id)); + vat_json_object_add_uint (node, "vss-oui", ntohl (mp->vss_oui)); + + if (mp->is_ipv6) + { + clib_memcpy (&ip6, &mp->dhcp_src_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "src_address", ip6); + } + else + { + clib_memcpy (&ip4, &mp->dhcp_src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + } + + for (i = 0; i < count; i++) + { + s = &mp->servers[i]; + + vat_json_object_add_uint (node, "server-table-id", + ntohl (s->server_vrf_id)); + + if (mp->is_ipv6) + { + clib_memcpy (&ip4, &s->dhcp_server, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + } + else + { + clib_memcpy (&ip6, &s->dhcp_server, sizeof (ip6)); + vat_json_object_add_ip6 (node, "server_address", ip6); + } + } +} + +static int +api_dhcp_proxy_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_control_ping_t *mp_ping; + vl_api_dhcp_proxy_dump_t *mp; + u8 is_ipv6 = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "ipv6")) + is_ipv6 = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (DHCP_PROXY_DUMP, mp); + + mp->is_ip6 = is_ipv6; + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_dhcp_proxy_set_vss (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_dhcp_proxy_set_vss_t *mp; + u8 is_ipv6 = 0; + u8 is_add = 1; + u32 tbl_id = ~0; + u8 vss_type = VSS_TYPE_DEFAULT; + u8 *vpn_ascii_id = 0; + u32 oui = 0; + u32 fib_id = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "tbl_id %d", &tbl_id)) + ; + else if (unformat (i, "vpn_ascii_id %s", &vpn_ascii_id)) + vss_type = VSS_TYPE_ASCII; + else if (unformat (i, "fib_id %d", &fib_id)) + vss_type = VSS_TYPE_VPN_ID; + else if (unformat (i, "oui %d", &oui)) + vss_type = VSS_TYPE_VPN_ID; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else if (unformat (i, "del")) + is_add = 0; + else + break; + } + + if (tbl_id == ~0) + { + errmsg ("missing tbl_id "); + vec_free (vpn_ascii_id); + return -99; + } + + if ((vpn_ascii_id) && (vec_len (vpn_ascii_id) > 128)) + { + errmsg ("vpn_ascii_id cannot be longer than 128 "); + vec_free (vpn_ascii_id); + return -99; + } + + M (DHCP_PROXY_SET_VSS, mp); + mp->tbl_id = ntohl (tbl_id); + mp->vss_type = vss_type; + if (vpn_ascii_id) + { + clib_memcpy (mp->vpn_ascii_id, vpn_ascii_id, vec_len (vpn_ascii_id)); + mp->vpn_ascii_id[vec_len (vpn_ascii_id)] = 0; + } + mp->vpn_index = ntohl (fib_id); + mp->oui = ntohl (oui); + mp->is_ipv6 = is_ipv6; + mp->is_add = is_add; + + S (mp); + W (ret); + + vec_free (vpn_ascii_id); + return ret; +} + +static int +api_dhcp_client_config (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_dhcp_client_config_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 is_add = 1; + u8 *hostname = 0; + u8 disable_event = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "hostname %s", &hostname)) + ; + else if (unformat (i, "disable_event")) + disable_event = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (vec_len (hostname) > 63) + { + errmsg ("hostname too long"); + } + vec_add1 (hostname, 0); + + /* Construct the API message */ + M (DHCP_CLIENT_CONFIG, mp); + + mp->sw_if_index = htonl (sw_if_index); + clib_memcpy (mp->hostname, hostname, vec_len (hostname)); + vec_free (hostname); + mp->is_add = is_add; + mp->want_dhcp_event = disable_event ? 0 : 1; + mp->pid = htonl (getpid ()); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_set_ip_flow_hash (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_set_ip_flow_hash_t *mp; + u32 vrf_id = 0; + u8 is_ipv6 = 0; + u8 vrf_id_set = 0; + u8 src = 0; + u8 dst = 0; + u8 sport = 0; + u8 dport = 0; + u8 proto = 0; + u8 reverse = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vrf %d", &vrf_id)) + vrf_id_set = 1; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else if (unformat (i, "src")) + src = 1; + else if (unformat (i, "dst")) + dst = 1; + else if (unformat (i, "sport")) + sport = 1; + else if (unformat (i, "dport")) + dport = 1; + else if (unformat (i, "proto")) + proto = 1; + else if (unformat (i, "reverse")) + reverse = 1; + + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (vrf_id_set == 0) + { + errmsg ("missing vrf id"); + return -99; + } + + M (SET_IP_FLOW_HASH, mp); + mp->src = src; + mp->dst = dst; + mp->sport = sport; + mp->dport = dport; + mp->proto = proto; + mp->reverse = reverse; + mp->vrf_id = ntohl (vrf_id); + mp->is_ipv6 = is_ipv6; + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_ip6_enable_disable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_ip6_enable_disable_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 enable = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (SW_INTERFACE_IP6_ENABLE_DISABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = enable; + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_ip6_set_link_local_address (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_ip6_set_link_local_address_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 v6_address_set = 0; + ip6_address_t v6address; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "%U", unformat_ip6_address, &v6address)) + v6_address_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (!v6_address_set) + { + errmsg ("no address set"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, mp); + + mp->sw_if_index = ntohl (sw_if_index); + clib_memcpy (mp->address, &v6address, sizeof (v6address)); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_ip6nd_proxy_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip6nd_proxy_add_del_t *mp; + u32 sw_if_index = ~0; + u8 v6_address_set = 0; + ip6_address_t v6address; + u8 is_del = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "%U", unformat_ip6_address, &v6address)) + v6_address_set = 1; + if (unformat (i, "del")) + is_del = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (!v6_address_set) + { + errmsg ("no address set"); + return -99; + } + + /* Construct the API message */ + M (IP6ND_PROXY_ADD_DEL, mp); + + mp->is_del = is_del; + mp->sw_if_index = ntohl (sw_if_index); + clib_memcpy (mp->address, &v6address, sizeof (v6address)); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_ip6nd_proxy_dump (vat_main_t * vam) +{ + vl_api_ip6nd_proxy_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (IP6ND_PROXY_DUMP, mp); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void vl_api_ip6nd_proxy_details_t_handler + (vl_api_ip6nd_proxy_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "host %U sw_if_index %d", + format_ip6_address, mp->address, ntohl (mp->sw_if_index)); +} + +static void vl_api_ip6nd_proxy_details_t_handler_json + (vl_api_ip6nd_proxy_details_t * mp) +{ + vat_main_t *vam = &vat_main; + struct in6_addr ip6; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + + clib_memcpy (&ip6, mp->address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "host", ip6); +} + +static int +api_sw_interface_ip6nd_ra_prefix (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_ip6nd_ra_prefix_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u32 address_length = 0; + u8 v6_address_set = 0; + ip6_address_t v6address; + u8 use_default = 0; + u8 no_advertise = 0; + u8 off_link = 0; + u8 no_autoconfig = 0; + u8 no_onlink = 0; + u8 is_no = 0; + u32 val_lifetime = 0; + u32 pref_lifetime = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "%U/%d", + unformat_ip6_address, &v6address, &address_length)) + v6_address_set = 1; + else if (unformat (i, "val_life %d", &val_lifetime)) + ; + else if (unformat (i, "pref_life %d", &pref_lifetime)) + ; + else if (unformat (i, "def")) + use_default = 1; + else if (unformat (i, "noadv")) + no_advertise = 1; + else if (unformat (i, "offl")) + off_link = 1; + else if (unformat (i, "noauto")) + no_autoconfig = 1; + else if (unformat (i, "nolink")) + no_onlink = 1; + else if (unformat (i, "isno")) + is_no = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (!v6_address_set) + { + errmsg ("no address set"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_IP6ND_RA_PREFIX, mp); + + mp->sw_if_index = ntohl (sw_if_index); + clib_memcpy (mp->address, &v6address, sizeof (v6address)); + mp->address_length = address_length; + mp->use_default = use_default; + mp->no_advertise = no_advertise; + mp->off_link = off_link; + mp->no_autoconfig = no_autoconfig; + mp->no_onlink = no_onlink; + mp->is_no = is_no; + mp->val_lifetime = ntohl (val_lifetime); + mp->pref_lifetime = ntohl (pref_lifetime); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_sw_interface_ip6nd_ra_config (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_ip6nd_ra_config_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 suppress = 0; + u8 managed = 0; + u8 other = 0; + u8 ll_option = 0; + u8 send_unicast = 0; + u8 cease = 0; + u8 is_no = 0; + u8 default_router = 0; + u32 max_interval = 0; + u32 min_interval = 0; + u32 lifetime = 0; + u32 initial_count = 0; + u32 initial_interval = 0; + int ret; + + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "maxint %d", &max_interval)) + ; + else if (unformat (i, "minint %d", &min_interval)) + ; + else if (unformat (i, "life %d", &lifetime)) + ; + else if (unformat (i, "count %d", &initial_count)) + ; + else if (unformat (i, "interval %d", &initial_interval)) + ; + else if (unformat (i, "suppress") || unformat (i, "surpress")) + suppress = 1; + else if (unformat (i, "managed")) + managed = 1; + else if (unformat (i, "other")) + other = 1; + else if (unformat (i, "ll")) + ll_option = 1; + else if (unformat (i, "send")) + send_unicast = 1; + else if (unformat (i, "cease")) + cease = 1; + else if (unformat (i, "isno")) + is_no = 1; + else if (unformat (i, "def")) + default_router = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_IP6ND_RA_CONFIG, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->max_interval = ntohl (max_interval); + mp->min_interval = ntohl (min_interval); + mp->lifetime = ntohl (lifetime); + mp->initial_count = ntohl (initial_count); + mp->initial_interval = ntohl (initial_interval); + mp->suppress = suppress; + mp->managed = managed; + mp->other = other; + mp->ll_option = ll_option; + mp->send_unicast = send_unicast; + mp->cease = cease; + mp->is_no = is_no; + mp->default_router = default_router; + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_set_arp_neighbor_limit (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_set_arp_neighbor_limit_t *mp; + u32 arp_nbr_limit; + u8 limit_set = 0; + u8 is_ipv6 = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "arp_nbr_limit %d", &arp_nbr_limit)) + limit_set = 1; + else if (unformat (i, "ipv6")) + is_ipv6 = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (limit_set == 0) + { + errmsg ("missing limit value"); + return -99; + } + + M (SET_ARP_NEIGHBOR_LIMIT, mp); + + mp->arp_neighbor_limit = ntohl (arp_nbr_limit); + mp->is_ipv6 = is_ipv6; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2_patch_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_patch_add_del_t *mp; + u32 rx_sw_if_index; + u8 rx_sw_if_index_set = 0; + u32 tx_sw_if_index; + u8 tx_sw_if_index_set = 0; + u8 is_add = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "rx_sw_if_index %d", &rx_sw_if_index)) + rx_sw_if_index_set = 1; + else if (unformat (i, "tx_sw_if_index %d", &tx_sw_if_index)) + tx_sw_if_index_set = 1; + else if (unformat (i, "rx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, + &rx_sw_if_index)) + rx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "tx")) + { + if (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, + &tx_sw_if_index)) + tx_sw_if_index_set = 1; + } + else + break; + } + else if (unformat (i, "del")) + is_add = 0; + else + break; + } + + if (rx_sw_if_index_set == 0) + { + errmsg ("missing rx interface name or rx_sw_if_index"); + return -99; + } + + if (tx_sw_if_index_set == 0) + { + errmsg ("missing tx interface name or tx_sw_if_index"); + return -99; + } + + M (L2_PATCH_ADD_DEL, mp); + + mp->rx_sw_if_index = ntohl (rx_sw_if_index); + mp->tx_sw_if_index = ntohl (tx_sw_if_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +u8 is_del; +u8 localsid_addr[16]; +u8 end_psp; +u8 behavior; +u32 sw_if_index; +u32 vlan_index; +u32 fib_table; +u8 nh_addr[16]; + +static int +api_sr_localsid_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sr_localsid_add_del_t *mp; + + u8 is_del; + ip6_address_t localsid; + u8 end_psp = 0; + u8 behavior = ~0; + u32 sw_if_index; + u32 fib_table = ~(u32) 0; + ip6_address_t next_hop; + + bool nexthop_set = 0; + + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_del = 1; + else if (unformat (i, "address %U", unformat_ip6_address, &localsid)); + else if (unformat (i, "next-hop %U", unformat_ip6_address, &next_hop)) + nexthop_set = 1; + else if (unformat (i, "behavior %u", &behavior)); + else if (unformat (i, "sw_if_index %u", &sw_if_index)); + else if (unformat (i, "fib-table %u", &fib_table)); + else if (unformat (i, "end.psp %u", &behavior)); + else + break; + } + + M (SR_LOCALSID_ADD_DEL, mp); + + clib_memcpy (mp->localsid_addr, &localsid, sizeof (mp->localsid_addr)); + if (nexthop_set) + clib_memcpy (mp->nh_addr, &next_hop, sizeof (mp->nh_addr)); + mp->behavior = behavior; + mp->sw_if_index = ntohl (sw_if_index); + mp->fib_table = ntohl (fib_table); + mp->end_psp = end_psp; + mp->is_del = is_del; + + S (mp); + W (ret); + return ret; +} + +static int +api_ioam_enable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_ioam_enable_t *mp; + u32 id = 0; + int has_trace_option = 0; + int has_pot_option = 0; + int has_seqno_option = 0; + int has_analyse_option = 0; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "trace")) + has_trace_option = 1; + else if (unformat (input, "pot")) + has_pot_option = 1; + else if (unformat (input, "seqno")) + has_seqno_option = 1; + else if (unformat (input, "analyse")) + has_analyse_option = 1; + else + break; + } + M (IOAM_ENABLE, mp); + mp->id = htons (id); + mp->seqno = has_seqno_option; + mp->analyse = has_analyse_option; + mp->pot_enable = has_pot_option; + mp->trace_enable = has_trace_option; + + S (mp); + W (ret); + return ret; +} + + +static int +api_ioam_disable (vat_main_t * vam) +{ + vl_api_ioam_disable_t *mp; + int ret; + + M (IOAM_DISABLE, mp); + S (mp); + W (ret); + return ret; +} + +#define foreach_tcp_proto_field \ +_(src_port) \ +_(dst_port) + +#define foreach_udp_proto_field \ +_(src_port) \ +_(dst_port) + +#define foreach_ip4_proto_field \ +_(src_address) \ +_(dst_address) \ +_(tos) \ +_(length) \ +_(fragment_id) \ +_(ttl) \ +_(protocol) \ +_(checksum) + +typedef struct +{ + u16 src_port, dst_port; +} tcpudp_header_t; + +#if VPP_API_TEST_BUILTIN == 0 +uword +unformat_tcp_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u8 *mask = 0; + u8 found_something = 0; + tcp_header_t *tcp; + +#define _(a) u8 a=0; + foreach_tcp_proto_field; +#undef _ + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (0); +#define _(a) else if (unformat (input, #a)) a=1; + foreach_tcp_proto_field +#undef _ + else + break; + } + +#define _(a) found_something += a; + foreach_tcp_proto_field; +#undef _ + + if (found_something == 0) + return 0; + + vec_validate (mask, sizeof (*tcp) - 1); + + tcp = (tcp_header_t *) mask; + +#define _(a) if (a) memset (&tcp->a, 0xff, sizeof (tcp->a)); + foreach_tcp_proto_field; +#undef _ + + *maskp = mask; + return 1; +} + +uword +unformat_udp_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u8 *mask = 0; + u8 found_something = 0; + udp_header_t *udp; + +#define _(a) u8 a=0; + foreach_udp_proto_field; +#undef _ + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (0); +#define _(a) else if (unformat (input, #a)) a=1; + foreach_udp_proto_field +#undef _ + else + break; + } + +#define _(a) found_something += a; + foreach_udp_proto_field; +#undef _ + + if (found_something == 0) + return 0; + + vec_validate (mask, sizeof (*udp) - 1); + + udp = (udp_header_t *) mask; + +#define _(a) if (a) memset (&udp->a, 0xff, sizeof (udp->a)); + foreach_udp_proto_field; +#undef _ + + *maskp = mask; + return 1; +} + +uword +unformat_l4_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u16 src_port = 0, dst_port = 0; + tcpudp_header_t *tcpudp; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "tcp %U", unformat_tcp_mask, maskp)) + return 1; + else if (unformat (input, "udp %U", unformat_udp_mask, maskp)) + return 1; + else if (unformat (input, "src_port")) + src_port = 0xFFFF; + else if (unformat (input, "dst_port")) + dst_port = 0xFFFF; + else + return 0; + } + + if (!src_port && !dst_port) + return 0; + + u8 *mask = 0; + vec_validate (mask, sizeof (tcpudp_header_t) - 1); + + tcpudp = (tcpudp_header_t *) mask; + tcpudp->src_port = src_port; + tcpudp->dst_port = dst_port; + + *maskp = mask; + + return 1; +} + +uword +unformat_ip4_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u8 *mask = 0; + u8 found_something = 0; + ip4_header_t *ip; + +#define _(a) u8 a=0; + foreach_ip4_proto_field; +#undef _ + u8 version = 0; + u8 hdr_length = 0; + + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "version")) + version = 1; + else if (unformat (input, "hdr_length")) + hdr_length = 1; + else if (unformat (input, "src")) + src_address = 1; + else if (unformat (input, "dst")) + dst_address = 1; + else if (unformat (input, "proto")) + protocol = 1; + +#define _(a) else if (unformat (input, #a)) a=1; + foreach_ip4_proto_field +#undef _ + else + break; + } + +#define _(a) found_something += a; + foreach_ip4_proto_field; +#undef _ + + if (found_something == 0) + return 0; + + vec_validate (mask, sizeof (*ip) - 1); + + ip = (ip4_header_t *) mask; + +#define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a)); + foreach_ip4_proto_field; +#undef _ + + ip->ip_version_and_header_length = 0; + + if (version) + ip->ip_version_and_header_length |= 0xF0; + + if (hdr_length) + ip->ip_version_and_header_length |= 0x0F; + + *maskp = mask; + return 1; +} + +#define foreach_ip6_proto_field \ +_(src_address) \ +_(dst_address) \ +_(payload_length) \ +_(hop_limit) \ +_(protocol) + +uword +unformat_ip6_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u8 *mask = 0; + u8 found_something = 0; + ip6_header_t *ip; + u32 ip_version_traffic_class_and_flow_label; + +#define _(a) u8 a=0; + foreach_ip6_proto_field; +#undef _ + u8 version = 0; + u8 traffic_class = 0; + u8 flow_label = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "version")) + version = 1; + else if (unformat (input, "traffic-class")) + traffic_class = 1; + else if (unformat (input, "flow-label")) + flow_label = 1; + else if (unformat (input, "src")) + src_address = 1; + else if (unformat (input, "dst")) + dst_address = 1; + else if (unformat (input, "proto")) + protocol = 1; + +#define _(a) else if (unformat (input, #a)) a=1; + foreach_ip6_proto_field +#undef _ + else + break; + } + +#define _(a) found_something += a; + foreach_ip6_proto_field; +#undef _ + + if (found_something == 0) + return 0; + + vec_validate (mask, sizeof (*ip) - 1); + + ip = (ip6_header_t *) mask; + +#define _(a) if (a) memset (&ip->a, 0xff, sizeof (ip->a)); + foreach_ip6_proto_field; +#undef _ + + ip_version_traffic_class_and_flow_label = 0; + + if (version) + ip_version_traffic_class_and_flow_label |= 0xF0000000; + + if (traffic_class) + ip_version_traffic_class_and_flow_label |= 0x0FF00000; + + if (flow_label) + ip_version_traffic_class_and_flow_label |= 0x000FFFFF; + + ip->ip_version_traffic_class_and_flow_label = + clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label); + + *maskp = mask; + return 1; +} + +uword +unformat_l3_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ip4 %U", unformat_ip4_mask, maskp)) + return 1; + else if (unformat (input, "ip6 %U", unformat_ip6_mask, maskp)) + return 1; + else + break; + } + return 0; +} + +uword +unformat_l2_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u8 *mask = 0; + u8 src = 0; + u8 dst = 0; + u8 proto = 0; + u8 tag1 = 0; + u8 tag2 = 0; + u8 ignore_tag1 = 0; + u8 ignore_tag2 = 0; + u8 cos1 = 0; + u8 cos2 = 0; + u8 dot1q = 0; + u8 dot1ad = 0; + int len = 14; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "src")) + src = 1; + else if (unformat (input, "dst")) + dst = 1; + else if (unformat (input, "proto")) + proto = 1; + else if (unformat (input, "tag1")) + tag1 = 1; + else if (unformat (input, "tag2")) + tag2 = 1; + else if (unformat (input, "ignore-tag1")) + ignore_tag1 = 1; + else if (unformat (input, "ignore-tag2")) + ignore_tag2 = 1; + else if (unformat (input, "cos1")) + cos1 = 1; + else if (unformat (input, "cos2")) + cos2 = 1; + else if (unformat (input, "dot1q")) + dot1q = 1; + else if (unformat (input, "dot1ad")) + dot1ad = 1; + else + break; + } + if ((src + dst + proto + tag1 + tag2 + dot1q + dot1ad + + ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0) + return 0; + + if (tag1 || ignore_tag1 || cos1 || dot1q) + len = 18; + if (tag2 || ignore_tag2 || cos2 || dot1ad) + len = 22; + + vec_validate (mask, len - 1); + + if (dst) + memset (mask, 0xff, 6); + + if (src) + memset (mask + 6, 0xff, 6); + + if (tag2 || dot1ad) + { + /* inner vlan tag */ + if (tag2) + { + mask[19] = 0xff; + mask[18] = 0x0f; + } + if (cos2) + mask[18] |= 0xe0; + if (proto) + mask[21] = mask[20] = 0xff; + if (tag1) + { + mask[15] = 0xff; + mask[14] = 0x0f; + } + if (cos1) + mask[14] |= 0xe0; + *maskp = mask; + return 1; + } + if (tag1 | dot1q) + { + if (tag1) + { + mask[15] = 0xff; + mask[14] = 0x0f; + } + if (cos1) + mask[14] |= 0xe0; + if (proto) + mask[16] = mask[17] = 0xff; + + *maskp = mask; + return 1; + } + if (cos2) + mask[18] |= 0xe0; + if (cos1) + mask[14] |= 0xe0; + if (proto) + mask[12] = mask[13] = 0xff; + + *maskp = mask; + return 1; +} + +uword +unformat_classify_mask (unformat_input_t * input, va_list * args) +{ + u8 **maskp = va_arg (*args, u8 **); + u32 *skipp = va_arg (*args, u32 *); + u32 *matchp = va_arg (*args, u32 *); + u32 match; + u8 *mask = 0; + u8 *l2 = 0; + u8 *l3 = 0; + u8 *l4 = 0; + int i; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "hex %U", unformat_hex_string, &mask)) + ; + else if (unformat (input, "l2 %U", unformat_l2_mask, &l2)) + ; + else if (unformat (input, "l3 %U", unformat_l3_mask, &l3)) + ; + else if (unformat (input, "l4 %U", unformat_l4_mask, &l4)) + ; + else + break; + } + + if (l4 && !l3) + { + vec_free (mask); + vec_free (l2); + vec_free (l4); + return 0; + } + + if (mask || l2 || l3 || l4) + { + if (l2 || l3 || l4) + { + /* "With a free Ethernet header in every package" */ + if (l2 == 0) + vec_validate (l2, 13); + mask = l2; + if (vec_len (l3)) + { + vec_append (mask, l3); + vec_free (l3); + } + if (vec_len (l4)) + { + vec_append (mask, l4); + vec_free (l4); + } + } + + /* Scan forward looking for the first significant mask octet */ + for (i = 0; i < vec_len (mask); i++) + if (mask[i]) + break; + + /* compute (skip, match) params */ + *skipp = i / sizeof (u32x4); + vec_delete (mask, *skipp * sizeof (u32x4), 0); + + /* Pad mask to an even multiple of the vector size */ + while (vec_len (mask) % sizeof (u32x4)) + vec_add1 (mask, 0); + + match = vec_len (mask) / sizeof (u32x4); + + for (i = match * sizeof (u32x4); i > 0; i -= sizeof (u32x4)) + { + u64 *tmp = (u64 *) (mask + (i - sizeof (u32x4))); + if (*tmp || *(tmp + 1)) + break; + match--; + } + if (match == 0) + clib_warning ("BUG: match 0"); + + _vec_len (mask) = match * sizeof (u32x4); + + *matchp = match; + *maskp = mask; + + return 1; + } + + return 0; +} +#endif /* VPP_API_TEST_BUILTIN */ + +#define foreach_l2_next \ +_(drop, DROP) \ +_(ethernet, ETHERNET_INPUT) \ +_(ip4, IP4_INPUT) \ +_(ip6, IP6_INPUT) + +uword +unformat_l2_next_index (unformat_input_t * input, va_list * args) +{ + u32 *miss_next_indexp = va_arg (*args, u32 *); + u32 next_index = 0; + u32 tmp; + +#define _(n,N) \ + if (unformat (input, #n)) { next_index = L2_INPUT_CLASSIFY_NEXT_##N; goto out;} + foreach_l2_next; +#undef _ + + if (unformat (input, "%d", &tmp)) + { + next_index = tmp; + goto out; + } + + return 0; + +out: + *miss_next_indexp = next_index; + return 1; +} + +#define foreach_ip_next \ +_(drop, DROP) \ +_(local, LOCAL) \ +_(rewrite, REWRITE) + +uword +api_unformat_ip_next_index (unformat_input_t * input, va_list * args) +{ + u32 *miss_next_indexp = va_arg (*args, u32 *); + u32 next_index = 0; + u32 tmp; + +#define _(n,N) \ + if (unformat (input, #n)) { next_index = IP_LOOKUP_NEXT_##N; goto out;} + foreach_ip_next; +#undef _ + + if (unformat (input, "%d", &tmp)) + { + next_index = tmp; + goto out; + } + + return 0; + +out: + *miss_next_indexp = next_index; + return 1; +} + +#define foreach_acl_next \ +_(deny, DENY) + +uword +api_unformat_acl_next_index (unformat_input_t * input, va_list * args) +{ + u32 *miss_next_indexp = va_arg (*args, u32 *); + u32 next_index = 0; + u32 tmp; + +#define _(n,N) \ + if (unformat (input, #n)) { next_index = ACL_NEXT_INDEX_##N; goto out;} + foreach_acl_next; +#undef _ + + if (unformat (input, "permit")) + { + next_index = ~0; + goto out; + } + else if (unformat (input, "%d", &tmp)) + { + next_index = tmp; + goto out; + } + + return 0; + +out: + *miss_next_indexp = next_index; + return 1; +} + +uword +unformat_policer_precolor (unformat_input_t * input, va_list * args) +{ + u32 *r = va_arg (*args, u32 *); + + if (unformat (input, "conform-color")) + *r = POLICE_CONFORM; + else if (unformat (input, "exceed-color")) + *r = POLICE_EXCEED; + else + return 0; + + return 1; +} + +static int +api_classify_add_del_table (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_classify_add_del_table_t *mp; + + u32 nbuckets = 2; + u32 skip = ~0; + u32 match = ~0; + int is_add = 1; + int del_chain = 0; + u32 table_index = ~0; + u32 next_table_index = ~0; + u32 miss_next_index = ~0; + u32 memory_size = 32 << 20; + u8 *mask = 0; + u32 current_data_flag = 0; + int current_data_offset = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "del-chain")) + { + is_add = 0; + del_chain = 1; + } + else if (unformat (i, "buckets %d", &nbuckets)) + ; + else if (unformat (i, "memory_size %d", &memory_size)) + ; + else if (unformat (i, "skip %d", &skip)) + ; + else if (unformat (i, "match %d", &match)) + ; + else if (unformat (i, "table %d", &table_index)) + ; + else if (unformat (i, "mask %U", unformat_classify_mask, + &mask, &skip, &match)) + ; + else if (unformat (i, "next-table %d", &next_table_index)) + ; + else if (unformat (i, "miss-next %U", api_unformat_ip_next_index, + &miss_next_index)) + ; + else if (unformat (i, "l2-miss-next %U", unformat_l2_next_index, + &miss_next_index)) + ; + else if (unformat (i, "acl-miss-next %U", api_unformat_acl_next_index, + &miss_next_index)) + ; + else if (unformat (i, "current-data-flag %d", ¤t_data_flag)) + ; + else if (unformat (i, "current-data-offset %d", ¤t_data_offset)) + ; + else + break; + } + + if (is_add && mask == 0) + { + errmsg ("Mask required"); + return -99; + } + + if (is_add && skip == ~0) + { + errmsg ("skip count required"); + return -99; + } + + if (is_add && match == ~0) + { + errmsg ("match count required"); + return -99; + } + + if (!is_add && table_index == ~0) + { + errmsg ("table index required for delete"); + return -99; + } + + M2 (CLASSIFY_ADD_DEL_TABLE, mp, vec_len (mask)); + + mp->is_add = is_add; + mp->del_chain = del_chain; + mp->table_index = ntohl (table_index); + mp->nbuckets = ntohl (nbuckets); + mp->memory_size = ntohl (memory_size); + mp->skip_n_vectors = ntohl (skip); + mp->match_n_vectors = ntohl (match); + mp->next_table_index = ntohl (next_table_index); + mp->miss_next_index = ntohl (miss_next_index); + mp->current_data_flag = ntohl (current_data_flag); + mp->current_data_offset = ntohl (current_data_offset); + clib_memcpy (mp->mask, mask, vec_len (mask)); + + vec_free (mask); + + S (mp); + W (ret); + return ret; +} + +#if VPP_API_TEST_BUILTIN == 0 +uword +unformat_l4_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + + u8 *proto_header = 0; + int src_port = 0; + int dst_port = 0; + + tcpudp_header_t h; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "src_port %d", &src_port)) + ; + else if (unformat (input, "dst_port %d", &dst_port)) + ; + else + return 0; + } + + h.src_port = clib_host_to_net_u16 (src_port); + h.dst_port = clib_host_to_net_u16 (dst_port); + vec_validate (proto_header, sizeof (h) - 1); + memcpy (proto_header, &h, sizeof (h)); + + *matchp = proto_header; + + return 1; +} + +uword +unformat_ip4_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + u8 *match = 0; + ip4_header_t *ip; + int version = 0; + u32 version_val; + int hdr_length = 0; + u32 hdr_length_val; + int src = 0, dst = 0; + ip4_address_t src_val, dst_val; + int proto = 0; + u32 proto_val; + int tos = 0; + u32 tos_val; + int length = 0; + u32 length_val; + int fragment_id = 0; + u32 fragment_id_val; + int ttl = 0; + int ttl_val; + int checksum = 0; + u32 checksum_val; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "version %d", &version_val)) + version = 1; + else if (unformat (input, "hdr_length %d", &hdr_length_val)) + hdr_length = 1; + else if (unformat (input, "src %U", unformat_ip4_address, &src_val)) + src = 1; + else if (unformat (input, "dst %U", unformat_ip4_address, &dst_val)) + dst = 1; + else if (unformat (input, "proto %d", &proto_val)) + proto = 1; + else if (unformat (input, "tos %d", &tos_val)) + tos = 1; + else if (unformat (input, "length %d", &length_val)) + length = 1; + else if (unformat (input, "fragment_id %d", &fragment_id_val)) + fragment_id = 1; + else if (unformat (input, "ttl %d", &ttl_val)) + ttl = 1; + else if (unformat (input, "checksum %d", &checksum_val)) + checksum = 1; + else + break; + } + + if (version + hdr_length + src + dst + proto + tos + length + fragment_id + + ttl + checksum == 0) + return 0; + + /* + * Aligned because we use the real comparison functions + */ + vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4)); + + ip = (ip4_header_t *) match; + + /* These are realistically matched in practice */ + if (src) + ip->src_address.as_u32 = src_val.as_u32; + + if (dst) + ip->dst_address.as_u32 = dst_val.as_u32; + + if (proto) + ip->protocol = proto_val; + + + /* These are not, but they're included for completeness */ + if (version) + ip->ip_version_and_header_length |= (version_val & 0xF) << 4; + + if (hdr_length) + ip->ip_version_and_header_length |= (hdr_length_val & 0xF); + + if (tos) + ip->tos = tos_val; + + if (length) + ip->length = clib_host_to_net_u16 (length_val); + + if (ttl) + ip->ttl = ttl_val; + + if (checksum) + ip->checksum = clib_host_to_net_u16 (checksum_val); + + *matchp = match; + return 1; +} + +uword +unformat_ip6_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + u8 *match = 0; + ip6_header_t *ip; + int version = 0; + u32 version_val; + u8 traffic_class = 0; + u32 traffic_class_val = 0; + u8 flow_label = 0; + u8 flow_label_val; + int src = 0, dst = 0; + ip6_address_t src_val, dst_val; + int proto = 0; + u32 proto_val; + int payload_length = 0; + u32 payload_length_val; + int hop_limit = 0; + int hop_limit_val; + u32 ip_version_traffic_class_and_flow_label; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "version %d", &version_val)) + version = 1; + else if (unformat (input, "traffic_class %d", &traffic_class_val)) + traffic_class = 1; + else if (unformat (input, "flow_label %d", &flow_label_val)) + flow_label = 1; + else if (unformat (input, "src %U", unformat_ip6_address, &src_val)) + src = 1; + else if (unformat (input, "dst %U", unformat_ip6_address, &dst_val)) + dst = 1; + else if (unformat (input, "proto %d", &proto_val)) + proto = 1; + else if (unformat (input, "payload_length %d", &payload_length_val)) + payload_length = 1; + else if (unformat (input, "hop_limit %d", &hop_limit_val)) + hop_limit = 1; + else + break; + } + + if (version + traffic_class + flow_label + src + dst + proto + + payload_length + hop_limit == 0) + return 0; + + /* + * Aligned because we use the real comparison functions + */ + vec_validate_aligned (match, sizeof (*ip) - 1, sizeof (u32x4)); + + ip = (ip6_header_t *) match; + + if (src) + clib_memcpy (&ip->src_address, &src_val, sizeof (ip->src_address)); + + if (dst) + clib_memcpy (&ip->dst_address, &dst_val, sizeof (ip->dst_address)); + + if (proto) + ip->protocol = proto_val; + + ip_version_traffic_class_and_flow_label = 0; + + if (version) + ip_version_traffic_class_and_flow_label |= (version_val & 0xF) << 28; + + if (traffic_class) + ip_version_traffic_class_and_flow_label |= + (traffic_class_val & 0xFF) << 20; + + if (flow_label) + ip_version_traffic_class_and_flow_label |= (flow_label_val & 0xFFFFF); + + ip->ip_version_traffic_class_and_flow_label = + clib_host_to_net_u32 (ip_version_traffic_class_and_flow_label); + + if (payload_length) + ip->payload_length = clib_host_to_net_u16 (payload_length_val); + + if (hop_limit) + ip->hop_limit = hop_limit_val; + + *matchp = match; + return 1; +} + +uword +unformat_l3_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ip4 %U", unformat_ip4_match, matchp)) + return 1; + else if (unformat (input, "ip6 %U", unformat_ip6_match, matchp)) + return 1; + else + break; + } + return 0; +} + +uword +unformat_vlan_tag (unformat_input_t * input, va_list * args) +{ + u8 *tagp = va_arg (*args, u8 *); + u32 tag; + + if (unformat (input, "%d", &tag)) + { + tagp[0] = (tag >> 8) & 0x0F; + tagp[1] = tag & 0xFF; + return 1; + } + + return 0; +} + +uword +unformat_l2_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + u8 *match = 0; + u8 src = 0; + u8 src_val[6]; + u8 dst = 0; + u8 dst_val[6]; + u8 proto = 0; + u16 proto_val; + u8 tag1 = 0; + u8 tag1_val[2]; + u8 tag2 = 0; + u8 tag2_val[2]; + int len = 14; + u8 ignore_tag1 = 0; + u8 ignore_tag2 = 0; + u8 cos1 = 0; + u8 cos2 = 0; + u32 cos1_val = 0; + u32 cos2_val = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "src %U", unformat_ethernet_address, &src_val)) + src = 1; + else + if (unformat (input, "dst %U", unformat_ethernet_address, &dst_val)) + dst = 1; + else if (unformat (input, "proto %U", + unformat_ethernet_type_host_byte_order, &proto_val)) + proto = 1; + else if (unformat (input, "tag1 %U", unformat_vlan_tag, tag1_val)) + tag1 = 1; + else if (unformat (input, "tag2 %U", unformat_vlan_tag, tag2_val)) + tag2 = 1; + else if (unformat (input, "ignore-tag1")) + ignore_tag1 = 1; + else if (unformat (input, "ignore-tag2")) + ignore_tag2 = 1; + else if (unformat (input, "cos1 %d", &cos1_val)) + cos1 = 1; + else if (unformat (input, "cos2 %d", &cos2_val)) + cos2 = 1; + else + break; + } + if ((src + dst + proto + tag1 + tag2 + + ignore_tag1 + ignore_tag2 + cos1 + cos2) == 0) + return 0; + + if (tag1 || ignore_tag1 || cos1) + len = 18; + if (tag2 || ignore_tag2 || cos2) + len = 22; + + vec_validate_aligned (match, len - 1, sizeof (u32x4)); + + if (dst) + clib_memcpy (match, dst_val, 6); + + if (src) + clib_memcpy (match + 6, src_val, 6); + + if (tag2) + { + /* inner vlan tag */ + match[19] = tag2_val[1]; + match[18] = tag2_val[0]; + if (cos2) + match[18] |= (cos2_val & 0x7) << 5; + if (proto) + { + match[21] = proto_val & 0xff; + match[20] = proto_val >> 8; + } + if (tag1) + { + match[15] = tag1_val[1]; + match[14] = tag1_val[0]; + } + if (cos1) + match[14] |= (cos1_val & 0x7) << 5; + *matchp = match; + return 1; + } + if (tag1) + { + match[15] = tag1_val[1]; + match[14] = tag1_val[0]; + if (proto) + { + match[17] = proto_val & 0xff; + match[16] = proto_val >> 8; + } + if (cos1) + match[14] |= (cos1_val & 0x7) << 5; + + *matchp = match; + return 1; + } + if (cos2) + match[18] |= (cos2_val & 0x7) << 5; + if (cos1) + match[14] |= (cos1_val & 0x7) << 5; + if (proto) + { + match[13] = proto_val & 0xff; + match[12] = proto_val >> 8; + } + + *matchp = match; + return 1; +} +#endif + +uword +api_unformat_classify_match (unformat_input_t * input, va_list * args) +{ + u8 **matchp = va_arg (*args, u8 **); + u32 skip_n_vectors = va_arg (*args, u32); + u32 match_n_vectors = va_arg (*args, u32); + + u8 *match = 0; + u8 *l2 = 0; + u8 *l3 = 0; + u8 *l4 = 0; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "hex %U", unformat_hex_string, &match)) + ; + else if (unformat (input, "l2 %U", unformat_l2_match, &l2)) + ; + else if (unformat (input, "l3 %U", unformat_l3_match, &l3)) + ; + else if (unformat (input, "l4 %U", unformat_l4_match, &l4)) + ; + else + break; + } + + if (l4 && !l3) + { + vec_free (match); + vec_free (l2); + vec_free (l4); + return 0; + } + + if (match || l2 || l3 || l4) + { + if (l2 || l3 || l4) + { + /* "Win a free Ethernet header in every packet" */ + if (l2 == 0) + vec_validate_aligned (l2, 13, sizeof (u32x4)); + match = l2; + if (vec_len (l3)) + { + vec_append_aligned (match, l3, sizeof (u32x4)); + vec_free (l3); + } + if (vec_len (l4)) + { + vec_append_aligned (match, l4, sizeof (u32x4)); + vec_free (l4); + } + } + + /* Make sure the vector is big enough even if key is all 0's */ + vec_validate_aligned + (match, ((match_n_vectors + skip_n_vectors) * sizeof (u32x4)) - 1, + sizeof (u32x4)); + + /* Set size, include skipped vectors */ + _vec_len (match) = (match_n_vectors + skip_n_vectors) * sizeof (u32x4); + + *matchp = match; + + return 1; + } + + return 0; +} + +static int +api_classify_add_del_session (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_classify_add_del_session_t *mp; + int is_add = 1; + u32 table_index = ~0; + u32 hit_next_index = ~0; + u32 opaque_index = ~0; + u8 *match = 0; + i32 advance = 0; + u32 skip_n_vectors = 0; + u32 match_n_vectors = 0; + u32 action = 0; + u32 metadata = 0; + int ret; + + /* + * Warning: you have to supply skip_n and match_n + * because the API client cant simply look at the classify + * table object. + */ + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "hit-next %U", api_unformat_ip_next_index, + &hit_next_index)) + ; + else if (unformat (i, "l2-hit-next %U", unformat_l2_next_index, + &hit_next_index)) + ; + else if (unformat (i, "acl-hit-next %U", api_unformat_acl_next_index, + &hit_next_index)) + ; + else if (unformat (i, "policer-hit-next %d", &hit_next_index)) + ; + else if (unformat (i, "%U", unformat_policer_precolor, &opaque_index)) + ; + else if (unformat (i, "opaque-index %d", &opaque_index)) + ; + else if (unformat (i, "skip_n %d", &skip_n_vectors)) + ; + else if (unformat (i, "match_n %d", &match_n_vectors)) + ; + else if (unformat (i, "match %U", api_unformat_classify_match, + &match, skip_n_vectors, match_n_vectors)) + ; + else if (unformat (i, "advance %d", &advance)) + ; + else if (unformat (i, "table-index %d", &table_index)) + ; + else if (unformat (i, "action set-ip4-fib-id %d", &metadata)) + action = 1; + else if (unformat (i, "action set-ip6-fib-id %d", &metadata)) + action = 2; + else if (unformat (i, "action %d", &action)) + ; + else if (unformat (i, "metadata %d", &metadata)) + ; + else + break; + } + + if (table_index == ~0) + { + errmsg ("Table index required"); + return -99; + } + + if (is_add && match == 0) + { + errmsg ("Match value required"); + return -99; + } + + M2 (CLASSIFY_ADD_DEL_SESSION, mp, vec_len (match)); + + mp->is_add = is_add; + mp->table_index = ntohl (table_index); + mp->hit_next_index = ntohl (hit_next_index); + mp->opaque_index = ntohl (opaque_index); + mp->advance = ntohl (advance); + mp->action = action; + mp->metadata = ntohl (metadata); + clib_memcpy (mp->match, match, vec_len (match)); + vec_free (match); + + S (mp); + W (ret); + return ret; +} + +static int +api_classify_set_interface_ip_table (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_classify_set_interface_ip_table_t *mp; + u32 sw_if_index; + int sw_if_index_set; + u32 table_index = ~0; + u8 is_ipv6 = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "table %d", &table_index)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + + M (CLASSIFY_SET_INTERFACE_IP_TABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->table_index = ntohl (table_index); + mp->is_ipv6 = is_ipv6; + + S (mp); + W (ret); + return ret; +} + +static int +api_classify_set_interface_l2_tables (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_classify_set_interface_l2_tables_t *mp; + u32 sw_if_index; + int sw_if_index_set; + u32 ip4_table_index = ~0; + u32 ip6_table_index = ~0; + u32 other_table_index = ~0; + u32 is_input = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "ip4-table %d", &ip4_table_index)) + ; + else if (unformat (i, "ip6-table %d", &ip6_table_index)) + ; + else if (unformat (i, "other-table %d", &other_table_index)) + ; + else if (unformat (i, "is-input %d", &is_input)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + + M (CLASSIFY_SET_INTERFACE_L2_TABLES, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->ip4_table_index = ntohl (ip4_table_index); + mp->ip6_table_index = ntohl (ip6_table_index); + mp->other_table_index = ntohl (other_table_index); + mp->is_input = (u8) is_input; + + S (mp); + W (ret); + return ret; +} + +static int +api_set_ipfix_exporter (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_set_ipfix_exporter_t *mp; + ip4_address_t collector_address; + u8 collector_address_set = 0; + u32 collector_port = ~0; + ip4_address_t src_address; + u8 src_address_set = 0; + u32 vrf_id = ~0; + u32 path_mtu = ~0; + u32 template_interval = ~0; + u8 udp_checksum = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "collector_address %U", unformat_ip4_address, + &collector_address)) + collector_address_set = 1; + else if (unformat (i, "collector_port %d", &collector_port)) + ; + else if (unformat (i, "src_address %U", unformat_ip4_address, + &src_address)) + src_address_set = 1; + else if (unformat (i, "vrf_id %d", &vrf_id)) + ; + else if (unformat (i, "path_mtu %d", &path_mtu)) + ; + else if (unformat (i, "template_interval %d", &template_interval)) + ; + else if (unformat (i, "udp_checksum")) + udp_checksum = 1; + else + break; + } + + if (collector_address_set == 0) + { + errmsg ("collector_address required"); + return -99; + } + + if (src_address_set == 0) + { + errmsg ("src_address required"); + return -99; + } + + M (SET_IPFIX_EXPORTER, mp); + + memcpy (mp->collector_address, collector_address.data, + sizeof (collector_address.data)); + mp->collector_port = htons ((u16) collector_port); + memcpy (mp->src_address, src_address.data, sizeof (src_address.data)); + mp->vrf_id = htonl (vrf_id); + mp->path_mtu = htonl (path_mtu); + mp->template_interval = htonl (template_interval); + mp->udp_checksum = udp_checksum; + + S (mp); + W (ret); + return ret; +} + +static int +api_set_ipfix_classify_stream (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_set_ipfix_classify_stream_t *mp; + u32 domain_id = 0; + u32 src_port = UDP_DST_PORT_ipfix; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "domain %d", &domain_id)) + ; + else if (unformat (i, "src_port %d", &src_port)) + ; + else + { + errmsg ("unknown input `%U'", format_unformat_error, i); + return -99; + } + } + + M (SET_IPFIX_CLASSIFY_STREAM, mp); + + mp->domain_id = htonl (domain_id); + mp->src_port = htons ((u16) src_port); + + S (mp); + W (ret); + return ret; +} + +static int +api_ipfix_classify_table_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipfix_classify_table_add_del_t *mp; + int is_add = -1; + u32 classify_table_index = ~0; + u8 ip_version = 0; + u8 transport_protocol = 255; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "add")) + is_add = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "table %d", &classify_table_index)) + ; + else if (unformat (i, "ip4")) + ip_version = 4; + else if (unformat (i, "ip6")) + ip_version = 6; + else if (unformat (i, "tcp")) + transport_protocol = 6; + else if (unformat (i, "udp")) + transport_protocol = 17; + else + { + errmsg ("unknown input `%U'", format_unformat_error, i); + return -99; + } + } + + if (is_add == -1) + { + errmsg ("expecting: add|del"); + return -99; + } + if (classify_table_index == ~0) + { + errmsg ("classifier table not specified"); + return -99; + } + if (ip_version == 0) + { + errmsg ("IP version not specified"); + return -99; + } + + M (IPFIX_CLASSIFY_TABLE_ADD_DEL, mp); + + mp->is_add = is_add; + mp->table_id = htonl (classify_table_index); + mp->ip_version = ip_version; + mp->transport_protocol = transport_protocol; + + S (mp); + W (ret); + return ret; +} + +static int +api_get_node_index (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_get_node_index_t *mp; + u8 *name = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "node %s", &name)) + ; + else + break; + } + if (name == 0) + { + errmsg ("node name required"); + return -99; + } + if (vec_len (name) >= ARRAY_LEN (mp->node_name)) + { + errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name)); + return -99; + } + + M (GET_NODE_INDEX, mp); + clib_memcpy (mp->node_name, name, vec_len (name)); + vec_free (name); + + S (mp); + W (ret); + return ret; +} + +static int +api_get_next_index (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_get_next_index_t *mp; + u8 *node_name = 0, *next_node_name = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "node-name %s", &node_name)) + ; + else if (unformat (i, "next-node-name %s", &next_node_name)) + break; + } + + if (node_name == 0) + { + errmsg ("node name required"); + return -99; + } + if (vec_len (node_name) >= ARRAY_LEN (mp->node_name)) + { + errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name)); + return -99; + } + + if (next_node_name == 0) + { + errmsg ("next node name required"); + return -99; + } + if (vec_len (next_node_name) >= ARRAY_LEN (mp->next_name)) + { + errmsg ("next node name too long, max %d", ARRAY_LEN (mp->next_name)); + return -99; + } + + M (GET_NEXT_INDEX, mp); + clib_memcpy (mp->node_name, node_name, vec_len (node_name)); + clib_memcpy (mp->next_name, next_node_name, vec_len (next_node_name)); + vec_free (node_name); + vec_free (next_node_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_add_node_next (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_add_node_next_t *mp; + u8 *name = 0; + u8 *next = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "node %s", &name)) + ; + else if (unformat (i, "next %s", &next)) + ; + else + break; + } + if (name == 0) + { + errmsg ("node name required"); + return -99; + } + if (vec_len (name) >= ARRAY_LEN (mp->node_name)) + { + errmsg ("node name too long, max %d", ARRAY_LEN (mp->node_name)); + return -99; + } + if (next == 0) + { + errmsg ("next node required"); + return -99; + } + if (vec_len (next) >= ARRAY_LEN (mp->next_name)) + { + errmsg ("next name too long, max %d", ARRAY_LEN (mp->next_name)); + return -99; + } + + M (ADD_NODE_NEXT, mp); + clib_memcpy (mp->node_name, name, vec_len (name)); + clib_memcpy (mp->next_name, next, vec_len (next)); + vec_free (name); + vec_free (next); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2tpv3_create_tunnel (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + ip6_address_t client_address, our_address; + int client_address_set = 0; + int our_address_set = 0; + u32 local_session_id = 0; + u32 remote_session_id = 0; + u64 local_cookie = 0; + u64 remote_cookie = 0; + u8 l2_sublayer_present = 0; + vl_api_l2tpv3_create_tunnel_t *mp; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "client_address %U", unformat_ip6_address, + &client_address)) + client_address_set = 1; + else if (unformat (i, "our_address %U", unformat_ip6_address, + &our_address)) + our_address_set = 1; + else if (unformat (i, "local_session_id %d", &local_session_id)) + ; + else if (unformat (i, "remote_session_id %d", &remote_session_id)) + ; + else if (unformat (i, "local_cookie %lld", &local_cookie)) + ; + else if (unformat (i, "remote_cookie %lld", &remote_cookie)) + ; + else if (unformat (i, "l2-sublayer-present")) + l2_sublayer_present = 1; + else + break; + } + + if (client_address_set == 0) + { + errmsg ("client_address required"); + return -99; + } + + if (our_address_set == 0) + { + errmsg ("our_address required"); + return -99; + } + + M (L2TPV3_CREATE_TUNNEL, mp); + + clib_memcpy (mp->client_address, client_address.as_u8, + sizeof (mp->client_address)); + + clib_memcpy (mp->our_address, our_address.as_u8, sizeof (mp->our_address)); + + mp->local_session_id = ntohl (local_session_id); + mp->remote_session_id = ntohl (remote_session_id); + mp->local_cookie = clib_host_to_net_u64 (local_cookie); + mp->remote_cookie = clib_host_to_net_u64 (remote_cookie); + mp->l2_sublayer_present = l2_sublayer_present; + mp->is_ipv6 = 1; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2tpv3_set_tunnel_cookies (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u64 new_local_cookie = 0; + u64 new_remote_cookie = 0; + vl_api_l2tpv3_set_tunnel_cookies_t *mp; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "new_local_cookie %lld", &new_local_cookie)) + ; + else if (unformat (i, "new_remote_cookie %lld", &new_remote_cookie)) + ; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2TPV3_SET_TUNNEL_COOKIES, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->new_local_cookie = clib_host_to_net_u64 (new_local_cookie); + mp->new_remote_cookie = clib_host_to_net_u64 (new_remote_cookie); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2tpv3_interface_enable_disable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2tpv3_interface_enable_disable_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 enable_disable = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + enable_disable = 1; + else if (unformat (i, "disable")) + enable_disable = 0; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (L2TPV3_INTERFACE_ENABLE_DISABLE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable_disable; + + S (mp); + W (ret); + return ret; +} + +static int +api_l2tpv3_set_lookup_key (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2tpv3_set_lookup_key_t *mp; + u8 key = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "lookup_v6_src")) + key = L2T_LOOKUP_SRC_ADDRESS; + else if (unformat (i, "lookup_v6_dst")) + key = L2T_LOOKUP_DST_ADDRESS; + else if (unformat (i, "lookup_session_id")) + key = L2T_LOOKUP_SESSION_ID; + else + break; + } + + if (key == (u8) ~ 0) + { + errmsg ("l2tp session lookup key unset"); + return -99; + } + + M (L2TPV3_SET_LOOKUP_KEY, mp); + + mp->key = key; + + S (mp); + W (ret); + return ret; +} + +static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler + (vl_api_sw_if_l2tpv3_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "* %U (our) %U (client) (sw_if_index %d)", + format_ip6_address, mp->our_address, + format_ip6_address, mp->client_address, + clib_net_to_host_u32 (mp->sw_if_index)); + + print (vam->ofp, + " local cookies %016llx %016llx remote cookie %016llx", + clib_net_to_host_u64 (mp->local_cookie[0]), + clib_net_to_host_u64 (mp->local_cookie[1]), + clib_net_to_host_u64 (mp->remote_cookie)); + + print (vam->ofp, " local session-id %d remote session-id %d", + clib_net_to_host_u32 (mp->local_session_id), + clib_net_to_host_u32 (mp->remote_session_id)); + + print (vam->ofp, " l2 specific sublayer %s\n", + mp->l2_sublayer_present ? "preset" : "absent"); + +} + +static void vl_api_sw_if_l2tpv3_tunnel_details_t_handler_json + (vl_api_sw_if_l2tpv3_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr addr; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + + clib_memcpy (&addr, mp->our_address, sizeof (addr)); + vat_json_object_add_ip6 (node, "our_address", addr); + clib_memcpy (&addr, mp->client_address, sizeof (addr)); + vat_json_object_add_ip6 (node, "client_address", addr); + + vat_json_node_t *lc = vat_json_object_add (node, "local_cookie"); + vat_json_init_array (lc); + vat_json_array_add_uint (lc, clib_net_to_host_u64 (mp->local_cookie[0])); + vat_json_array_add_uint (lc, clib_net_to_host_u64 (mp->local_cookie[1])); + vat_json_object_add_uint (node, "remote_cookie", + clib_net_to_host_u64 (mp->remote_cookie)); + + printf ("local id: %u", clib_net_to_host_u32 (mp->local_session_id)); + vat_json_object_add_uint (node, "local_session_id", + clib_net_to_host_u32 (mp->local_session_id)); + vat_json_object_add_uint (node, "remote_session_id", + clib_net_to_host_u32 (mp->remote_session_id)); + vat_json_object_add_string_copy (node, "l2_sublayer", + mp->l2_sublayer_present ? (u8 *) "present" + : (u8 *) "absent"); +} + +static int +api_sw_if_l2tpv3_tunnel_dump (vat_main_t * vam) +{ + vl_api_sw_if_l2tpv3_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + /* Get list of l2tpv3-tunnel interfaces */ + M (SW_IF_L2TPV3_TUNNEL_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + + +static void vl_api_sw_interface_tap_details_t_handler + (vl_api_sw_interface_tap_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%-16s %d", + mp->dev_name, clib_net_to_host_u32 (mp->sw_if_index)); +} + +static void vl_api_sw_interface_tap_details_t_handler_json + (vl_api_sw_interface_tap_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_string_copy (node, "dev_name", mp->dev_name); +} + +static int +api_sw_interface_tap_dump (vat_main_t * vam) +{ + vl_api_sw_interface_tap_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + print (vam->ofp, "\n%-16s %s", "dev_name", "sw_if_index"); + /* Get list of tap interfaces */ + M (SW_INTERFACE_TAP_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void vl_api_sw_interface_tap_v2_details_t_handler + (vl_api_sw_interface_tap_v2_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + u8 *ip4 = format (0, "%U/%d", format_ip4_address, mp->host_ip4_addr, + mp->host_ip4_prefix_len); + u8 *ip6 = format (0, "%U/%d", format_ip6_address, mp->host_ip6_addr, + mp->host_ip6_prefix_len); + + print (vam->ofp, + "\n%-16s %-12d %-5d %-12d %-12d %-14U %-30s %-20s %-20s %-30s", + mp->dev_name, ntohl (mp->sw_if_index), ntohl (mp->id), + ntohs (mp->rx_ring_sz), ntohs (mp->tx_ring_sz), + format_ethernet_address, mp->host_mac_addr, mp->host_namespace, + mp->host_bridge, ip4, ip6); + + vec_free (ip4); + vec_free (ip6); +} + +static void vl_api_sw_interface_tap_v2_details_t_handler_json + (vl_api_sw_interface_tap_v2_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "id", ntohl (mp->id)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_string_copy (node, "dev_name", mp->dev_name); + vat_json_object_add_uint (node, "rx_ring_sz", ntohs (mp->rx_ring_sz)); + vat_json_object_add_uint (node, "tx_ring_sz", ntohs (mp->tx_ring_sz)); + vat_json_object_add_string_copy (node, "host_mac_addr", + format (0, "%U", format_ethernet_address, + &mp->host_mac_addr)); + vat_json_object_add_string_copy (node, "host_namespace", + mp->host_namespace); + vat_json_object_add_string_copy (node, "host_bridge", mp->host_bridge); + vat_json_object_add_string_copy (node, "host_ip4_addr", + format (0, "%U/%d", format_ip4_address, + mp->host_ip4_addr, + mp->host_ip4_prefix_len)); + vat_json_object_add_string_copy (node, "host_ip6_addr", + format (0, "%U/%d", format_ip6_address, + mp->host_ip6_addr, + mp->host_ip6_prefix_len)); + +} + +static int +api_sw_interface_tap_v2_dump (vat_main_t * vam) +{ + vl_api_sw_interface_tap_v2_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + print (vam->ofp, + "\n%-16s %-12s %-5s %-12s %-12s %-14s %-30s %-20s %-20s %-30s", + "dev_name", "sw_if_index", "id", "rx_ring_sz", "tx_ring_sz", + "host_mac_addr", "host_namespace", "host_bridge", "host_ip4_addr", + "host_ip6_addr"); + + /* Get list of tap interfaces */ + M (SW_INTERFACE_TAP_V2_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static uword unformat_vxlan_decap_next + (unformat_input_t * input, va_list * args) +{ + u32 *result = va_arg (*args, u32 *); + u32 tmp; + + if (unformat (input, "l2")) + *result = VXLAN_INPUT_NEXT_L2_INPUT; + else if (unformat (input, "%d", &tmp)) + *result = tmp; + else + return 0; + return 1; +} + +static int +api_vxlan_add_del_tunnel (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_vxlan_add_del_tunnel_t *mp; + ip46_address_t src, dst; + u8 is_add = 1; + u8 ipv4_set = 0, ipv6_set = 0; + u8 src_set = 0; + u8 dst_set = 0; + u8 grp_set = 0; + u32 mcast_sw_if_index = ~0; + u32 encap_vrf_id = 0; + u32 decap_next_index = ~0; + u32 vni = 0; + int ret; + + /* Can't "universally zero init" (={0}) due to GCC bug 53119 */ + memset (&src, 0, sizeof src); + memset (&dst, 0, sizeof dst); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else + if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4)) + { + ipv4_set = 1; + src_set = 1; + } + else + if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4)) + { + ipv4_set = 1; + dst_set = 1; + } + else + if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6)) + { + ipv6_set = 1; + src_set = 1; + } + else + if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6)) + { + ipv6_set = 1; + dst_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip4_address, &dst.ip4, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip4_address, &dst.ip4)) + { + grp_set = dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip6_address, &dst.ip6, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = dst_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip6_address, &dst.ip6)) + { + grp_set = dst_set = 1; + ipv6_set = 1; + } + else + if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index)) + ; + else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id)) + ; + else if (unformat (line_input, "decap-next %U", + unformat_vxlan_decap_next, &decap_next_index)) + ; + else if (unformat (line_input, "vni %d", &vni)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, line_input); + return -99; + } + } + + if (src_set == 0) + { + errmsg ("tunnel src address not specified"); + return -99; + } + if (dst_set == 0) + { + errmsg ("tunnel dst address not specified"); + return -99; + } + + if (grp_set && !ip46_address_is_multicast (&dst)) + { + errmsg ("tunnel group address not multicast"); + return -99; + } + if (grp_set && mcast_sw_if_index == ~0) + { + errmsg ("tunnel nonexistent multicast device"); + return -99; + } + if (grp_set == 0 && ip46_address_is_multicast (&dst)) + { + errmsg ("tunnel dst address must be unicast"); + return -99; + } + + + if (ipv4_set && ipv6_set) + { + errmsg ("both IPv4 and IPv6 addresses specified"); + return -99; + } + + if ((vni == 0) || (vni >> 24)) + { + errmsg ("vni not specified or out of range"); + return -99; + } + + M (VXLAN_ADD_DEL_TUNNEL, mp); + + if (ipv6_set) + { + clib_memcpy (mp->src_address, &src.ip6, sizeof (src.ip6)); + clib_memcpy (mp->dst_address, &dst.ip6, sizeof (dst.ip6)); + } + else + { + clib_memcpy (mp->src_address, &src.ip4, sizeof (src.ip4)); + clib_memcpy (mp->dst_address, &dst.ip4, sizeof (dst.ip4)); + } + mp->encap_vrf_id = ntohl (encap_vrf_id); + mp->decap_next_index = ntohl (decap_next_index); + mp->mcast_sw_if_index = ntohl (mcast_sw_if_index); + mp->vni = ntohl (vni); + mp->is_add = is_add; + mp->is_ipv6 = ipv6_set; + + S (mp); + W (ret); + return ret; +} + +static void vl_api_vxlan_tunnel_details_t_handler + (vl_api_vxlan_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + ip46_address_t src = to_ip46 (mp->is_ipv6, mp->dst_address); + ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->src_address); + + print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d", + ntohl (mp->sw_if_index), + format_ip46_address, &src, IP46_TYPE_ANY, + format_ip46_address, &dst, IP46_TYPE_ANY, + ntohl (mp->encap_vrf_id), + ntohl (mp->decap_next_index), ntohl (mp->vni), + ntohl (mp->mcast_sw_if_index)); +} + +static void vl_api_vxlan_tunnel_details_t_handler_json + (vl_api_vxlan_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + if (mp->is_ipv6) + { + struct in6_addr ip6; + + clib_memcpy (&ip6, mp->src_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "src_address", ip6); + clib_memcpy (&ip6, mp->dst_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "dst_address", ip6); + } + else + { + struct in_addr ip4; + + clib_memcpy (&ip4, mp->src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + clib_memcpy (&ip4, mp->dst_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "dst_address", ip4); + } + vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id)); + vat_json_object_add_uint (node, "decap_next_index", + ntohl (mp->decap_next_index)); + vat_json_object_add_uint (node, "vni", ntohl (mp->vni)); + vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0); + vat_json_object_add_uint (node, "mcast_sw_if_index", + ntohl (mp->mcast_sw_if_index)); +} + +static int +api_vxlan_tunnel_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_vxlan_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + sw_if_index = ~0; + } + + if (!vam->json_output) + { + print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s", + "sw_if_index", "src_address", "dst_address", + "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index"); + } + + /* Get list of vxlan-tunnel interfaces */ + M (VXLAN_TUNNEL_DUMP, mp); + + mp->sw_if_index = htonl (sw_if_index); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static uword unformat_geneve_decap_next + (unformat_input_t * input, va_list * args) +{ + u32 *result = va_arg (*args, u32 *); + u32 tmp; + + if (unformat (input, "l2")) + *result = GENEVE_INPUT_NEXT_L2_INPUT; + else if (unformat (input, "%d", &tmp)) + *result = tmp; + else + return 0; + return 1; +} + +static int +api_geneve_add_del_tunnel (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_geneve_add_del_tunnel_t *mp; + ip46_address_t src, dst; + u8 is_add = 1; + u8 ipv4_set = 0, ipv6_set = 0; + u8 src_set = 0; + u8 dst_set = 0; + u8 grp_set = 0; + u32 mcast_sw_if_index = ~0; + u32 encap_vrf_id = 0; + u32 decap_next_index = ~0; + u32 vni = 0; + int ret; + + /* Can't "universally zero init" (={0}) due to GCC bug 53119 */ + memset (&src, 0, sizeof src); + memset (&dst, 0, sizeof dst); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else + if (unformat (line_input, "src %U", unformat_ip4_address, &src.ip4)) + { + ipv4_set = 1; + src_set = 1; + } + else + if (unformat (line_input, "dst %U", unformat_ip4_address, &dst.ip4)) + { + ipv4_set = 1; + dst_set = 1; + } + else + if (unformat (line_input, "src %U", unformat_ip6_address, &src.ip6)) + { + ipv6_set = 1; + src_set = 1; + } + else + if (unformat (line_input, "dst %U", unformat_ip6_address, &dst.ip6)) + { + ipv6_set = 1; + dst_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip4_address, &dst.ip4, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip4_address, &dst.ip4)) + { + grp_set = dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip6_address, &dst.ip6, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = dst_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip6_address, &dst.ip6)) + { + grp_set = dst_set = 1; + ipv6_set = 1; + } + else + if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index)) + ; + else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id)) + ; + else if (unformat (line_input, "decap-next %U", + unformat_geneve_decap_next, &decap_next_index)) + ; + else if (unformat (line_input, "vni %d", &vni)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, line_input); + return -99; + } + } + + if (src_set == 0) + { + errmsg ("tunnel src address not specified"); + return -99; + } + if (dst_set == 0) + { + errmsg ("tunnel dst address not specified"); + return -99; + } + + if (grp_set && !ip46_address_is_multicast (&dst)) + { + errmsg ("tunnel group address not multicast"); + return -99; + } + if (grp_set && mcast_sw_if_index == ~0) + { + errmsg ("tunnel nonexistent multicast device"); + return -99; + } + if (grp_set == 0 && ip46_address_is_multicast (&dst)) + { + errmsg ("tunnel dst address must be unicast"); + return -99; + } + + + if (ipv4_set && ipv6_set) + { + errmsg ("both IPv4 and IPv6 addresses specified"); + return -99; + } + + if ((vni == 0) || (vni >> 24)) + { + errmsg ("vni not specified or out of range"); + return -99; + } + + M (GENEVE_ADD_DEL_TUNNEL, mp); + + if (ipv6_set) + { + clib_memcpy (mp->local_address, &src.ip6, sizeof (src.ip6)); + clib_memcpy (mp->remote_address, &dst.ip6, sizeof (dst.ip6)); + } + else + { + clib_memcpy (mp->local_address, &src.ip4, sizeof (src.ip4)); + clib_memcpy (mp->remote_address, &dst.ip4, sizeof (dst.ip4)); + } + mp->encap_vrf_id = ntohl (encap_vrf_id); + mp->decap_next_index = ntohl (decap_next_index); + mp->mcast_sw_if_index = ntohl (mcast_sw_if_index); + mp->vni = ntohl (vni); + mp->is_add = is_add; + mp->is_ipv6 = ipv6_set; + + S (mp); + W (ret); + return ret; +} + +static void vl_api_geneve_tunnel_details_t_handler + (vl_api_geneve_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + ip46_address_t src = to_ip46 (mp->is_ipv6, mp->dst_address); + ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->src_address); + + print (vam->ofp, "%11d%24U%24U%14d%18d%13d%19d", + ntohl (mp->sw_if_index), + format_ip46_address, &src, IP46_TYPE_ANY, + format_ip46_address, &dst, IP46_TYPE_ANY, + ntohl (mp->encap_vrf_id), + ntohl (mp->decap_next_index), ntohl (mp->vni), + ntohl (mp->mcast_sw_if_index)); +} + +static void vl_api_geneve_tunnel_details_t_handler_json + (vl_api_geneve_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + if (mp->is_ipv6) + { + struct in6_addr ip6; + + clib_memcpy (&ip6, mp->src_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "src_address", ip6); + clib_memcpy (&ip6, mp->dst_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "dst_address", ip6); + } + else + { + struct in_addr ip4; + + clib_memcpy (&ip4, mp->src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + clib_memcpy (&ip4, mp->dst_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "dst_address", ip4); + } + vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id)); + vat_json_object_add_uint (node, "decap_next_index", + ntohl (mp->decap_next_index)); + vat_json_object_add_uint (node, "vni", ntohl (mp->vni)); + vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0); + vat_json_object_add_uint (node, "mcast_sw_if_index", + ntohl (mp->mcast_sw_if_index)); +} + +static int +api_geneve_tunnel_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_geneve_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + sw_if_index = ~0; + } + + if (!vam->json_output) + { + print (vam->ofp, "%11s%24s%24s%14s%18s%13s%19s", + "sw_if_index", "local_address", "remote_address", + "encap_vrf_id", "decap_next_index", "vni", "mcast_sw_if_index"); + } + + /* Get list of geneve-tunnel interfaces */ + M (GENEVE_TUNNEL_DUMP, mp); + + mp->sw_if_index = htonl (sw_if_index); + + S (mp); + + /* Use a control ping for synchronization */ + M (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_gre_add_del_tunnel (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_gre_add_del_tunnel_t *mp; + ip4_address_t src4, dst4; + ip6_address_t src6, dst6; + u8 is_add = 1; + u8 ipv4_set = 0; + u8 ipv6_set = 0; + u8 teb = 0; + u8 src_set = 0; + u8 dst_set = 0; + u32 outer_fib_id = 0; + int ret; + + memset (&src4, 0, sizeof src4); + memset (&dst4, 0, sizeof dst4); + memset (&src6, 0, sizeof src6); + memset (&dst6, 0, sizeof dst6); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "src %U", unformat_ip4_address, &src4)) + { + src_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "dst %U", unformat_ip4_address, &dst4)) + { + dst_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "src %U", unformat_ip6_address, &src6)) + { + src_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "dst %U", unformat_ip6_address, &dst6)) + { + dst_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "outer-fib-id %d", &outer_fib_id)) + ; + else if (unformat (line_input, "teb")) + teb = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, line_input); + return -99; + } + } + + if (src_set == 0) + { + errmsg ("tunnel src address not specified"); + return -99; + } + if (dst_set == 0) + { + errmsg ("tunnel dst address not specified"); + return -99; + } + if (ipv4_set && ipv6_set) + { + errmsg ("both IPv4 and IPv6 addresses specified"); + return -99; + } + + + M (GRE_ADD_DEL_TUNNEL, mp); + + if (ipv4_set) + { + clib_memcpy (&mp->src_address, &src4, 4); + clib_memcpy (&mp->dst_address, &dst4, 4); + } + else + { + clib_memcpy (&mp->src_address, &src6, 16); + clib_memcpy (&mp->dst_address, &dst6, 16); + } + mp->outer_fib_id = ntohl (outer_fib_id); + mp->is_add = is_add; + mp->teb = teb; + mp->is_ipv6 = ipv6_set; + + S (mp); + W (ret); + return ret; +} + +static void vl_api_gre_tunnel_details_t_handler + (vl_api_gre_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + ip46_address_t src = to_ip46 (mp->is_ipv6, mp->src_address); + ip46_address_t dst = to_ip46 (mp->is_ipv6, mp->dst_address); + + print (vam->ofp, "%11d%24U%24U%6d%14d", + ntohl (mp->sw_if_index), + format_ip46_address, &src, IP46_TYPE_ANY, + format_ip46_address, &dst, IP46_TYPE_ANY, + mp->teb, ntohl (mp->outer_fib_id)); +} + +static void vl_api_gre_tunnel_details_t_handler_json + (vl_api_gre_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in_addr ip4; + struct in6_addr ip6; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + if (!mp->is_ipv6) + { + clib_memcpy (&ip4, &mp->src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "dst_address", ip4); + } + else + { + clib_memcpy (&ip6, &mp->src_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "src_address", ip6); + clib_memcpy (&ip6, &mp->dst_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "dst_address", ip6); + } + vat_json_object_add_uint (node, "teb", mp->teb); + vat_json_object_add_uint (node, "outer_fib_id", ntohl (mp->outer_fib_id)); + vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6); +} + +static int +api_gre_tunnel_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_gre_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + sw_if_index = ~0; + } + + if (!vam->json_output) + { + print (vam->ofp, "%11s%24s%24s%6s%14s", + "sw_if_index", "src_address", "dst_address", "teb", + "outer_fib_id"); + } + + /* Get list of gre-tunnel interfaces */ + M (GRE_TUNNEL_DUMP, mp); + + mp->sw_if_index = htonl (sw_if_index); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_l2_fib_clear_table (vat_main_t * vam) +{ +// unformat_input_t * i = vam->input; + vl_api_l2_fib_clear_table_t *mp; + int ret; + + M (L2_FIB_CLEAR_TABLE, mp); + + S (mp); + W (ret); + return ret; +} + +static int +api_l2_interface_efp_filter (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_interface_efp_filter_t *mp; + u32 sw_if_index; + u8 enable = 1; + u8 sw_if_index_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "enable")) + enable = 1; + else if (unformat (i, "disable")) + enable = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing sw_if_index"); + return -99; + } + + M (L2_INTERFACE_EFP_FILTER, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable; + + S (mp); + W (ret); + return ret; +} + +#define foreach_vtr_op \ +_("disable", L2_VTR_DISABLED) \ +_("push-1", L2_VTR_PUSH_1) \ +_("push-2", L2_VTR_PUSH_2) \ +_("pop-1", L2_VTR_POP_1) \ +_("pop-2", L2_VTR_POP_2) \ +_("translate-1-1", L2_VTR_TRANSLATE_1_1) \ +_("translate-1-2", L2_VTR_TRANSLATE_1_2) \ +_("translate-2-1", L2_VTR_TRANSLATE_2_1) \ +_("translate-2-2", L2_VTR_TRANSLATE_2_2) + +static int +api_l2_interface_vlan_tag_rewrite (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_interface_vlan_tag_rewrite_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u8 vtr_op_set = 0; + u32 vtr_op = 0; + u32 push_dot1q = 1; + u32 tag1 = ~0; + u32 tag2 = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "vtr_op %d", &vtr_op)) + vtr_op_set = 1; +#define _(n,v) else if (unformat(i, n)) {vtr_op = v; vtr_op_set = 1;} + foreach_vtr_op +#undef _ + else if (unformat (i, "push_dot1q %d", &push_dot1q)) + ; + else if (unformat (i, "tag1 %d", &tag1)) + ; + else if (unformat (i, "tag2 %d", &tag2)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if ((sw_if_index_set == 0) || (vtr_op_set == 0)) + { + errmsg ("missing vtr operation or sw_if_index"); + return -99; + } + + M (L2_INTERFACE_VLAN_TAG_REWRITE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->vtr_op = ntohl (vtr_op); + mp->push_dot1q = ntohl (push_dot1q); + mp->tag1 = ntohl (tag1); + mp->tag2 = ntohl (tag2); + + S (mp); + W (ret); + return ret; +} + +static int +api_create_vhost_user_if (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_create_vhost_user_if_t *mp; + u8 *file_name; + u8 is_server = 0; + u8 file_name_set = 0; + u32 custom_dev_instance = ~0; + u8 hwaddr[6]; + u8 use_custom_mac = 0; + u8 *tag = 0; + int ret; + + /* Shut up coverity */ + memset (hwaddr, 0, sizeof (hwaddr)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "socket %s", &file_name)) + { + file_name_set = 1; + } + else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance)) + ; + else if (unformat (i, "mac %U", unformat_ethernet_address, hwaddr)) + use_custom_mac = 1; + else if (unformat (i, "server")) + is_server = 1; + else if (unformat (i, "tag %s", &tag)) + ; + else + break; + } + + if (file_name_set == 0) + { + errmsg ("missing socket file name"); + return -99; + } + + if (vec_len (file_name) > 255) + { + errmsg ("socket file name too long"); + return -99; + } + vec_add1 (file_name, 0); + + M (CREATE_VHOST_USER_IF, mp); + + mp->is_server = is_server; + clib_memcpy (mp->sock_filename, file_name, vec_len (file_name)); + vec_free (file_name); + if (custom_dev_instance != ~0) + { + mp->renumber = 1; + mp->custom_dev_instance = ntohl (custom_dev_instance); + } + mp->use_custom_mac = use_custom_mac; + clib_memcpy (mp->mac_address, hwaddr, 6); + if (tag) + strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); + vec_free (tag); + + S (mp); + W (ret); + return ret; +} + +static int +api_modify_vhost_user_if (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_modify_vhost_user_if_t *mp; + u8 *file_name; + u8 is_server = 0; + u8 file_name_set = 0; + u32 custom_dev_instance = ~0; + u8 sw_if_index_set = 0; + u32 sw_if_index = (u32) ~ 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "socket %s", &file_name)) + { + file_name_set = 1; + } + else if (unformat (i, "renumber %" PRIu32, &custom_dev_instance)) + ; + else if (unformat (i, "server")) + is_server = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing sw_if_index or interface name"); + return -99; + } + + if (file_name_set == 0) + { + errmsg ("missing socket file name"); + return -99; + } + + if (vec_len (file_name) > 255) + { + errmsg ("socket file name too long"); + return -99; + } + vec_add1 (file_name, 0); + + M (MODIFY_VHOST_USER_IF, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_server = is_server; + clib_memcpy (mp->sock_filename, file_name, vec_len (file_name)); + vec_free (file_name); + if (custom_dev_instance != ~0) + { + mp->renumber = 1; + mp->custom_dev_instance = ntohl (custom_dev_instance); + } + + S (mp); + W (ret); + return ret; +} + +static int +api_delete_vhost_user_if (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_delete_vhost_user_if_t *mp; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing sw_if_index or interface name"); + return -99; + } + + + M (DELETE_VHOST_USER_IF, mp); + + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +static void vl_api_sw_interface_vhost_user_details_t_handler + (vl_api_sw_interface_vhost_user_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%-25s %3" PRIu32 " %6" PRIu32 " %8x %6d %7d %s", + (char *) mp->interface_name, + ntohl (mp->sw_if_index), ntohl (mp->virtio_net_hdr_sz), + clib_net_to_host_u64 (mp->features), mp->is_server, + ntohl (mp->num_regions), (char *) mp->sock_filename); + print (vam->ofp, " Status: '%s'", strerror (ntohl (mp->sock_errno))); +} + +static void vl_api_sw_interface_vhost_user_details_t_handler_json + (vl_api_sw_interface_vhost_user_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_string_copy (node, "interface_name", + mp->interface_name); + vat_json_object_add_uint (node, "virtio_net_hdr_sz", + ntohl (mp->virtio_net_hdr_sz)); + vat_json_object_add_uint (node, "features", + clib_net_to_host_u64 (mp->features)); + vat_json_object_add_uint (node, "is_server", mp->is_server); + vat_json_object_add_string_copy (node, "sock_filename", mp->sock_filename); + vat_json_object_add_uint (node, "num_regions", ntohl (mp->num_regions)); + vat_json_object_add_uint (node, "sock_errno", ntohl (mp->sock_errno)); +} + +static int +api_sw_interface_vhost_user_dump (vat_main_t * vam) +{ + vl_api_sw_interface_vhost_user_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + print (vam->ofp, + "Interface name idx hdr_sz features server regions filename"); + + /* Get list of vhost-user interfaces */ + M (SW_INTERFACE_VHOST_USER_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_show_version (vat_main_t * vam) +{ + vl_api_show_version_t *mp; + int ret; + + M (SHOW_VERSION, mp); + + S (mp); + W (ret); + return ret; +} + + +static int +api_vxlan_gpe_add_del_tunnel (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_vxlan_gpe_add_del_tunnel_t *mp; + ip4_address_t local4, remote4; + ip6_address_t local6, remote6; + u8 is_add = 1; + u8 ipv4_set = 0, ipv6_set = 0; + u8 local_set = 0; + u8 remote_set = 0; + u8 grp_set = 0; + u32 mcast_sw_if_index = ~0; + u32 encap_vrf_id = 0; + u32 decap_vrf_id = 0; + u8 protocol = ~0; + u32 vni; + u8 vni_set = 0; + int ret; + + /* Can't "universally zero init" (={0}) due to GCC bug 53119 */ + memset (&local4, 0, sizeof local4); + memset (&remote4, 0, sizeof remote4); + memset (&local6, 0, sizeof local6); + memset (&remote6, 0, sizeof remote6); + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "local %U", + unformat_ip4_address, &local4)) + { + local_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "remote %U", + unformat_ip4_address, &remote4)) + { + remote_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "local %U", + unformat_ip6_address, &local6)) + { + local_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "remote %U", + unformat_ip6_address, &remote6)) + { + remote_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip4_address, &remote4, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = remote_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip4_address, &remote4)) + { + grp_set = remote_set = 1; + ipv4_set = 1; + } + else if (unformat (line_input, "group %U %U", + unformat_ip6_address, &remote6, + api_unformat_sw_if_index, vam, &mcast_sw_if_index)) + { + grp_set = remote_set = 1; + ipv6_set = 1; + } + else if (unformat (line_input, "group %U", + unformat_ip6_address, &remote6)) + { + grp_set = remote_set = 1; + ipv6_set = 1; + } + else + if (unformat (line_input, "mcast_sw_if_index %u", &mcast_sw_if_index)) + ; + else if (unformat (line_input, "encap-vrf-id %d", &encap_vrf_id)) + ; + else if (unformat (line_input, "decap-vrf-id %d", &decap_vrf_id)) + ; + else if (unformat (line_input, "vni %d", &vni)) + vni_set = 1; + else if (unformat (line_input, "next-ip4")) + protocol = 1; + else if (unformat (line_input, "next-ip6")) + protocol = 2; + else if (unformat (line_input, "next-ethernet")) + protocol = 3; + else if (unformat (line_input, "next-nsh")) + protocol = 4; + else + { + errmsg ("parse error '%U'", format_unformat_error, line_input); + return -99; + } + } + + if (local_set == 0) + { + errmsg ("tunnel local address not specified"); + return -99; + } + if (remote_set == 0) + { + errmsg ("tunnel remote address not specified"); + return -99; + } + if (grp_set && mcast_sw_if_index == ~0) + { + errmsg ("tunnel nonexistent multicast device"); + return -99; + } + if (ipv4_set && ipv6_set) + { + errmsg ("both IPv4 and IPv6 addresses specified"); + return -99; + } + + if (vni_set == 0) + { + errmsg ("vni not specified"); + return -99; + } + + M (VXLAN_GPE_ADD_DEL_TUNNEL, mp); + + + if (ipv6_set) + { + clib_memcpy (&mp->local, &local6, sizeof (local6)); + clib_memcpy (&mp->remote, &remote6, sizeof (remote6)); + } + else + { + clib_memcpy (&mp->local, &local4, sizeof (local4)); + clib_memcpy (&mp->remote, &remote4, sizeof (remote4)); + } + + mp->mcast_sw_if_index = ntohl (mcast_sw_if_index); + mp->encap_vrf_id = ntohl (encap_vrf_id); + mp->decap_vrf_id = ntohl (decap_vrf_id); + mp->protocol = protocol; + mp->vni = ntohl (vni); + mp->is_add = is_add; + mp->is_ipv6 = ipv6_set; + + S (mp); + W (ret); + return ret; +} + +static void vl_api_vxlan_gpe_tunnel_details_t_handler + (vl_api_vxlan_gpe_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + ip46_address_t local = to_ip46 (mp->is_ipv6, mp->local); + ip46_address_t remote = to_ip46 (mp->is_ipv6, mp->remote); + + print (vam->ofp, "%11d%24U%24U%13d%12d%19d%14d%14d", + ntohl (mp->sw_if_index), + format_ip46_address, &local, IP46_TYPE_ANY, + format_ip46_address, &remote, IP46_TYPE_ANY, + ntohl (mp->vni), mp->protocol, + ntohl (mp->mcast_sw_if_index), + ntohl (mp->encap_vrf_id), ntohl (mp->decap_vrf_id)); +} + + +static void vl_api_vxlan_gpe_tunnel_details_t_handler_json + (vl_api_vxlan_gpe_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in_addr ip4; + struct in6_addr ip6; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + if (mp->is_ipv6) + { + clib_memcpy (&ip6, &(mp->local[0]), sizeof (ip6)); + vat_json_object_add_ip6 (node, "local", ip6); + clib_memcpy (&ip6, &(mp->remote[0]), sizeof (ip6)); + vat_json_object_add_ip6 (node, "remote", ip6); + } + else + { + clib_memcpy (&ip4, &(mp->local[0]), sizeof (ip4)); + vat_json_object_add_ip4 (node, "local", ip4); + clib_memcpy (&ip4, &(mp->remote[0]), sizeof (ip4)); + vat_json_object_add_ip4 (node, "remote", ip4); + } + vat_json_object_add_uint (node, "vni", ntohl (mp->vni)); + vat_json_object_add_uint (node, "protocol", ntohl (mp->protocol)); + vat_json_object_add_uint (node, "mcast_sw_if_index", + ntohl (mp->mcast_sw_if_index)); + vat_json_object_add_uint (node, "encap_vrf_id", ntohl (mp->encap_vrf_id)); + vat_json_object_add_uint (node, "decap_vrf_id", ntohl (mp->decap_vrf_id)); + vat_json_object_add_uint (node, "is_ipv6", mp->is_ipv6 ? 1 : 0); +} + +static int +api_vxlan_gpe_tunnel_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_vxlan_gpe_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + sw_if_index = ~0; + } + + if (!vam->json_output) + { + print (vam->ofp, "%11s%24s%24s%13s%15s%19s%14s%14s", + "sw_if_index", "local", "remote", "vni", + "protocol", "mcast_sw_if_index", "encap_vrf_id", "decap_vrf_id"); + } + + /* Get list of vxlan-tunnel interfaces */ + M (VXLAN_GPE_TUNNEL_DUMP, mp); + + mp->sw_if_index = htonl (sw_if_index); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void vl_api_l2_fib_table_details_t_handler + (vl_api_l2_fib_table_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%3" PRIu32 " %U %3" PRIu32 + " %d %d %d", + ntohl (mp->bd_id), format_ethernet_address, mp->mac, + ntohl (mp->sw_if_index), mp->static_mac, mp->filter_mac, + mp->bvi_mac); +} + +static void vl_api_l2_fib_table_details_t_handler_json + (vl_api_l2_fib_table_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "bd_id", ntohl (mp->bd_id)); + vat_json_object_add_bytes (node, "mac", mp->mac, 6); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_uint (node, "static_mac", mp->static_mac); + vat_json_object_add_uint (node, "filter_mac", mp->filter_mac); + vat_json_object_add_uint (node, "bvi_mac", mp->bvi_mac); +} + +static int +api_l2_fib_table_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_fib_table_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 bd_id; + u8 bd_id_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "bd_id %d", &bd_id)) + bd_id_set = 1; + else + break; + } + + if (bd_id_set == 0) + { + errmsg ("missing bridge domain"); + return -99; + } + + print (vam->ofp, "BD-ID Mac Address sw-ndx Static Filter BVI"); + + /* Get list of l2 fib entries */ + M (L2_FIB_TABLE_DUMP, mp); + + mp->bd_id = ntohl (bd_id); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + + +static int +api_interface_name_renumber (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_interface_name_renumber_t *mp; + u32 sw_if_index = ~0; + u32 new_show_dev_instance = ~0; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", api_unformat_sw_if_index, vam, + &sw_if_index)) + ; + else if (unformat (line_input, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (line_input, "new_show_dev_instance %d", + &new_show_dev_instance)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (new_show_dev_instance == ~0) + { + errmsg ("missing new_show_dev_instance"); + return -99; + } + + M (INTERFACE_NAME_RENUMBER, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->new_show_dev_instance = ntohl (new_show_dev_instance); + + S (mp); + W (ret); + return ret; +} + +static int +api_want_ip4_arp_events (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_want_ip4_arp_events_t *mp; + ip4_address_t address; + int address_set = 0; + u32 enable_disable = 1; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "address %U", unformat_ip4_address, &address)) + address_set = 1; + else if (unformat (line_input, "del")) + enable_disable = 0; + else + break; + } + + if (address_set == 0) + { + errmsg ("missing addresses"); + return -99; + } + + M (WANT_IP4_ARP_EVENTS, mp); + mp->enable_disable = enable_disable; + mp->pid = htonl (getpid ()); + mp->address = address.as_u32; + + S (mp); + W (ret); + return ret; +} + +static int +api_want_ip6_nd_events (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_want_ip6_nd_events_t *mp; + ip6_address_t address; + int address_set = 0; + u32 enable_disable = 1; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "address %U", unformat_ip6_address, &address)) + address_set = 1; + else if (unformat (line_input, "del")) + enable_disable = 0; + else + break; + } + + if (address_set == 0) + { + errmsg ("missing addresses"); + return -99; + } + + M (WANT_IP6_ND_EVENTS, mp); + mp->enable_disable = enable_disable; + mp->pid = htonl (getpid ()); + clib_memcpy (mp->address, &address, sizeof (ip6_address_t)); + + S (mp); + W (ret); + return ret; +} + +static int +api_want_l2_macs_events (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_want_l2_macs_events_t *mp; + u8 enable_disable = 1; + u32 scan_delay = 0; + u32 max_macs_in_event = 0; + u32 learn_limit = 0; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "learn-limit %d", &learn_limit)) + ; + else if (unformat (line_input, "scan-delay %d", &scan_delay)) + ; + else if (unformat (line_input, "max-entries %d", &max_macs_in_event)) + ; + else if (unformat (line_input, "disable")) + enable_disable = 0; + else + break; + } + + M (WANT_L2_MACS_EVENTS, mp); + mp->enable_disable = enable_disable; + mp->pid = htonl (getpid ()); + mp->learn_limit = htonl (learn_limit); + mp->scan_delay = (u8) scan_delay; + mp->max_macs_in_event = (u8) (max_macs_in_event / 10); + S (mp); + W (ret); + return ret; +} + +static int +api_input_acl_set_interface (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_input_acl_set_interface_t *mp; + u32 sw_if_index; + int sw_if_index_set; + u32 ip4_table_index = ~0; + u32 ip6_table_index = ~0; + u32 l2_table_index = ~0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "ip4-table %d", &ip4_table_index)) + ; + else if (unformat (i, "ip6-table %d", &ip6_table_index)) + ; + else if (unformat (i, "l2-table %d", &l2_table_index)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (INPUT_ACL_SET_INTERFACE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->ip4_table_index = ntohl (ip4_table_index); + mp->ip6_table_index = ntohl (ip6_table_index); + mp->l2_table_index = ntohl (l2_table_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_ip_address_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_address_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + u8 ipv4_set = 0; + u8 ipv6_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "ipv4")) + ipv4_set = 1; + else if (unformat (i, "ipv6")) + ipv6_set = 1; + else + break; + } + + if (ipv4_set && ipv6_set) + { + errmsg ("ipv4 and ipv6 flags cannot be both set"); + return -99; + } + + if ((!ipv4_set) && (!ipv6_set)) + { + errmsg ("no ipv4 nor ipv6 flag set"); + return -99; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + vam->current_sw_if_index = sw_if_index; + vam->is_ipv6 = ipv6_set; + + M (IP_ADDRESS_DUMP, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->is_ipv6 = ipv6_set; + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_ip_dump (vat_main_t * vam) +{ + vl_api_ip_dump_t *mp; + vl_api_control_ping_t *mp_ping; + unformat_input_t *in = vam->input; + int ipv4_set = 0; + int ipv6_set = 0; + int is_ipv6; + int i; + int ret; + + while (unformat_check_input (in) != UNFORMAT_END_OF_INPUT) + { + if (unformat (in, "ipv4")) + ipv4_set = 1; + else if (unformat (in, "ipv6")) + ipv6_set = 1; + else + break; + } + + if (ipv4_set && ipv6_set) + { + errmsg ("ipv4 and ipv6 flags cannot be both set"); + return -99; + } + + if ((!ipv4_set) && (!ipv6_set)) + { + errmsg ("no ipv4 nor ipv6 flag set"); + return -99; + } + + is_ipv6 = ipv6_set; + vam->is_ipv6 = is_ipv6; + + /* free old data */ + for (i = 0; i < vec_len (vam->ip_details_by_sw_if_index[is_ipv6]); i++) + { + vec_free (vam->ip_details_by_sw_if_index[is_ipv6][i].addr); + } + vec_free (vam->ip_details_by_sw_if_index[is_ipv6]); + + M (IP_DUMP, mp); + mp->is_ipv6 = ipv6_set; + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_ipsec_spd_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_spd_add_del_t *mp; + u32 spd_id = ~0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "spd_id %d", &spd_id)) + ; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + if (spd_id == ~0) + { + errmsg ("spd_id must be set"); + return -99; + } + + M (IPSEC_SPD_ADD_DEL, mp); + + mp->spd_id = ntohl (spd_id); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_ipsec_interface_add_del_spd (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_interface_add_del_spd_t *mp; + u32 sw_if_index; + u8 sw_if_index_set = 0; + u32 spd_id = (u32) ~ 0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "spd_id %d", &spd_id)) + ; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + + } + + if (spd_id == (u32) ~ 0) + { + errmsg ("spd_id must be set"); + return -99; + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (IPSEC_INTERFACE_ADD_DEL_SPD, mp); + + mp->spd_id = ntohl (spd_id); + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_ipsec_spd_add_del_entry (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_spd_add_del_entry_t *mp; + u8 is_add = 1, is_outbound = 0, is_ipv6 = 0, is_ip_any = 1; + u32 spd_id = 0, sa_id = 0, protocol = 0, policy = 0; + i32 priority = 0; + u32 rport_start = 0, rport_stop = (u32) ~ 0; + u32 lport_start = 0, lport_stop = (u32) ~ 0; + ip4_address_t laddr4_start, laddr4_stop, raddr4_start, raddr4_stop; + ip6_address_t laddr6_start, laddr6_stop, raddr6_start, raddr6_stop; + int ret; + + laddr4_start.as_u32 = raddr4_start.as_u32 = 0; + laddr4_stop.as_u32 = raddr4_stop.as_u32 = (u32) ~ 0; + laddr6_start.as_u64[0] = raddr6_start.as_u64[0] = 0; + laddr6_start.as_u64[1] = raddr6_start.as_u64[1] = 0; + laddr6_stop.as_u64[0] = raddr6_stop.as_u64[0] = (u64) ~ 0; + laddr6_stop.as_u64[1] = raddr6_stop.as_u64[1] = (u64) ~ 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + if (unformat (i, "outbound")) + is_outbound = 1; + if (unformat (i, "inbound")) + is_outbound = 0; + else if (unformat (i, "spd_id %d", &spd_id)) + ; + else if (unformat (i, "sa_id %d", &sa_id)) + ; + else if (unformat (i, "priority %d", &priority)) + ; + else if (unformat (i, "protocol %d", &protocol)) + ; + else if (unformat (i, "lport_start %d", &lport_start)) + ; + else if (unformat (i, "lport_stop %d", &lport_stop)) + ; + else if (unformat (i, "rport_start %d", &rport_start)) + ; + else if (unformat (i, "rport_stop %d", &rport_stop)) + ; + else + if (unformat + (i, "laddr_start %U", unformat_ip4_address, &laddr4_start)) + { + is_ipv6 = 0; + is_ip_any = 0; + } + else + if (unformat (i, "laddr_stop %U", unformat_ip4_address, &laddr4_stop)) + { + is_ipv6 = 0; + is_ip_any = 0; + } + else + if (unformat + (i, "raddr_start %U", unformat_ip4_address, &raddr4_start)) + { + is_ipv6 = 0; + is_ip_any = 0; + } + else + if (unformat (i, "raddr_stop %U", unformat_ip4_address, &raddr4_stop)) + { + is_ipv6 = 0; + is_ip_any = 0; + } + else + if (unformat + (i, "laddr_start %U", unformat_ip6_address, &laddr6_start)) + { + is_ipv6 = 1; + is_ip_any = 0; + } + else + if (unformat (i, "laddr_stop %U", unformat_ip6_address, &laddr6_stop)) + { + is_ipv6 = 1; + is_ip_any = 0; + } + else + if (unformat + (i, "raddr_start %U", unformat_ip6_address, &raddr6_start)) + { + is_ipv6 = 1; + is_ip_any = 0; + } + else + if (unformat (i, "raddr_stop %U", unformat_ip6_address, &raddr6_stop)) + { + is_ipv6 = 1; + is_ip_any = 0; + } + else + if (unformat (i, "action %U", unformat_ipsec_policy_action, &policy)) + { + if (policy == IPSEC_POLICY_ACTION_RESOLVE) + { + clib_warning ("unsupported action: 'resolve'"); + return -99; + } + } + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + + } + + M (IPSEC_SPD_ADD_DEL_ENTRY, mp); + + mp->spd_id = ntohl (spd_id); + mp->priority = ntohl (priority); + mp->is_outbound = is_outbound; + + mp->is_ipv6 = is_ipv6; + if (is_ipv6 || is_ip_any) + { + clib_memcpy (mp->remote_address_start, &raddr6_start, + sizeof (ip6_address_t)); + clib_memcpy (mp->remote_address_stop, &raddr6_stop, + sizeof (ip6_address_t)); + clib_memcpy (mp->local_address_start, &laddr6_start, + sizeof (ip6_address_t)); + clib_memcpy (mp->local_address_stop, &laddr6_stop, + sizeof (ip6_address_t)); + } + else + { + clib_memcpy (mp->remote_address_start, &raddr4_start, + sizeof (ip4_address_t)); + clib_memcpy (mp->remote_address_stop, &raddr4_stop, + sizeof (ip4_address_t)); + clib_memcpy (mp->local_address_start, &laddr4_start, + sizeof (ip4_address_t)); + clib_memcpy (mp->local_address_stop, &laddr4_stop, + sizeof (ip4_address_t)); + } + mp->protocol = (u8) protocol; + mp->local_port_start = ntohs ((u16) lport_start); + mp->local_port_stop = ntohs ((u16) lport_stop); + mp->remote_port_start = ntohs ((u16) rport_start); + mp->remote_port_stop = ntohs ((u16) rport_stop); + mp->policy = (u8) policy; + mp->sa_id = ntohl (sa_id); + mp->is_add = is_add; + mp->is_ip_any = is_ip_any; + S (mp); + W (ret); + return ret; +} + +static int +api_ipsec_sad_add_del_entry (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_sad_add_del_entry_t *mp; + u32 sad_id = 0, spi = 0; + u8 *ck = 0, *ik = 0; + u8 is_add = 1; + + u8 protocol = IPSEC_PROTOCOL_AH; + u8 is_tunnel = 0, is_tunnel_ipv6 = 0; + u32 crypto_alg = 0, integ_alg = 0; + ip4_address_t tun_src4; + ip4_address_t tun_dst4; + ip6_address_t tun_src6; + ip6_address_t tun_dst6; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "sad_id %d", &sad_id)) + ; + else if (unformat (i, "spi %d", &spi)) + ; + else if (unformat (i, "esp")) + protocol = IPSEC_PROTOCOL_ESP; + else if (unformat (i, "tunnel_src %U", unformat_ip4_address, &tun_src4)) + { + is_tunnel = 1; + is_tunnel_ipv6 = 0; + } + else if (unformat (i, "tunnel_dst %U", unformat_ip4_address, &tun_dst4)) + { + is_tunnel = 1; + is_tunnel_ipv6 = 0; + } + else if (unformat (i, "tunnel_src %U", unformat_ip6_address, &tun_src6)) + { + is_tunnel = 1; + is_tunnel_ipv6 = 1; + } + else if (unformat (i, "tunnel_dst %U", unformat_ip6_address, &tun_dst6)) + { + is_tunnel = 1; + is_tunnel_ipv6 = 1; + } + else + if (unformat + (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) + { + if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 || + crypto_alg >= IPSEC_CRYPTO_N_ALG) + { + clib_warning ("unsupported crypto-alg: '%U'", + format_ipsec_crypto_alg, crypto_alg); + return -99; + } + } + else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck)) + ; + else + if (unformat + (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) + { + if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 || + integ_alg >= IPSEC_INTEG_N_ALG) + { + clib_warning ("unsupported integ-alg: '%U'", + format_ipsec_integ_alg, integ_alg); + return -99; + } + } + else if (unformat (i, "integ_key %U", unformat_hex_string, &ik)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + + } + + M (IPSEC_SAD_ADD_DEL_ENTRY, mp); + + mp->sad_id = ntohl (sad_id); + mp->is_add = is_add; + mp->protocol = protocol; + mp->spi = ntohl (spi); + mp->is_tunnel = is_tunnel; + mp->is_tunnel_ipv6 = is_tunnel_ipv6; + mp->crypto_algorithm = crypto_alg; + mp->integrity_algorithm = integ_alg; + mp->crypto_key_length = vec_len (ck); + mp->integrity_key_length = vec_len (ik); + + if (mp->crypto_key_length > sizeof (mp->crypto_key)) + mp->crypto_key_length = sizeof (mp->crypto_key); + + if (mp->integrity_key_length > sizeof (mp->integrity_key)) + mp->integrity_key_length = sizeof (mp->integrity_key); + + if (ck) + clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length); + if (ik) + clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length); + + if (is_tunnel) + { + if (is_tunnel_ipv6) + { + clib_memcpy (mp->tunnel_src_address, &tun_src6, + sizeof (ip6_address_t)); + clib_memcpy (mp->tunnel_dst_address, &tun_dst6, + sizeof (ip6_address_t)); + } + else + { + clib_memcpy (mp->tunnel_src_address, &tun_src4, + sizeof (ip4_address_t)); + clib_memcpy (mp->tunnel_dst_address, &tun_dst4, + sizeof (ip4_address_t)); + } + } + + S (mp); + W (ret); + return ret; +} + +static int +api_ipsec_sa_set_key (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_sa_set_key_t *mp; + u32 sa_id; + u8 *ck = 0, *ik = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sa_id %d", &sa_id)) + ; + else if (unformat (i, "crypto_key %U", unformat_hex_string, &ck)) + ; + else if (unformat (i, "integ_key %U", unformat_hex_string, &ik)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IPSEC_SA_SET_KEY, mp); + + mp->sa_id = ntohl (sa_id); + mp->crypto_key_length = vec_len (ck); + mp->integrity_key_length = vec_len (ik); + + if (mp->crypto_key_length > sizeof (mp->crypto_key)) + mp->crypto_key_length = sizeof (mp->crypto_key); + + if (mp->integrity_key_length > sizeof (mp->integrity_key)) + mp->integrity_key_length = sizeof (mp->integrity_key); + + if (ck) + clib_memcpy (mp->crypto_key, ck, mp->crypto_key_length); + if (ik) + clib_memcpy (mp->integrity_key, ik, mp->integrity_key_length); + + S (mp); + W (ret); + return ret; +} + +static int +api_ipsec_tunnel_if_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_tunnel_if_add_del_t *mp; + u32 local_spi = 0, remote_spi = 0; + u32 crypto_alg = 0, integ_alg = 0; + u8 *lck = NULL, *rck = NULL; + u8 *lik = NULL, *rik = NULL; + ip4_address_t local_ip = { {0} }; + ip4_address_t remote_ip = { {0} }; + u8 is_add = 1; + u8 esn = 0; + u8 anti_replay = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "esn")) + esn = 1; + else if (unformat (i, "anti_replay")) + anti_replay = 1; + else if (unformat (i, "local_spi %d", &local_spi)) + ; + else if (unformat (i, "remote_spi %d", &remote_spi)) + ; + else if (unformat (i, "local_ip %U", unformat_ip4_address, &local_ip)) + ; + else if (unformat (i, "remote_ip %U", unformat_ip4_address, &remote_ip)) + ; + else if (unformat (i, "local_crypto_key %U", unformat_hex_string, &lck)) + ; + else + if (unformat (i, "remote_crypto_key %U", unformat_hex_string, &rck)) + ; + else if (unformat (i, "local_integ_key %U", unformat_hex_string, &lik)) + ; + else if (unformat (i, "remote_integ_key %U", unformat_hex_string, &rik)) + ; + else + if (unformat + (i, "crypto_alg %U", unformat_ipsec_crypto_alg, &crypto_alg)) + { + if (crypto_alg < IPSEC_CRYPTO_ALG_AES_CBC_128 || + crypto_alg >= IPSEC_CRYPTO_N_ALG) + { + errmsg ("unsupported crypto-alg: '%U'\n", + format_ipsec_crypto_alg, crypto_alg); + return -99; + } + } + else + if (unformat + (i, "integ_alg %U", unformat_ipsec_integ_alg, &integ_alg)) + { + if (integ_alg < IPSEC_INTEG_ALG_SHA1_96 || + integ_alg >= IPSEC_INTEG_N_ALG) + { + errmsg ("unsupported integ-alg: '%U'\n", + format_ipsec_integ_alg, integ_alg); + return -99; + } + } + else + { + errmsg ("parse error '%U'\n", format_unformat_error, i); + return -99; + } + } + + M (IPSEC_TUNNEL_IF_ADD_DEL, mp); + + mp->is_add = is_add; + mp->esn = esn; + mp->anti_replay = anti_replay; + + clib_memcpy (mp->local_ip, &local_ip, sizeof (ip4_address_t)); + clib_memcpy (mp->remote_ip, &remote_ip, sizeof (ip4_address_t)); + + mp->local_spi = htonl (local_spi); + mp->remote_spi = htonl (remote_spi); + mp->crypto_alg = (u8) crypto_alg; + + mp->local_crypto_key_len = 0; + if (lck) + { + mp->local_crypto_key_len = vec_len (lck); + if (mp->local_crypto_key_len > sizeof (mp->local_crypto_key)) + mp->local_crypto_key_len = sizeof (mp->local_crypto_key); + clib_memcpy (mp->local_crypto_key, lck, mp->local_crypto_key_len); + } + + mp->remote_crypto_key_len = 0; + if (rck) + { + mp->remote_crypto_key_len = vec_len (rck); + if (mp->remote_crypto_key_len > sizeof (mp->remote_crypto_key)) + mp->remote_crypto_key_len = sizeof (mp->remote_crypto_key); + clib_memcpy (mp->remote_crypto_key, rck, mp->remote_crypto_key_len); + } + + mp->integ_alg = (u8) integ_alg; + + mp->local_integ_key_len = 0; + if (lik) + { + mp->local_integ_key_len = vec_len (lik); + if (mp->local_integ_key_len > sizeof (mp->local_integ_key)) + mp->local_integ_key_len = sizeof (mp->local_integ_key); + clib_memcpy (mp->local_integ_key, lik, mp->local_integ_key_len); + } + + mp->remote_integ_key_len = 0; + if (rik) + { + mp->remote_integ_key_len = vec_len (rik); + if (mp->remote_integ_key_len > sizeof (mp->remote_integ_key)) + mp->remote_integ_key_len = sizeof (mp->remote_integ_key); + clib_memcpy (mp->remote_integ_key, rik, mp->remote_integ_key_len); + } + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_ipsec_sa_details_t_handler (vl_api_ipsec_sa_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "sa_id %u sw_if_index %u spi %u proto %u crypto_alg %u " + "crypto_key %U integ_alg %u integ_key %U use_esn %u " + "use_anti_replay %u is_tunnel %u is_tunnel_ip6 %u " + "tunnel_src_addr %U tunnel_dst_addr %U " + "salt %u seq_outbound %lu last_seq_inbound %lu " + "replay_window %lu total_data_size %lu\n", + ntohl (mp->sa_id), ntohl (mp->sw_if_index), ntohl (mp->spi), + mp->protocol, + mp->crypto_alg, format_hex_bytes, mp->crypto_key, mp->crypto_key_len, + mp->integ_alg, format_hex_bytes, mp->integ_key, mp->integ_key_len, + mp->use_esn, mp->use_anti_replay, mp->is_tunnel, mp->is_tunnel_ip6, + (mp->is_tunnel_ip6) ? format_ip6_address : format_ip4_address, + mp->tunnel_src_addr, + (mp->is_tunnel_ip6) ? format_ip6_address : format_ip4_address, + mp->tunnel_dst_addr, + ntohl (mp->salt), + clib_net_to_host_u64 (mp->seq_outbound), + clib_net_to_host_u64 (mp->last_seq_inbound), + clib_net_to_host_u64 (mp->replay_window), + clib_net_to_host_u64 (mp->total_data_size)); +} + +#define vl_api_ipsec_sa_details_t_endian vl_noop_handler +#define vl_api_ipsec_sa_details_t_print vl_noop_handler + +static void vl_api_ipsec_sa_details_t_handler_json + (vl_api_ipsec_sa_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in_addr src_ip4, dst_ip4; + struct in6_addr src_ip6, dst_ip6; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sa_id", ntohl (mp->sa_id)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + vat_json_object_add_uint (node, "spi", ntohl (mp->spi)); + vat_json_object_add_uint (node, "proto", mp->protocol); + vat_json_object_add_uint (node, "crypto_alg", mp->crypto_alg); + vat_json_object_add_uint (node, "integ_alg", mp->integ_alg); + vat_json_object_add_uint (node, "use_esn", mp->use_esn); + vat_json_object_add_uint (node, "use_anti_replay", mp->use_anti_replay); + vat_json_object_add_uint (node, "is_tunnel", mp->is_tunnel); + vat_json_object_add_uint (node, "is_tunnel_ip6", mp->is_tunnel_ip6); + vat_json_object_add_bytes (node, "crypto_key", mp->crypto_key, + mp->crypto_key_len); + vat_json_object_add_bytes (node, "integ_key", mp->integ_key, + mp->integ_key_len); + if (mp->is_tunnel_ip6) + { + clib_memcpy (&src_ip6, mp->tunnel_src_addr, sizeof (src_ip6)); + vat_json_object_add_ip6 (node, "tunnel_src_addr", src_ip6); + clib_memcpy (&dst_ip6, mp->tunnel_dst_addr, sizeof (dst_ip6)); + vat_json_object_add_ip6 (node, "tunnel_dst_addr", dst_ip6); + } + else + { + clib_memcpy (&src_ip4, mp->tunnel_src_addr, sizeof (src_ip4)); + vat_json_object_add_ip4 (node, "tunnel_src_addr", src_ip4); + clib_memcpy (&dst_ip4, mp->tunnel_dst_addr, sizeof (dst_ip4)); + vat_json_object_add_ip4 (node, "tunnel_dst_addr", dst_ip4); + } + vat_json_object_add_uint (node, "replay_window", + clib_net_to_host_u64 (mp->replay_window)); + vat_json_object_add_uint (node, "total_data_size", + clib_net_to_host_u64 (mp->total_data_size)); + +} + +static int +api_ipsec_sa_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_sa_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sa_id = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sa_id %d", &sa_id)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IPSEC_SA_DUMP, mp); + + mp->sa_id = ntohl (sa_id); + + S (mp); + + /* Use a control ping for synchronization */ + M (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_ipsec_tunnel_if_set_key (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_tunnel_if_set_key_t *mp; + u32 sw_if_index = ~0; + u8 key_type = IPSEC_IF_SET_KEY_TYPE_NONE; + u8 *key = 0; + u32 alg = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else + if (unformat (i, "local crypto %U", unformat_ipsec_crypto_alg, &alg)) + key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_CRYPTO; + else + if (unformat (i, "remote crypto %U", unformat_ipsec_crypto_alg, &alg)) + key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_CRYPTO; + else if (unformat (i, "local integ %U", unformat_ipsec_integ_alg, &alg)) + key_type = IPSEC_IF_SET_KEY_TYPE_LOCAL_INTEG; + else + if (unformat (i, "remote integ %U", unformat_ipsec_integ_alg, &alg)) + key_type = IPSEC_IF_SET_KEY_TYPE_REMOTE_INTEG; + else if (unformat (i, "%U", unformat_hex_string, &key)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index == ~0) + { + errmsg ("interface must be specified"); + return -99; + } + + if (key_type == IPSEC_IF_SET_KEY_TYPE_NONE) + { + errmsg ("key type must be specified"); + return -99; + } + + if (alg == ~0) + { + errmsg ("algorithm must be specified"); + return -99; + } + + if (vec_len (key) == 0) + { + errmsg ("key must be specified"); + return -99; + } + + M (IPSEC_TUNNEL_IF_SET_KEY, mp); + + mp->sw_if_index = htonl (sw_if_index); + mp->alg = alg; + mp->key_type = key_type; + mp->key_len = vec_len (key); + clib_memcpy (mp->key, key, vec_len (key)); + + S (mp); + W (ret); + + return ret; +} + +static int +api_ipsec_tunnel_if_set_sa (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_tunnel_if_set_sa_t *mp; + u32 sw_if_index = ~0; + u32 sa_id = ~0; + u8 is_outbound = (u8) ~ 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sa_id %d", &sa_id)) + ; + else if (unformat (i, "outbound")) + is_outbound = 1; + else if (unformat (i, "inbound")) + is_outbound = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index == ~0) + { + errmsg ("interface must be specified"); + return -99; + } + + if (sa_id == ~0) + { + errmsg ("SA ID must be specified"); + return -99; + } + + M (IPSEC_TUNNEL_IF_SET_SA, mp); + + mp->sw_if_index = htonl (sw_if_index); + mp->sa_id = htonl (sa_id); + mp->is_outbound = is_outbound; + + S (mp); + W (ret); + + return ret; +} + +static int +api_ikev2_profile_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_profile_add_del_t *mp; + u8 is_add = 1; + u8 *name = 0; + int ret; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "name %U", unformat_token, valid_chars, &name)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_PROFILE_ADD_DEL, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + mp->is_add = is_add; + vec_free (name); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_profile_set_auth (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_profile_set_auth_t *mp; + u8 *name = 0; + u8 *data = 0; + u32 auth_method = 0; + u8 is_hex = 0; + int ret; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %U", unformat_token, valid_chars, &name)) + vec_add1 (name, 0); + else if (unformat (i, "auth_method %U", + unformat_ikev2_auth_method, &auth_method)) + ; + else if (unformat (i, "auth_data 0x%U", unformat_hex_string, &data)) + is_hex = 1; + else if (unformat (i, "auth_data %v", &data)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + if (!vec_len (data)) + { + errmsg ("auth_data must be specified"); + return -99; + } + + if (!auth_method) + { + errmsg ("auth_method must be specified"); + return -99; + } + + M (IKEV2_PROFILE_SET_AUTH, mp); + + mp->is_hex = is_hex; + mp->auth_method = (u8) auth_method; + mp->data_len = vec_len (data); + clib_memcpy (mp->name, name, vec_len (name)); + clib_memcpy (mp->data, data, vec_len (data)); + vec_free (name); + vec_free (data); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_profile_set_id (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_profile_set_id_t *mp; + u8 *name = 0; + u8 *data = 0; + u8 is_local = 0; + u32 id_type = 0; + ip4_address_t ip4; + int ret; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %U", unformat_token, valid_chars, &name)) + vec_add1 (name, 0); + else if (unformat (i, "id_type %U", unformat_ikev2_id_type, &id_type)) + ; + else if (unformat (i, "id_data %U", unformat_ip4_address, &ip4)) + { + data = vec_new (u8, 4); + clib_memcpy (data, ip4.as_u8, 4); + } + else if (unformat (i, "id_data 0x%U", unformat_hex_string, &data)) + ; + else if (unformat (i, "id_data %v", &data)) + ; + else if (unformat (i, "local")) + is_local = 1; + else if (unformat (i, "remote")) + is_local = 0; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + if (!vec_len (data)) + { + errmsg ("id_data must be specified"); + return -99; + } + + if (!id_type) + { + errmsg ("id_type must be specified"); + return -99; + } + + M (IKEV2_PROFILE_SET_ID, mp); + + mp->is_local = is_local; + mp->id_type = (u8) id_type; + mp->data_len = vec_len (data); + clib_memcpy (mp->name, name, vec_len (name)); + clib_memcpy (mp->data, data, vec_len (data)); + vec_free (name); + vec_free (data); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_profile_set_ts (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_profile_set_ts_t *mp; + u8 *name = 0; + u8 is_local = 0; + u32 proto = 0, start_port = 0, end_port = (u32) ~ 0; + ip4_address_t start_addr, end_addr; + + const char *valid_chars = "a-zA-Z0-9_"; + int ret; + + start_addr.as_u32 = 0; + end_addr.as_u32 = (u32) ~ 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %U", unformat_token, valid_chars, &name)) + vec_add1 (name, 0); + else if (unformat (i, "protocol %d", &proto)) + ; + else if (unformat (i, "start_port %d", &start_port)) + ; + else if (unformat (i, "end_port %d", &end_port)) + ; + else + if (unformat (i, "start_addr %U", unformat_ip4_address, &start_addr)) + ; + else if (unformat (i, "end_addr %U", unformat_ip4_address, &end_addr)) + ; + else if (unformat (i, "local")) + is_local = 1; + else if (unformat (i, "remote")) + is_local = 0; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_PROFILE_SET_TS, mp); + + mp->is_local = is_local; + mp->proto = (u8) proto; + mp->start_port = (u16) start_port; + mp->end_port = (u16) end_port; + mp->start_addr = start_addr.as_u32; + mp->end_addr = end_addr.as_u32; + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_set_local_key (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_set_local_key_t *mp; + u8 *file = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "file %v", &file)) + vec_add1 (file, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (file)) + { + errmsg ("RSA key file must be specified"); + return -99; + } + + if (vec_len (file) > 256) + { + errmsg ("file name too long"); + return -99; + } + + M (IKEV2_SET_LOCAL_KEY, mp); + + clib_memcpy (mp->key_file, file, vec_len (file)); + vec_free (file); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_set_responder (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_set_responder_t *mp; + int ret; + u8 *name = 0; + u32 sw_if_index = ~0; + ip4_address_t address; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (i, "%U interface %d address %U", unformat_token, valid_chars, + &name, &sw_if_index, unformat_ip4_address, &address)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_SET_RESPONDER, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + + mp->sw_if_index = sw_if_index; + clib_memcpy (mp->address, &address, sizeof (address)); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_set_ike_transforms (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_set_ike_transforms_t *mp; + int ret; + u8 *name = 0; + u32 crypto_alg, crypto_key_size, integ_alg, dh_group; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U %d %d %d %d", unformat_token, valid_chars, &name, + &crypto_alg, &crypto_key_size, &integ_alg, &dh_group)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_SET_IKE_TRANSFORMS, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + mp->crypto_alg = crypto_alg; + mp->crypto_key_size = crypto_key_size; + mp->integ_alg = integ_alg; + mp->dh_group = dh_group; + + S (mp); + W (ret); + return ret; +} + + +static int +api_ikev2_set_esp_transforms (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_set_esp_transforms_t *mp; + int ret; + u8 *name = 0; + u32 crypto_alg, crypto_key_size, integ_alg, dh_group; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U %d %d %d %d", unformat_token, valid_chars, &name, + &crypto_alg, &crypto_key_size, &integ_alg, &dh_group)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_SET_ESP_TRANSFORMS, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + mp->crypto_alg = crypto_alg; + mp->crypto_key_size = crypto_key_size; + mp->integ_alg = integ_alg; + mp->dh_group = dh_group; + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_set_sa_lifetime (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_set_sa_lifetime_t *mp; + int ret; + u8 *name = 0; + u64 lifetime, lifetime_maxdata; + u32 lifetime_jitter, handover; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U %lu %u %u %lu", unformat_token, valid_chars, &name, + &lifetime, &lifetime_jitter, &handover, + &lifetime_maxdata)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_SET_SA_LIFETIME, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + mp->lifetime = lifetime; + mp->lifetime_jitter = lifetime_jitter; + mp->handover = handover; + mp->lifetime_maxdata = lifetime_maxdata; + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_initiate_sa_init (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_initiate_sa_init_t *mp; + int ret; + u8 *name = 0; + + const char *valid_chars = "a-zA-Z0-9_"; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_token, valid_chars, &name)) + vec_add1 (name, 0); + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vec_len (name)) + { + errmsg ("profile name must be specified"); + return -99; + } + + if (vec_len (name) > 64) + { + errmsg ("profile name too long"); + return -99; + } + + M (IKEV2_INITIATE_SA_INIT, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_initiate_del_ike_sa (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_initiate_del_ike_sa_t *mp; + int ret; + u64 ispi; + + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%lx", &ispi)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IKEV2_INITIATE_DEL_IKE_SA, mp); + + mp->ispi = ispi; + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_initiate_del_child_sa (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_initiate_del_child_sa_t *mp; + int ret; + u32 ispi; + + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%x", &ispi)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IKEV2_INITIATE_DEL_CHILD_SA, mp); + + mp->ispi = ispi; + + S (mp); + W (ret); + return ret; +} + +static int +api_ikev2_initiate_rekey_child_sa (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ikev2_initiate_rekey_child_sa_t *mp; + int ret; + u32 ispi; + + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%x", &ispi)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IKEV2_INITIATE_REKEY_CHILD_SA, mp); + + mp->ispi = ispi; + + S (mp); + W (ret); + return ret; +} + +/* + * MAP + */ +static int +api_map_add_domain (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_map_add_domain_t *mp; + + ip4_address_t ip4_prefix; + ip6_address_t ip6_prefix; + ip6_address_t ip6_src; + u32 num_m_args = 0; + u32 ip6_prefix_len = 0, ip4_prefix_len = 0, ea_bits_len = 0, psid_offset = + 0, psid_length = 0; + u8 is_translation = 0; + u32 mtu = 0; + u32 ip6_src_len = 128; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "ip4-pfx %U/%d", unformat_ip4_address, + &ip4_prefix, &ip4_prefix_len)) + num_m_args++; + else if (unformat (i, "ip6-pfx %U/%d", unformat_ip6_address, + &ip6_prefix, &ip6_prefix_len)) + num_m_args++; + else + if (unformat + (i, "ip6-src %U/%d", unformat_ip6_address, &ip6_src, + &ip6_src_len)) + num_m_args++; + else if (unformat (i, "ip6-src %U", unformat_ip6_address, &ip6_src)) + num_m_args++; + else if (unformat (i, "ea-bits-len %d", &ea_bits_len)) + num_m_args++; + else if (unformat (i, "psid-offset %d", &psid_offset)) + num_m_args++; + else if (unformat (i, "psid-len %d", &psid_length)) + num_m_args++; + else if (unformat (i, "mtu %d", &mtu)) + num_m_args++; + else if (unformat (i, "map-t")) + is_translation = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (num_m_args < 3) + { + errmsg ("mandatory argument(s) missing"); + return -99; + } + + /* Construct the API message */ + M (MAP_ADD_DOMAIN, mp); + + clib_memcpy (mp->ip4_prefix, &ip4_prefix, sizeof (ip4_prefix)); + mp->ip4_prefix_len = ip4_prefix_len; + + clib_memcpy (mp->ip6_prefix, &ip6_prefix, sizeof (ip6_prefix)); + mp->ip6_prefix_len = ip6_prefix_len; + + clib_memcpy (mp->ip6_src, &ip6_src, sizeof (ip6_src)); + mp->ip6_src_prefix_len = ip6_src_len; + + mp->ea_bits_len = ea_bits_len; + mp->psid_offset = psid_offset; + mp->psid_length = psid_length; + mp->is_translation = is_translation; + mp->mtu = htons (mtu); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_map_del_domain (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_map_del_domain_t *mp; + + u32 num_m_args = 0; + u32 index; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "index %d", &index)) + num_m_args++; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (num_m_args != 1) + { + errmsg ("mandatory argument(s) missing"); + return -99; + } + + /* Construct the API message */ + M (MAP_DEL_DOMAIN, mp); + + mp->index = ntohl (index); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_map_add_del_rule (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_map_add_del_rule_t *mp; + u8 is_add = 1; + ip6_address_t ip6_dst; + u32 num_m_args = 0, index, psid = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "index %d", &index)) + num_m_args++; + else if (unformat (i, "psid %d", &psid)) + num_m_args++; + else if (unformat (i, "dst %U", unformat_ip6_address, &ip6_dst)) + num_m_args++; + else if (unformat (i, "del")) + { + is_add = 0; + } + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + /* Construct the API message */ + M (MAP_ADD_DEL_RULE, mp); + + mp->index = ntohl (index); + mp->is_add = is_add; + clib_memcpy (mp->ip6_dst, &ip6_dst, sizeof (ip6_dst)); + mp->psid = ntohs (psid); + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static int +api_map_domain_dump (vat_main_t * vam) +{ + vl_api_map_domain_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + /* Construct the API message */ + M (MAP_DOMAIN_DUMP, mp); + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_map_rule_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_map_rule_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 domain_index = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "index %u", &domain_index)) + ; + else + break; + } + + if (domain_index == ~0) + { + clib_warning ("parse error: domain index expected"); + return -99; + } + + /* Construct the API message */ + M (MAP_RULE_DUMP, mp); + + mp->domain_index = htonl (domain_index); + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void vl_api_map_add_domain_reply_t_handler + (vl_api_map_add_domain_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + vam->result_ready = 1; + } +} + +static void vl_api_map_add_domain_reply_t_handler_json + (vl_api_map_add_domain_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "index", ntohl (mp->index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static int +api_get_first_msg_id (vat_main_t * vam) +{ + vl_api_get_first_msg_id_t *mp; + unformat_input_t *i = vam->input; + u8 *name; + u8 name_set = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "client %s", &name)) + name_set = 1; + else + break; + } + + if (name_set == 0) + { + errmsg ("missing client name"); + return -99; + } + vec_add1 (name, 0); + + if (vec_len (name) > 63) + { + errmsg ("client name too long"); + return -99; + } + + M (GET_FIRST_MSG_ID, mp); + clib_memcpy (mp->name, name, vec_len (name)); + S (mp); + W (ret); + return ret; +} + +static int +api_cop_interface_enable_disable (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_cop_interface_enable_disable_t *mp; + u32 sw_if_index = ~0; + u8 enable_disable = 1; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "disable")) + enable_disable = 0; + if (unformat (line_input, "enable")) + enable_disable = 1; + else if (unformat (line_input, "%U", api_unformat_sw_if_index, + vam, &sw_if_index)) + ; + else if (unformat (line_input, "sw_if_index %d", &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (COP_INTERFACE_ENABLE_DISABLE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->enable_disable = enable_disable; + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +static int +api_cop_whitelist_enable_disable (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_cop_whitelist_enable_disable_t *mp; + u32 sw_if_index = ~0; + u8 ip4 = 0, ip6 = 0, default_cop = 0; + u32 fib_id = 0; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "ip4")) + ip4 = 1; + else if (unformat (line_input, "ip6")) + ip6 = 1; + else if (unformat (line_input, "default")) + default_cop = 1; + else if (unformat (line_input, "%U", api_unformat_sw_if_index, + vam, &sw_if_index)) + ; + else if (unformat (line_input, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (line_input, "fib-id %d", &fib_id)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (COP_WHITELIST_ENABLE_DISABLE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->fib_id = ntohl (fib_id); + mp->ip4 = ip4; + mp->ip6 = ip6; + mp->default_cop = default_cop; + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +static int +api_get_node_graph (vat_main_t * vam) +{ + vl_api_get_node_graph_t *mp; + int ret; + + M (GET_NODE_GRAPH, mp); + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +/* *INDENT-OFF* */ +/** Used for parsing LISP eids */ +typedef CLIB_PACKED(struct{ + u8 addr[16]; /**< eid address */ + u32 len; /**< prefix length if IP */ + u8 type; /**< type of eid */ +}) lisp_eid_vat_t; +/* *INDENT-ON* */ + +static uword +unformat_lisp_eid_vat (unformat_input_t * input, va_list * args) +{ + lisp_eid_vat_t *a = va_arg (*args, lisp_eid_vat_t *); + + memset (a, 0, sizeof (a[0])); + + if (unformat (input, "%U/%d", unformat_ip4_address, a->addr, &a->len)) + { + a->type = 0; /* ipv4 type */ + } + else if (unformat (input, "%U/%d", unformat_ip6_address, a->addr, &a->len)) + { + a->type = 1; /* ipv6 type */ + } + else if (unformat (input, "%U", unformat_ethernet_address, a->addr)) + { + a->type = 2; /* mac type */ + } + else if (unformat (input, "%U", unformat_nsh_address, a->addr)) + { + a->type = 3; /* NSH type */ + lisp_nsh_api_t *nsh = (lisp_nsh_api_t *) a->addr; + nsh->spi = clib_host_to_net_u32 (nsh->spi); + } + else + { + return 0; + } + + if ((a->type == 0 && a->len > 32) || (a->type == 1 && a->len > 128)) + { + return 0; + } + + return 1; +} + +static int +lisp_eid_size_vat (u8 type) +{ + switch (type) + { + case 0: + return 4; + case 1: + return 16; + case 2: + return 6; + case 3: + return 5; + } + return 0; +} + +static void +lisp_eid_put_vat (u8 * dst, u8 eid[16], u8 type) +{ + clib_memcpy (dst, eid, lisp_eid_size_vat (type)); +} + +static int +api_one_add_del_locator_set (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_locator_set_t *mp; + u8 is_add = 1; + u8 *locator_set_name = NULL; + u8 locator_set_name_set = 0; + vl_api_local_locator_t locator, *locators = 0; + u32 sw_if_index, priority, weight; + u32 data_len = 0; + + int ret; + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "locator-set %s", &locator_set_name)) + { + locator_set_name_set = 1; + } + else if (unformat (input, "sw_if_index %u p %u w %u", + &sw_if_index, &priority, &weight)) + { + locator.sw_if_index = htonl (sw_if_index); + locator.priority = priority; + locator.weight = weight; + vec_add1 (locators, locator); + } + else + if (unformat + (input, "iface %U p %u w %u", api_unformat_sw_if_index, vam, + &sw_if_index, &priority, &weight)) + { + locator.sw_if_index = htonl (sw_if_index); + locator.priority = priority; + locator.weight = weight; + vec_add1 (locators, locator); + } + else + break; + } + + if (locator_set_name_set == 0) + { + errmsg ("missing locator-set name"); + vec_free (locators); + return -99; + } + + if (vec_len (locator_set_name) > 64) + { + errmsg ("locator-set name too long"); + vec_free (locator_set_name); + vec_free (locators); + return -99; + } + vec_add1 (locator_set_name, 0); + + data_len = sizeof (vl_api_local_locator_t) * vec_len (locators); + + /* Construct the API message */ + M2 (ONE_ADD_DEL_LOCATOR_SET, mp, data_len); + + mp->is_add = is_add; + clib_memcpy (mp->locator_set_name, locator_set_name, + vec_len (locator_set_name)); + vec_free (locator_set_name); + + mp->locator_num = clib_host_to_net_u32 (vec_len (locators)); + if (locators) + clib_memcpy (mp->locators, locators, data_len); + vec_free (locators); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_locator_set api_one_add_del_locator_set + +static int +api_one_add_del_locator (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_locator_t *mp; + u32 tmp_if_index = ~0; + u32 sw_if_index = ~0; + u8 sw_if_index_set = 0; + u8 sw_if_index_if_name_set = 0; + u32 priority = ~0; + u8 priority_set = 0; + u32 weight = ~0; + u8 weight_set = 0; + u8 is_add = 1; + u8 *locator_set_name = NULL; + u8 locator_set_name_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "locator-set %s", &locator_set_name)) + { + locator_set_name_set = 1; + } + else if (unformat (input, "iface %U", api_unformat_sw_if_index, vam, + &tmp_if_index)) + { + sw_if_index_if_name_set = 1; + sw_if_index = tmp_if_index; + } + else if (unformat (input, "sw_if_index %d", &tmp_if_index)) + { + sw_if_index_set = 1; + sw_if_index = tmp_if_index; + } + else if (unformat (input, "p %d", &priority)) + { + priority_set = 1; + } + else if (unformat (input, "w %d", &weight)) + { + weight_set = 1; + } + else + break; + } + + if (locator_set_name_set == 0) + { + errmsg ("missing locator-set name"); + return -99; + } + + if (sw_if_index_set == 0 && sw_if_index_if_name_set == 0) + { + errmsg ("missing sw_if_index"); + vec_free (locator_set_name); + return -99; + } + + if (sw_if_index_set != 0 && sw_if_index_if_name_set != 0) + { + errmsg ("cannot use both params interface name and sw_if_index"); + vec_free (locator_set_name); + return -99; + } + + if (priority_set == 0) + { + errmsg ("missing locator-set priority"); + vec_free (locator_set_name); + return -99; + } + + if (weight_set == 0) + { + errmsg ("missing locator-set weight"); + vec_free (locator_set_name); + return -99; + } + + if (vec_len (locator_set_name) > 64) + { + errmsg ("locator-set name too long"); + vec_free (locator_set_name); + return -99; + } + vec_add1 (locator_set_name, 0); + + /* Construct the API message */ + M (ONE_ADD_DEL_LOCATOR, mp); + + mp->is_add = is_add; + mp->sw_if_index = ntohl (sw_if_index); + mp->priority = priority; + mp->weight = weight; + clib_memcpy (mp->locator_set_name, locator_set_name, + vec_len (locator_set_name)); + vec_free (locator_set_name); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_locator api_one_add_del_locator + +uword +unformat_hmac_key_id (unformat_input_t * input, va_list * args) +{ + u32 *key_id = va_arg (*args, u32 *); + u8 *s = 0; + + if (unformat (input, "%s", &s)) + { + if (!strcmp ((char *) s, "sha1")) + key_id[0] = HMAC_SHA_1_96; + else if (!strcmp ((char *) s, "sha256")) + key_id[0] = HMAC_SHA_256_128; + else + { + clib_warning ("invalid key_id: '%s'", s); + key_id[0] = HMAC_NO_KEY; + } + } + else + return 0; + + vec_free (s); + return 1; +} + +static int +api_one_add_del_local_eid (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_local_eid_t *mp; + u8 is_add = 1; + u8 eid_set = 0; + lisp_eid_vat_t _eid, *eid = &_eid; + u8 *locator_set_name = 0; + u8 locator_set_name_set = 0; + u32 vni = 0; + u16 key_id = 0; + u8 *key = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "vni %d", &vni)) + { + ; + } + else if (unformat (input, "eid %U", unformat_lisp_eid_vat, eid)) + { + eid_set = 1; + } + else if (unformat (input, "locator-set %s", &locator_set_name)) + { + locator_set_name_set = 1; + } + else if (unformat (input, "key-id %U", unformat_hmac_key_id, &key_id)) + ; + else if (unformat (input, "secret-key %_%v%_", &key)) + ; + else + break; + } + + if (locator_set_name_set == 0) + { + errmsg ("missing locator-set name"); + return -99; + } + + if (0 == eid_set) + { + errmsg ("EID address not set!"); + vec_free (locator_set_name); + return -99; + } + + if (key && (0 == key_id)) + { + errmsg ("invalid key_id!"); + return -99; + } + + if (vec_len (key) > 64) + { + errmsg ("key too long"); + vec_free (key); + return -99; + } + + if (vec_len (locator_set_name) > 64) + { + errmsg ("locator-set name too long"); + vec_free (locator_set_name); + return -99; + } + vec_add1 (locator_set_name, 0); + + /* Construct the API message */ + M (ONE_ADD_DEL_LOCAL_EID, mp); + + mp->is_add = is_add; + lisp_eid_put_vat (mp->eid, eid->addr, eid->type); + mp->eid_type = eid->type; + mp->prefix_len = eid->len; + mp->vni = clib_host_to_net_u32 (vni); + mp->key_id = clib_host_to_net_u16 (key_id); + clib_memcpy (mp->locator_set_name, locator_set_name, + vec_len (locator_set_name)); + clib_memcpy (mp->key, key, vec_len (key)); + + vec_free (locator_set_name); + vec_free (key); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_local_eid api_one_add_del_local_eid + +static int +api_lisp_gpe_add_del_fwd_entry (vat_main_t * vam) +{ + u32 dp_table = 0, vni = 0;; + unformat_input_t *input = vam->input; + vl_api_gpe_add_del_fwd_entry_t *mp; + u8 is_add = 1; + lisp_eid_vat_t _rmt_eid, *rmt_eid = &_rmt_eid; + lisp_eid_vat_t _lcl_eid, *lcl_eid = &_lcl_eid; + u8 rmt_eid_set = 0, lcl_eid_set = 0; + u32 action = ~0, w; + ip4_address_t rmt_rloc4, lcl_rloc4; + ip6_address_t rmt_rloc6, lcl_rloc6; + vl_api_gpe_locator_t *rmt_locs = 0, *lcl_locs = 0, rloc, *curr_rloc = 0; + int ret; + + memset (&rloc, 0, sizeof (rloc)); + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "add")) + is_add = 1; + else if (unformat (input, "reid %U", unformat_lisp_eid_vat, rmt_eid)) + { + rmt_eid_set = 1; + } + else if (unformat (input, "leid %U", unformat_lisp_eid_vat, lcl_eid)) + { + lcl_eid_set = 1; + } + else if (unformat (input, "vrf %d", &dp_table)) + ; + else if (unformat (input, "bd %d", &dp_table)) + ; + else if (unformat (input, "vni %d", &vni)) + ; + else if (unformat (input, "w %d", &w)) + { + if (!curr_rloc) + { + errmsg ("No RLOC configured for setting priority/weight!"); + return -99; + } + curr_rloc->weight = w; + } + else if (unformat (input, "loc-pair %U %U", unformat_ip4_address, + &lcl_rloc4, unformat_ip4_address, &rmt_rloc4)) + { + rloc.is_ip4 = 1; + + clib_memcpy (&rloc.addr, &lcl_rloc4, sizeof (lcl_rloc4)); + rloc.weight = 0; + vec_add1 (lcl_locs, rloc); + + clib_memcpy (&rloc.addr, &rmt_rloc4, sizeof (rmt_rloc4)); + vec_add1 (rmt_locs, rloc); + /* weight saved in rmt loc */ + curr_rloc = &rmt_locs[vec_len (rmt_locs) - 1]; + } + else if (unformat (input, "loc-pair %U %U", unformat_ip6_address, + &lcl_rloc6, unformat_ip6_address, &rmt_rloc6)) + { + rloc.is_ip4 = 0; + clib_memcpy (&rloc.addr, &lcl_rloc6, sizeof (lcl_rloc6)); + rloc.weight = 0; + vec_add1 (lcl_locs, rloc); + + clib_memcpy (&rloc.addr, &rmt_rloc6, sizeof (rmt_rloc6)); + vec_add1 (rmt_locs, rloc); + /* weight saved in rmt loc */ + curr_rloc = &rmt_locs[vec_len (rmt_locs) - 1]; + } + else if (unformat (input, "action %d", &action)) + { + ; + } + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!rmt_eid_set) + { + errmsg ("remote eid addresses not set"); + return -99; + } + + if (lcl_eid_set && rmt_eid->type != lcl_eid->type) + { + errmsg ("eid types don't match"); + return -99; + } + + if (0 == rmt_locs && (u32) ~ 0 == action) + { + errmsg ("action not set for negative mapping"); + return -99; + } + + /* Construct the API message */ + M2 (GPE_ADD_DEL_FWD_ENTRY, mp, + sizeof (vl_api_gpe_locator_t) * vec_len (rmt_locs) * 2); + + mp->is_add = is_add; + lisp_eid_put_vat (mp->rmt_eid, rmt_eid->addr, rmt_eid->type); + lisp_eid_put_vat (mp->lcl_eid, lcl_eid->addr, lcl_eid->type); + mp->eid_type = rmt_eid->type; + mp->dp_table = clib_host_to_net_u32 (dp_table); + mp->vni = clib_host_to_net_u32 (vni); + mp->rmt_len = rmt_eid->len; + mp->lcl_len = lcl_eid->len; + mp->action = action; + + if (0 != rmt_locs && 0 != lcl_locs) + { + mp->loc_num = clib_host_to_net_u32 (vec_len (rmt_locs) * 2); + clib_memcpy (mp->locs, lcl_locs, + (sizeof (vl_api_gpe_locator_t) * vec_len (lcl_locs))); + + u32 offset = sizeof (vl_api_gpe_locator_t) * vec_len (lcl_locs); + clib_memcpy (((u8 *) mp->locs) + offset, rmt_locs, + (sizeof (vl_api_gpe_locator_t) * vec_len (rmt_locs))); + } + vec_free (lcl_locs); + vec_free (rmt_locs); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_add_del_map_server (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_map_server_t *mp; + u8 is_add = 1; + u8 ipv4_set = 0; + u8 ipv6_set = 0; + ip4_address_t ipv4; + ip6_address_t ipv6; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "%U", unformat_ip4_address, &ipv4)) + { + ipv4_set = 1; + } + else if (unformat (input, "%U", unformat_ip6_address, &ipv6)) + { + ipv6_set = 1; + } + else + break; + } + + if (ipv4_set && ipv6_set) + { + errmsg ("both eid v4 and v6 addresses set"); + return -99; + } + + if (!ipv4_set && !ipv6_set) + { + errmsg ("eid addresses not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ADD_DEL_MAP_SERVER, mp); + + mp->is_add = is_add; + if (ipv6_set) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->ip_address, &ipv6, sizeof (ipv6)); + } + else + { + mp->is_ipv6 = 0; + clib_memcpy (mp->ip_address, &ipv4, sizeof (ipv4)); + } + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_map_server api_one_add_del_map_server + +static int +api_one_add_del_map_resolver (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_map_resolver_t *mp; + u8 is_add = 1; + u8 ipv4_set = 0; + u8 ipv6_set = 0; + ip4_address_t ipv4; + ip6_address_t ipv6; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "%U", unformat_ip4_address, &ipv4)) + { + ipv4_set = 1; + } + else if (unformat (input, "%U", unformat_ip6_address, &ipv6)) + { + ipv6_set = 1; + } + else + break; + } + + if (ipv4_set && ipv6_set) + { + errmsg ("both eid v4 and v6 addresses set"); + return -99; + } + + if (!ipv4_set && !ipv6_set) + { + errmsg ("eid addresses not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ADD_DEL_MAP_RESOLVER, mp); + + mp->is_add = is_add; + if (ipv6_set) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->ip_address, &ipv6, sizeof (ipv6)); + } + else + { + mp->is_ipv6 = 0; + clib_memcpy (mp->ip_address, &ipv4, sizeof (ipv4)); + } + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_map_resolver api_one_add_del_map_resolver + +static int +api_lisp_gpe_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_gpe_enable_disable_t *mp; + u8 is_set = 0; + u8 is_en = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + is_en = 0; + } + else + break; + } + + if (is_set == 0) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (GPE_ENABLE_DISABLE, mp); + + mp->is_en = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_rloc_probe_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_rloc_probe_enable_disable_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + is_set = 1; + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_RLOC_PROBE_ENABLE_DISABLE, mp); + + mp->is_enabled = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_rloc_probe_enable_disable api_one_rloc_probe_enable_disable + +static int +api_one_map_register_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_register_enable_disable_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + is_set = 1; + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_MAP_REGISTER_ENABLE_DISABLE, mp); + + mp->is_enabled = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_map_register_enable_disable api_one_map_register_enable_disable + +static int +api_one_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_enable_disable_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ENABLE_DISABLE, mp); + + mp->is_en = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_enable_disable api_one_enable_disable + +static int +api_one_enable_disable_xtr_mode (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_enable_disable_xtr_mode_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ENABLE_DISABLE_XTR_MODE, mp); + + mp->is_en = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_show_xtr_mode (vat_main_t * vam) +{ + vl_api_one_show_xtr_mode_t *mp; + int ret; + + /* Construct the API message */ + M (ONE_SHOW_XTR_MODE, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_enable_disable_pitr_mode (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_enable_disable_pitr_mode_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ENABLE_DISABLE_PITR_MODE, mp); + + mp->is_en = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_show_pitr_mode (vat_main_t * vam) +{ + vl_api_one_show_pitr_mode_t *mp; + int ret; + + /* Construct the API message */ + M (ONE_SHOW_PITR_MODE, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_enable_disable_petr_mode (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_enable_disable_petr_mode_t *mp; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + /* Construct the API message */ + M (ONE_ENABLE_DISABLE_PETR_MODE, mp); + + mp->is_en = is_en; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_show_petr_mode (vat_main_t * vam) +{ + vl_api_one_show_petr_mode_t *mp; + int ret; + + /* Construct the API message */ + M (ONE_SHOW_PETR_MODE, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_map_register_state (vat_main_t * vam) +{ + vl_api_show_one_map_register_state_t *mp; + int ret; + + M (SHOW_ONE_MAP_REGISTER_STATE, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_show_lisp_map_register_state api_show_one_map_register_state + +static int +api_show_one_rloc_probe_state (vat_main_t * vam) +{ + vl_api_show_one_rloc_probe_state_t *mp; + int ret; + + M (SHOW_ONE_RLOC_PROBE_STATE, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_show_lisp_rloc_probe_state api_show_one_rloc_probe_state + +static int +api_one_add_del_ndp_entry (vat_main_t * vam) +{ + vl_api_one_add_del_ndp_entry_t *mp; + unformat_input_t *input = vam->input; + u8 is_add = 1; + u8 mac_set = 0; + u8 bd_set = 0; + u8 ip_set = 0; + u8 mac[6] = { 0, }; + u8 ip6[16] = { 0, }; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (input, "ip %U", unformat_ip6_address, ip6)) + ip_set = 1; + else if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set || !ip_set || (!mac_set && is_add)) + { + errmsg ("Missing BD, IP or MAC!"); + return -99; + } + + M (ONE_ADD_DEL_NDP_ENTRY, mp); + mp->is_add = is_add; + clib_memcpy (mp->mac, mac, 6); + mp->bd = clib_host_to_net_u32 (bd); + clib_memcpy (mp->ip6, ip6, sizeof (mp->ip6)); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_add_del_l2_arp_entry (vat_main_t * vam) +{ + vl_api_one_add_del_l2_arp_entry_t *mp; + unformat_input_t *input = vam->input; + u8 is_add = 1; + u8 mac_set = 0; + u8 bd_set = 0; + u8 ip_set = 0; + u8 mac[6] = { 0, }; + u32 ip4 = 0, bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "mac %U", unformat_ethernet_address, mac)) + mac_set = 1; + else if (unformat (input, "ip %U", unformat_ip4_address, &ip4)) + ip_set = 1; + else if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set || !ip_set || (!mac_set && is_add)) + { + errmsg ("Missing BD, IP or MAC!"); + return -99; + } + + M (ONE_ADD_DEL_L2_ARP_ENTRY, mp); + mp->is_add = is_add; + clib_memcpy (mp->mac, mac, 6); + mp->bd = clib_host_to_net_u32 (bd); + mp->ip4 = ip4; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_ndp_bd_get (vat_main_t * vam) +{ + vl_api_one_ndp_bd_get_t *mp; + int ret; + + M (ONE_NDP_BD_GET, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_ndp_entries_get (vat_main_t * vam) +{ + vl_api_one_ndp_entries_get_t *mp; + unformat_input_t *input = vam->input; + u8 bd_set = 0; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set) + { + errmsg ("Expected bridge domain!"); + return -99; + } + + M (ONE_NDP_ENTRIES_GET, mp); + mp->bd = clib_host_to_net_u32 (bd); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_l2_arp_bd_get (vat_main_t * vam) +{ + vl_api_one_l2_arp_bd_get_t *mp; + int ret; + + M (ONE_L2_ARP_BD_GET, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_l2_arp_entries_get (vat_main_t * vam) +{ + vl_api_one_l2_arp_entries_get_t *mp; + unformat_input_t *input = vam->input; + u8 bd_set = 0; + u32 bd = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "bd %d", &bd)) + bd_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!bd_set) + { + errmsg ("Expected bridge domain!"); + return -99; + } + + M (ONE_L2_ARP_ENTRIES_GET, mp); + mp->bd = clib_host_to_net_u32 (bd); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_one_stats_enable_disable (vat_main_t * vam) +{ + vl_api_one_stats_enable_disable_t *mp; + unformat_input_t *input = vam->input; + u8 is_set = 0; + u8 is_en = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "enable")) + { + is_set = 1; + is_en = 1; + } + else if (unformat (input, "disable")) + { + is_set = 1; + } + else + break; + } + + if (!is_set) + { + errmsg ("Value not set"); + return -99; + } + + M (ONE_STATS_ENABLE_DISABLE, mp); + mp->is_en = is_en; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_show_one_stats_enable_disable (vat_main_t * vam) +{ + vl_api_show_one_stats_enable_disable_t *mp; + int ret; + + M (SHOW_ONE_STATS_ENABLE_DISABLE, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_show_one_map_request_mode (vat_main_t * vam) +{ + vl_api_show_one_map_request_mode_t *mp; + int ret; + + M (SHOW_ONE_MAP_REQUEST_MODE, mp); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_show_lisp_map_request_mode api_show_one_map_request_mode + +static int +api_one_map_request_mode (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_request_mode_t *mp; + u8 mode = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "dst-only")) + mode = 0; + else if (unformat (input, "src-dst")) + mode = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + M (ONE_MAP_REQUEST_MODE, mp); + + mp->mode = mode; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_lisp_map_request_mode api_one_map_request_mode + +/** + * Enable/disable ONE proxy ITR. + * + * @param vam vpp API test context + * @return return code + */ +static int +api_one_pitr_set_locator_set (vat_main_t * vam) +{ + u8 ls_name_set = 0; + unformat_input_t *input = vam->input; + vl_api_one_pitr_set_locator_set_t *mp; + u8 is_add = 1; + u8 *ls_name = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "locator-set %s", &ls_name)) + ls_name_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!ls_name_set) + { + errmsg ("locator-set name not set!"); + return -99; + } + + M (ONE_PITR_SET_LOCATOR_SET, mp); + + mp->is_add = is_add; + clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name)); + vec_free (ls_name); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_lisp_pitr_set_locator_set api_one_pitr_set_locator_set + +static int +api_one_nsh_set_locator_set (vat_main_t * vam) +{ + u8 ls_name_set = 0; + unformat_input_t *input = vam->input; + vl_api_one_nsh_set_locator_set_t *mp; + u8 is_add = 1; + u8 *ls_name = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "ls %s", &ls_name)) + ls_name_set = 1; + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!ls_name_set && is_add) + { + errmsg ("locator-set name not set!"); + return -99; + } + + M (ONE_NSH_SET_LOCATOR_SET, mp); + + mp->is_add = is_add; + clib_memcpy (mp->ls_name, ls_name, vec_len (ls_name)); + vec_free (ls_name); + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +static int +api_show_one_pitr (vat_main_t * vam) +{ + vl_api_show_one_pitr_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "lisp status:"); + } + + M (SHOW_ONE_PITR, mp); + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_show_lisp_pitr api_show_one_pitr + +static int +api_one_use_petr (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_use_petr_t *mp; + u8 is_add = 0; + ip_address_t ip; + int ret; + + memset (&ip, 0, sizeof (ip)); + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "disable")) + is_add = 0; + else + if (unformat (input, "%U", unformat_ip4_address, &ip_addr_v4 (&ip))) + { + is_add = 1; + ip_addr_version (&ip) = IP4; + } + else + if (unformat (input, "%U", unformat_ip6_address, &ip_addr_v6 (&ip))) + { + is_add = 1; + ip_addr_version (&ip) = IP6; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + M (ONE_USE_PETR, mp); + + mp->is_add = is_add; + if (is_add) + { + mp->is_ip4 = ip_addr_version (&ip) == IP4 ? 1 : 0; + if (mp->is_ip4) + clib_memcpy (mp->address, &ip, 4); + else + clib_memcpy (mp->address, &ip, 16); + } + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_lisp_use_petr api_one_use_petr + +static int +api_show_one_nsh_mapping (vat_main_t * vam) +{ + vl_api_show_one_use_petr_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "local ONE NSH mapping:"); + } + + M (SHOW_ONE_NSH_MAPPING, mp); + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_use_petr (vat_main_t * vam) +{ + vl_api_show_one_use_petr_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "Proxy-ETR status:"); + } + + M (SHOW_ONE_USE_PETR, mp); + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_show_lisp_use_petr api_show_one_use_petr + +/** + * Add/delete mapping between vni and vrf + */ +static int +api_one_eid_table_add_del_map (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_eid_table_add_del_map_t *mp; + u8 is_add = 1, vni_set = 0, vrf_set = 0, bd_index_set = 0; + u32 vni, vrf, bd_index; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "vrf %d", &vrf)) + vrf_set = 1; + else if (unformat (input, "bd_index %d", &bd_index)) + bd_index_set = 1; + else if (unformat (input, "vni %d", &vni)) + vni_set = 1; + else + break; + } + + if (!vni_set || (!vrf_set && !bd_index_set)) + { + errmsg ("missing arguments!"); + return -99; + } + + if (vrf_set && bd_index_set) + { + errmsg ("error: both vrf and bd entered!"); + return -99; + } + + M (ONE_EID_TABLE_ADD_DEL_MAP, mp); + + mp->is_add = is_add; + mp->vni = htonl (vni); + mp->dp_table = vrf_set ? htonl (vrf) : htonl (bd_index); + mp->is_l2 = bd_index_set; + + /* send */ + S (mp); + + /* wait for reply */ + W (ret); + return ret; +} + +#define api_lisp_eid_table_add_del_map api_one_eid_table_add_del_map + +uword +unformat_negative_mapping_action (unformat_input_t * input, va_list * args) +{ + u32 *action = va_arg (*args, u32 *); + u8 *s = 0; + + if (unformat (input, "%s", &s)) + { + if (!strcmp ((char *) s, "no-action")) + action[0] = 0; + else if (!strcmp ((char *) s, "natively-forward")) + action[0] = 1; + else if (!strcmp ((char *) s, "send-map-request")) + action[0] = 2; + else if (!strcmp ((char *) s, "drop")) + action[0] = 3; + else + { + clib_warning ("invalid action: '%s'", s); + action[0] = 3; + } + } + else + return 0; + + vec_free (s); + return 1; +} + +/** + * Add/del remote mapping to/from ONE control plane + * + * @param vam vpp API test context + * @return return code + */ +static int +api_one_add_del_remote_mapping (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_remote_mapping_t *mp; + u32 vni = 0; + lisp_eid_vat_t _eid, *eid = &_eid; + lisp_eid_vat_t _seid, *seid = &_seid; + u8 is_add = 1, del_all = 0, eid_set = 0, seid_set = 0; + u32 action = ~0, p, w, data_len; + ip4_address_t rloc4; + ip6_address_t rloc6; + vl_api_remote_locator_t *rlocs = 0, rloc, *curr_rloc = 0; + int ret; + + memset (&rloc, 0, sizeof (rloc)); + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del-all")) + { + del_all = 1; + } + else if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "add")) + { + is_add = 1; + } + else if (unformat (input, "eid %U", unformat_lisp_eid_vat, eid)) + { + eid_set = 1; + } + else if (unformat (input, "seid %U", unformat_lisp_eid_vat, seid)) + { + seid_set = 1; + } + else if (unformat (input, "vni %d", &vni)) + { + ; + } + else if (unformat (input, "p %d w %d", &p, &w)) + { + if (!curr_rloc) + { + errmsg ("No RLOC configured for setting priority/weight!"); + return -99; + } + curr_rloc->priority = p; + curr_rloc->weight = w; + } + else if (unformat (input, "rloc %U", unformat_ip4_address, &rloc4)) + { + rloc.is_ip4 = 1; + clib_memcpy (&rloc.addr, &rloc4, sizeof (rloc4)); + vec_add1 (rlocs, rloc); + curr_rloc = &rlocs[vec_len (rlocs) - 1]; + } + else if (unformat (input, "rloc %U", unformat_ip6_address, &rloc6)) + { + rloc.is_ip4 = 0; + clib_memcpy (&rloc.addr, &rloc6, sizeof (rloc6)); + vec_add1 (rlocs, rloc); + curr_rloc = &rlocs[vec_len (rlocs) - 1]; + } + else if (unformat (input, "action %U", + unformat_negative_mapping_action, &action)) + { + ; + } + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (0 == eid_set) + { + errmsg ("missing params!"); + return -99; + } + + if (is_add && (~0 == action) && 0 == vec_len (rlocs)) + { + errmsg ("no action set for negative map-reply!"); + return -99; + } + + data_len = vec_len (rlocs) * sizeof (vl_api_remote_locator_t); + + M2 (ONE_ADD_DEL_REMOTE_MAPPING, mp, data_len); + mp->is_add = is_add; + mp->vni = htonl (vni); + mp->action = (u8) action; + mp->is_src_dst = seid_set; + mp->eid_len = eid->len; + mp->seid_len = seid->len; + mp->del_all = del_all; + mp->eid_type = eid->type; + lisp_eid_put_vat (mp->eid, eid->addr, eid->type); + lisp_eid_put_vat (mp->seid, seid->addr, seid->type); + + mp->rloc_num = clib_host_to_net_u32 (vec_len (rlocs)); + clib_memcpy (mp->rlocs, rlocs, data_len); + vec_free (rlocs); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_remote_mapping api_one_add_del_remote_mapping + +/** + * Add/del ONE adjacency. Saves mapping in ONE control plane and updates + * forwarding entries in data-plane accordingly. + * + * @param vam vpp API test context + * @return return code + */ +static int +api_one_add_del_adjacency (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_adjacency_t *mp; + u32 vni = 0; + ip4_address_t leid4, reid4; + ip6_address_t leid6, reid6; + u8 reid_mac[6] = { 0 }; + u8 leid_mac[6] = { 0 }; + u8 reid_type, leid_type; + u32 leid_len = 0, reid_len = 0, len; + u8 is_add = 1; + int ret; + + leid_type = reid_type = (u8) ~ 0; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "add")) + { + is_add = 1; + } + else if (unformat (input, "reid %U/%d", unformat_ip4_address, + &reid4, &len)) + { + reid_type = 0; /* ipv4 */ + reid_len = len; + } + else if (unformat (input, "reid %U/%d", unformat_ip6_address, + &reid6, &len)) + { + reid_type = 1; /* ipv6 */ + reid_len = len; + } + else if (unformat (input, "reid %U", unformat_ethernet_address, + reid_mac)) + { + reid_type = 2; /* mac */ + } + else if (unformat (input, "leid %U/%d", unformat_ip4_address, + &leid4, &len)) + { + leid_type = 0; /* ipv4 */ + leid_len = len; + } + else if (unformat (input, "leid %U/%d", unformat_ip6_address, + &leid6, &len)) + { + leid_type = 1; /* ipv6 */ + leid_len = len; + } + else if (unformat (input, "leid %U", unformat_ethernet_address, + leid_mac)) + { + leid_type = 2; /* mac */ + } + else if (unformat (input, "vni %d", &vni)) + { + ; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if ((u8) ~ 0 == reid_type) + { + errmsg ("missing params!"); + return -99; + } + + if (leid_type != reid_type) + { + errmsg ("remote and local EIDs are of different types!"); + return -99; + } + + M (ONE_ADD_DEL_ADJACENCY, mp); + mp->is_add = is_add; + mp->vni = htonl (vni); + mp->leid_len = leid_len; + mp->reid_len = reid_len; + mp->eid_type = reid_type; + + switch (mp->eid_type) + { + case 0: + clib_memcpy (mp->leid, &leid4, sizeof (leid4)); + clib_memcpy (mp->reid, &reid4, sizeof (reid4)); + break; + case 1: + clib_memcpy (mp->leid, &leid6, sizeof (leid6)); + clib_memcpy (mp->reid, &reid6, sizeof (reid6)); + break; + case 2: + clib_memcpy (mp->leid, leid_mac, 6); + clib_memcpy (mp->reid, reid_mac, 6); + break; + default: + errmsg ("unknown EID type %d!", mp->eid_type); + return 0; + } + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_adjacency api_one_add_del_adjacency + +uword +unformat_gpe_encap_mode (unformat_input_t * input, va_list * args) +{ + u32 *mode = va_arg (*args, u32 *); + + if (unformat (input, "lisp")) + *mode = 0; + else if (unformat (input, "vxlan")) + *mode = 1; + else + return 0; + + return 1; +} + +static int +api_gpe_get_encap_mode (vat_main_t * vam) +{ + vl_api_gpe_get_encap_mode_t *mp; + int ret; + + /* Construct the API message */ + M (GPE_GET_ENCAP_MODE, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_gpe_set_encap_mode (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_gpe_set_encap_mode_t *mp; + int ret; + u32 mode = 0; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_gpe_encap_mode, &mode)) + ; + else + break; + } + + /* Construct the API message */ + M (GPE_SET_ENCAP_MODE, mp); + + mp->mode = mode; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_lisp_gpe_add_del_iface (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_gpe_add_del_iface_t *mp; + u8 action_set = 0, is_add = 1, is_l2 = 0, dp_table_set = 0, vni_set = 0; + u32 dp_table = 0, vni = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "up")) + { + action_set = 1; + is_add = 1; + } + else if (unformat (input, "down")) + { + action_set = 1; + is_add = 0; + } + else if (unformat (input, "table_id %d", &dp_table)) + { + dp_table_set = 1; + } + else if (unformat (input, "bd_id %d", &dp_table)) + { + dp_table_set = 1; + is_l2 = 1; + } + else if (unformat (input, "vni %d", &vni)) + { + vni_set = 1; + } + else + break; + } + + if (action_set == 0) + { + errmsg ("Action not set"); + return -99; + } + if (dp_table_set == 0 || vni_set == 0) + { + errmsg ("vni and dp_table must be set"); + return -99; + } + + /* Construct the API message */ + M (GPE_ADD_DEL_IFACE, mp); + + mp->is_add = is_add; + mp->dp_table = clib_host_to_net_u32 (dp_table); + mp->is_l2 = is_l2; + mp->vni = clib_host_to_net_u32 (vni); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_map_register_fallback_threshold (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_register_fallback_threshold_t *mp; + u32 value = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%u", &value)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("fallback threshold value is missing!"); + return -99; + } + + M (ONE_MAP_REGISTER_FALLBACK_THRESHOLD, mp); + mp->value = clib_host_to_net_u32 (value); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_map_register_fallback_threshold (vat_main_t * vam) +{ + vl_api_show_one_map_register_fallback_threshold_t *mp; + int ret; + + M (SHOW_ONE_MAP_REGISTER_FALLBACK_THRESHOLD, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +uword +unformat_lisp_transport_protocol (unformat_input_t * input, va_list * args) +{ + u32 *proto = va_arg (*args, u32 *); + + if (unformat (input, "udp")) + *proto = 1; + else if (unformat (input, "api")) + *proto = 2; + else + return 0; + + return 1; +} + +static int +api_one_set_transport_protocol (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_set_transport_protocol_t *mp; + u8 is_set = 0; + u32 protocol = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", unformat_lisp_transport_protocol, &protocol)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("Transport protocol missing!"); + return -99; + } + + M (ONE_SET_TRANSPORT_PROTOCOL, mp); + mp->protocol = (u8) protocol; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_get_transport_protocol (vat_main_t * vam) +{ + vl_api_one_get_transport_protocol_t *mp; + int ret; + + M (ONE_GET_TRANSPORT_PROTOCOL, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_map_register_set_ttl (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_map_register_set_ttl_t *mp; + u32 ttl = 0; + u8 is_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%u", &ttl)) + is_set = 1; + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_set) + { + errmsg ("TTL value missing!"); + return -99; + } + + M (ONE_MAP_REGISTER_SET_TTL, mp); + mp->ttl = clib_host_to_net_u32 (ttl); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_map_register_ttl (vat_main_t * vam) +{ + vl_api_show_one_map_register_ttl_t *mp; + int ret; + + M (SHOW_ONE_MAP_REGISTER_TTL, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +/** + * Add/del map request itr rlocs from ONE control plane and updates + * + * @param vam vpp API test context + * @return return code + */ +static int +api_one_add_del_map_request_itr_rlocs (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_add_del_map_request_itr_rlocs_t *mp; + u8 *locator_set_name = 0; + u8 locator_set_name_set = 0; + u8 is_add = 1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "del")) + { + is_add = 0; + } + else if (unformat (input, "%_%v%_", &locator_set_name)) + { + locator_set_name_set = 1; + } + else + { + clib_warning ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (is_add && !locator_set_name_set) + { + errmsg ("itr-rloc is not set!"); + return -99; + } + + if (is_add && vec_len (locator_set_name) > 64) + { + errmsg ("itr-rloc locator-set name too long"); + vec_free (locator_set_name); + return -99; + } + + M (ONE_ADD_DEL_MAP_REQUEST_ITR_RLOCS, mp); + mp->is_add = is_add; + if (is_add) + { + clib_memcpy (mp->locator_set_name, locator_set_name, + vec_len (locator_set_name)); + } + else + { + memset (mp->locator_set_name, 0, sizeof (mp->locator_set_name)); + } + vec_free (locator_set_name); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_add_del_map_request_itr_rlocs api_one_add_del_map_request_itr_rlocs + +static int +api_one_locator_dump (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_one_locator_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 is_index_set = 0, is_name_set = 0; + u8 *ls_name = 0; + u32 ls_index = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "ls_name %_%v%_", &ls_name)) + { + is_name_set = 1; + } + else if (unformat (input, "ls_index %d", &ls_index)) + { + is_index_set = 1; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!is_index_set && !is_name_set) + { + errmsg ("error: expected one of index or name!"); + return -99; + } + + if (is_index_set && is_name_set) + { + errmsg ("error: only one param expected!"); + return -99; + } + + if (vec_len (ls_name) > 62) + { + errmsg ("error: locator set name too long!"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%=16s%=16s%=16s", "locator", "priority", "weight"); + } + + M (ONE_LOCATOR_DUMP, mp); + mp->is_index_set = is_index_set; + + if (is_index_set) + mp->ls_index = clib_host_to_net_u32 (ls_index); + else + { + vec_add1 (ls_name, 0); + strncpy ((char *) mp->ls_name, (char *) ls_name, + sizeof (mp->ls_name) - 1); + } + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_locator_dump api_one_locator_dump + +static int +api_one_locator_set_dump (vat_main_t * vam) +{ + vl_api_one_locator_set_dump_t *mp; + vl_api_control_ping_t *mp_ping; + unformat_input_t *input = vam->input; + u8 filter = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "local")) + { + filter = 1; + } + else if (unformat (input, "remote")) + { + filter = 2; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!vam->json_output) + { + print (vam->ofp, "%=10s%=15s", "ls_index", "ls_name"); + } + + M (ONE_LOCATOR_SET_DUMP, mp); + + mp->filter = filter; + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_locator_set_dump api_one_locator_set_dump + +static int +api_one_eid_table_map_dump (vat_main_t * vam) +{ + u8 is_l2 = 0; + u8 mode_set = 0; + unformat_input_t *input = vam->input; + vl_api_one_eid_table_map_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "l2")) + { + is_l2 = 1; + mode_set = 1; + } + else if (unformat (input, "l3")) + { + is_l2 = 0; + mode_set = 1; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, input); + return -99; + } + } + + if (!mode_set) + { + errmsg ("expected one of 'l2' or 'l3' parameter!"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%=10s%=10s", "VNI", is_l2 ? "BD" : "VRF"); + } + + M (ONE_EID_TABLE_MAP_DUMP, mp); + mp->is_l2 = is_l2; + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_eid_table_map_dump api_one_eid_table_map_dump + +static int +api_one_eid_table_vni_dump (vat_main_t * vam) +{ + vl_api_one_eid_table_vni_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "VNI"); + } + + M (ONE_EID_TABLE_VNI_DUMP, mp); + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_eid_table_vni_dump api_one_eid_table_vni_dump + +static int +api_one_eid_table_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_one_eid_table_dump_t *mp; + vl_api_control_ping_t *mp_ping; + struct in_addr ip4; + struct in6_addr ip6; + u8 mac[6]; + u8 eid_type = ~0, eid_set = 0; + u32 prefix_length = ~0, t, vni = 0; + u8 filter = 0; + int ret; + lisp_nsh_api_t nsh; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "eid %U/%d", unformat_ip4_address, &ip4, &t)) + { + eid_set = 1; + eid_type = 0; + prefix_length = t; + } + else if (unformat (i, "eid %U/%d", unformat_ip6_address, &ip6, &t)) + { + eid_set = 1; + eid_type = 1; + prefix_length = t; + } + else if (unformat (i, "eid %U", unformat_ethernet_address, mac)) + { + eid_set = 1; + eid_type = 2; + } + else if (unformat (i, "eid %U", unformat_nsh_address, &nsh)) + { + eid_set = 1; + eid_type = 3; + } + else if (unformat (i, "vni %d", &t)) + { + vni = t; + } + else if (unformat (i, "local")) + { + filter = 1; + } + else if (unformat (i, "remote")) + { + filter = 2; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vam->json_output) + { + print (vam->ofp, "%-35s%-20s%-30s%-20s%-20s%-10s%-20s", "EID", + "type", "ls_index", "ttl", "authoritative", "key_id", "key"); + } + + M (ONE_EID_TABLE_DUMP, mp); + + mp->filter = filter; + if (eid_set) + { + mp->eid_set = 1; + mp->vni = htonl (vni); + mp->eid_type = eid_type; + switch (eid_type) + { + case 0: + mp->prefix_length = prefix_length; + clib_memcpy (mp->eid, &ip4, sizeof (ip4)); + break; + case 1: + mp->prefix_length = prefix_length; + clib_memcpy (mp->eid, &ip6, sizeof (ip6)); + break; + case 2: + clib_memcpy (mp->eid, mac, sizeof (mac)); + break; + case 3: + clib_memcpy (mp->eid, &nsh, sizeof (nsh)); + break; + default: + errmsg ("unknown EID type %d!", eid_type); + return -99; + } + } + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_eid_table_dump api_one_eid_table_dump + +static int +api_lisp_gpe_fwd_entries_get (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_gpe_fwd_entries_get_t *mp; + u8 vni_set = 0; + u32 vni = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vni %d", &vni)) + { + vni_set = 1; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vni_set) + { + errmsg ("vni not set!"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%10s %10s %s %40s", "fwd_index", "dp_table", + "leid", "reid"); + } + + M (GPE_FWD_ENTRIES_GET, mp); + mp->vni = clib_host_to_net_u32 (vni); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define vl_api_gpe_native_fwd_rpaths_get_reply_t_endian vl_noop_handler +#define vl_api_gpe_native_fwd_rpaths_get_reply_t_print vl_noop_handler +#define vl_api_gpe_fwd_entry_vnis_get_reply_t_endian vl_noop_handler +#define vl_api_gpe_fwd_entry_vnis_get_reply_t_print vl_noop_handler +#define vl_api_gpe_fwd_entries_get_reply_t_endian vl_noop_handler +#define vl_api_gpe_fwd_entries_get_reply_t_print vl_noop_handler +#define vl_api_gpe_fwd_entry_path_details_t_endian vl_noop_handler +#define vl_api_gpe_fwd_entry_path_details_t_print vl_noop_handler + +static int +api_one_adjacencies_get (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_one_adjacencies_get_t *mp; + u8 vni_set = 0; + u32 vni = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "vni %d", &vni)) + { + vni_set = 1; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!vni_set) + { + errmsg ("vni not set!"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%s %40s", "leid", "reid"); + } + + M (ONE_ADJACENCIES_GET, mp); + mp->vni = clib_host_to_net_u32 (vni); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_adjacencies_get api_one_adjacencies_get + +static int +api_gpe_native_fwd_rpaths_get (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_gpe_native_fwd_rpaths_get_t *mp; + int ret; + u8 ip_family_set = 0, is_ip4 = 1; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "ip4")) + { + ip_family_set = 1; + is_ip4 = 1; + } + else if (unformat (i, "ip6")) + { + ip_family_set = 1; + is_ip4 = 0; + } + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!ip_family_set) + { + errmsg ("ip family not set!"); + return -99; + } + + M (GPE_NATIVE_FWD_RPATHS_GET, mp); + mp->is_ip4 = is_ip4; + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_gpe_fwd_entry_vnis_get (vat_main_t * vam) +{ + vl_api_gpe_fwd_entry_vnis_get_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "VNIs"); + } + + M (GPE_FWD_ENTRY_VNIS_GET, mp); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_gpe_add_del_native_fwd_rpath (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_gpe_add_del_native_fwd_rpath_t *mp; + int ret = 0; + u8 is_add = 1, ip_set = 0, is_ip4 = 1; + struct in_addr ip4; + struct in6_addr ip6; + u32 table_id = 0, nh_sw_if_index = ~0; + + memset (&ip4, 0, sizeof (ip4)); + memset (&ip6, 0, sizeof (ip6)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "via %U %U", unformat_ip4_address, &ip4, + api_unformat_sw_if_index, vam, &nh_sw_if_index)) + { + ip_set = 1; + is_ip4 = 1; + } + else if (unformat (i, "via %U %U", unformat_ip6_address, &ip6, + api_unformat_sw_if_index, vam, &nh_sw_if_index)) + { + ip_set = 1; + is_ip4 = 0; + } + else if (unformat (i, "via %U", unformat_ip4_address, &ip4)) + { + ip_set = 1; + is_ip4 = 1; + nh_sw_if_index = ~0; + } + else if (unformat (i, "via %U", unformat_ip6_address, &ip6)) + { + ip_set = 1; + is_ip4 = 0; + nh_sw_if_index = ~0; + } + else if (unformat (i, "table %d", &table_id)) + ; + else + { + errmsg ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (!ip_set) + { + errmsg ("nh addr not set!"); + return -99; + } + + M (GPE_ADD_DEL_NATIVE_FWD_RPATH, mp); + mp->is_add = is_add; + mp->table_id = clib_host_to_net_u32 (table_id); + mp->nh_sw_if_index = clib_host_to_net_u32 (nh_sw_if_index); + mp->is_ip4 = is_ip4; + if (is_ip4) + clib_memcpy (mp->nh_addr, &ip4, sizeof (ip4)); + else + clib_memcpy (mp->nh_addr, &ip6, sizeof (ip6)); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_map_server_dump (vat_main_t * vam) +{ + vl_api_one_map_server_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "Map server"); + } + + M (ONE_MAP_SERVER_DUMP, mp); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_map_server_dump api_one_map_server_dump + +static int +api_one_map_resolver_dump (vat_main_t * vam) +{ + vl_api_one_map_resolver_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "Map resolver"); + } + + M (ONE_MAP_RESOLVER_DUMP, mp); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_map_resolver_dump api_one_map_resolver_dump + +static int +api_one_stats_flush (vat_main_t * vam) +{ + vl_api_one_stats_flush_t *mp; + int ret = 0; + + M (ONE_STATS_FLUSH, mp); + S (mp); + W (ret); + return ret; +} + +static int +api_one_stats_dump (vat_main_t * vam) +{ + vl_api_one_stats_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (ONE_STATS_DUMP, mp); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_show_one_status (vat_main_t * vam) +{ + vl_api_show_one_status_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%-20s%-16s", "ONE status", "locator-set"); + } + + M (SHOW_ONE_STATUS, mp); + /* send it... */ + S (mp); + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_show_lisp_status api_show_one_status + +static int +api_lisp_gpe_fwd_entry_path_dump (vat_main_t * vam) +{ + vl_api_gpe_fwd_entry_path_dump_t *mp; + vl_api_control_ping_t *mp_ping; + unformat_input_t *i = vam->input; + u32 fwd_entry_index = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "index %d", &fwd_entry_index)) + ; + else + break; + } + + if (~0 == fwd_entry_index) + { + errmsg ("no index specified!"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "first line"); + } + + M (GPE_FWD_ENTRY_PATH_DUMP, mp); + + /* send it... */ + S (mp); + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_one_get_map_request_itr_rlocs (vat_main_t * vam) +{ + vl_api_one_get_map_request_itr_rlocs_t *mp; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "itr-rlocs:"); + } + + M (ONE_GET_MAP_REQUEST_ITR_RLOCS, mp); + /* send it... */ + S (mp); + /* Wait for a reply... */ + W (ret); + return ret; +} + +#define api_lisp_get_map_request_itr_rlocs api_one_get_map_request_itr_rlocs + +static int +api_af_packet_create (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_af_packet_create_t *mp; + u8 *host_if_name = 0; + u8 hw_addr[6]; + u8 random_hw_addr = 1; + int ret; + + memset (hw_addr, 0, sizeof (hw_addr)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %s", &host_if_name)) + vec_add1 (host_if_name, 0); + else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr)) + random_hw_addr = 0; + else + break; + } + + if (!vec_len (host_if_name)) + { + errmsg ("host-interface name must be specified"); + return -99; + } + + if (vec_len (host_if_name) > 64) + { + errmsg ("host-interface name too long"); + return -99; + } + + M (AF_PACKET_CREATE, mp); + + clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name)); + clib_memcpy (mp->hw_addr, hw_addr, 6); + mp->use_random_hw_addr = random_hw_addr; + vec_free (host_if_name); + + S (mp); + + /* *INDENT-OFF* */ + W2 (ret, + ({ + if (ret == 0) + fprintf (vam->ofp ? vam->ofp : stderr, + " new sw_if_index = %d\n", vam->sw_if_index); + })); + /* *INDENT-ON* */ + return ret; +} + +static int +api_af_packet_delete (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_af_packet_delete_t *mp; + u8 *host_if_name = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %s", &host_if_name)) + vec_add1 (host_if_name, 0); + else + break; + } + + if (!vec_len (host_if_name)) + { + errmsg ("host-interface name must be specified"); + return -99; + } + + if (vec_len (host_if_name) > 64) + { + errmsg ("host-interface name too long"); + return -99; + } + + M (AF_PACKET_DELETE, mp); + + clib_memcpy (mp->host_if_name, host_if_name, vec_len (host_if_name)); + vec_free (host_if_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_policer_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_policer_add_del_t *mp; + 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; + u8 color_aware = 0; + sse2_qos_pol_action_params_st conform_action, exceed_action, violate_action; + int ret; + + conform_action.action_type = SSE2_QOS_ACTION_TRANSMIT; + conform_action.dscp = 0; + exceed_action.action_type = SSE2_QOS_ACTION_MARK_AND_TRANSMIT; + exceed_action.dscp = 0; + violate_action.action_type = SSE2_QOS_ACTION_DROP; + violate_action.dscp = 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 if (unformat (i, "conform_action %U", unformat_policer_action_type, + &conform_action)) + ; + else if (unformat (i, "exceed_action %U", unformat_policer_action_type, + &exceed_action)) + ; + else if (unformat (i, "violate_action %U", unformat_policer_action_type, + &violate_action)) + ; + else if (unformat (i, "color-aware")) + color_aware = 1; + 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, mp); + + clib_memcpy (mp->name, name, vec_len (name)); + vec_free (name); + mp->is_add = is_add; + mp->cir = ntohl (cir); + mp->eir = ntohl (eir); + mp->cb = clib_net_to_host_u64 (cb); + mp->eb = clib_net_to_host_u64 (eb); + mp->rate_type = rate_type; + mp->round_type = round_type; + mp->type = type; + mp->conform_action_type = conform_action.action_type; + mp->conform_dscp = conform_action.dscp; + mp->exceed_action_type = exceed_action.action_type; + mp->exceed_dscp = exceed_action.dscp; + mp->violate_action_type = violate_action.action_type; + mp->violate_dscp = violate_action.dscp; + mp->color_aware = color_aware; + + S (mp); + W (ret); + return ret; +} + +static int +api_policer_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_policer_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 *match_name = 0; + u8 match_name_valid = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %s", &match_name)) + { + vec_add1 (match_name, 0); + match_name_valid = 1; + } + else + break; + } + + M (POLICER_DUMP, mp); + mp->match_name_valid = match_name_valid; + clib_memcpy (mp->match_name, match_name, vec_len (match_name)); + vec_free (match_name); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_policer_classify_set_interface (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_policer_classify_set_interface_t *mp; + u32 sw_if_index; + int sw_if_index_set; + u32 ip4_table_index = ~0; + u32 ip6_table_index = ~0; + u32 l2_table_index = ~0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "ip4-table %d", &ip4_table_index)) + ; + else if (unformat (i, "ip6-table %d", &ip6_table_index)) + ; + else if (unformat (i, "l2-table %d", &l2_table_index)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (POLICER_CLASSIFY_SET_INTERFACE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->ip4_table_index = ntohl (ip4_table_index); + mp->ip6_table_index = ntohl (ip6_table_index); + mp->l2_table_index = ntohl (l2_table_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_policer_classify_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_policer_classify_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 type = POLICER_CLASSIFY_N_TABLES; + int ret; + + if (unformat (i, "type %U", unformat_policer_classify_table_type, &type)) + ; + else + { + errmsg ("classify table type must be specified"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table"); + } + + M (POLICER_CLASSIFY_DUMP, mp); + mp->type = type; + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_netmap_create (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_netmap_create_t *mp; + u8 *if_name = 0; + u8 hw_addr[6]; + u8 random_hw_addr = 1; + u8 is_pipe = 0; + u8 is_master = 0; + int ret; + + memset (hw_addr, 0, sizeof (hw_addr)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %s", &if_name)) + vec_add1 (if_name, 0); + else if (unformat (i, "hw_addr %U", unformat_ethernet_address, hw_addr)) + random_hw_addr = 0; + else if (unformat (i, "pipe")) + is_pipe = 1; + else if (unformat (i, "master")) + is_master = 1; + else if (unformat (i, "slave")) + is_master = 0; + else + break; + } + + if (!vec_len (if_name)) + { + errmsg ("interface name must be specified"); + return -99; + } + + if (vec_len (if_name) > 64) + { + errmsg ("interface name too long"); + return -99; + } + + M (NETMAP_CREATE, mp); + + clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name)); + clib_memcpy (mp->hw_addr, hw_addr, 6); + mp->use_random_hw_addr = random_hw_addr; + mp->is_pipe = is_pipe; + mp->is_master = is_master; + vec_free (if_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_netmap_delete (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_netmap_delete_t *mp; + u8 *if_name = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "name %s", &if_name)) + vec_add1 (if_name, 0); + else + break; + } + + if (!vec_len (if_name)) + { + errmsg ("interface name must be specified"); + return -99; + } + + if (vec_len (if_name) > 64) + { + errmsg ("interface name too long"); + return -99; + } + + M (NETMAP_DELETE, mp); + + clib_memcpy (mp->netmap_if_name, if_name, vec_len (if_name)); + vec_free (if_name); + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_mpls_fib_path_print (vat_main_t * vam, vl_api_fib_path2_t * fp) +{ + if (fp->afi == IP46_TYPE_IP6) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip6_address, fp->next_hop); + else if (fp->afi == IP46_TYPE_IP4) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip4_address, fp->next_hop); +} + +static void +vl_api_mpls_fib_path_json_print (vat_json_node_t * node, + vl_api_fib_path2_t * fp) +{ + struct in_addr ip4; + struct in6_addr ip6; + + vat_json_object_add_uint (node, "weight", ntohl (fp->weight)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index)); + vat_json_object_add_uint (node, "is_local", fp->is_local); + vat_json_object_add_uint (node, "is_drop", fp->is_drop); + vat_json_object_add_uint (node, "is_unreach", fp->is_unreach); + vat_json_object_add_uint (node, "is_prohibit", fp->is_prohibit); + vat_json_object_add_uint (node, "next_hop_afi", fp->afi); + if (fp->afi == IP46_TYPE_IP4) + { + clib_memcpy (&ip4, &fp->next_hop, sizeof (ip4)); + vat_json_object_add_ip4 (node, "next_hop", ip4); + } + else if (fp->afi == IP46_TYPE_IP6) + { + clib_memcpy (&ip6, &fp->next_hop, sizeof (ip6)); + vat_json_object_add_ip6 (node, "next_hop", ip6); + } +} + +static void +vl_api_mpls_tunnel_details_t_handler (vl_api_mpls_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->mt_count); + vl_api_fib_path2_t *fp; + i32 i; + + print (vam->ofp, "[%d]: sw_if_index %d via:", + ntohl (mp->mt_tunnel_index), ntohl (mp->mt_sw_if_index)); + fp = mp->mt_paths; + for (i = 0; i < count; i++) + { + vl_api_mpls_fib_path_print (vam, fp); + fp++; + } + + print (vam->ofp, ""); +} + +#define vl_api_mpls_tunnel_details_t_endian vl_noop_handler +#define vl_api_mpls_tunnel_details_t_print vl_noop_handler + +static void +vl_api_mpls_tunnel_details_t_handler_json (vl_api_mpls_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + int count = ntohl (mp->mt_count); + vl_api_fib_path2_t *fp; + i32 i; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "tunnel_index", + ntohl (mp->mt_tunnel_index)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->mt_sw_if_index)); + + vat_json_object_add_uint (node, "l2_only", mp->mt_l2_only); + + fp = mp->mt_paths; + for (i = 0; i < count; i++) + { + vl_api_mpls_fib_path_json_print (node, fp); + fp++; + } +} + +static int +api_mpls_tunnel_dump (vat_main_t * vam) +{ + vl_api_mpls_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + i32 index = -1; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (vam->input) != UNFORMAT_END_OF_INPUT) + { + if (!unformat (vam->input, "tunnel_index %d", &index)) + { + index = -1; + break; + } + } + + print (vam->ofp, " tunnel_index %d", index); + + M (MPLS_TUNNEL_DUMP, mp); + mp->tunnel_index = htonl (index); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +#define vl_api_mpls_fib_details_t_endian vl_noop_handler +#define vl_api_mpls_fib_details_t_print vl_noop_handler + + +static void +vl_api_mpls_fib_details_t_handler (vl_api_mpls_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vl_api_fib_path2_t *fp; + int i; + + print (vam->ofp, + "table-id %d, label %u, ess_bit %u", + ntohl (mp->table_id), ntohl (mp->label), mp->eos_bit); + fp = mp->path; + for (i = 0; i < count; i++) + { + vl_api_mpls_fib_path_print (vam, fp); + fp++; + } +} + +static void vl_api_mpls_fib_details_t_handler_json + (vl_api_mpls_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vat_json_node_t *node = NULL; + vl_api_fib_path2_t *fp; + int i; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "table", ntohl (mp->table_id)); + vat_json_object_add_uint (node, "s_bit", mp->eos_bit); + vat_json_object_add_uint (node, "label", ntohl (mp->label)); + vat_json_object_add_uint (node, "path_count", count); + fp = mp->path; + for (i = 0; i < count; i++) + { + vl_api_mpls_fib_path_json_print (node, fp); + fp++; + } +} + +static int +api_mpls_fib_dump (vat_main_t * vam) +{ + vl_api_mpls_fib_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (MPLS_FIB_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +#define vl_api_ip_fib_details_t_endian vl_noop_handler +#define vl_api_ip_fib_details_t_print vl_noop_handler + +static void +vl_api_ip_fib_details_t_handler (vl_api_ip_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vl_api_fib_path_t *fp; + int i; + + print (vam->ofp, + "table-id %d, prefix %U/%d", + ntohl (mp->table_id), format_ip4_address, mp->address, + mp->address_length); + fp = mp->path; + for (i = 0; i < count; i++) + { + if (fp->afi == IP46_TYPE_IP6) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip6_address, fp->next_hop); + else if (fp->afi == IP46_TYPE_IP4) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip4_address, fp->next_hop); + fp++; + } +} + +static void vl_api_ip_fib_details_t_handler_json + (vl_api_ip_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vat_json_node_t *node = NULL; + struct in_addr ip4; + struct in6_addr ip6; + vl_api_fib_path_t *fp; + int i; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "table", ntohl (mp->table_id)); + clib_memcpy (&ip4, &mp->address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "prefix", ip4); + vat_json_object_add_uint (node, "mask_length", mp->address_length); + vat_json_object_add_uint (node, "path_count", count); + fp = mp->path; + for (i = 0; i < count; i++) + { + vat_json_object_add_uint (node, "weight", ntohl (fp->weight)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index)); + vat_json_object_add_uint (node, "is_local", fp->is_local); + vat_json_object_add_uint (node, "is_drop", fp->is_drop); + vat_json_object_add_uint (node, "is_unreach", fp->is_unreach); + vat_json_object_add_uint (node, "is_prohibit", fp->is_prohibit); + vat_json_object_add_uint (node, "next_hop_afi", fp->afi); + if (fp->afi == IP46_TYPE_IP4) + { + clib_memcpy (&ip4, &fp->next_hop, sizeof (ip4)); + vat_json_object_add_ip4 (node, "next_hop", ip4); + } + else if (fp->afi == IP46_TYPE_IP6) + { + clib_memcpy (&ip6, &fp->next_hop, sizeof (ip6)); + vat_json_object_add_ip6 (node, "next_hop", ip6); + } + } +} + +static int +api_ip_fib_dump (vat_main_t * vam) +{ + vl_api_ip_fib_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (IP_FIB_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_ip_mfib_dump (vat_main_t * vam) +{ + vl_api_ip_mfib_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (IP_MFIB_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void vl_api_ip_neighbor_details_t_handler + (vl_api_ip_neighbor_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%c %U %U", + (mp->is_static) ? 'S' : 'D', + format_ethernet_address, &mp->mac_address, + (mp->is_ipv6) ? format_ip6_address : format_ip4_address, + &mp->ip_address); +} + +static void vl_api_ip_neighbor_details_t_handler_json + (vl_api_ip_neighbor_details_t * mp) +{ + + vat_main_t *vam = &vat_main; + vat_json_node_t *node; + struct in_addr ip4; + struct in6_addr ip6; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_string_copy (node, "flag", + (mp->is_static) ? (u8 *) "static" : (u8 *) + "dynamic"); + + vat_json_object_add_string_copy (node, "link_layer", + format (0, "%U", format_ethernet_address, + &mp->mac_address)); + + if (mp->is_ipv6) + { + clib_memcpy (&ip6, &mp->ip_address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "ip_address", ip6); + } + else + { + clib_memcpy (&ip4, &mp->ip_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "ip_address", ip4); + } +} + +static int +api_ip_neighbor_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ip_neighbor_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 is_ipv6 = 0; + u32 sw_if_index = ~0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "ip6")) + is_ipv6 = 1; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (IP_NEIGHBOR_DUMP, mp); + mp->is_ipv6 = (u8) is_ipv6; + mp->sw_if_index = ntohl (sw_if_index); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +#define vl_api_ip6_fib_details_t_endian vl_noop_handler +#define vl_api_ip6_fib_details_t_print vl_noop_handler + +static void +vl_api_ip6_fib_details_t_handler (vl_api_ip6_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vl_api_fib_path_t *fp; + int i; + + print (vam->ofp, + "table-id %d, prefix %U/%d", + ntohl (mp->table_id), format_ip6_address, mp->address, + mp->address_length); + fp = mp->path; + for (i = 0; i < count; i++) + { + if (fp->afi == IP46_TYPE_IP6) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip6_address, fp->next_hop); + else if (fp->afi == IP46_TYPE_IP4) + print (vam->ofp, + " weight %d, sw_if_index %d, is_local %d, is_drop %d, " + "is_unreach %d, is_prohitbit %d, afi %d, next_hop %U", + ntohl (fp->weight), ntohl (fp->sw_if_index), fp->is_local, + fp->is_drop, fp->is_unreach, fp->is_prohibit, fp->afi, + format_ip4_address, fp->next_hop); + fp++; + } +} + +static void vl_api_ip6_fib_details_t_handler_json + (vl_api_ip6_fib_details_t * mp) +{ + vat_main_t *vam = &vat_main; + int count = ntohl (mp->count); + vat_json_node_t *node = NULL; + struct in_addr ip4; + struct in6_addr ip6; + vl_api_fib_path_t *fp; + int i; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "table", ntohl (mp->table_id)); + clib_memcpy (&ip6, &mp->address, sizeof (ip6)); + vat_json_object_add_ip6 (node, "prefix", ip6); + vat_json_object_add_uint (node, "mask_length", mp->address_length); + vat_json_object_add_uint (node, "path_count", count); + fp = mp->path; + for (i = 0; i < count; i++) + { + vat_json_object_add_uint (node, "weight", ntohl (fp->weight)); + vat_json_object_add_uint (node, "sw_if_index", ntohl (fp->sw_if_index)); + vat_json_object_add_uint (node, "is_local", fp->is_local); + vat_json_object_add_uint (node, "is_drop", fp->is_drop); + vat_json_object_add_uint (node, "is_unreach", fp->is_unreach); + vat_json_object_add_uint (node, "is_prohibit", fp->is_prohibit); + vat_json_object_add_uint (node, "next_hop_afi", fp->afi); + if (fp->afi == IP46_TYPE_IP4) + { + clib_memcpy (&ip4, &fp->next_hop, sizeof (ip4)); + vat_json_object_add_ip4 (node, "next_hop", ip4); + } + else if (fp->afi == IP46_TYPE_IP6) + { + clib_memcpy (&ip6, &fp->next_hop, sizeof (ip6)); + vat_json_object_add_ip6 (node, "next_hop", ip6); + } + } +} + +static int +api_ip6_fib_dump (vat_main_t * vam) +{ + vl_api_ip6_fib_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (IP6_FIB_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_ip6_mfib_dump (vat_main_t * vam) +{ + vl_api_ip6_mfib_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + M (IP6_MFIB_DUMP, mp); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +int +api_classify_table_ids (vat_main_t * vam) +{ + vl_api_classify_table_ids_t *mp; + int ret; + + /* Construct the API message */ + M (CLASSIFY_TABLE_IDS, mp); + mp->context = 0; + + S (mp); + W (ret); + return ret; +} + +int +api_classify_table_by_interface (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_classify_table_by_interface_t *mp; + + u32 sw_if_index = ~0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (input, "sw_if_index %d", &sw_if_index)) + ; + else + break; + } + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (CLASSIFY_TABLE_BY_INTERFACE, mp); + mp->context = 0; + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +int +api_classify_table_info (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_classify_table_info_t *mp; + + u32 table_id = ~0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table_id %d", &table_id)) + ; + else + break; + } + if (table_id == ~0) + { + errmsg ("missing table id"); + return -99; + } + + /* Construct the API message */ + M (CLASSIFY_TABLE_INFO, mp); + mp->context = 0; + mp->table_id = ntohl (table_id); + + S (mp); + W (ret); + return ret; +} + +int +api_classify_session_dump (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_classify_session_dump_t *mp; + vl_api_control_ping_t *mp_ping; + + u32 table_id = ~0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "table_id %d", &table_id)) + ; + else + break; + } + if (table_id == ~0) + { + errmsg ("missing table id"); + return -99; + } + + /* Construct the API message */ + M (CLASSIFY_SESSION_DUMP, mp); + mp->context = 0; + mp->table_id = ntohl (table_id); + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void +vl_api_ipfix_exporter_details_t_handler (vl_api_ipfix_exporter_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "collector_address %U, collector_port %d, " + "src_address %U, vrf_id %d, path_mtu %u, " + "template_interval %u, udp_checksum %d", + format_ip4_address, mp->collector_address, + ntohs (mp->collector_port), + format_ip4_address, mp->src_address, + ntohl (mp->vrf_id), ntohl (mp->path_mtu), + ntohl (mp->template_interval), mp->udp_checksum); + + vam->retval = 0; + vam->result_ready = 1; +} + +static void + vl_api_ipfix_exporter_details_t_handler_json + (vl_api_ipfix_exporter_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + struct in_addr collector_address; + struct in_addr src_address; + + vat_json_init_object (&node); + clib_memcpy (&collector_address, &mp->collector_address, + sizeof (collector_address)); + vat_json_object_add_ip4 (&node, "collector_address", collector_address); + vat_json_object_add_uint (&node, "collector_port", + ntohs (mp->collector_port)); + clib_memcpy (&src_address, &mp->src_address, sizeof (src_address)); + vat_json_object_add_ip4 (&node, "src_address", src_address); + vat_json_object_add_int (&node, "vrf_id", ntohl (mp->vrf_id)); + vat_json_object_add_uint (&node, "path_mtu", ntohl (mp->path_mtu)); + vat_json_object_add_uint (&node, "template_interval", + ntohl (mp->template_interval)); + vat_json_object_add_int (&node, "udp_checksum", mp->udp_checksum); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + vam->retval = 0; + vam->result_ready = 1; +} + +int +api_ipfix_exporter_dump (vat_main_t * vam) +{ + vl_api_ipfix_exporter_dump_t *mp; + int ret; + + /* Construct the API message */ + M (IPFIX_EXPORTER_DUMP, mp); + mp->context = 0; + + S (mp); + W (ret); + return ret; +} + +static int +api_ipfix_classify_stream_dump (vat_main_t * vam) +{ + vl_api_ipfix_classify_stream_dump_t *mp; + int ret; + + /* Construct the API message */ + M (IPFIX_CLASSIFY_STREAM_DUMP, mp); + mp->context = 0; + + S (mp); + W (ret); + return ret; + /* NOTREACHED */ + return 0; +} + +static void + vl_api_ipfix_classify_stream_details_t_handler + (vl_api_ipfix_classify_stream_details_t * mp) +{ + vat_main_t *vam = &vat_main; + print (vam->ofp, "domain_id %d, src_port %d", + ntohl (mp->domain_id), ntohs (mp->src_port)); + vam->retval = 0; + vam->result_ready = 1; +} + +static void + vl_api_ipfix_classify_stream_details_t_handler_json + (vl_api_ipfix_classify_stream_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_uint (&node, "domain_id", ntohl (mp->domain_id)); + vat_json_object_add_uint (&node, "src_port", ntohs (mp->src_port)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + vam->retval = 0; + vam->result_ready = 1; +} + +static int +api_ipfix_classify_table_dump (vat_main_t * vam) +{ + vl_api_ipfix_classify_table_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%15s%15s%20s", "table_id", "ip_version", + "transport_protocol"); + } + + /* Construct the API message */ + M (IPFIX_CLASSIFY_TABLE_DUMP, mp); + + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static void + vl_api_ipfix_classify_table_details_t_handler + (vl_api_ipfix_classify_table_details_t * mp) +{ + vat_main_t *vam = &vat_main; + print (vam->ofp, "%15d%15d%20d", ntohl (mp->table_id), mp->ip_version, + mp->transport_protocol); +} + +static void + vl_api_ipfix_classify_table_details_t_handler_json + (vl_api_ipfix_classify_table_details_t * mp) +{ + vat_json_node_t *node = NULL; + vat_main_t *vam = &vat_main; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + vat_json_object_add_uint (node, "table_id", ntohl (mp->table_id)); + vat_json_object_add_uint (node, "ip_version", mp->ip_version); + vat_json_object_add_uint (node, "transport_protocol", + mp->transport_protocol); +} + +static int +api_sw_interface_span_enable_disable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_span_enable_disable_t *mp; + u32 src_sw_if_index = ~0; + u32 dst_sw_if_index = ~0; + u8 state = 3; + int ret; + u8 is_l2 = 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat + (i, "src %U", api_unformat_sw_if_index, vam, &src_sw_if_index)) + ; + else if (unformat (i, "src_sw_if_index %d", &src_sw_if_index)) + ; + else + if (unformat + (i, "dst %U", api_unformat_sw_if_index, vam, &dst_sw_if_index)) + ; + else if (unformat (i, "dst_sw_if_index %d", &dst_sw_if_index)) + ; + else if (unformat (i, "disable")) + state = 0; + else if (unformat (i, "rx")) + state = 1; + else if (unformat (i, "tx")) + state = 2; + else if (unformat (i, "both")) + state = 3; + else if (unformat (i, "l2")) + is_l2 = 1; + else + break; + } + + M (SW_INTERFACE_SPAN_ENABLE_DISABLE, mp); + + mp->sw_if_index_from = htonl (src_sw_if_index); + mp->sw_if_index_to = htonl (dst_sw_if_index); + mp->state = state; + mp->is_l2 = is_l2; + + S (mp); + W (ret); + return ret; +} + +static void +vl_api_sw_interface_span_details_t_handler (vl_api_sw_interface_span_details_t + * mp) +{ + vat_main_t *vam = &vat_main; + u8 *sw_if_from_name = 0; + u8 *sw_if_to_name = 0; + u32 sw_if_index_from = ntohl (mp->sw_if_index_from); + u32 sw_if_index_to = ntohl (mp->sw_if_index_to); + char *states[] = { "none", "rx", "tx", "both" }; + hash_pair_t *p; + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, + ({ + if ((u32) p->value[0] == sw_if_index_from) + { + sw_if_from_name = (u8 *)(p->key); + if (sw_if_to_name) + break; + } + if ((u32) p->value[0] == sw_if_index_to) + { + sw_if_to_name = (u8 *)(p->key); + if (sw_if_from_name) + break; + } + })); + /* *INDENT-ON* */ + print (vam->ofp, "%20s => %20s (%s)", + sw_if_from_name, sw_if_to_name, states[mp->state]); +} + +static void + vl_api_sw_interface_span_details_t_handler_json + (vl_api_sw_interface_span_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + u8 *sw_if_from_name = 0; + u8 *sw_if_to_name = 0; + u32 sw_if_index_from = ntohl (mp->sw_if_index_from); + u32 sw_if_index_to = ntohl (mp->sw_if_index_to); + hash_pair_t *p; + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->sw_if_index_by_interface_name, + ({ + if ((u32) p->value[0] == sw_if_index_from) + { + sw_if_from_name = (u8 *)(p->key); + if (sw_if_to_name) + break; + } + if ((u32) p->value[0] == sw_if_index_to) + { + sw_if_to_name = (u8 *)(p->key); + if (sw_if_from_name) + break; + } + })); + /* *INDENT-ON* */ + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "src-if-index", sw_if_index_from); + vat_json_object_add_string_copy (node, "src-if-name", sw_if_from_name); + vat_json_object_add_uint (node, "dst-if-index", sw_if_index_to); + if (0 != sw_if_to_name) + { + vat_json_object_add_string_copy (node, "dst-if-name", sw_if_to_name); + } + vat_json_object_add_uint (node, "state", mp->state); +} + +static int +api_sw_interface_span_dump (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_sw_interface_span_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 is_l2 = 0; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "l2")) + is_l2 = 1; + else + break; + } + + M (SW_INTERFACE_SPAN_DUMP, mp); + mp->is_l2 = is_l2; + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +int +api_pg_create_interface (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_pg_create_interface_t *mp; + + u32 if_id = ~0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "if_id %d", &if_id)) + ; + else + break; + } + if (if_id == ~0) + { + errmsg ("missing pg interface index"); + return -99; + } + + /* Construct the API message */ + M (PG_CREATE_INTERFACE, mp); + mp->context = 0; + mp->interface_id = ntohl (if_id); + + S (mp); + W (ret); + return ret; +} + +int +api_pg_capture (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_pg_capture_t *mp; + + u32 if_id = ~0; + u8 enable = 1; + u32 count = 1; + u8 pcap_file_set = 0; + u8 *pcap_file = 0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "if_id %d", &if_id)) + ; + else if (unformat (input, "pcap %s", &pcap_file)) + pcap_file_set = 1; + else if (unformat (input, "count %d", &count)) + ; + else if (unformat (input, "disable")) + enable = 0; + else + break; + } + if (if_id == ~0) + { + errmsg ("missing pg interface index"); + return -99; + } + if (pcap_file_set > 0) + { + if (vec_len (pcap_file) > 255) + { + errmsg ("pcap file name is too long"); + return -99; + } + } + + u32 name_len = vec_len (pcap_file); + /* Construct the API message */ + M (PG_CAPTURE, mp); + mp->context = 0; + mp->interface_id = ntohl (if_id); + mp->is_enabled = enable; + mp->count = ntohl (count); + mp->pcap_name_length = ntohl (name_len); + if (pcap_file_set != 0) + { + clib_memcpy (mp->pcap_file_name, pcap_file, name_len); + } + vec_free (pcap_file); + + S (mp); + W (ret); + return ret; +} + +int +api_pg_enable_disable (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_pg_enable_disable_t *mp; + + u8 enable = 1; + u8 stream_name_set = 0; + u8 *stream_name = 0; + int ret; + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "stream %s", &stream_name)) + stream_name_set = 1; + else if (unformat (input, "disable")) + enable = 0; + else + break; + } + + if (stream_name_set > 0) + { + if (vec_len (stream_name) > 255) + { + errmsg ("stream name too long"); + return -99; + } + } + + u32 name_len = vec_len (stream_name); + /* Construct the API message */ + M (PG_ENABLE_DISABLE, mp); + mp->context = 0; + mp->is_enabled = enable; + if (stream_name_set != 0) + { + mp->stream_name_length = ntohl (name_len); + clib_memcpy (mp->stream_name, stream_name, name_len); + } + vec_free (stream_name); + + S (mp); + W (ret); + return ret; +} + +int +api_ip_source_and_port_range_check_add_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_ip_source_and_port_range_check_add_del_t *mp; + + u16 *low_ports = 0; + u16 *high_ports = 0; + u16 this_low; + u16 this_hi; + ip4_address_t ip4_addr; + ip6_address_t ip6_addr; + u32 length; + u32 tmp, tmp2; + u8 prefix_set = 0; + u32 vrf_id = ~0; + u8 is_add = 1; + u8 is_ipv6 = 0; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U/%d", unformat_ip4_address, &ip4_addr, &length)) + { + prefix_set = 1; + } + else + if (unformat + (input, "%U/%d", unformat_ip6_address, &ip6_addr, &length)) + { + prefix_set = 1; + is_ipv6 = 1; + } + else if (unformat (input, "vrf %d", &vrf_id)) + ; + else if (unformat (input, "del")) + is_add = 0; + else if (unformat (input, "port %d", &tmp)) + { + if (tmp == 0 || tmp > 65535) + { + errmsg ("port %d out of range", tmp); + return -99; + } + this_low = tmp; + this_hi = this_low + 1; + vec_add1 (low_ports, this_low); + vec_add1 (high_ports, this_hi); + } + else if (unformat (input, "range %d - %d", &tmp, &tmp2)) + { + if ((tmp > tmp2) || (tmp == 0) || (tmp2 > 65535)) + { + errmsg ("incorrect range parameters"); + return -99; + } + this_low = tmp; + /* Note: in debug CLI +1 is added to high before + passing to real fn that does "the work" + (ip_source_and_port_range_check_add_del). + This fn is a wrapper around the binary API fn a + control plane will call, which expects this increment + to have occurred. Hence letting the binary API control + plane fn do the increment for consistency between VAT + and other control planes. + */ + this_hi = tmp2; + vec_add1 (low_ports, this_low); + vec_add1 (high_ports, this_hi); + } + else + break; + } + + if (prefix_set == 0) + { + errmsg ("
/ not specified"); + return -99; + } + + if (vrf_id == ~0) + { + errmsg ("VRF ID required, not specified"); + return -99; + } + + if (vrf_id == 0) + { + errmsg + ("VRF ID should not be default. Should be distinct VRF for this purpose."); + return -99; + } + + if (vec_len (low_ports) == 0) + { + errmsg ("At least one port or port range required"); + return -99; + } + + M (IP_SOURCE_AND_PORT_RANGE_CHECK_ADD_DEL, mp); + + mp->is_add = is_add; + + if (is_ipv6) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->address, &ip6_addr, sizeof (ip6_addr)); + } + else + { + mp->is_ipv6 = 0; + clib_memcpy (mp->address, &ip4_addr, sizeof (ip4_addr)); + } + + mp->mask_length = length; + mp->number_of_ranges = vec_len (low_ports); + + clib_memcpy (mp->low_ports, low_ports, vec_len (low_ports)); + vec_free (low_ports); + + clib_memcpy (mp->high_ports, high_ports, vec_len (high_ports)); + vec_free (high_ports); + + mp->vrf_id = ntohl (vrf_id); + + S (mp); + W (ret); + return ret; +} + +int +api_ip_source_and_port_range_check_interface_add_del (vat_main_t * vam) +{ + unformat_input_t *input = vam->input; + vl_api_ip_source_and_port_range_check_interface_add_del_t *mp; + u32 sw_if_index = ~0; + int vrf_set = 0; + u32 tcp_out_vrf_id = ~0, udp_out_vrf_id = ~0; + u32 tcp_in_vrf_id = ~0, udp_in_vrf_id = ~0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (input, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (input, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (input, "tcp-out-vrf %d", &tcp_out_vrf_id)) + vrf_set = 1; + else if (unformat (input, "udp-out-vrf %d", &udp_out_vrf_id)) + vrf_set = 1; + else if (unformat (input, "tcp-in-vrf %d", &tcp_in_vrf_id)) + vrf_set = 1; + else if (unformat (input, "udp-in-vrf %d", &udp_in_vrf_id)) + vrf_set = 1; + else if (unformat (input, "del")) + is_add = 0; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("Interface required but not specified"); + return -99; + } + + if (vrf_set == 0) + { + errmsg ("VRF ID required but not specified"); + return -99; + } + + if (tcp_out_vrf_id == 0 + || udp_out_vrf_id == 0 || tcp_in_vrf_id == 0 || udp_in_vrf_id == 0) + { + errmsg + ("VRF ID should not be default. Should be distinct VRF for this purpose."); + return -99; + } + + /* Construct the API message */ + M (IP_SOURCE_AND_PORT_RANGE_CHECK_INTERFACE_ADD_DEL, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = is_add; + mp->tcp_out_vrf_id = ntohl (tcp_out_vrf_id); + mp->udp_out_vrf_id = ntohl (udp_out_vrf_id); + mp->tcp_in_vrf_id = ntohl (tcp_in_vrf_id); + mp->udp_in_vrf_id = ntohl (udp_in_vrf_id); + + /* send it... */ + S (mp); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_ipsec_gre_add_del_tunnel (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_gre_add_del_tunnel_t *mp; + u32 local_sa_id = 0; + u32 remote_sa_id = 0; + ip4_address_t src_address; + ip4_address_t dst_address; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "local_sa %d", &local_sa_id)) + ; + else if (unformat (i, "remote_sa %d", &remote_sa_id)) + ; + else if (unformat (i, "src %U", unformat_ip4_address, &src_address)) + ; + else if (unformat (i, "dst %U", unformat_ip4_address, &dst_address)) + ; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (IPSEC_GRE_ADD_DEL_TUNNEL, mp); + + mp->local_sa_id = ntohl (local_sa_id); + mp->remote_sa_id = ntohl (remote_sa_id); + clib_memcpy (mp->src_address, &src_address, sizeof (src_address)); + clib_memcpy (mp->dst_address, &dst_address, sizeof (dst_address)); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_punt (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_punt_t *mp; + u32 ipv = ~0; + u32 protocol = ~0; + u32 port = ~0; + int is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "ip %d", &ipv)) + ; + else if (unformat (i, "protocol %d", &protocol)) + ; + else if (unformat (i, "port %d", &port)) + ; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + M (PUNT, mp); + + mp->is_add = (u8) is_add; + mp->ipv = (u8) ipv; + mp->l4_protocol = (u8) protocol; + mp->l4_port = htons ((u16) port); + + S (mp); + W (ret); + return ret; +} + +static void vl_api_ipsec_gre_tunnel_details_t_handler + (vl_api_ipsec_gre_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%11d%15U%15U%14d%14d", + ntohl (mp->sw_if_index), + format_ip4_address, &mp->src_address, + format_ip4_address, &mp->dst_address, + ntohl (mp->local_sa_id), ntohl (mp->remote_sa_id)); +} + +static void vl_api_ipsec_gre_tunnel_details_t_handler_json + (vl_api_ipsec_gre_tunnel_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "sw_if_index", ntohl (mp->sw_if_index)); + clib_memcpy (&ip4, &mp->src_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "src_address", ip4); + clib_memcpy (&ip4, &mp->dst_address, sizeof (ip4)); + vat_json_object_add_ip4 (node, "dst_address", ip4); + vat_json_object_add_uint (node, "local_sa_id", ntohl (mp->local_sa_id)); + vat_json_object_add_uint (node, "remote_sa_id", ntohl (mp->remote_sa_id)); +} + +static int +api_ipsec_gre_tunnel_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_ipsec_gre_tunnel_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u32 sw_if_index; + u8 sw_if_index_set = 0; + int ret; + + /* Parse args required to build the message */ + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else + break; + } + + if (sw_if_index_set == 0) + { + sw_if_index = ~0; + } + + if (!vam->json_output) + { + print (vam->ofp, "%11s%15s%15s%14s%14s", + "sw_if_index", "src_address", "dst_address", + "local_sa_id", "remote_sa_id"); + } + + /* Get list of gre-tunnel interfaces */ + M (IPSEC_GRE_TUNNEL_DUMP, mp); + + mp->sw_if_index = htonl (sw_if_index); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_delete_subif (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_delete_subif_t *mp; + u32 sw_if_index = ~0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (DELETE_SUBIF, mp); + mp->sw_if_index = ntohl (sw_if_index); + + S (mp); + W (ret); + return ret; +} + +#define foreach_pbb_vtr_op \ +_("disable", L2_VTR_DISABLED) \ +_("pop", L2_VTR_POP_2) \ +_("push", L2_VTR_PUSH_2) + +static int +api_l2_interface_pbb_tag_rewrite (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_l2_interface_pbb_tag_rewrite_t *mp; + u32 sw_if_index = ~0, vtr_op = ~0; + u16 outer_tag = ~0; + u8 dmac[6], smac[6]; + u8 dmac_set = 0, smac_set = 0; + u16 vlanid = 0; + u32 sid = ~0; + u32 tmp; + int ret; + + /* Shut up coverity */ + memset (dmac, 0, sizeof (dmac)); + memset (smac, 0, sizeof (smac)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "vtr_op %d", &vtr_op)) + ; +#define _(n,v) else if (unformat(i, n)) {vtr_op = v;} + foreach_pbb_vtr_op +#undef _ + else if (unformat (i, "translate_pbb_stag")) + { + if (unformat (i, "%d", &tmp)) + { + vtr_op = L2_VTR_TRANSLATE_2_1; + outer_tag = tmp; + } + else + { + errmsg + ("translate_pbb_stag operation requires outer tag definition"); + return -99; + } + } + else if (unformat (i, "dmac %U", unformat_ethernet_address, dmac)) + dmac_set++; + else if (unformat (i, "smac %U", unformat_ethernet_address, smac)) + smac_set++; + else if (unformat (i, "sid %d", &sid)) + ; + else if (unformat (i, "vlanid %d", &tmp)) + vlanid = tmp; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if ((sw_if_index == ~0) || (vtr_op == ~0)) + { + errmsg ("missing sw_if_index or vtr operation"); + return -99; + } + if (((vtr_op == L2_VTR_PUSH_2) || (vtr_op == L2_VTR_TRANSLATE_2_2)) + && ((dmac_set == 0) || (smac_set == 0) || (sid == ~0))) + { + errmsg + ("push and translate_qinq operations require dmac, smac, sid and optionally vlanid"); + return -99; + } + + M (L2_INTERFACE_PBB_TAG_REWRITE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->vtr_op = ntohl (vtr_op); + mp->outer_tag = ntohs (outer_tag); + clib_memcpy (mp->b_dmac, dmac, sizeof (dmac)); + clib_memcpy (mp->b_smac, smac, sizeof (smac)); + mp->b_vlanid = ntohs (vlanid); + mp->i_sid = ntohl (sid); + + S (mp); + W (ret); + return ret; +} + +static int +api_flow_classify_set_interface (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_flow_classify_set_interface_t *mp; + u32 sw_if_index; + int sw_if_index_set; + u32 ip4_table_index = ~0; + u32 ip6_table_index = ~0; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "ip4-table %d", &ip4_table_index)) + ; + else if (unformat (i, "ip6-table %d", &ip6_table_index)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (sw_if_index_set == 0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + M (FLOW_CLASSIFY_SET_INTERFACE, mp); + + mp->sw_if_index = ntohl (sw_if_index); + mp->ip4_table_index = ntohl (ip4_table_index); + mp->ip6_table_index = ntohl (ip6_table_index); + mp->is_add = is_add; + + S (mp); + W (ret); + return ret; +} + +static int +api_flow_classify_dump (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_flow_classify_dump_t *mp; + vl_api_control_ping_t *mp_ping; + u8 type = FLOW_CLASSIFY_N_TABLES; + int ret; + + if (unformat (i, "type %U", unformat_flow_classify_table_type, &type)) + ; + else + { + errmsg ("classify table type must be specified"); + return -99; + } + + if (!vam->json_output) + { + print (vam->ofp, "%10s%20s", "Intfc idx", "Classify table"); + } + + M (FLOW_CLASSIFY_DUMP, mp); + mp->type = type; + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_feature_enable_disable (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_feature_enable_disable_t *mp; + u8 *arc_name = 0; + u8 *feature_name = 0; + u32 sw_if_index = ~0; + u8 enable = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "arc_name %s", &arc_name)) + ; + else if (unformat (i, "feature_name %s", &feature_name)) + ; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "disable")) + enable = 0; + else + break; + } + + if (arc_name == 0) + { + errmsg ("missing arc name"); + return -99; + } + if (vec_len (arc_name) > 63) + { + errmsg ("arc name too long"); + } + + if (feature_name == 0) + { + errmsg ("missing feature name"); + return -99; + } + if (vec_len (feature_name) > 63) + { + errmsg ("feature name too long"); + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + M (FEATURE_ENABLE_DISABLE, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = enable; + clib_memcpy (mp->arc_name, arc_name, vec_len (arc_name)); + clib_memcpy (mp->feature_name, feature_name, vec_len (feature_name)); + vec_free (arc_name); + vec_free (feature_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_tag_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_tag_add_del_t *mp; + u32 sw_if_index = ~0; + u8 *tag = 0; + u8 enable = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "tag %s", &tag)) + ; + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "del")) + enable = 0; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (enable && (tag == 0)) + { + errmsg ("no tag specified"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_TAG_ADD_DEL, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->is_add = enable; + if (enable) + strncpy ((char *) mp->tag, (char *) tag, ARRAY_LEN (mp->tag) - 1); + vec_free (tag); + + S (mp); + W (ret); + return ret; +} + +static void vl_api_l2_xconnect_details_t_handler + (vl_api_l2_xconnect_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + print (vam->ofp, "%15d%15d", + ntohl (mp->rx_sw_if_index), ntohl (mp->tx_sw_if_index)); +} + +static void vl_api_l2_xconnect_details_t_handler_json + (vl_api_l2_xconnect_details_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + + vat_json_init_object (node); + vat_json_object_add_uint (node, "rx_sw_if_index", + ntohl (mp->rx_sw_if_index)); + vat_json_object_add_uint (node, "tx_sw_if_index", + ntohl (mp->tx_sw_if_index)); +} + +static int +api_l2_xconnect_dump (vat_main_t * vam) +{ + vl_api_l2_xconnect_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%15s%15s", "rx_sw_if_index", "tx_sw_if_index"); + } + + M (L2_XCONNECT_DUMP, mp); + + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + W (ret); + return ret; +} + +static int +api_sw_interface_set_mtu (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_mtu_t *mp; + u32 sw_if_index = ~0; + u32 mtu = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "mtu %d", &mtu)) + ; + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + if (mtu == 0) + { + errmsg ("no mtu specified"); + return -99; + } + + /* Construct the API message */ + M (SW_INTERFACE_SET_MTU, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->mtu = ntohs ((u16) mtu); + + S (mp); + W (ret); + return ret; +} + +static int +api_p2p_ethernet_add (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_p2p_ethernet_add_t *mp; + u32 parent_if_index = ~0; + u32 sub_id = ~0; + u8 remote_mac[6]; + u8 mac_set = 0; + int ret; + + memset (remote_mac, 0, sizeof (remote_mac)); + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &parent_if_index)) + ; + else + if (unformat + (i, "remote_mac %U", unformat_ethernet_address, remote_mac)) + mac_set++; + else if (unformat (i, "sub_id %d", &sub_id)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (parent_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (mac_set == 0) + { + errmsg ("missing remote mac address"); + return -99; + } + if (sub_id == ~0) + { + errmsg ("missing sub-interface id"); + return -99; + } + + M (P2P_ETHERNET_ADD, mp); + mp->parent_if_index = ntohl (parent_if_index); + mp->subif_id = ntohl (sub_id); + clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac)); + + S (mp); + W (ret); + return ret; +} + +static int +api_p2p_ethernet_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_p2p_ethernet_del_t *mp; + u32 parent_if_index = ~0; + u8 remote_mac[6]; + u8 mac_set = 0; + int ret; + + memset (remote_mac, 0, sizeof (remote_mac)); + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &parent_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &parent_if_index)) + ; + else + if (unformat + (i, "remote_mac %U", unformat_ethernet_address, remote_mac)) + mac_set++; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (parent_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + if (mac_set == 0) + { + errmsg ("missing remote mac address"); + return -99; + } + + M (P2P_ETHERNET_DEL, mp); + mp->parent_if_index = ntohl (parent_if_index); + clib_memcpy (mp->remote_mac, remote_mac, sizeof (remote_mac)); + + S (mp); + W (ret); + return ret; +} + +static int +api_lldp_config (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_lldp_config_t *mp; + int tx_hold = 0; + int tx_interval = 0; + u8 *sys_name = NULL; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "system-name %s", &sys_name)) + ; + else if (unformat (i, "tx-hold %d", &tx_hold)) + ; + else if (unformat (i, "tx-interval %d", &tx_interval)) + ; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + vec_add1 (sys_name, 0); + + M (LLDP_CONFIG, mp); + mp->tx_hold = htonl (tx_hold); + mp->tx_interval = htonl (tx_interval); + clib_memcpy (mp->system_name, sys_name, vec_len (sys_name)); + vec_free (sys_name); + + S (mp); + W (ret); + return ret; +} + +static int +api_sw_interface_set_lldp (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_sw_interface_set_lldp_t *mp; + u32 sw_if_index = ~0; + u32 enable = 1; + u8 *port_desc = NULL, *mgmt_oid = NULL; + ip4_address_t ip4_addr; + ip6_address_t ip6_addr; + int ret; + + memset (&ip4_addr, 0, sizeof (ip4_addr)); + memset (&ip6_addr, 0, sizeof (ip6_addr)); + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "disable")) + enable = 0; + else + if (unformat (i, "%U", api_unformat_sw_if_index, vam, &sw_if_index)) + ; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + ; + else if (unformat (i, "port-desc %s", &port_desc)) + ; + else if (unformat (i, "mgmt-ip4 %U", unformat_ip4_address, &ip4_addr)) + ; + else if (unformat (i, "mgmt-ip6 %U", unformat_ip6_address, &ip6_addr)) + ; + else if (unformat (i, "mgmt-oid %s", &mgmt_oid)) + ; + else + break; + } + + if (sw_if_index == ~0) + { + errmsg ("missing interface name or sw_if_index"); + return -99; + } + + /* Construct the API message */ + vec_add1 (port_desc, 0); + vec_add1 (mgmt_oid, 0); + M (SW_INTERFACE_SET_LLDP, mp); + mp->sw_if_index = ntohl (sw_if_index); + mp->enable = enable; + clib_memcpy (mp->port_desc, port_desc, vec_len (port_desc)); + clib_memcpy (mp->mgmt_oid, mgmt_oid, vec_len (mgmt_oid)); + clib_memcpy (mp->mgmt_ip4, &ip4_addr, sizeof (ip4_addr)); + clib_memcpy (mp->mgmt_ip6, &ip6_addr, sizeof (ip6_addr)); + vec_free (port_desc); + vec_free (mgmt_oid); + + S (mp); + W (ret); + return ret; +} + +static int +api_tcp_configure_src_addresses (vat_main_t * vam) +{ + vl_api_tcp_configure_src_addresses_t *mp; + unformat_input_t *i = vam->input; + ip4_address_t v4first, v4last; + ip6_address_t v6first, v6last; + u8 range_set = 0; + u32 vrf_id = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U - %U", + unformat_ip4_address, &v4first, + unformat_ip4_address, &v4last)) + { + if (range_set) + { + errmsg ("one range per message (range already set)"); + return -99; + } + range_set = 1; + } + else if (unformat (i, "%U - %U", + unformat_ip6_address, &v6first, + unformat_ip6_address, &v6last)) + { + if (range_set) + { + errmsg ("one range per message (range already set)"); + return -99; + } + range_set = 2; + } + else if (unformat (i, "vrf %d", &vrf_id)) + ; + else + break; + } + + if (range_set == 0) + { + errmsg ("address range not set"); + return -99; + } + + M (TCP_CONFIGURE_SRC_ADDRESSES, mp); + mp->vrf_id = ntohl (vrf_id); + /* ipv6? */ + if (range_set == 2) + { + mp->is_ipv6 = 1; + clib_memcpy (mp->first_address, &v6first, sizeof (v6first)); + clib_memcpy (mp->last_address, &v6last, sizeof (v6last)); + } + else + { + mp->is_ipv6 = 0; + clib_memcpy (mp->first_address, &v4first, sizeof (v4first)); + clib_memcpy (mp->last_address, &v4last, sizeof (v4last)); + } + S (mp); + W (ret); + return ret; +} + +static void vl_api_app_namespace_add_del_reply_t_handler + (vl_api_app_namespace_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + i32 retval = ntohl (mp->retval); + if (vam->async_mode) + { + vam->async_errors += (retval < 0); + } + else + { + vam->retval = retval; + if (retval == 0) + errmsg ("app ns index %d\n", ntohl (mp->appns_index)); + vam->result_ready = 1; + } +} + +static void vl_api_app_namespace_add_del_reply_t_handler_json + (vl_api_app_namespace_add_del_reply_t * mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t node; + + vat_json_init_object (&node); + vat_json_object_add_int (&node, "retval", ntohl (mp->retval)); + vat_json_object_add_uint (&node, "appns_index", ntohl (mp->appns_index)); + + vat_json_print (vam->ofp, &node); + vat_json_free (&node); + + vam->retval = ntohl (mp->retval); + vam->result_ready = 1; +} + +static int +api_app_namespace_add_del (vat_main_t * vam) +{ + vl_api_app_namespace_add_del_t *mp; + unformat_input_t *i = vam->input; + u8 *ns_id = 0, secret_set = 0, sw_if_index_set = 0; + u32 sw_if_index, ip4_fib_id, ip6_fib_id; + u64 secret; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "id %_%v%_", &ns_id)) + ; + else if (unformat (i, "secret %lu", &secret)) + secret_set = 1; + else if (unformat (i, "sw_if_index %d", &sw_if_index)) + sw_if_index_set = 1; + else if (unformat (i, "ip4_fib_id %d", &ip4_fib_id)) + ; + else if (unformat (i, "ip6_fib_id %d", &ip6_fib_id)) + ; + else + break; + } + if (!ns_id || !secret_set || !sw_if_index_set) + { + errmsg ("namespace id, secret and sw_if_index must be set"); + return -99; + } + if (vec_len (ns_id) > 64) + { + errmsg ("namespace id too long"); + return -99; + } + M (APP_NAMESPACE_ADD_DEL, mp); + + clib_memcpy (mp->namespace_id, ns_id, vec_len (ns_id)); + mp->namespace_id_len = vec_len (ns_id); + mp->secret = clib_host_to_net_u64 (secret); + mp->sw_if_index = clib_host_to_net_u32 (sw_if_index); + mp->ip4_fib_id = clib_host_to_net_u32 (ip4_fib_id); + mp->ip6_fib_id = clib_host_to_net_u32 (ip6_fib_id); + vec_free (ns_id); + S (mp); + W (ret); + return ret; +} + +static int +api_memfd_segment_create (vat_main_t * vam) +{ +#if VPP_API_TEST_BUILTIN == 0 + unformat_input_t *i = vam->input; + vl_api_memfd_segment_create_t *mp; + u64 size = 64 << 20; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "size %U", unformat_memory_size, &size)) + ; + else + break; + } + + M (MEMFD_SEGMENT_CREATE, mp); + mp->requested_size = size; + S (mp); + W (ret); + return ret; + +#else + errmsg ("memfd_segment_create (builtin) not supported"); + return -99; +#endif +} + +static int +api_sock_init_shm (vat_main_t * vam) +{ +#if VPP_API_TEST_BUILTIN == 0 + unformat_input_t *i = vam->input; + vl_api_shm_elem_config_t *config = 0; + u64 size = 64 << 20; + int rv; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "size %U", unformat_memory_size, &size)) + ; + else + break; + } + + /* Try customized config to see if it works */ + vec_validate (config, 3); + config[0].type = VL_API_VLIB_RING; + config[0].count = 256; + config[0].size = 256; + config[1].type = VL_API_CLIENT_RING; + config[1].count = 256; + config[1].size = 1024; + config[2].type = VL_API_CLIENT_RING; + config[2].count = 8; + config[2].size = 4096; + config[3].type = VL_API_QUEUE; + config[3].count = 256; + config[3].size = sizeof (uword); + rv = vl_socket_client_init_shm (config); + if (!rv) + vam->client_index_invalid = 1; + return rv; +#else + return -99; +#endif +} + +static int +api_dns_enable_disable (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_dns_enable_disable_t *mp; + u8 enable_disable = 1; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "disable")) + enable_disable = 0; + if (unformat (line_input, "enable")) + enable_disable = 1; + else + break; + } + + /* Construct the API message */ + M (DNS_ENABLE_DISABLE, mp); + mp->enable = enable_disable; + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +static int +api_dns_resolve_name (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_dns_resolve_name_t *mp; + u8 *name = 0; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%s", &name)) + ; + else + break; + } + + if (vec_len (name) > 127) + { + errmsg ("name too long"); + return -99; + } + + /* Construct the API message */ + M (DNS_RESOLVE_NAME, mp); + memcpy (mp->name, name, vec_len (name)); + vec_free (name); + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +static int +api_dns_resolve_ip (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + vl_api_dns_resolve_ip_t *mp; + int is_ip6 = -1; + ip4_address_t addr4; + ip6_address_t addr6; + int ret; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%U", unformat_ip6_address, &addr6)) + is_ip6 = 1; + else if (unformat (line_input, "%U", unformat_ip4_address, &addr4)) + is_ip6 = 0; + else + break; + } + + if (is_ip6 == -1) + { + errmsg ("missing address"); + return -99; + } + + /* Construct the API message */ + M (DNS_RESOLVE_IP, mp); + mp->is_ip6 = is_ip6; + if (is_ip6) + memcpy (mp->address, &addr6, sizeof (addr6)); + else + memcpy (mp->address, &addr4, sizeof (addr4)); + + /* send it... */ + S (mp); + /* Wait for the reply */ + W (ret); + return ret; +} + +static int +api_dns_name_server_add_del (vat_main_t * vam) +{ + unformat_input_t *i = vam->input; + vl_api_dns_name_server_add_del_t *mp; + u8 is_add = 1; + ip6_address_t ip6_server; + ip4_address_t ip4_server; + int ip6_set = 0; + int ip4_set = 0; + int ret = 0; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "%U", unformat_ip6_address, &ip6_server)) + ip6_set = 1; + else if (unformat (i, "%U", unformat_ip4_address, &ip4_server)) + ip4_set = 1; + else if (unformat (i, "del")) + is_add = 0; + else + { + clib_warning ("parse error '%U'", format_unformat_error, i); + return -99; + } + } + + if (ip4_set && ip6_set) + { + errmsg ("Only one server address allowed per message"); + return -99; + } + if ((ip4_set + ip6_set) == 0) + { + errmsg ("Server address required"); + return -99; + } + + /* Construct the API message */ + M (DNS_NAME_SERVER_ADD_DEL, mp); + + if (ip6_set) + { + memcpy (mp->server_address, &ip6_server, sizeof (ip6_address_t)); + mp->is_ip6 = 1; + } + else + { + memcpy (mp->server_address, &ip4_server, sizeof (ip4_address_t)); + mp->is_ip6 = 0; + } + + mp->is_add = is_add; + + /* send it... */ + S (mp); + + /* Wait for a reply, return good/bad news */ + W (ret); + return ret; +} + +static void +vl_api_session_rules_details_t_handler (vl_api_session_rules_details_t * mp) +{ + vat_main_t *vam = &vat_main; + + if (mp->is_ip4) + { + print (vam->ofp, + "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s", + clib_net_to_host_u32 (mp->appns_index), mp->transport_proto, + mp->scope, format_ip4_address, &mp->lcl_ip, mp->lcl_plen, + clib_net_to_host_u16 (mp->lcl_port), format_ip4_address, + &mp->rmt_ip, mp->rmt_plen, clib_net_to_host_u16 (mp->rmt_port), + clib_net_to_host_u32 (mp->action_index), mp->tag); + } + else + { + print (vam->ofp, + "appns %u tp %u scope %d %U/%d %d %U/%d %d action: %d tag: %s", + clib_net_to_host_u32 (mp->appns_index), mp->transport_proto, + mp->scope, format_ip6_address, &mp->lcl_ip, mp->lcl_plen, + clib_net_to_host_u16 (mp->lcl_port), format_ip6_address, + &mp->rmt_ip, mp->rmt_plen, clib_net_to_host_u16 (mp->rmt_port), + clib_net_to_host_u32 (mp->action_index), mp->tag); + } +} + +static void +vl_api_session_rules_details_t_handler_json (vl_api_session_rules_details_t * + mp) +{ + vat_main_t *vam = &vat_main; + vat_json_node_t *node = NULL; + struct in6_addr ip6; + struct in_addr ip4; + + if (VAT_JSON_ARRAY != vam->json_tree.type) + { + ASSERT (VAT_JSON_NONE == vam->json_tree.type); + vat_json_init_array (&vam->json_tree); + } + node = vat_json_array_add (&vam->json_tree); + vat_json_init_object (node); + + vat_json_object_add_uint (node, "is_ip4", mp->is_ip4 ? 1 : 0); + vat_json_object_add_uint (node, "appns_index", + clib_net_to_host_u32 (mp->appns_index)); + vat_json_object_add_uint (node, "transport_proto", mp->transport_proto); + vat_json_object_add_uint (node, "scope", mp->scope); + vat_json_object_add_uint (node, "action_index", + clib_net_to_host_u32 (mp->action_index)); + vat_json_object_add_uint (node, "lcl_port", + clib_net_to_host_u16 (mp->lcl_port)); + vat_json_object_add_uint (node, "rmt_port", + clib_net_to_host_u16 (mp->rmt_port)); + vat_json_object_add_uint (node, "lcl_plen", mp->lcl_plen); + vat_json_object_add_uint (node, "rmt_plen", mp->rmt_plen); + vat_json_object_add_string_copy (node, "tag", mp->tag); + if (mp->is_ip4) + { + clib_memcpy (&ip4, mp->lcl_ip, sizeof (ip4)); + vat_json_object_add_ip4 (node, "lcl_ip", ip4); + clib_memcpy (&ip4, mp->rmt_ip, sizeof (ip4)); + vat_json_object_add_ip4 (node, "rmt_ip", ip4); + } + else + { + clib_memcpy (&ip6, mp->lcl_ip, sizeof (ip6)); + vat_json_object_add_ip6 (node, "lcl_ip", ip6); + clib_memcpy (&ip6, mp->rmt_ip, sizeof (ip6)); + vat_json_object_add_ip6 (node, "rmt_ip", ip6); + } +} + +static int +api_session_rule_add_del (vat_main_t * vam) +{ + vl_api_session_rule_add_del_t *mp; + unformat_input_t *i = vam->input; + u32 proto = ~0, lcl_port, rmt_port, action = 0, lcl_plen, rmt_plen; + u32 appns_index = 0, scope = 0; + ip4_address_t lcl_ip4, rmt_ip4; + ip6_address_t lcl_ip6, rmt_ip6; + u8 is_ip4 = 1, conn_set = 0; + u8 is_add = 1, *tag = 0; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + ; + else if (unformat (i, "proto tcp")) + proto = 0; + else if (unformat (i, "proto udp")) + proto = 1; + else if (unformat (i, "appns %d", &appns_index)) + ; + else if (unformat (i, "scope %d", &scope)) + ; + else if (unformat (i, "tag %_%v%_", &tag)) + ; + else + if (unformat + (i, "%U/%d %d %U/%d %d", unformat_ip4_address, &lcl_ip4, + &lcl_plen, &lcl_port, unformat_ip4_address, &rmt_ip4, &rmt_plen, + &rmt_port)) + { + is_ip4 = 1; + conn_set = 1; + } + else + if (unformat + (i, "%U/%d %d %U/%d %d", unformat_ip6_address, &lcl_ip6, + &lcl_plen, &lcl_port, unformat_ip6_address, &rmt_ip6, &rmt_plen, + &rmt_port)) + { + is_ip4 = 0; + conn_set = 1; + } + else if (unformat (i, "action %d", &action)) + ; + else + break; + } + if (proto == ~0 || !conn_set || action == ~0) + { + errmsg ("transport proto, connection and action must be set"); + return -99; + } + + if (scope > 3) + { + errmsg ("scope should be 0-3"); + return -99; + } + + M (SESSION_RULE_ADD_DEL, mp); + + mp->is_ip4 = is_ip4; + mp->transport_proto = proto; + mp->lcl_port = clib_host_to_net_u16 ((u16) lcl_port); + mp->rmt_port = clib_host_to_net_u16 ((u16) rmt_port); + mp->lcl_plen = lcl_plen; + mp->rmt_plen = rmt_plen; + mp->action_index = clib_host_to_net_u32 (action); + mp->appns_index = clib_host_to_net_u32 (appns_index); + mp->scope = scope; + mp->is_add = is_add; + if (is_ip4) + { + clib_memcpy (mp->lcl_ip, &lcl_ip4, sizeof (lcl_ip4)); + clib_memcpy (mp->rmt_ip, &rmt_ip4, sizeof (rmt_ip4)); + } + else + { + clib_memcpy (mp->lcl_ip, &lcl_ip6, sizeof (lcl_ip6)); + clib_memcpy (mp->rmt_ip, &rmt_ip6, sizeof (rmt_ip6)); + } + if (tag) + { + clib_memcpy (mp->tag, tag, vec_len (tag)); + vec_free (tag); + } + + S (mp); + W (ret); + return ret; +} + +static int +api_session_rules_dump (vat_main_t * vam) +{ + vl_api_session_rules_dump_t *mp; + vl_api_control_ping_t *mp_ping; + int ret; + + if (!vam->json_output) + { + print (vam->ofp, "%=20s", "Session Rules"); + } + + M (SESSION_RULES_DUMP, mp); + /* send it... */ + S (mp); + + /* Use a control ping for synchronization */ + MPING (CONTROL_PING, mp_ping); + S (mp_ping); + + /* Wait for a reply... */ + W (ret); + return ret; +} + +static int +api_ip_container_proxy_add_del (vat_main_t * vam) +{ + vl_api_ip_container_proxy_add_del_t *mp; + unformat_input_t *i = vam->input; + u32 plen = ~0, sw_if_index = ~0; + ip4_address_t ip4; + ip6_address_t ip6; + u8 is_ip4 = 1; + u8 is_add = 1; + int ret; + + while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) + { + if (unformat (i, "del")) + is_add = 0; + else if (unformat (i, "add")) + ; + if (unformat (i, "%U", unformat_ip4_address, &ip4)) + { + is_ip4 = 1; + plen = 32; + } + else if (unformat (i, "%U", unformat_ip6_address, &ip6)) + { + is_ip4 = 0; + plen = 128; + } + else if (unformat (i, "sw_if_index %u", &sw_if_index)) + ; + else + break; + } + if (sw_if_index == ~0 || plen == ~0) + { + errmsg ("address and sw_if_index must be set"); + return -99; + } + + M (IP_CONTAINER_PROXY_ADD_DEL, mp); + + mp->is_ip4 = is_ip4; + mp->sw_if_index = clib_host_to_net_u32 (sw_if_index); + mp->plen = plen; + mp->is_add = is_add; + if (is_ip4) + clib_memcpy (mp->ip, &ip4, sizeof (ip4)); + else + clib_memcpy (mp->ip, &ip6, sizeof (ip6)); + + S (mp); + W (ret); + return ret; +} + +static int +q_or_quit (vat_main_t * vam) +{ +#if VPP_API_TEST_BUILTIN == 0 + longjmp (vam->jump_buf, 1); +#endif + return 0; /* not so much */ +} + +static int +q (vat_main_t * vam) +{ + return q_or_quit (vam); +} + +static int +quit (vat_main_t * vam) +{ + return q_or_quit (vam); +} + +static int +comment (vat_main_t * vam) +{ + return 0; +} + +static int +cmd_cmp (void *a1, void *a2) +{ + u8 **c1 = a1; + u8 **c2 = a2; + + return strcmp ((char *) (c1[0]), (char *) (c2[0])); +} + +static int +help (vat_main_t * vam) +{ + u8 **cmds = 0; + u8 *name = 0; + hash_pair_t *p; + unformat_input_t *i = vam->input; + int j; + + if (unformat (i, "%s", &name)) + { + uword *hs; + + vec_add1 (name, 0); + + hs = hash_get_mem (vam->help_by_name, name); + if (hs) + print (vam->ofp, "usage: %s %s", name, hs[0]); + else + print (vam->ofp, "No such msg / command '%s'", name); + vec_free (name); + return 0; + } + + print (vam->ofp, "Help is available for the following:"); + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->function_by_name, + ({ + vec_add1 (cmds, (u8 *)(p->key)); + })); + /* *INDENT-ON* */ + + vec_sort_with_function (cmds, cmd_cmp); + + for (j = 0; j < vec_len (cmds); j++) + print (vam->ofp, "%s", cmds[j]); + + vec_free (cmds); + return 0; +} + +static int +set (vat_main_t * vam) +{ + u8 *name = 0, *value = 0; + unformat_input_t *i = vam->input; + + if (unformat (i, "%s", &name)) + { + /* The input buffer is a vector, not a string. */ + value = vec_dup (i->buffer); + vec_delete (value, i->index, 0); + /* Almost certainly has a trailing newline */ + if (value[vec_len (value) - 1] == '\n') + value[vec_len (value) - 1] = 0; + /* Make sure it's a proper string, one way or the other */ + vec_add1 (value, 0); + (void) clib_macro_set_value (&vam->macro_main, + (char *) name, (char *) value); + } + else + errmsg ("usage: set "); + + vec_free (name); + vec_free (value); + return 0; +} + +static int +unset (vat_main_t * vam) +{ + u8 *name = 0; + + if (unformat (vam->input, "%s", &name)) + if (clib_macro_unset (&vam->macro_main, (char *) name) == 1) + errmsg ("unset: %s wasn't set", name); + vec_free (name); + return 0; +} + +typedef struct +{ + u8 *name; + u8 *value; +} macro_sort_t; + + +static int +macro_sort_cmp (void *a1, void *a2) +{ + macro_sort_t *s1 = a1; + macro_sort_t *s2 = a2; + + return strcmp ((char *) (s1->name), (char *) (s2->name)); +} + +static int +dump_macro_table (vat_main_t * vam) +{ + macro_sort_t *sort_me = 0, *sm; + int i; + hash_pair_t *p; + + /* *INDENT-OFF* */ + hash_foreach_pair (p, vam->macro_main.the_value_table_hash, + ({ + vec_add2 (sort_me, sm, 1); + sm->name = (u8 *)(p->key); + sm->value = (u8 *) (p->value[0]); + })); + /* *INDENT-ON* */ + + vec_sort_with_function (sort_me, macro_sort_cmp); + + if (vec_len (sort_me)) + print (vam->ofp, "%-15s%s", "Name", "Value"); + else + print (vam->ofp, "The macro table is empty..."); + + for (i = 0; i < vec_len (sort_me); i++) + print (vam->ofp, "%-15s%s", sort_me[i].name, sort_me[i].value); + return 0; +} + +static int +dump_node_table (vat_main_t * vam) +{ + int i, j; + vlib_node_t *node, *next_node; + + if (vec_len (vam->graph_nodes) == 0) + { + print (vam->ofp, "Node table empty, issue get_node_graph..."); + return 0; + } + + for (i = 0; i < vec_len (vam->graph_nodes); i++) + { + node = vam->graph_nodes[i]; + print (vam->ofp, "[%d] %s", i, node->name); + for (j = 0; j < vec_len (node->next_nodes); j++) + { + if (node->next_nodes[j] != ~0) + { + next_node = vam->graph_nodes[node->next_nodes[j]]; + print (vam->ofp, " [%d] %s", j, next_node->name); + } + } + } + return 0; +} + +static int +value_sort_cmp (void *a1, void *a2) +{ + name_sort_t *n1 = a1; + name_sort_t *n2 = a2; + + if (n1->value < n2->value) + return -1; + if (n1->value > n2->value) + return 1; + return 0; +} + + +static int +dump_msg_api_table (vat_main_t * vam) +{ + api_main_t *am = &api_main; + name_sort_t *nses = 0, *ns; + hash_pair_t *hp; + int i; + + /* *INDENT-OFF* */ + hash_foreach_pair (hp, am->msg_index_by_name_and_crc, + ({ + vec_add2 (nses, ns, 1); + ns->name = (u8 *)(hp->key); + ns->value = (u32) hp->value[0]; + })); + /* *INDENT-ON* */ + + vec_sort_with_function (nses, value_sort_cmp); + + for (i = 0; i < vec_len (nses); i++) + print (vam->ofp, " [%d]: %s", nses[i].value, nses[i].name); + vec_free (nses); + return 0; +} + +static int +get_msg_id (vat_main_t * vam) +{ + u8 *name_and_crc; + u32 message_index; + + if (unformat (vam->input, "%s", &name_and_crc)) + { + message_index = vl_msg_api_get_msg_index (name_and_crc); + if (message_index == ~0) + { + print (vam->ofp, " '%s' not found", name_and_crc); + return 0; + } + print (vam->ofp, " '%s' has message index %d", + name_and_crc, message_index); + return 0; + } + errmsg ("name_and_crc required..."); + return 0; +} + +static int +search_node_table (vat_main_t * vam) +{ + unformat_input_t *line_input = vam->input; + u8 *node_to_find; + int j; + vlib_node_t *node, *next_node; + uword *p; + + if (vam->graph_node_index_by_name == 0) + { + print (vam->ofp, "Node table empty, issue get_node_graph..."); + return 0; + } + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "%s", &node_to_find)) + { + vec_add1 (node_to_find, 0); + p = hash_get_mem (vam->graph_node_index_by_name, node_to_find); + if (p == 0) + { + print (vam->ofp, "%s not found...", node_to_find); + goto out; + } + node = vam->graph_nodes[p[0]]; + print (vam->ofp, "[%d] %s", p[0], node->name); + for (j = 0; j < vec_len (node->next_nodes); j++) + { + if (node->next_nodes[j] != ~0) + { + next_node = vam->graph_nodes[node->next_nodes[j]]; + print (vam->ofp, " [%d] %s", j, next_node->name); + } + } + } + + else + { + clib_warning ("parse error '%U'", format_unformat_error, + line_input); + return -99; + } + + out: + vec_free (node_to_find); + + } + + return 0; +} + + +static int +script (vat_main_t * vam) +{ +#if (VPP_API_TEST_BUILTIN==0) + u8 *s = 0; + char *save_current_file; + unformat_input_t save_input; + jmp_buf save_jump_buf; + u32 save_line_number; + + FILE *new_fp, *save_ifp; + + if (unformat (vam->input, "%s", &s)) + { + new_fp = fopen ((char *) s, "r"); + if (new_fp == 0) + { + errmsg ("Couldn't open script file %s", s); + vec_free (s); + return -99; + } + } + else + { + errmsg ("Missing script name"); + return -99; + } + + clib_memcpy (&save_input, &vam->input, sizeof (save_input)); + clib_memcpy (&save_jump_buf, &vam->jump_buf, sizeof (save_jump_buf)); + save_ifp = vam->ifp; + save_line_number = vam->input_line_number; + save_current_file = (char *) vam->current_file; + + vam->input_line_number = 0; + vam->ifp = new_fp; + vam->current_file = s; + do_one_file (vam); + + clib_memcpy (&vam->input, &save_input, sizeof (vam->input)); + clib_memcpy (&vam->jump_buf, &save_jump_buf, sizeof (save_jump_buf)); + vam->ifp = save_ifp; + vam->input_line_number = save_line_number; + vam->current_file = (u8 *) save_current_file; + vec_free (s); + + return 0; +#else + clib_warning ("use the exec command..."); + return -99; +#endif +} + +static int +echo (vat_main_t * vam) +{ + print (vam->ofp, "%v", vam->input->buffer); + return 0; +} + +/* List of API message constructors, CLI names map to api_xxx */ +#define foreach_vpe_api_msg \ +_(create_loopback,"[mac ] [instance ]") \ +_(sw_interface_dump,"") \ +_(sw_interface_set_flags, \ + " | sw_if_index admin-up | admin-down link-up | link down") \ +_(sw_interface_add_del_address, \ + " | sw_if_index | [del] [del-all] ") \ +_(sw_interface_set_rx_mode, \ + " | sw_if_index [queue ] ") \ +_(sw_interface_set_table, \ + " | sw_if_index vrf [ipv6]") \ +_(sw_interface_set_mpls_enable, \ + " | sw_if_index [disable | dis]") \ +_(sw_interface_set_vpath, \ + " | sw_if_index enable | disable") \ +_(sw_interface_set_vxlan_bypass, \ + " | sw_if_index [ip4 | ip6] [enable | disable]") \ +_(sw_interface_set_geneve_bypass, \ + " | sw_if_index [ip4 | ip6] [enable | disable]") \ +_(sw_interface_set_l2_xconnect, \ + "rx | rx_sw_if_index tx | tx_sw_if_index \n" \ + "enable | disable") \ +_(sw_interface_set_l2_bridge, \ + "{ | sw_if_index } bd_id \n" \ + "[shg ] [bvi]\n" \ + "enable | disable") \ +_(bridge_domain_set_mac_age, "bd_id mac-age 0-255") \ +_(bridge_domain_add_del, \ + "bd_id [flood 1|0] [uu-flood 1|0] [forward 1|0] [learn 1|0] [arp-term 1|0] [mac-age 0-255] [bd-tag ] [del]\n") \ +_(bridge_domain_dump, "[bd_id ]\n") \ +_(l2fib_add_del, \ + "mac bd_id [del] | sw_if | sw_if_index [static] [filter] [bvi] [count ]\n") \ +_(l2fib_flush_bd, "bd_id ") \ +_(l2fib_flush_int, " | sw_if_index ") \ +_(l2_flags, \ + "sw_if | sw_if_index [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \ +_(bridge_flags, \ + "bd_id [learn] [forward] [uu-flood] [flood] [arp-term] [disable]\n") \ +_(tap_connect, \ + "tapname mac | random-mac [tag ]") \ +_(tap_modify, \ + " | sw_if_index tapname mac | random-mac") \ +_(tap_delete, \ + " | sw_if_index ") \ +_(sw_interface_tap_dump, "") \ +_(tap_create_v2, \ + "name [hw-addr ] [host-ns ] [rx-ring-size [tx-ring-size ]") \ +_(tap_delete_v2, \ + " | sw_if_index ") \ +_(sw_interface_tap_v2_dump, "") \ +_(ip_table_add_del, \ + "table-id [ipv6]\n") \ +_(ip_add_del_route, \ + "/ via [table-id ]\n" \ + "[ | sw_if_index ] [resolve-attempts ]\n" \ + "[weight ] [drop] [local] [classify ] [del]\n" \ + "[multipath] [count ]") \ +_(ip_mroute_add_del, \ + " / [table-id ]\n" \ + "[ | sw_if_index ] [local] [del]") \ +_(mpls_table_add_del, \ + "table-id \n") \ +_(mpls_route_add_del, \ + "