X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=vpp%2Fvpp-api%2Fapi.c;h=91ec833e7b03f8d860098d3257c96adc89f71f98;hb=9e6ed6e2e1b8af46a317f9448da2bca8d8c5395d;hp=58f7aeff5fd992c3c41e3d560c8d738320c67830;hpb=f727db9e6fb50b2930aedf18bcdda55fe0b96889;p=vpp.git diff --git a/vpp/vpp-api/api.c b/vpp/vpp-api/api.c index 58f7aeff5fd..91ec833e7b0 100644 --- a/vpp/vpp-api/api.c +++ b/vpp/vpp-api/api.c @@ -79,6 +79,7 @@ #include #include #include +#include #undef BIHASH_TYPE #undef __included_bihash_template_h__ @@ -346,6 +347,7 @@ _(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) \ +_(SHOW_LISP_PITR, show_lisp_pitr) \ _(SR_MULTICAST_MAP_ADD_DEL, sr_multicast_map_add_del) \ _(AF_PACKET_CREATE, af_packet_create) \ _(AF_PACKET_DELETE, af_packet_delete) \ @@ -365,7 +367,13 @@ _(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) +_(CLASSIFY_SESSION_DETAILS,classify_session_details) \ +_(IPFIX_ENABLE,ipfix_enable) \ +_(IPFIX_DUMP,ipfix_dump) \ +_(GET_NEXT_INDEX, get_next_index) \ +_(PG_CREATE_INTERFACE, pg_create_interface) \ +_(PG_CAPTURE, pg_capture) \ +_(PG_ENABLE_DISABLE, pg_enable_disable) #define QUOTE_(x) #x #define QUOTE(x) QUOTE_(x) @@ -862,7 +870,7 @@ static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) uword * p; clib_error_t * e; u32 ai; - ip_adjacency_t *nh_adj, *add_adj = 0; + ip_adjacency_t *adj; p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id)); if (!p) { @@ -879,7 +887,8 @@ static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) fib_index = p[0]; } - if (pool_is_free_index (vnm->interface_main.sw_interfaces, + if (~0 != mp->next_hop_sw_if_index && + pool_is_free_index (vnm->interface_main.sw_interfaces, ntohl(mp->next_hop_sw_if_index))) return VNET_API_ERROR_NO_MATCHING_INTERFACE; @@ -887,7 +896,7 @@ static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) sizeof (next_hop_address.data)); /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed) { + if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) { u32 lookup_result; ip_adjacency_t * adj; @@ -971,50 +980,43 @@ static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) else if (mp->is_local) ai = lm->local_adj_index; else if (mp->is_classify) { - ip_adjacency_t cadj; - memset(&cadj, 0, sizeof(cadj)); - cadj.lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY; - cadj.classify.table_index = ntohl(mp->classify_table_index); - if (pool_is_free_index (cm->tables, cadj.classify.table_index)) { + if (pool_is_free_index (cm->tables, ntohl(mp->classify_table_index))) { dsunlock(sm); return VNET_API_ERROR_NO_SUCH_TABLE; } - vec_add1 (add_adj, cadj); - goto do_add_del; - } - else { - ai = ip4_fib_lookup_with_table - (im, fib_index, &next_hop_address, - 1 /* disable default route */); - if (ai == lm->miss_adj_index) { - dsunlock(sm); - return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB; - } - } + adj = ip_add_adjacency (lm, + /* template */ 0, + /* block size */ 1, + &ai); - nh_adj = ip_get_adjacency (lm, ai); - 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; + adj->lookup_next_index = IP_LOOKUP_NEXT_CLASSIFY; + adj->classify.table_index = ntohl(mp->classify_table_index); } - vec_add1 (add_adj, nh_adj[0]); - if (mp->lookup_in_vrf) { + else if (mp->lookup_in_vrf) { p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf)); - if (p) - add_adj[0].explicit_fib_index = p[0]; + if (p) { + adj = ip_add_adjacency (lm, + /* template */ 0, + /* block size */ 1, + &ai); + adj->explicit_fib_index = p[0]; + } else { - vec_free (add_adj); dsunlock(sm); - return VNET_API_ERROR_NO_SUCH_INNER_FIB; - } - } + return VNET_API_ERROR_NO_SUCH_INNER_FIB; + } + } + else + ai = ip4_route_get_next_hop_adj (im, + fib_index, + &next_hop_address, + ntohl(mp->next_hop_sw_if_index), + fib_index); + + if (ai == lm->miss_adj_index) { + dsunlock(sm); + return VNET_API_ERROR_NO_SUCH_INNER_FIB; + } } else { ip_adjacency_t * adj; int disable_default_route = 1; @@ -1038,15 +1040,9 @@ static int ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) } } -do_add_del: - a.adj_index = ~0; - a.add_adj = add_adj; - a.n_add_adj = vec_len(add_adj); + a.adj_index = ai; ip4_add_del_route (im, &a); - vec_free (add_adj); - -done: dsunlock (sm); return 0; } @@ -1067,7 +1063,7 @@ static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) u32 fib_index; uword * p; clib_error_t * e; - ip_adjacency_t * nh_adj, * add_adj = 0; + ip_adjacency_t *adj = 0; u32 ai; p = hash_get (im->fib_index_by_table_id, ntohl(mp->vrf_id)); @@ -1086,7 +1082,8 @@ static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) fib_index = p[0]; } - if (pool_is_free_index (vnm->interface_main.sw_interfaces, + if (~0 != mp->next_hop_sw_if_index && + pool_is_free_index (vnm->interface_main.sw_interfaces, ntohl(mp->next_hop_sw_if_index))) return VNET_API_ERROR_NO_MATCHING_INTERFACE; @@ -1094,7 +1091,7 @@ static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) sizeof (next_hop_address.as_u8)); /* Arp for the next_hop if necessary */ - if (mp->is_add && mp->resolve_if_needed) { + if (mp->is_add && mp->resolve_if_needed && ~0 != mp->next_hop_sw_if_index) { u32 lookup_result; ip_adjacency_t * adj; @@ -1176,27 +1173,30 @@ static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) ai = lm->drop_adj_index; else if (mp->is_local) ai = lm->local_adj_index; - else { - ai = ip6_fib_lookup_with_table - (im, fib_index, &next_hop_address); - if (ai == lm->miss_adj_index) { - dsunlock(sm); - return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB; - } - } - - nh_adj = ip_get_adjacency (lm, ai); - vec_add1 (add_adj, nh_adj[0]); - if (mp->lookup_in_vrf) { + else if (mp->lookup_in_vrf) { p = hash_get (im->fib_index_by_table_id, ntohl(mp->lookup_in_vrf)); - if (p) - add_adj[0].explicit_fib_index = p[0]; + if (p) { + adj = ip_add_adjacency (lm, + /* template */ 0, + /* block size */ 1, + &ai); + adj->explicit_fib_index = p[0]; + } else { - vec_free (add_adj); - dsunlock(sm); + dsunlock(sm); return VNET_API_ERROR_NO_SUCH_INNER_FIB; - } - } + } + } + else + ai = ip6_route_get_next_hop_adj (im, + fib_index, + &next_hop_address, + ntohl(mp->next_hop_sw_if_index), + fib_index); + if (ai == lm->miss_adj_index) { + dsunlock(sm); + return VNET_API_ERROR_NEXT_HOP_NOT_IN_FIB; + } } else { ip_adjacency_t * adj; @@ -1213,13 +1213,9 @@ static int ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t *mp) } } - a.adj_index = ~0; - a.add_adj = add_adj; - a.n_add_adj = vec_len(add_adj); + a.adj_index = ai; ip6_add_del_route (im, &a); - vec_free (add_adj); - dsunlock (sm); return 0; } @@ -1652,6 +1648,7 @@ vl_api_l2fib_add_del_t_handler ( u32 bd_index; u32 static_mac; u32 filter_mac; + u32 bvi_mac; uword * p; mac = mp->mac; @@ -1678,8 +1675,9 @@ vl_api_l2fib_add_del_t_handler ( } static_mac = mp->static_mac ? 1 : 0; filter_mac = mp->filter_mac ? 1 : 0; + bvi_mac = mp->bvi_mac ? 1 : 0; l2fib_add_entry(mac, bd_index, sw_if_index, static_mac, filter_mac, - 0 /* bvi_mac */); + bvi_mac); } else { l2fib_del_entry(mac, bd_index); } @@ -4250,6 +4248,48 @@ static void vl_api_get_node_index_t_handler })) } +static void vl_api_get_next_index_t_handler +(vl_api_get_next_index_t * mp) +{ + vlib_main_t * vm = vlib_get_main(); + vl_api_get_next_index_reply_t * rmp; + vlib_node_t * node, * next_node; + int rv = 0; + u32 next_node_index = ~0, next_index = ~0; + uword * p; + + node = vlib_get_node_by_name (vm, mp->node_name); + + if (node == 0) { + rv = VNET_API_ERROR_NO_SUCH_NODE; + goto out; + } + + next_node = vlib_get_node_by_name (vm, mp->next_name); + + if (next_node == 0) { + rv = VNET_API_ERROR_NO_SUCH_NODE2; + goto out; + } + else + next_node_index = next_node->index; + + p = hash_get (node->next_slot_by_node, next_node_index); + + if (p == 0) { + rv = VNET_API_ERROR_NO_SUCH_ENTRY; + goto out; + } + else + next_index = p[0]; + + out: + REPLY_MACRO2(VL_API_GET_NEXT_INDEX_REPLY, + ({ + rmp->next_index = ntohl(next_index); + })); +} + static void vl_api_add_node_next_t_handler (vl_api_add_node_next_t * mp) { @@ -4293,6 +4333,20 @@ static void vl_api_l2tpv3_create_tunnel_t_handler goto out; } + u32 encap_fib_index; + + if (mp->encap_vrf_id != ~0) { + uword *p; + ip6_main_t *im = &ip6_main; + if (!(p = hash_get (im->fib_index_by_table_id, ntohl(mp->encap_vrf_id)))) { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + encap_fib_index = p[0]; + } else { + encap_fib_index = ~0; + } + rv = create_l2tpv3_ipv6_tunnel (lm, (ip6_address_t *) mp->client_address, (ip6_address_t *) mp->our_address, @@ -4301,6 +4355,7 @@ static void vl_api_l2tpv3_create_tunnel_t_handler clib_net_to_host_u64(mp->local_cookie), clib_net_to_host_u64(mp->remote_cookie), mp->l2_sublayer_present, + encap_fib_index, &sw_if_index); out: @@ -5020,6 +5075,8 @@ vl_api_lisp_add_del_map_request_itr_rlocs_t_handler typedef CLIB_PACKED(struct { u8 is_ip4; /**< is locator an IPv4 address */ + u8 priority; /**< locator priority */ + u8 weight; /**< locator weight */ u8 addr[16]; /**< IPv4/IPv6 address */ }) rloc_t; @@ -5097,35 +5154,29 @@ vl_api_lisp_add_del_remote_mapping_t_handler ( r->is_ip4 ? IP4 : IP6); gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128; gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX; - /* TODO fix API to pass priority and weight */ - rloc.priority = 1; - rloc.weight = 1; + rloc.priority = r->priority; + rloc.weight = r->weight; vec_add1 (rlocs, rloc); } - /* TODO Uncomment once https://gerrit.fd.io/r/#/c/1802 is merged and CSIT - * is switched to lisp_add_del_adjacency */ -// if (!mp->is_add) { -// vnet_lisp_add_del_adjacency_args_t _a, * a = &_a; -// gid_address_copy(&a->deid, deid); -// a->is_add = 0; -// rv = vnet_lisp_add_del_adjacency (a); -// } else { -// /* NOTE: for now this works as a static remote mapping, i.e., -// * not authoritative and ttl infinite. */ -// rv = vnet_lisp_add_del_mapping (deid, rlocs, mp->action, 0, ~0, -// mp->is_add, 0); -// } - - /* TODO: remove once the above is merged */ - vnet_lisp_add_del_adjacency_args_t _a, * a = &_a; - a->is_add = mp->is_add; - a->authoritative = 0; - a->action = mp->action; - a->locators = rlocs; - gid_address_copy(&a->seid, seid); - gid_address_copy(&a->deid, deid); - rv = vnet_lisp_add_del_adjacency (a); + if (!mp->is_add) { + vnet_lisp_add_del_adjacency_args_t _a, * a = &_a; + gid_address_copy(&a->deid, deid); + a->is_add = 0; + rv = vnet_lisp_add_del_adjacency (a); + } else { + /* NOTE: for now this works as a static remote mapping, i.e., + * not authoritative and ttl infinite. */ + rv = vnet_lisp_add_del_mapping (deid, rlocs, mp->action, 0, ~0, + mp->is_add, 0); + + /* TODO remove once CSIT switched to lisp_add_del_adjacency */ + vnet_lisp_add_del_adjacency_args_t _a, * a = &_a; + gid_address_copy(&a->seid, seid); + gid_address_copy(&a->deid, deid); + a->is_add = 1; + vnet_lisp_add_del_adjacency (a); + } if (mp->del_all) vnet_lisp_clear_all_remote_adjacencies (); @@ -5139,8 +5190,6 @@ static void vl_api_lisp_add_del_adjacency_t_handler ( vl_api_lisp_add_del_adjacency_t *mp) { - u32 i; - locator_t rloc; vl_api_lisp_add_del_adjacency_reply_t * rmp; vnet_lisp_add_del_adjacency_args_t _a, * a = &_a; @@ -5184,30 +5233,9 @@ vl_api_lisp_add_del_adjacency_t_handler ( goto send_reply; } - for (i = 0; i < mp->rloc_num; i++) { - rloc_t * r = &((rloc_t *) mp->rlocs)[i]; - memset(&rloc, 0, sizeof(rloc)); - ip_address_set(&gid_address_ip(&rloc.address), &r->addr, - r->is_ip4 ? IP4 : IP6); - gid_address_ippref_len(&rloc.address) = r->is_ip4 ? 32: 128; - gid_address_type(&rloc.address) = GID_ADDR_IP_PREFIX; - /* TODO fix API to pass priority and weight */ - rloc.priority = 1; - rloc.weight = 1; - vec_add1 (a->locators, rloc); - } - - a->action = mp->action; a->is_add = mp->is_add; - - /* NOTE: the remote mapping is static, i.e., not authoritative and - * ttl is infinite. */ - a->authoritative = 0; - a->ttl = ~0; - rv = vnet_lisp_add_del_adjacency (a); - vec_free (a->locators); send_reply: REPLY_MACRO(VL_API_LISP_ADD_DEL_ADJACENCY_REPLY); } @@ -5337,19 +5365,50 @@ static void vl_api_lisp_local_eid_table_dump_t_handler ( vl_api_lisp_local_eid_table_dump_t *mp) { + u32 mi; unix_shared_memory_queue_t * q = NULL; lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); mapping_t * mapit = NULL; + gid_address_t _eid, * eid = &_eid; q = vl_api_client_index_to_input_queue (mp->client_index); if (q == 0) { return; } - pool_foreach (mapit, lcm->mapping_pool, + if (mp->eid_set) { + memset (eid, 0, sizeof (*eid)); + gid_address_vni(eid) = ntohl(mp->vni); + switch (mp->eid_type) { + case 0: + gid_address_type(eid) = GID_ADDR_IP_PREFIX; + gid_address_ippref_len(eid) = mp->prefix_length; + gid_address_ip_version(eid) = IP4; + clib_memcpy (&gid_address_ippref(eid), mp->eid, 4); + break; + case 1: + gid_address_type(eid) = GID_ADDR_IP_PREFIX; + gid_address_ippref_len(eid) = mp->prefix_length; + gid_address_ip_version(eid) = IP6; + clib_memcpy (&gid_address_ippref(eid), mp->eid, 16); + break; + case 2: + gid_address_type(eid) = GID_ADDR_MAC; + clib_memcpy (gid_address_mac(eid), mp->eid, 6); + break; + } + mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, eid); + if ((u32)~0 == mi) + return; + + mapit = pool_elt_at_index (lcm->mapping_pool, mi); + send_lisp_local_eid_table_details(mapit, q, mp->context); + } else { + pool_foreach (mapit, lcm->mapping_pool, ({ send_lisp_local_eid_table_details(mapit, q, mp->context); })); + } } static void @@ -5456,6 +5515,23 @@ vl_api_lisp_map_resolver_dump_t_handler ( } +static void +send_eid_table_map_pair (hash_pair_t * p, + unix_shared_memory_queue_t * q, + u32 context) +{ + vl_api_lisp_eid_table_map_details_t * rmp = NULL; + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs(VL_API_LISP_EID_TABLE_MAP_DETAILS); + + rmp->vni = clib_host_to_net_u32 (p->key); + rmp->vrf = clib_host_to_net_u32 (p->value[0]); + rmp->context = context; + vl_msg_api_send_shmem (q, (u8 *)&rmp); +} + static void vl_api_lisp_eid_table_map_dump_t_handler ( vl_api_lisp_eid_table_map_dump_t *mp) @@ -5469,12 +5545,7 @@ vl_api_lisp_eid_table_map_dump_t_handler ( 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; + send_eid_table_map_pair (p, q, mp->context); }); } @@ -5541,6 +5612,43 @@ vl_api_lisp_get_map_request_itr_rlocs_t_handler ( vec_free(tmp_str); } +static void +vl_api_show_lisp_pitr_t_handler (vl_api_show_lisp_pitr_t * mp) +{ + unix_shared_memory_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; + locator_set_t * ls = 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->pitr_map_index) { + tmp_str = format(0, "N/A"); + } else { + m = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index); + if (~0 != m->locator_set_index) { + ls = pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index); + tmp_str = format(0, "%s", ls->name); + } else { + tmp_str = format(0, "N/A"); + } + } + vec_add1(tmp_str, 0); + + REPLY_MACRO2(VL_API_SHOW_LISP_PITR_REPLY, + ({ + rmp->status = lcm->lisp_pitr; + strncpy((char *) rmp->locator_set_name, (char *) tmp_str, + ARRAY_LEN(rmp->locator_set_name) - 1); + })); +} + static void vl_api_interface_name_renumber_t_handler (vl_api_interface_name_renumber_t *mp) { @@ -5722,7 +5830,7 @@ static void vl_api_ipsec_spd_add_del_entry_t_handler p.is_outbound = mp->is_outbound; p.is_ipv6 = mp->is_ipv6; - if (mp->is_ipv6) { + if (mp->is_ipv6 || mp->is_ip_any) { clib_memcpy(&p.raddr.start, mp->remote_address_start, 16); clib_memcpy(&p.raddr.stop, mp->remote_address_stop, 16); clib_memcpy(&p.laddr.start, mp->local_address_start, 16); @@ -6331,6 +6439,12 @@ vl_api_policer_add_del_t_handler cfg.rb.kbps.eir_kbps = mp->eir; cfg.rb.kbps.cb_bytes = mp->cb; cfg.rb.kbps.eb_bytes = mp->eb; + cfg.conform_action.action_type = mp->conform_action_type; + cfg.conform_action.dscp = mp->conform_dscp; + cfg.exceed_action.action_type = mp->exceed_action_type; + cfg.exceed_action.dscp = mp->exceed_dscp; + cfg.violate_action.action_type = mp->violate_action_type; + cfg.violate_action.dscp = mp->violate_dscp; error = policer_add_del(vm, name, &cfg, mp->is_add); @@ -6360,6 +6474,12 @@ send_policer_details (u8 *name, mp->rate_type = config->rate_type; mp->round_type = config->rnd_type; mp->type = config->rfc; + mp->conform_action_type = config->conform_action.action_type; + mp->conform_dscp = config->conform_action.dscp; + mp->exceed_action_type = config->exceed_action.action_type; + mp->exceed_dscp = config->exceed_action.dscp; + mp->violate_action_type = config->violate_action.action_type; + mp->violate_dscp = config->violate_action.dscp; mp->single_rate = templ->single_rate ? 1 : 0; mp->color_aware = templ->color_aware ? 1 : 0; mp->scale = htonl(templ->scale); @@ -6995,6 +7115,186 @@ static void vl_api_classify_session_dump_t_handler (vl_api_classify_session_dump })); } +static void vl_api_ipfix_enable_t_handler (vl_api_ipfix_enable_t *mp) +{ + vlib_main_t *vm = vlib_get_main(); + flow_report_main_t * frm = &flow_report_main; + vl_api_ipfix_enable_reply_t *rmp; + ip4_address_t collector, src; + u16 collector_port = UDP_DST_PORT_ipfix; + u32 path_mtu; + u32 template_interval; + u32 fib_id; + u32 fib_index = ~0; + int rv = 0; + + memcpy(collector.data, mp->collector_address, sizeof(collector.data)); + collector_port = ntohs(mp->collector_port); + if (collector_port == (u16)~0) + collector_port = UDP_DST_PORT_ipfix; + memcpy(src.data, mp->src_address, sizeof(src.data)); + fib_id = ntohl(mp->vrf_id); + + ip4_main_t * im = &ip4_main; + uword * p = hash_get (im->fib_index_by_table_id, fib_id); + if (! p) { + rv = VNET_API_ERROR_NO_SUCH_FIB; + goto out; + } + fib_index = p[0]; + + path_mtu = ntohl(mp->path_mtu); + if (path_mtu == ~0) + path_mtu = 512; // RFC 7011 section 10.3.3. + template_interval = ntohl(mp->template_interval); + if (template_interval == ~0) + template_interval = 20; + + if (collector.as_u32 == 0) { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + if (src.as_u32 == 0) { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + if (path_mtu > 1450 /* vpp does not support fragmentation */) { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + if (path_mtu < 68) { + rv = VNET_API_ERROR_INVALID_VALUE; + goto out; + } + + /* Reset report streams if we are reconfiguring IP addresses */ + if (frm->ipfix_collector.as_u32 != collector.as_u32 || + frm->src_address.as_u32 != src.as_u32 || + frm->collector_port != collector_port) + vnet_flow_reports_reset(frm); + + frm->ipfix_collector.as_u32 = collector.as_u32; + frm->collector_port = collector_port; + frm->src_address.as_u32 = src.as_u32; + frm->fib_index = fib_index; + frm->path_mtu = path_mtu; + frm->template_interval = template_interval; + + /* Turn on the flow reporting process */ + vlib_process_signal_event (vm, flow_report_process_node.index, + 1, 0); + +out: + REPLY_MACRO(VL_API_IPFIX_ENABLE_REPLY); +} + +static void vl_api_ipfix_dump_t_handler (vl_api_ipfix_dump_t *mp) +{ + flow_report_main_t * frm = &flow_report_main; + unix_shared_memory_queue_t * q; + vl_api_ipfix_details_t *rmp; + + q = vl_api_client_index_to_input_queue (mp->client_index); + + rmp = vl_msg_api_alloc (sizeof (*rmp)); + memset (rmp, 0, sizeof (*rmp)); + rmp->_vl_msg_id = ntohs(VL_API_IPFIX_DETAILS); + rmp->context = mp->context; + memcpy(rmp->collector_address, frm->ipfix_collector.data, + sizeof(frm->ipfix_collector.data)); + rmp->collector_port = htons(frm->collector_port); + memcpy(rmp->src_address, frm->src_address.data, + sizeof(frm->src_address.data)); + rmp->fib_index = htonl(frm->fib_index); + rmp->path_mtu = htonl(frm->path_mtu); + rmp->template_interval = htonl(frm->template_interval); + + vl_msg_api_send_shmem (q, (u8 *)&rmp); +} + +static void vl_api_pg_create_interface_t_handler (vl_api_pg_create_interface_t *mp) +{ + vl_api_pg_create_interface_reply_t *rmp; + int rv = 0; + + pg_main_t * pg = &pg_main; + u32 sw_if_index = pg_interface_add_or_get (pg, ntohl(mp->interface_id)); + + REPLY_MACRO2(VL_API_PG_CREATE_INTERFACE_REPLY, + ({ + rmp->sw_if_index = ntohl(sw_if_index); + })); +} + +static void vl_api_pg_capture_t_handler (vl_api_pg_capture_t *mp) +{ + vl_api_pg_capture_reply_t *rmp; + int rv = 0; + + vnet_main_t * vnm = vnet_get_main(); + vnet_interface_main_t * im = &vnm->interface_main; + vnet_hw_interface_t * hi = 0; + + u8 * intf_name = format (0, "pg%d", ntohl(mp->interface_id), 0); + u32 hw_if_index = ~0; + uword * p = hash_get_mem (im->hw_interface_by_name, intf_name); + if (p) + hw_if_index = *p; + vec_free (intf_name); + + if (hw_if_index != ~0) { + pg_capture_args_t _a, *a=&_a; + + u32 len = ntohl(mp->pcap_name_length); + u8 * pcap_file_name = vec_new(u8, len); + clib_memcpy(pcap_file_name, mp->pcap_file_name, len); + + hi = vnet_get_sup_hw_interface (vnm, hw_if_index); + a->hw_if_index = hw_if_index; + a->dev_instance = hi->dev_instance; + a->is_enabled = mp->is_enabled; + a->pcap_file_name = pcap_file_name; + a->count = ntohl(mp->count); + + clib_error_t * e = pg_capture (a); + if (e) { + clib_error_report(e); + rv = VNET_API_ERROR_CANNOT_CREATE_PCAP_FILE; + } + + vec_free (pcap_file_name); + } + REPLY_MACRO(VL_API_PG_CAPTURE_REPLY); +} + +static void vl_api_pg_enable_disable_t_handler (vl_api_pg_enable_disable_t *mp) +{ + vl_api_pg_enable_disable_reply_t *rmp; + int rv = 0; + + pg_main_t * pg = &pg_main; + u32 stream_index = ~0; + + int is_enable = mp->is_enabled != 0; + u32 len = ntohl(mp->stream_name_length)-1; + + if (len>0) { + u8 * stream_name = vec_new(u8, len); + clib_memcpy(stream_name, mp->stream_name, len); + uword * p = hash_get_mem (pg->stream_index_by_name, stream_name); + if (p) + stream_index = *p; + vec_free(stream_name); + } + + pg_enable_disable (stream_index, is_enable); + + REPLY_MACRO(VL_API_PG_ENABLE_DISABLE_REPLY); +} + #define BOUNCE_HANDLER(nn) \ static void vl_api_##nn##_t_handler ( \ vl_api_##nn##_t *mp) \