_(LISP_GPE_ADD_DEL_IFACE, lisp_gpe_add_del_iface) \
_(LISP_ADD_DEL_REMOTE_MAPPING, lisp_add_del_remote_mapping) \
_(LISP_PITR_SET_LOCATOR_SET, lisp_pitr_set_locator_set) \
+_(LISP_EID_TABLE_ADD_DEL_MAP, lisp_eid_table_add_del_map) \
_(LISP_LOCATOR_SET_DUMP, lisp_locator_set_dump) \
_(LISP_LOCAL_EID_TABLE_DUMP, lisp_local_eid_table_dump) \
_(LISP_GPE_TUNNEL_DUMP, lisp_gpe_tunnel_dump) \
_(LISP_MAP_RESOLVER_DUMP, lisp_map_resolver_dump) \
+_(LISP_EID_TABLE_MAP_DUMP, lisp_eid_table_map_dump) \
_(LISP_ENABLE_DISABLE_STATUS_DUMP, \
lisp_enable_disable_status_dump) \
+_(LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS, \
+ lisp_add_del_map_request_itr_rlocs) \
+_(LISP_GET_MAP_REQUEST_ITR_RLOCS, lisp_get_map_request_itr_rlocs) \
_(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del) \
_(AF_PACKET_CREATE, af_packet_create) \
_(AF_PACKET_DELETE, af_packet_delete) \
_(POLICER_ADD_DEL, policer_add_del) \
_(POLICER_DUMP, policer_dump) \
_(NETMAP_CREATE, netmap_create) \
-_(NETMAP_DELETE, netmap_delete)
+_(NETMAP_DELETE, netmap_delete) \
+_(MPLS_GRE_TUNNEL_DUMP, mpls_gre_tunnel_dump) \
+_(MPLS_GRE_TUNNEL_DETAILS, mpls_gre_tunnel_details) \
+_(MPLS_ETH_TUNNEL_DUMP, mpls_eth_tunnel_dump) \
+_(MPLS_ETH_TUNNEL_DETAILS, mpls_eth_tunnel_details) \
+_(MPLS_FIB_ENCAP_DUMP, mpls_fib_encap_dump) \
+_(MPLS_FIB_ENCAP_DETAILS, mpls_fib_encap_details) \
+_(MPLS_FIB_DECAP_DUMP, mpls_fib_decap_dump) \
+_(MPLS_FIB_DECAP_DETAILS, mpls_fib_decap_details) \
+_(CLASSIFY_TABLE_IDS,classify_table_ids) \
+_(CLASSIFY_TABLE_BY_INTERFACE, classify_table_by_interface) \
+_(CLASSIFY_TABLE_INFO,classify_table_info) \
+_(CLASSIFY_SESSION_DUMP,classify_session_dump) \
+_(CLASSIFY_SESSION_DETAILS,classify_session_details)
#define QUOTE_(x) #x
#define QUOTE(x) QUOTE_(x)
}
nh_adj = ip_get_adjacency (lm, ai);
- vec_add1 (add_adj, nh_adj[0]);
+ if (nh_adj->lookup_next_index == IP_LOOKUP_NEXT_ARP &&
+ nh_adj->arp.next_hop.ip4.as_u32 == 0) {
+ /* the next-hop resovles via a glean adj. create and use
+ * a ARP adj for the next-hop */
+ a.adj_index = vnet_arp_glean_add(fib_index, &next_hop_address);
+ a.add_adj = NULL;
+ a.n_add_adj = 0;
+ ip4_add_del_route (im, &a);
+
+ goto done;
+ }
+ vec_add1 (add_adj, nh_adj[0]);
if (mp->lookup_in_vrf) {
p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf));
if (p)
vec_free (add_adj);
+done:
dsunlock (sm);
return 0;
}
vl_api_sw_interface_set_vpath_t_handler (vl_api_sw_interface_set_vpath_t *mp)
{
vlib_main_t *vm = vlib_get_main();
+ ip4_main_t * im4 = &ip4_main;
+ ip6_main_t * im6 = &ip6_main;
vl_api_sw_interface_set_vpath_reply_t * rmp;
int rv = 0;
u32 ci;
if (mp->enable) {
ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
ci = vnet_config_add_feature(vm, &rx_cm4u->config_main,
- ci, IP4_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im4->ip4_unicast_rx_feature_vpath,
+ 0, 0);
rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
ci = vnet_config_add_feature(vm, &rx_cm4m->config_main,
- ci, IP4_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im4->ip4_multicast_rx_feature_vpath,
+ 0, 0);
rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
ci = vnet_config_add_feature(vm, &rx_cm6u->config_main,
- ci, IP6_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im6->ip6_unicast_rx_feature_vpath,
+ 0, 0);
rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
ci = vnet_config_add_feature(vm, &rx_cm6m->config_main,
- ci, IP6_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im6->ip6_multicast_rx_feature_vpath,
+ 0, 0);
rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
} else {
ci = rx_cm4u->config_index_by_sw_if_index[sw_if_index]; //IP4 unicast
ci = vnet_config_del_feature(vm, &rx_cm4u->config_main,
- ci, IP4_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im4->ip4_unicast_rx_feature_vpath,
+ 0, 0);
rx_cm4u->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm4m->config_index_by_sw_if_index[sw_if_index]; //IP4 mcast
ci = vnet_config_del_feature(vm, &rx_cm4m->config_main,
- ci, IP4_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im4->ip4_multicast_rx_feature_vpath,
+ 0, 0);
rx_cm4m->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm6u->config_index_by_sw_if_index[sw_if_index]; //IP6 unicast
ci = vnet_config_del_feature(vm, &rx_cm6u->config_main,
- ci, IP6_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im6->ip6_unicast_rx_feature_vpath,
+ 0, 0);
rx_cm6u->config_index_by_sw_if_index[sw_if_index] = ci;
ci = rx_cm6m->config_index_by_sw_if_index[sw_if_index]; //IP6 mcast
ci = vnet_config_del_feature(vm, &rx_cm6m->config_main,
- ci, IP6_RX_FEATURE_VPATH, 0, 0);
+ ci,
+ im6->ip6_multicast_rx_feature_vpath,
+ 0, 0);
rx_cm6m->config_index_by_sw_if_index[sw_if_index] = ci;
}
}
encap_fib_index = p[0];
- protocol = ntohl(mp->protocol);
+ protocol = mp->protocol;
/* Interpret decap_vrf_id as an opaque if sending to other-than-ip4-input */
if (protocol == VXLAN_GPE_INPUT_NEXT_IP4_INPUT) {
u32 locator_set_index = ~0, map_index = ~0;
vnet_lisp_add_del_mapping_args_t _a, *a = &_a;
u8 *name = NULL;
+ memset (a, 0, sizeof (a[0]));
prefp = &gid_address_ippref(&eid);
ip_eid = &ip_prefix_addr(prefp);
/* XXX treat batch configuration */
a->is_add = mp->is_add;
+ gid_address_vni (&eid) = clib_net_to_host_u32 (mp->vni);
a->deid = eid;
a->locator_set_index = locator_set_index;
a->local = 1;
-
rv = vnet_lisp_add_del_local_mapping(a, &map_index);
out:
vec_free(name);
+ gid_address_free (&a->deid);
REPLY_MACRO(VL_API_LISP_ADD_DEL_LOCAL_EID_REPLY);
}
+static void
+vl_api_lisp_eid_table_add_del_map_t_handler(
+ vl_api_lisp_eid_table_add_del_map_t *mp)
+{
+ vl_api_lisp_eid_table_add_del_map_reply_t *rmp;
+ int rv = 0;
+ rv = vnet_lisp_eid_table_map (clib_net_to_host_u32 (mp->vni),
+ clib_net_to_host_u32 (mp->vrf), mp->is_add);
+ REPLY_MACRO(VL_API_LISP_EID_TABLE_ADD_DEL_MAP_REPLY)
+}
+
static void
lisp_gpe_add_del_fwd_entry_set_address(
vl_api_lisp_gpe_add_del_fwd_entry_t *mp,
a->is_add = mp->is_add;
a->table_id = mp->table_id;
a->vni = mp->vni;
- vnet_lisp_gpe_add_del_iface (a, 0);
+ rv = vnet_lisp_gpe_add_del_iface (a, 0);
REPLY_MACRO(VL_API_LISP_GPE_ADD_DEL_IFACE_REPLY);
}
REPLY_MACRO(VL_API_LISP_PITR_SET_LOCATOR_SET_REPLY);
}
+static void
+vl_api_lisp_add_del_map_request_itr_rlocs_t_handler
+(vl_api_lisp_add_del_map_request_itr_rlocs_t *mp)
+{
+ vl_api_lisp_add_del_map_request_itr_rlocs_reply_t *rmp;
+ int rv = 0;
+ u8 * locator_set_name = NULL;
+ vnet_lisp_add_del_mreq_itr_rloc_args_t _a, * a = &_a;
+
+ locator_set_name = format (0, "%s", mp->locator_set_name);
+
+ a->is_add = mp->is_add;
+ a->locator_set_name = locator_set_name;
+
+ rv = vnet_lisp_add_del_mreq_itr_rlocs(a);
+
+ vec_free(locator_set_name);
+
+ REPLY_MACRO(VL_API_LISP_ADD_DEL_MAP_REQUEST_ITR_RLOCS_REPLY);
+}
+
/** Used for transferring locators via VPP API */
typedef CLIB_PACKED(struct
{
ip_address_t * deid_addr = &ip_prefix_addr(deid_pref);
ip_prefix_len(seid_pref) = mp->seid_len;
ip_prefix_len(deid_pref) = mp->deid_len;
- gid_address_set_vni (seid, ntohl (mp->vni));
- gid_address_set_vni (deid, ntohl (mp->vni));
+ gid_address_vni (seid) = ntohl (mp->vni);
+ gid_address_vni (deid) = ntohl (mp->vni);
if (mp->eid_is_ip4) {
ip_prefix_version(seid_pref) = IP4;
}
rmp->eid_prefix_len = ip_prefix_len(ip_prefix);
rmp->context = context;
-
+ rmp->vni = clib_host_to_net_u32 (gid_address_vni (gid));
vl_msg_api_send_shmem (q, (u8 *)&rmp);
}
static void
vl_api_lisp_gpe_tunnel_dump_t_handler (
- vl_api_lisp_local_eid_table_dump_t *mp)
+ vl_api_lisp_gpe_tunnel_dump_t *mp)
{
unix_shared_memory_queue_t * q = NULL;
lisp_gpe_main_t * lgm = &lisp_gpe_main;
static void
vl_api_lisp_map_resolver_dump_t_handler (
- vl_api_lisp_local_eid_table_dump_t *mp)
+ vl_api_lisp_map_resolver_dump_t *mp)
{
unix_shared_memory_queue_t * q = NULL;
lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
}
+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;
+ lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
+ hash_pair_t * p;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0) {
+ return;
+ }
+ hash_foreach_pair (p, lcm->table_id_by_vni, {
+ vl_api_lisp_eid_table_map_details_t * rmp = NULL;
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs(VL_API_LISP_EID_TABLE_MAP_DETAILS);
+ rmp->vni = p->key;
+ rmp->vrf = p->value[0];
+ rmp->context = mp->context;
+ });
+}
+
static void
send_lisp_enable_disable_details (unix_shared_memory_queue_t *q,
u32 context)
send_lisp_enable_disable_details(q, mp->context);
}
+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;
+ 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;
+ u8 * tmp_str = 0;
+ int rv = 0;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0) {
+ return;
+ }
+
+ if (~0 == lcm->mreq_itr_rlocs) {
+ tmp_str = format(0, " ");
+ } else {
+ loc_set = pool_elt_at_index (lcm->locator_set_pool, lcm->mreq_itr_rlocs);
+ tmp_str = format(0, "%s", loc_set->name);
+ }
+
+ REPLY_MACRO2(VL_API_LISP_GET_MAP_REQUEST_ITR_RLOCS_REPLY,
+ ({
+ strncpy((char *) rmp->locator_set_name, (char *) tmp_str,
+ ARRAY_LEN(rmp->locator_set_name) - 1);
+ }));
+
+ vec_free(tmp_str);
+}
+
static void
vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *mp)
{
vl_api_af_packet_create_reply_t *rmp;
int rv = 0;
u8 *host_if_name = NULL;
+ u32 sw_if_index;
host_if_name = format(0, "%s", mp->host_if_name);
vec_add1 (host_if_name, 0);
rv = af_packet_create_if(vm, host_if_name,
- mp->use_random_hw_addr ? 0 : mp->hw_addr, 0);
+ mp->use_random_hw_addr ? 0 : mp->hw_addr, &sw_if_index);
vec_free(host_if_name);
- REPLY_MACRO(VL_API_AF_PACKET_CREATE_REPLY);
+ REPLY_MACRO2(VL_API_AF_PACKET_CREATE_REPLY,
+ rmp->sw_if_index = clib_host_to_net_u32(sw_if_index));
}
static void
REPLY_MACRO(VL_API_NETMAP_DELETE_REPLY);
}
+static void vl_api_mpls_gre_tunnel_details_t_handler (
+ vl_api_mpls_gre_tunnel_details_t * mp)
+{
+ clib_warning ("BUG");
+}
+
+static void send_mpls_gre_tunnel_entry (vpe_api_main_t * am,
+ unix_shared_memory_queue_t *q,
+ mpls_gre_tunnel_t * gt,
+ u32 index,
+ u32 context)
+{
+ vl_api_mpls_gre_tunnel_details_t * mp;
+
+ mp = vl_msg_api_alloc (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = ntohs(VL_API_MPLS_GRE_TUNNEL_DETAILS);
+ mp->context = context;
+
+ if (gt != NULL) {
+ mp->tunnel_index = htonl(index);
+ mp->tunnel_src = gt->tunnel_src.as_u32;
+ mp->tunnel_dst = gt->tunnel_dst.as_u32;
+ mp->intfc_address = gt->intfc_address.as_u32;
+ mp->mask_width = htonl(gt->mask_width);
+ mp->inner_fib_index = htonl(gt->inner_fib_index);
+ mp->outer_fib_index = htonl(gt->outer_fib_index);
+ mp->encap_index = htonl(gt->encap_index);
+ mp->hw_if_index = htonl(gt->hw_if_index);
+ mp->l2_only = htonl(gt->l2_only);
+ }
+
+ mpls_main_t * mm = &mpls_main;
+ mpls_encap_t * e;
+ int i;
+ u32 len = 0;
+
+ e = pool_elt_at_index (mm->encaps, gt->encap_index);
+ len = vec_len (e->labels);
+ mp->nlabels = htonl(len);
+
+ for (i = 0; i < len; i++) {
+ mp->labels[i] = htonl(vnet_mpls_uc_get_label(
+ clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
+ }
+
+ vl_msg_api_send_shmem (q, (u8 *)&mp);
+}
+
+static void
+vl_api_mpls_gre_tunnel_dump_t_handler (vl_api_mpls_gre_tunnel_dump_t *mp)
+{
+ vpe_api_main_t * am = &vpe_api_main;
+ unix_shared_memory_queue_t * q;
+ vlib_main_t * vm = &vlib_global_main;
+ mpls_main_t * mm = &mpls_main;
+ mpls_gre_tunnel_t * gt;
+ u32 index = ntohl(mp->tunnel_index);
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ if (pool_elts (mm->gre_tunnels)) {
+ if(mp->tunnel_index >= 0) {
+ vlib_cli_output (vm, "MPLS-GRE tunnel %u", index);
+ gt = pool_elt_at_index (mm->gre_tunnels, index);
+ send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, mp->context);
+ } else {
+ vlib_cli_output (vm, "MPLS-GRE tunnels");
+ pool_foreach (gt, mm->gre_tunnels,
+ ({
+ send_mpls_gre_tunnel_entry (am, q, gt, gt - mm->gre_tunnels, mp->context);
+ }));
+ }
+ } else {
+ vlib_cli_output (vm, "No MPLS-GRE tunnels");
+ }
+}
+
+static void vl_api_mpls_eth_tunnel_details_t_handler (
+ vl_api_mpls_eth_tunnel_details_t * mp)
+{
+ clib_warning ("BUG");
+}
+
+static void send_mpls_eth_tunnel_entry (vpe_api_main_t * am,
+ unix_shared_memory_queue_t *q,
+ mpls_eth_tunnel_t * et,
+ u32 index,
+ u32 context)
+{
+ vl_api_mpls_eth_tunnel_details_t * mp;
+
+ mp = vl_msg_api_alloc (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = ntohs(VL_API_MPLS_ETH_TUNNEL_DETAILS);
+ mp->context = context;
+
+ if (et != NULL) {
+ mp->tunnel_index = htonl(index);
+ memcpy(mp->tunnel_dst_mac, et->tunnel_dst, 6);
+ mp->intfc_address = et->intfc_address.as_u32;
+ mp->tx_sw_if_index = htonl(et->tx_sw_if_index);
+ mp->inner_fib_index = htonl(et->inner_fib_index);
+ mp->mask_width = htonl(et->mask_width);
+ mp->encap_index = htonl(et->encap_index);
+ mp->hw_if_index = htonl(et->hw_if_index);
+ mp->l2_only = htonl(et->l2_only);
+ }
+
+ mpls_main_t * mm = &mpls_main;
+ mpls_encap_t * e;
+ int i;
+ u32 len = 0;
+
+ e = pool_elt_at_index (mm->encaps, et->encap_index);
+ len = vec_len (e->labels);
+ mp->nlabels = htonl(len);
+
+ for (i = 0; i < len; i++) {
+ mp->labels[i] = htonl(vnet_mpls_uc_get_label(
+ clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
+ }
+
+ vl_msg_api_send_shmem (q, (u8 *)&mp);
+}
+
+static void
+vl_api_mpls_eth_tunnel_dump_t_handler (vl_api_mpls_eth_tunnel_dump_t *mp)
+{
+ vpe_api_main_t * am = &vpe_api_main;
+ unix_shared_memory_queue_t * q;
+ vlib_main_t * vm = &vlib_global_main;
+ mpls_main_t * mm = &mpls_main;
+ mpls_eth_tunnel_t * et;
+ u32 index = ntohl(mp->tunnel_index);
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ clib_warning("Received mpls_eth_tunnel_dump");
+ clib_warning("Received tunnel index: %u from client %u", index, mp->client_index);
+
+ if (pool_elts (mm->eth_tunnels)) {
+ if(mp->tunnel_index >= 0) {
+ vlib_cli_output (vm, "MPLS-Ethernet tunnel %u", index);
+ et = pool_elt_at_index (mm->eth_tunnels, index);
+ send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels, mp->context);
+ } else {
+ clib_warning("MPLS-Ethernet tunnels");
+ pool_foreach (et, mm->eth_tunnels,
+ ({
+ send_mpls_eth_tunnel_entry (am, q, et, et - mm->eth_tunnels, mp->context);
+ }));
+ }
+ } else {
+ clib_warning("No MPLS-Ethernet tunnels");
+ }
+}
+
+static void vl_api_mpls_fib_encap_details_t_handler (
+ vl_api_mpls_fib_encap_details_t * mp)
+{
+ clib_warning ("BUG");
+}
+
+static void send_mpls_fib_encap_details (vpe_api_main_t * am,
+ unix_shared_memory_queue_t *q,
+ show_mpls_fib_t *s,
+ u32 context)
+{
+ vl_api_mpls_fib_encap_details_t * mp;
+
+ mp = vl_msg_api_alloc (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = ntohs(VL_API_MPLS_FIB_ENCAP_DETAILS);
+ mp->context = context;
+
+ mp->fib_index = htonl(s->fib_index);
+ mp->entry_index = htonl(s->entry_index);
+ mp->dest = s->dest;
+ mp->s_bit = htonl(s->s_bit);
+
+ mpls_main_t * mm = &mpls_main;
+ mpls_encap_t * e;
+ int i;
+ u32 len = 0;
+
+ e = pool_elt_at_index (mm->encaps, s->entry_index);
+ len = vec_len (e->labels);
+ mp->nlabels = htonl(len);
+
+ for (i = 0; i < len; i++) {
+ mp->labels[i] = htonl(vnet_mpls_uc_get_label(
+ clib_host_to_net_u32(e->labels[i].label_exp_s_ttl)));
+ }
+
+ vl_msg_api_send_shmem (q, (u8 *)&mp);
+}
+
+static void
+vl_api_mpls_fib_encap_dump_t_handler (vl_api_mpls_fib_encap_dump_t *mp)
+{
+ vpe_api_main_t * am = &vpe_api_main;
+ unix_shared_memory_queue_t * q;
+ vlib_main_t * vm = &vlib_global_main;
+ u64 key;
+ u32 value;
+ show_mpls_fib_t *records = 0;
+ show_mpls_fib_t *s;
+ mpls_main_t * mm = &mpls_main;
+ ip4_main_t * im = &ip4_main;
+ ip4_fib_t * rx_fib;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ hash_foreach (key, value, mm->mpls_encap_by_fib_and_dest,
+ ({
+ vec_add2 (records, s, 1);
+ s->fib_index = (u32)(key>>32);
+ s->dest = (u32)(key & 0xFFFFFFFF);
+ s->entry_index = (u32) value;
+ }));
+
+ if (0 == vec_len(records)) {
+ vlib_cli_output(vm, "MPLS encap table empty");
+ goto out;
+ }
+
+ /* sort output by dst address within fib */
+ vec_sort_with_function(records, mpls_dest_cmp);
+ vec_sort_with_function(records, mpls_fib_index_cmp);
+ vlib_cli_output(vm, "MPLS encap table");
+ vlib_cli_output(vm, "%=6s%=16s%=16s", "Table", "Dest address", "Labels");
+ vec_foreach (s, records)
+ {
+ rx_fib = vec_elt_at_index(im->fibs, s->fib_index);
+ vlib_cli_output(vm, "%=6d%=16U%=16U", rx_fib->table_id,
+ format_ip4_address, &s->dest, format_mpls_encap_index, mm,
+ s->entry_index);
+ send_mpls_fib_encap_details (am, q, s, mp->context);
+ }
+
+out:
+ vec_free(records);
+}
+
+static void vl_api_mpls_fib_decap_details_t_handler (
+ vl_api_mpls_fib_decap_details_t * mp)
+{
+ clib_warning ("BUG");
+}
+
+static void send_mpls_fib_decap_details (vpe_api_main_t * am,
+ unix_shared_memory_queue_t *q,
+ show_mpls_fib_t *s,
+ u32 rx_table_id,
+ u32 tx_table_id,
+ char *swif_tag,
+ u32 context)
+{
+ vl_api_mpls_fib_decap_details_t * mp;
+
+ mp = vl_msg_api_alloc (sizeof (*mp));
+ memset (mp, 0, sizeof (*mp));
+ mp->_vl_msg_id = ntohs(VL_API_MPLS_FIB_DECAP_DETAILS);
+ mp->context = context;
+
+ mp->fib_index = htonl(s->fib_index);
+ mp->entry_index = htonl(s->entry_index);
+ mp->dest = s->dest;
+ mp->s_bit = htonl(s->s_bit);
+ mp->label = htonl(s->label);
+ mp->rx_table_id = htonl(rx_table_id);
+ mp->tx_table_id = htonl(tx_table_id);
+ strncpy ((char *) mp->swif_tag,
+ (char *) swif_tag, ARRAY_LEN(mp->swif_tag)-1);
+
+ vl_msg_api_send_shmem (q, (u8 *)&mp);
+}
+
+static void
+vl_api_mpls_fib_decap_dump_t_handler (vl_api_mpls_fib_decap_dump_t *mp)
+{
+ vpe_api_main_t * am = &vpe_api_main;
+ unix_shared_memory_queue_t * q;
+ vlib_main_t * vm = &vlib_global_main;
+ u64 key;
+ u32 value;
+ show_mpls_fib_t *records = 0;
+ show_mpls_fib_t *s;
+ mpls_main_t * mm = &mpls_main;
+ ip4_main_t * im = &ip4_main;
+ ip4_fib_t * rx_fib;
+ ip4_fib_t *tx_fib;
+ u32 tx_table_id;
+ char *swif_tag;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ hash_foreach (key, value, mm->mpls_decap_by_rx_fib_and_label,
+ ({
+ vec_add2 (records, s, 1);
+ s->fib_index = (u32)(key>>32);
+ s->entry_index = (u32) value;
+ s->label = ((u32) key)>>12;
+ s->s_bit = (key & (1<<8)) != 0;
+ }));
+
+ if (!vec_len(records)) {
+ vlib_cli_output(vm, "MPLS decap table empty");
+ goto out;
+ }
+
+ vec_sort_with_function(records, mpls_label_cmp);
+ vlib_cli_output(vm, "MPLS decap table");
+ vlib_cli_output(vm, "%=10s%=15s%=6s%=6s", "RX Table", "TX Table/Intfc",
+ "Label", "S-bit");
+ vec_foreach (s, records)
+ {
+ mpls_decap_t * d;
+ d = pool_elt_at_index(mm->decaps, s->entry_index);
+ if (d->next_index == MPLS_INPUT_NEXT_IP4_INPUT) {
+ tx_fib = vec_elt_at_index(im->fibs, d->tx_fib_index);
+ tx_table_id = tx_fib->table_id;
+ swif_tag = " ";
+ } else {
+ tx_table_id = d->tx_fib_index;
+ swif_tag = "(i) ";
+ }
+ rx_fib = vec_elt_at_index(im->fibs, s->fib_index);
+
+ vlib_cli_output(vm, "%=10d%=10d%=5s%=6d%=6d", rx_fib->table_id,
+ tx_table_id, swif_tag, s->label, s->s_bit);
+
+ send_mpls_fib_decap_details (am, q, s, rx_fib->table_id,
+ tx_table_id, swif_tag, mp->context);
+ }
+
+out:
+ vec_free(records);
+}
+
+static void vl_api_classify_table_ids_t_handler (vl_api_classify_table_ids_t *mp)
+{
+ unix_shared_memory_queue_t * q;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ vnet_classify_main_t * cm = &vnet_classify_main;
+ vnet_classify_table_t * t;
+ u32 * table_ids = 0;
+ u32 count;
+
+ pool_foreach (t, cm->tables,
+ ({
+ vec_add1 (table_ids, ntohl(t - cm->tables));
+ }));
+ count = vec_len(table_ids);
+
+ vl_api_classify_table_ids_reply_t *rmp;
+ rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + count);
+ rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_IDS_REPLY);
+ rmp->context = mp->context;
+ rmp->count = ntohl(count);
+ clib_memcpy(rmp->ids, table_ids, count * sizeof(u32));
+ rmp->retval = 0;
+
+ vl_msg_api_send_shmem (q, (u8 *)&rmp);
+
+ vec_free (table_ids);
+}
+
+static void vl_api_classify_table_by_interface_t_handler (vl_api_classify_table_by_interface_t *mp)
+{
+ vl_api_classify_table_by_interface_reply_t *rmp;
+ int rv = 0;
+
+ u32 sw_if_index = ntohl(mp->sw_if_index);
+ u32 * acl = 0;
+
+ vec_validate (acl, INPUT_ACL_N_TABLES - 1);
+ vec_set (acl, ~0);
+
+ VALIDATE_SW_IF_INDEX(mp);
+
+ input_acl_main_t * am = &input_acl_main;
+
+ int if_idx;
+ u32 type;
+
+ for (type = 0; type < INPUT_ACL_N_TABLES; type++)
+ {
+ u32 * vec_tbl = am->classify_table_index_by_sw_if_index[type];
+ if (vec_len(vec_tbl)) {
+ for (if_idx = 0; if_idx < vec_len (vec_tbl); if_idx++)
+ {
+ if (vec_elt(vec_tbl, if_idx) == ~0 || sw_if_index != if_idx) {
+ continue;
+ }
+ acl[type] = vec_elt(vec_tbl, if_idx);
+ }
+ }
+ }
+
+ BAD_SW_IF_INDEX_LABEL;
+
+ REPLY_MACRO2(VL_API_CLASSIFY_TABLE_BY_INTERFACE_REPLY,
+ ({
+ rmp->sw_if_index = ntohl(sw_if_index);
+ rmp->l2_table_id = ntohl(acl[INPUT_ACL_TABLE_L2]);
+ rmp->ip4_table_id = ntohl(acl[INPUT_ACL_TABLE_IP4]);
+ rmp->ip6_table_id = ntohl(acl[INPUT_ACL_TABLE_IP6]);
+ }));
+ vec_free(acl);
+}
+
+static void vl_api_classify_table_info_t_handler (vl_api_classify_table_info_t *mp)
+{
+ unix_shared_memory_queue_t * q;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+ if (q == 0)
+ return;
+
+ vl_api_classify_table_info_reply_t *rmp = 0;
+
+ vnet_classify_main_t * cm = &vnet_classify_main;
+ u32 table_id = ntohl(mp->table_id);
+ vnet_classify_table_t * t;
+
+ pool_foreach (t, cm->tables,
+ ({
+ if (table_id == t - cm->tables) {
+ rmp = vl_msg_api_alloc_as_if_client(sizeof (*rmp) + t->match_n_vectors * sizeof (u32x4));
+ rmp->_vl_msg_id = ntohs (VL_API_CLASSIFY_TABLE_INFO_REPLY);
+ rmp->context = mp->context;
+ rmp->table_id = ntohl(table_id);
+ rmp->nbuckets = ntohl(t->nbuckets);
+ rmp->match_n_vectors = ntohl(t->match_n_vectors);
+ rmp->skip_n_vectors = ntohl(t->skip_n_vectors);
+ rmp->active_sessions = ntohl(t->active_elements);
+ rmp->next_table_index = ntohl(t->next_table_index);
+ rmp->miss_next_index = ntohl(t->miss_next_index);
+ rmp->mask_length = ntohl(t->match_n_vectors * sizeof (u32x4));
+ clib_memcpy(rmp->mask, t->mask, t->match_n_vectors * sizeof(u32x4));
+ rmp->retval = 0;
+ break;
+ }
+ }));
+
+ if (rmp == 0) {
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs((VL_API_CLASSIFY_TABLE_INFO_REPLY));
+ rmp->context = mp->context;
+ rmp->retval = ntohl(VNET_API_ERROR_CLASSIFY_TABLE_NOT_FOUND);
+ }
+
+ vl_msg_api_send_shmem (q, (u8 *)&rmp);
+}
+
+static void vl_api_classify_session_details_t_handler (vl_api_classify_session_details_t * mp)
+{
+ clib_warning ("BUG");
+}
+
+static void send_classify_session_details (unix_shared_memory_queue_t * q,
+ u32 table_id,
+ u32 match_length,
+ vnet_classify_entry_t * e,
+ u32 context)
+{
+ vl_api_classify_session_details_t *rmp;
+
+ rmp = vl_msg_api_alloc (sizeof (*rmp));
+ memset (rmp, 0, sizeof (*rmp));
+ rmp->_vl_msg_id = ntohs(VL_API_CLASSIFY_SESSION_DETAILS);
+ rmp->context = context;
+ rmp->table_id = ntohl(table_id);
+ rmp->hit_next_index = ntohl(e->next_index);
+ rmp->advance = ntohl(e->advance);
+ rmp->opaque_index = ntohl(e->opaque_index);
+ rmp->match_length = ntohl(match_length);
+ clib_memcpy(rmp->match, e->key, match_length);
+
+ vl_msg_api_send_shmem (q, (u8 *)&rmp);
+}
+
+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;
+
+ u32 table_id = ntohl(mp->table_id);
+ vnet_classify_table_t * t;
+
+ q = vl_api_client_index_to_input_queue (mp->client_index);
+
+ pool_foreach (t, cm->tables,
+ ({
+ if (table_id == t - cm->tables) {
+ vnet_classify_bucket_t * b;
+ vnet_classify_entry_t * v, * save_v;
+ int i, j, k;
+
+ for (i = 0; i < t->nbuckets; i++)
+ {
+ b = &t->buckets [i];
+ if (b->offset == 0)
+ continue;
+
+ save_v = vnet_classify_get_entry (t, b->offset);
+ for (j = 0; j < (1<<b->log2_pages); j++)
+ {
+ for (k = 0; k < t->entries_per_page; k++)
+ {
+ v = vnet_classify_entry_at_index (t, save_v, j*t->entries_per_page + k);
+ if (vnet_classify_entry_is_free (v))
+ continue;
+
+ send_classify_session_details(q, table_id,
+ t->match_n_vectors * sizeof (u32x4), v, mp->context);
+ }
+ }
+ }
+ break;
+ }
+ }));
+}
+
#define BOUNCE_HANDLER(nn) \
static void vl_api_##nn##_t_handler ( \
vl_api_##nn##_t *mp) \