-static int
-add_del_route_t_handler (u8 is_multipath,
- u8 is_add,
- u8 is_drop,
- u8 is_unreach,
- u8 is_prohibit,
- u8 is_local,
- u8 is_classify,
- u32 classify_table_index,
- u8 is_resolve_host,
- u8 is_resolve_attached,
- u32 fib_index,
- const fib_prefix_t * prefix,
- u8 next_hop_proto_is_ip4,
- const ip46_address_t * next_hop,
- u32 next_hop_sw_if_index,
- u8 next_hop_fib_index,
- u32 next_hop_weight,
- mpls_label_t next_hop_via_label,
- mpls_label_t * next_hop_out_label_stack)
-{
- vnet_classify_main_t *cm = &vnet_classify_main;
- stats_main_t *sm = &stats_main;
- fib_route_path_flags_t path_flags = FIB_ROUTE_PATH_FLAG_NONE;
- fib_route_path_t path = {
- .frp_proto = (next_hop_proto_is_ip4 ?
- FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6),
- .frp_addr = (NULL == next_hop ? zero_addr : *next_hop),
- .frp_sw_if_index = next_hop_sw_if_index,
- .frp_fib_index = next_hop_fib_index,
- .frp_weight = next_hop_weight,
- .frp_label_stack = next_hop_out_label_stack,
- };
- fib_route_path_t *paths = NULL;
-
- if (MPLS_LABEL_INVALID != next_hop_via_label)
- {
- path.frp_proto = FIB_PROTOCOL_MPLS;
- path.frp_local_label = next_hop_via_label;
- }
- if (is_resolve_host)
- path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
- if (is_resolve_attached)
- path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED;
-
- path.frp_flags = path_flags;
-
- if (is_multipath)
- {
- dslock (sm, 1 /* release hint */ , 10 /* tag */ );
-
-
- vec_add1 (paths, path);
-
- if (is_add)
- fib_table_entry_path_add2 (fib_index,
- prefix,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_NONE, paths);
- else
- fib_table_entry_path_remove2 (fib_index,
- prefix, FIB_SOURCE_API, paths);
-
- vec_free (paths);
- dsunlock (sm);
- return 0;
- }
-
- dslock (sm, 1 /* release hint */ , 2 /* tag */ );
-
- if (is_drop || is_local || is_classify || is_unreach || is_prohibit)
- {
- /*
- * special route types that link directly to the adj
- */
- if (is_add)
- {
- dpo_id_t dpo = DPO_INVALID;
- dpo_proto_t dproto;
-
- dproto = fib_proto_to_dpo (prefix->fp_proto);
-
- if (is_drop)
- ip_null_dpo_add_and_lock (dproto, IP_NULL_ACTION_NONE, &dpo);
- else if (is_local)
- receive_dpo_add_or_lock (dproto, ~0, NULL, &dpo);
- else if (is_unreach)
- ip_null_dpo_add_and_lock (dproto,
- IP_NULL_ACTION_SEND_ICMP_UNREACH, &dpo);
- else if (is_prohibit)
- ip_null_dpo_add_and_lock (dproto,
- IP_NULL_ACTION_SEND_ICMP_PROHIBIT,
- &dpo);
- else if (is_classify)
- {
- if (pool_is_free_index (cm->tables,
- ntohl (classify_table_index)))
- {
- dsunlock (sm);
- return VNET_API_ERROR_NO_SUCH_TABLE;
- }
-
- dpo_set (&dpo, DPO_CLASSIFY, dproto,
- classify_dpo_create (dproto,
- ntohl (classify_table_index)));
- }
- else
- {
- dsunlock (sm);
- return VNET_API_ERROR_NO_SUCH_TABLE;
- }
-
- fib_table_entry_special_dpo_update (fib_index,
- prefix,
- FIB_SOURCE_API,
- FIB_ENTRY_FLAG_EXCLUSIVE, &dpo);
- dpo_reset (&dpo);
- }
- else
- {
- fib_table_entry_special_remove (fib_index, prefix, FIB_SOURCE_API);
- }
- }
- else
- {
- if (is_add)
- {
- vec_add1 (paths, path);
- fib_table_entry_update (fib_index,
- prefix,
- FIB_SOURCE_API, FIB_ENTRY_FLAG_NONE, paths);
- vec_free (paths);
- }
- else
- {
- fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API);
- }
- }
-
- dsunlock (sm);
- return (0);
-}
-
-static int
-add_del_route_check (fib_protocol_t table_proto,
- u32 table_id,
- u32 next_hop_sw_if_index,
- fib_protocol_t next_hop_table_proto,
- u32 next_hop_table_id,
- u8 create_missing_tables,
- u32 * fib_index, u32 * next_hop_fib_index)
-{
- vnet_main_t *vnm = vnet_get_main ();
-
- *fib_index = fib_table_find (table_proto, ntohl (table_id));
- if (~0 == *fib_index)
- {
- if (create_missing_tables)
- {
- *fib_index = fib_table_find_or_create_and_lock (table_proto,
- ntohl (table_id));
- }
- else
- {
- /* No such VRF, and we weren't asked to create one */
- return VNET_API_ERROR_NO_SUCH_FIB;
- }
- }
-
- if (~0 != ntohl (next_hop_sw_if_index))
- {
- if (pool_is_free_index (vnm->interface_main.sw_interfaces,
- ntohl (next_hop_sw_if_index)))
- {
- return VNET_API_ERROR_NO_MATCHING_INTERFACE;
- }
- }
- else
- {
- *next_hop_fib_index = fib_table_find (next_hop_table_proto,
- ntohl (next_hop_table_id));
-
- if (~0 == *next_hop_fib_index)
- {
- if (create_missing_tables)
- {
- *next_hop_fib_index =
- fib_table_find_or_create_and_lock (next_hop_table_proto,
- ntohl (next_hop_table_id));
- }
- else
- {
- /* No such VRF, and we weren't asked to create one */
- return VNET_API_ERROR_NO_SUCH_FIB;
- }
- }
- }
-
- return (0);
-}
-
-static int
-ip4_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
-{
- u32 fib_index, next_hop_fib_index;
- mpls_label_t *label_stack = NULL;
- int rv, ii, n_labels;;
-
- rv = add_del_route_check (FIB_PROTOCOL_IP4,
- mp->table_id,
- mp->next_hop_sw_if_index,
- FIB_PROTOCOL_IP4,
- mp->next_hop_table_id,
- mp->create_vrf_if_needed,
- &fib_index, &next_hop_fib_index);
-
- if (0 != rv)
- return (rv);
-
- fib_prefix_t pfx = {
- .fp_len = mp->dst_address_length,
- .fp_proto = FIB_PROTOCOL_IP4,
- };
- clib_memcpy (&pfx.fp_addr.ip4, mp->dst_address, sizeof (pfx.fp_addr.ip4));
-
- ip46_address_t nh;
- memset (&nh, 0, sizeof (nh));
- memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4));
-
- n_labels = mp->next_hop_n_out_labels;
- if (n_labels == 0)
- ;
- else if (1 == n_labels)
- vec_add1 (label_stack, ntohl (mp->next_hop_out_label_stack[0]));
- else
- {
- vec_validate (label_stack, n_labels - 1);
- for (ii = 0; ii < n_labels; ii++)
- label_stack[ii] = ntohl (mp->next_hop_out_label_stack[ii]);
- }
-
- return (add_del_route_t_handler (mp->is_multipath,
- mp->is_add,
- mp->is_drop,
- mp->is_unreach,
- mp->is_prohibit,
- mp->is_local,
- mp->is_classify,
- mp->classify_table_index,
- mp->is_resolve_host,
- mp->is_resolve_attached,
- fib_index, &pfx, 1,
- &nh,
- ntohl (mp->next_hop_sw_if_index),
- next_hop_fib_index,
- mp->next_hop_weight,
- ntohl (mp->next_hop_via_label),
- label_stack));
-}
-
-static int
-ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp)
-{
- u32 fib_index, next_hop_fib_index;
- mpls_label_t *label_stack = NULL;
- int rv, ii, n_labels;;
-
- rv = add_del_route_check (FIB_PROTOCOL_IP6,
- mp->table_id,
- mp->next_hop_sw_if_index,
- FIB_PROTOCOL_IP6,
- mp->next_hop_table_id,
- mp->create_vrf_if_needed,
- &fib_index, &next_hop_fib_index);
-
- if (0 != rv)
- return (rv);
-
- fib_prefix_t pfx = {
- .fp_len = mp->dst_address_length,
- .fp_proto = FIB_PROTOCOL_IP6,
- };
- clib_memcpy (&pfx.fp_addr.ip6, mp->dst_address, sizeof (pfx.fp_addr.ip6));
-
- ip46_address_t nh;
- memset (&nh, 0, sizeof (nh));
- memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6));
-
- n_labels = mp->next_hop_n_out_labels;
- if (n_labels == 0)
- ;
- else if (1 == n_labels)
- vec_add1 (label_stack, ntohl (mp->next_hop_out_label_stack[0]));
- else
- {
- vec_validate (label_stack, n_labels - 1);
- for (ii = 0; ii < n_labels; ii++)
- label_stack[ii] = ntohl (mp->next_hop_out_label_stack[ii]);
- }
-
- return (add_del_route_t_handler (mp->is_multipath,
- mp->is_add,
- mp->is_drop,
- mp->is_unreach,
- mp->is_prohibit,
- mp->is_local,
- mp->is_classify,
- mp->classify_table_index,
- mp->is_resolve_host,
- mp->is_resolve_attached,
- fib_index, &pfx, 0,
- &nh, ntohl (mp->next_hop_sw_if_index),
- next_hop_fib_index,
- mp->next_hop_weight,
- ntohl (mp->next_hop_via_label),
- label_stack));
-}
-