_(IP_DUMP, ip_dump) \
_(IP_NEIGHBOR_ADD_DEL, ip_neighbor_add_del) \
_(IP_ADD_DEL_ROUTE, ip_add_del_route) \
+_(IP_TABLE_ADD_DEL, ip_table_add_del) \
+_(IP_PUNT_POLICE, ip_punt_police) \
+_(IP_PUNT_REDIRECT, ip_punt_redirect) \
_(SET_IP_FLOW_HASH,set_ip_flow_hash) \
_(SW_INTERFACE_IP6ND_RA_CONFIG, sw_interface_ip6nd_ra_config) \
_(SW_INTERFACE_IP6ND_RA_PREFIX, sw_interface_ip6nd_ra_prefix) \
_(IP6ND_PROXY_DUMP, ip6nd_proxy_dump) \
_(SW_INTERFACE_IP6_ENABLE_DISABLE, sw_interface_ip6_enable_disable ) \
_(SW_INTERFACE_IP6_SET_LINK_LOCAL_ADDRESS, \
- sw_interface_ip6_set_link_local_address)
+ sw_interface_ip6_set_link_local_address) \
+_(IP_CONTAINER_PROXY_ADD_DEL, ip_container_proxy_add_del )
extern void stats_dslock_with_hint (int hint, int tag);
extern void stats_dsunlock (void);
int is_ip4;
vl_api_fib_path_t *fp = (vl_api_fib_path_t *) fp_arg;
- if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP4)
+ if (api_rpath->rpath.frp_proto == DPO_PROTO_IP4)
fp->afi = IP46_TYPE_IP4;
- else if (api_rpath->rpath.frp_proto == FIB_PROTOCOL_IP6)
+ else if (api_rpath->rpath.frp_proto == DPO_PROTO_IP6)
fp->afi = IP46_TYPE_IP6;
else
{
static void
send_ip_fib_details (vpe_api_main_t * am,
unix_shared_memory_queue_t * q,
- u32 table_id, fib_prefix_t * pfx,
+ const fib_table_t * table,
+ const fib_prefix_t * pfx,
fib_route_path_encode_t * api_rpaths, u32 context)
{
vl_api_ip_fib_details_t *mp;
mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS);
mp->context = context;
- mp->table_id = htonl (table_id);
+ mp->table_id = htonl (table->ft_table_id);
+ memcpy (mp->table_name, table->ft_desc,
+ clib_min (vec_len (table->ft_desc), sizeof (mp->table_name)));
mp->address_length = pfx->fp_len;
memcpy (mp->address, &pfx->fp_addr.ip4, sizeof (pfx->fp_addr.ip4));
fib_table = fib_table_get (fib_index, pfx.fp_proto);
api_rpaths = NULL;
fib_entry_encode (*lfeip, &api_rpaths);
- send_ip_fib_details (am, q,
- fib_table->ft_table_id, &pfx, api_rpaths,
- mp->context);
+ send_ip_fib_details (am, q, fib_table, &pfx, api_rpaths, mp->context);
vec_free (api_rpaths);
}
}
fp->weight = api_rpath->rpath.frp_weight;
fp->preference = api_rpath->rpath.frp_preference;
- fp->sw_if_index = api_rpath->rpath.frp_sw_if_index;
+ fp->sw_if_index = htonl (api_rpath->rpath.frp_sw_if_index);
copy_fib_next_hop (api_rpath, fp);
fp++;
}
vec_free (api_rpaths);
}
+static void
+vl_api_ip_punt_police_t_handler (vl_api_ip_punt_police_t * mp,
+ vlib_main_t * vm)
+{
+ vl_api_ip_punt_police_reply_t *rmp;
+ int rv = 0;
+
+ if (mp->is_ip6)
+ ip6_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
+ else
+ ip4_punt_policer_add_del (mp->is_add, ntohl (mp->policer_index));
+
+ REPLY_MACRO (VL_API_IP_PUNT_POLICE_REPLY);
+}
+
+static void
+vl_api_ip_punt_redirect_t_handler (vl_api_ip_punt_redirect_t * mp,
+ vlib_main_t * vm)
+{
+ vl_api_ip_punt_redirect_reply_t *rmp;
+ int rv = 0;
+
+ if (mp->is_add)
+ {
+ ip46_address_t nh;
+
+ memset (&nh, 0, sizeof (nh));
+
+ if (mp->is_ip6)
+ {
+ memcpy (&nh.ip6, mp->nh, sizeof (nh.ip6));
+
+ ip6_punt_redirect_add (ntohl (mp->rx_sw_if_index),
+ ntohl (mp->tx_sw_if_index), &nh);
+ }
+ else
+ {
+ memcpy (&nh.ip4, mp->nh, sizeof (nh.ip4));
+
+ ip4_punt_redirect_add (ntohl (mp->rx_sw_if_index),
+ ntohl (mp->tx_sw_if_index), &nh);
+ }
+ }
+ else
+ {
+ if (mp->is_ip6)
+ {
+ ip6_punt_redirect_del (ntohl (mp->rx_sw_if_index));
+ }
+ else
+ {
+ ip4_punt_redirect_del (ntohl (mp->rx_sw_if_index));
+ }
+ }
+
+ REPLY_MACRO (VL_API_IP_PUNT_REDIRECT_REPLY);
+}
+
static void
vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp,
vlib_main_t * vm)
vnet_arp_unset_ip4_over_ethernet (vnm, ntohl (mp->sw_if_index), &a);
}
- BAD_SW_IF_INDEX_LABEL;
-
stats_dsunlock ();
+
+ BAD_SW_IF_INDEX_LABEL;
REPLY_MACRO (VL_API_IP_NEIGHBOR_ADD_DEL_REPLY);
}
+void
+ip_table_delete (fib_protocol_t fproto, u32 table_id, u8 is_api)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 != fib_index)
+ {
+ fib_table_unlock (fib_index, fproto,
+ (is_api ? FIB_SOURCE_API : FIB_SOURCE_CLI));
+ }
+ if (~0 != mfib_index)
+ {
+ mfib_table_unlock (mfib_index, fproto,
+ (is_api ? MFIB_SOURCE_API : MFIB_SOURCE_CLI));
+ }
+ }
+}
+
+void
+vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp)
+{
+ vl_api_ip_table_add_del_reply_t *rmp;
+ fib_protocol_t fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4);
+ u32 table_id = ntohl (mp->table_id);
+ int rv = 0;
+
+ if (mp->is_add)
+ {
+ ip_table_create (fproto, table_id, 1, mp->name);
+ }
+ else
+ {
+ ip_table_delete (fproto, table_id, 1);
+ }
+
+ REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY);
+}
+
int
add_del_route_t_handler (u8 is_multipath,
u8 is_add,
u8 is_resolve_attached,
u8 is_interface_rx,
u8 is_rpf_id,
+ u8 is_l2_bridged,
+ u8 is_source_lookup,
u32 fib_index,
const fib_prefix_t * prefix,
- u8 next_hop_proto_is_ip4,
+ dpo_proto_t next_hop_proto,
const ip46_address_t * next_hop,
u32 next_hop_sw_if_index,
u8 next_hop_fib_index,
vnet_classify_main_t *cm = &vnet_classify_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_proto = next_hop_proto,
.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,
fib_route_path_t *paths = NULL;
fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE;
- if (MPLS_LABEL_INVALID != next_hop_via_label)
+ /*
+ * the special INVALID label meams we are not recursing via a
+ * label. Exp-null value is never a valid via-label so that
+ * also means it's not a via-label and means clients that set
+ * it to 0 by default get the expected behaviour
+ */
+ if ((MPLS_LABEL_INVALID != next_hop_via_label) && (0 != next_hop_via_label))
{
- path.frp_proto = FIB_PROTOCOL_MPLS;
+ path.frp_proto = DPO_PROTO_MPLS;
path.frp_local_label = next_hop_via_label;
path.frp_eos = MPLS_NON_EOS;
}
+ if (is_l2_bridged)
+ path.frp_proto = DPO_PROTO_ETHERNET;
if (is_resolve_host)
path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST;
if (is_resolve_attached)
path_flags |= FIB_ROUTE_PATH_INTF_RX;
if (is_rpf_id)
path_flags |= FIB_ROUTE_PATH_RPF_ID;
+ if (is_source_lookup)
+ path_flags |= FIB_ROUTE_PATH_SOURCE_LOOKUP;
if (is_multicast)
entry_flags |= FIB_ENTRY_FLAG_MULTICAST;
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,
+ dpo_proto_t next_hop_table_proto,
u32 next_hop_table_id,
- u8 create_missing_tables,
u8 is_rpf_id, u32 * fib_index, u32 * next_hop_fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
+ /* Temporaray whilst I do the CSIT dance */
+ u8 create_missing_tables = 1;
+
*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));
+ ntohl (table_id),
+ FIB_SOURCE_API);
}
else
{
}
else
{
+ fib_protocol_t fib_nh_proto;
+
+ if (next_hop_table_proto > DPO_PROTO_MPLS)
+ return (0);
+
+ fib_nh_proto = dpo_proto_to_fib (next_hop_table_proto);
+
if (is_rpf_id)
- *next_hop_fib_index = mfib_table_find (next_hop_table_proto,
+ *next_hop_fib_index = mfib_table_find (fib_nh_proto,
ntohl (next_hop_table_id));
else
- *next_hop_fib_index = fib_table_find (next_hop_table_proto,
+ *next_hop_fib_index = fib_table_find (fib_nh_proto,
ntohl (next_hop_table_id));
if (~0 == *next_hop_fib_index)
{
if (is_rpf_id)
*next_hop_fib_index =
- mfib_table_find_or_create_and_lock (next_hop_table_proto,
+ mfib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ MFIB_SOURCE_API);
else
*next_hop_fib_index =
- fib_table_find_or_create_and_lock (next_hop_table_proto,
+ fib_table_find_or_create_and_lock (fib_nh_proto,
ntohl
- (next_hop_table_id));
+ (next_hop_table_id),
+ FIB_SOURCE_API);
}
else
{
rv = add_del_route_check (FIB_PROTOCOL_IP4,
mp->table_id,
mp->next_hop_sw_if_index,
- FIB_PROTOCOL_IP4,
+ DPO_PROTO_IP4,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
mp->classify_table_index,
mp->is_resolve_host,
mp->is_resolve_attached, 0, 0,
- fib_index, &pfx, 1,
+ mp->is_l2_bridged,
+ mp->is_source_lookup,
+ fib_index, &pfx, DPO_PROTO_IP4,
&nh,
ntohl (mp->next_hop_sw_if_index),
next_hop_fib_index,
rv = add_del_route_check (FIB_PROTOCOL_IP6,
mp->table_id,
mp->next_hop_sw_if_index,
- FIB_PROTOCOL_IP6,
+ DPO_PROTO_IP6,
mp->next_hop_table_id,
- mp->create_vrf_if_needed, 0,
- &fib_index, &next_hop_fib_index);
+ 0, &fib_index, &next_hop_fib_index);
if (0 != rv)
return (rv);
mp->classify_table_index,
mp->is_resolve_host,
mp->is_resolve_attached, 0, 0,
- fib_index, &pfx, 0,
+ mp->is_l2_bridged,
+ mp->is_source_lookup,
+ fib_index, &pfx, DPO_PROTO_IP6,
&nh, ntohl (mp->next_hop_sw_if_index),
next_hop_fib_index,
mp->next_hop_weight,
REPLY_MACRO (VL_API_IP_ADD_DEL_ROUTE_REPLY);
}
+void
+ip_table_create (fib_protocol_t fproto,
+ u32 table_id, u8 is_api, const u8 * name)
+{
+ u32 fib_index, mfib_index;
+
+ /*
+ * ignore action on the default table - this is always present
+ * and cannot be added nor deleted from the API
+ */
+ if (0 != table_id)
+ {
+ /*
+ * The API holds only one lock on the table.
+ * i.e. it can be added many times via the API but needs to be
+ * deleted only once.
+ * The FIB index for unicast and multicast is not necessarily the
+ * same, since internal VPP systesm (like LISP and SR) create
+ * their own unicast tables.
+ */
+ fib_index = fib_table_find (fproto, table_id);
+ mfib_index = mfib_table_find (fproto, table_id);
+
+ if (~0 == fib_index)
+ {
+ fib_table_find_or_create_and_lock_w_name (fproto, table_id,
+ (is_api ?
+ FIB_SOURCE_API :
+ FIB_SOURCE_CLI), name);
+ }
+ if (~0 == mfib_index)
+ {
+ mfib_table_find_or_create_and_lock_w_name (fproto, table_id,
+ (is_api ?
+ MFIB_SOURCE_API :
+ MFIB_SOURCE_CLI), name);
+ }
+ }
+}
+
static int
add_del_mroute_check (fib_protocol_t table_proto,
u32 table_id,
- u32 next_hop_sw_if_index,
- u8 is_local, u8 create_missing_tables, u32 * fib_index)
+ u32 next_hop_sw_if_index, u8 is_local, u32 * fib_index)
{
vnet_main_t *vnm = vnet_get_main ();
*fib_index = mfib_table_find (table_proto, ntohl (table_id));
if (~0 == *fib_index)
{
- if (create_missing_tables)
- {
- *fib_index = mfib_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;
- }
+ /* No such table */
+ return VNET_API_ERROR_NO_SUCH_FIB;
}
if (~0 != ntohl (next_hop_sw_if_index))
fib_route_path_t path = {
.frp_sw_if_index = next_hop_sw_if_index,
- .frp_proto = prefix->fp_proto,
+ .frp_proto = fib_proto_to_dpo (prefix->fp_proto),
};
if (is_local)
rv = add_del_mroute_check (fproto,
mp->table_id,
mp->next_hop_sw_if_index,
- mp->is_local,
- mp->create_vrf_if_needed, &fib_index);
+ mp->is_local, &fib_index);
if (0 != rv)
return (rv);
;
}
+static void
+ vl_api_ip_container_proxy_add_del_t_handler
+ (vl_api_ip_container_proxy_add_del_t * mp)
+{
+ vl_api_ip_container_proxy_add_del_reply_t *rmp;
+ vnet_ip_container_proxy_args_t args;
+ int rv = 0;
+ clib_error_t *error;
+
+ memset (&args, 0, sizeof (args));
+ ip_set (&args.prefix.fp_addr, mp->ip, mp->is_ip4);
+ args.prefix.fp_len = mp->plen ? mp->plen : (mp->is_ip4 ? 32 : 128);
+ args.sw_if_index = clib_net_to_host_u32 (mp->sw_if_index);
+ args.is_add = mp->is_add;
+ if ((error = vnet_ip_container_proxy_add_del (&args)))
+ {
+ rv = clib_error_get_code (error);
+ clib_error_report (error);
+ }
+
+ REPLY_MACRO (VL_API_IP_CONTAINER_PROXY_ADD_DEL_REPLY);
+}
+
#define vl_msg_name_crc_list
#include <vnet/ip/ip.api.h>
#undef vl_msg_name_crc_list