diff options
author | Neale Ranns <neale.ranns@cisco.com> | 2018-05-01 05:17:55 -0700 |
---|---|---|
committer | Ole Trøan <otroan@employees.org> | 2019-06-18 13:31:39 +0000 |
commit | 097fa66b986f06281f603767d321ab13ab6c88c3 (patch) | |
tree | ed052819615d08ee4bd0afbc34de7e64e4598105 /src/vnet/ip | |
parent | 39baa32186fd3e4b20d9f58afbbfe7b8daebed62 (diff) |
fib: fib api updates
Enhance the route add/del APIs to take a set of paths rather than just one.
Most unicast routing protocols calcualte all the available paths in one
run of the algorithm so updating all the paths at once is beneficial for the client.
two knobs control the behaviour:
is_multipath - if set the the set of paths passed will be added to those
that already exist, otherwise the set will replace them.
is_add - add or remove the set
is_add=0, is_multipath=1 and an empty set, results in deleting the route.
It is also considerably faster to add multiple paths at once, than one at a time:
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.11
100000 routes in .572240 secs, 174751.80 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.12
100000 routes in .528383 secs, 189256.54 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.13
100000 routes in .757131 secs, 132077.52 routes/sec
vat# ip_add_del_route 1.1.1.1/32 count 100000 multipath via 10.10.10.14
100000 routes in .878317 secs, 113854.12 routes/sec
vat# ip_route_add_del 1.1.1.1/32 count 100000 multipath via 10.10.10.11 via 10.10.10.12 via 10.10.10.13 via 10.10.10.14
100000 routes in .900212 secs, 111084.93 routes/sec
Change-Id: I416b93f7684745099c1adb0b33edac58c9339c1a
Signed-off-by: Neale Ranns <neale.ranns@cisco.com>
Signed-off-by: Ole Troan <ot@cisco.com>
Signed-off-by: Paul Vinciguerra <pvinci@vinciconsulting.com>
Diffstat (limited to 'src/vnet/ip')
-rw-r--r-- | src/vnet/ip/ip.api | 281 | ||||
-rw-r--r-- | src/vnet/ip/ip_api.c | 1056 | ||||
-rw-r--r-- | src/vnet/ip/ip_types_api.c | 3 | ||||
-rw-r--r-- | src/vnet/ip/lookup.c | 108 |
4 files changed, 396 insertions, 1052 deletions
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api index afb0960c78a..2dae4385602 100644 --- a/src/vnet/ip/ip.api +++ b/src/vnet/ip/ip.api @@ -20,15 +20,13 @@ called through a shared memory interface. */ -option version = "2.0.1"; -import "vnet/ip/ip_types.api"; +option version = "3.0.0"; + import "vnet/fib/fib_types.api"; import "vnet/ethernet/ethernet_types.api"; +import "vnet/mfib/mfib_types.api"; -/** \brief Add / del table request - A table can be added multiple times, but need be deleted only once. - @param client_index - opaque cookie to identify the sender - @param context - sender context, to match reply w/ request +/** \brief An IP table @param is_ipv6 - V4 or V6 table @param table_id - table ID associated with the route This table ID will apply to both the unicats @@ -37,70 +35,104 @@ import "vnet/ethernet/ethernet_types.api"; not set by the client, then VPP will generate something meaningfull. */ +typeonly define ip_table +{ + u32 table_id; + u8 is_ip6; + u8 name[64]; +}; + +/** \brief Add / del table request + A table can be added multiple times, but need be deleted only once. + @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request +*/ autoreply define ip_table_add_del { u32 client_index; u32 context; - u32 table_id; - u8 is_ipv6; u8 is_add; - u8 name[64]; + vl_api_ip_table_t table; }; -/** \brief Dump IP fib table +/** \brief Dump IP all fib tables @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request */ -define ip_fib_dump +define ip_table_dump { u32 client_index; u32 context; }; /** \brief IP FIB table response - @param table_id - IP fib table id - @address_length - mask length - @address - ip4 prefix - @param count - the number of fib_path in path - @param path - array of of fib_path structures + @param context - sender context + @param table - description of the table */ -manual_endian manual_print define ip_fib_details +manual_endian manual_print define ip_table_details { u32 context; + vl_api_ip_table_t table; +}; + +/** \brief An IP route + @param table_id The IP table the route is in + @param stats_index The index of the route in the stats segment + @param prefix the prefix for the route + @param n_paths The number of paths the route has + @param paths The paths of the route +*/ +typeonly define ip_route +{ u32 table_id; - u8 table_name[64]; - u8 address_length; - u8 address[4]; - u32 count; u32 stats_index; - vl_api_fib_path_t path[count]; + vl_api_prefix_t prefix; + u8 n_paths; + vl_api_fib_path_t paths[n_paths]; }; -/** \brief Dump IP6 fib table +/** \brief Add / del route request @param client_index - opaque cookie to identify the sender + @param context - sender context, to match reply w/ request + @param is_multipath - Set to 1 if these paths will be added/removed + to/from the existing set, or 0 to replace + the existing set. + is_add=0 & is_multipath=0 implies delete all paths + @param is_add - Are the paths being added or removed */ -define ip6_fib_dump +define ip_route_add_del { u32 client_index; u32 context; + u8 is_add; + u8 is_multipath; + vl_api_ip_route_t route; +}; +define ip_route_add_del_reply +{ + u32 context; + i32 retval; + u32 stats_index; }; -/** \brief IP6 FIB table entry response - @param table_id - IP6 fib table id - @param address_length - mask length - @param address - ip6 prefix - @param count - the number of fib_path in path - @param path - array of of fib_path structures +/** \brief Dump IP routes from a table + @param client_index - opaque cookie to identify the sender + @param table - The table from which to dump routes (ony ID an AF are needed) */ -manual_endian manual_print define ip6_fib_details +define ip_route_dump { + u32 client_index; u32 context; - u32 table_id; - u8 table_name[64]; - u8 address_length; - u8 address[16]; - u32 count; - u32 stats_index; - vl_api_fib_path_t path[count]; + vl_api_ip_table_t table; +}; + +/** \brief IP FIB table entry response + @param route The route entry in the table +*/ +manual_endian manual_print define ip_route_details +{ + u32 context; + vl_api_ip_route_t route; }; /** \brief IP neighbor flags @@ -359,76 +391,33 @@ autoreply define sw_interface_ip6_enable_disable u8 enable; /* set to true if enable */ }; -/** \brief Add / del route request +/** \brief IPv6 set link local address on interface request @param client_index - opaque cookie to identify the sender @param context - sender context, to match reply w/ request - @param sw_if_index - software index of the new vlan's parent interface - @param vrf_id - fib table /vrf associated with the route - @param lookup_in_vrf - - @param classify_table_index - - @param is_add - 1 if adding the route, 0 if deleting - @param is_drop - Drop the packet - @param is_unreach - Drop the packet and rate limit send ICMP unreachable - @param is_prohibit - Drop the packet and rate limit send ICMP prohibited - @param is_ipv6 - 0 if an ip4 route, else ip6 - @param is_local - The route will result in packets sent to VPP IP stack - @param is_udp_encap - The path describes a UDP-o-IP encapsulation. - @param is_classify - - @param is_multipath - Set to 1 if this is a multipath route, else 0 - @param is_dvr - Does the route resolve via a DVR interface. - @param is_source_lookup - The the path is a deaggregate path (i.e. a lookup - in another table) is the lookup on the packet's - source address or destination. - @param next_hop_weight - Weight for Unequal cost multi-path - @param next_hop_preference - Path that are up that have the best preference are - are used for forwarding. lower value is better. - @param next_hop_id - Used when the path resolves via an object that has a unique - identifier. - @param dst_address_length - - @param dst_address[16] - - @param next_hop_address[16] - - @param next_hop_n_out_labels - the number of labels in the label stack - @param next_hop_out_label_stack - the next-hop output label stack, outer most first - @param next_hop_via_label - The next-hop is a resolved via a local label + @param sw_if_index - interface to set link local on + @param address[] - the new link local address */ -define ip_add_del_route +autoreply define sw_interface_ip6_set_link_local_address { u32 client_index; u32 context; - u32 next_hop_sw_if_index; - u32 table_id; - u32 classify_table_index; - u32 next_hop_table_id; - u32 next_hop_id; - u8 is_add; - u8 is_drop; - u8 is_unreach; - u8 is_prohibit; - u8 is_ipv6; - u8 is_local; - u8 is_classify; - u8 is_multipath; - u8 is_resolve_host; - u8 is_resolve_attached; - u8 is_dvr; - u8 is_source_lookup; - u8 is_udp_encap; - u8 next_hop_weight; - u8 next_hop_preference; - u8 next_hop_proto; - u8 dst_address_length; - u8 dst_address[16]; - u8 next_hop_address[16]; - u8 next_hop_n_out_labels; - u32 next_hop_via_label; - vl_api_fib_mpls_label_t next_hop_out_label_stack[next_hop_n_out_labels]; -}; - -define ip_add_del_route_reply + u32 sw_if_index; + u8 address[16]; +}; + +/** \brief Dump IP multicast fib table + @param client_index - opaque cookie to identify the sender +*/ +define ip_mtable_dump { + u32 client_index; u32 context; - i32 retval; - u32 stats_index; +}; +define ip_mtable_details +{ + u32 client_index; + u32 context; + vl_api_ip_table_t table; }; /** \brief Add / del route request @@ -459,105 +448,55 @@ define ip_add_del_route_reply FIXME not complete yet */ -define ip_mroute_add_del +typedef ip_mroute { - u32 client_index; - u32 context; - u32 next_hop_sw_if_index; u32 table_id; u32 entry_flags; - u32 itf_flags; u32 rpf_id; - u32 bier_imp; - u16 grp_address_length; - u8 next_hop_afi; - u8 is_add; - u8 is_ipv6; - u8 is_local; - u8 grp_address[16]; - u8 src_address[16]; - u8 nh_address[16]; -}; - -define ip_mroute_add_del_reply -{ - u32 context; - i32 retval; - u32 stats_index; + vl_api_mprefix_t prefix; + u8 n_paths; + vl_api_mfib_path_t paths[n_paths]; }; -/** \brief Dump IP multicast fib table - @param client_index - opaque cookie to identify the sender -*/ -define ip_mfib_dump +define ip_mroute_add_del { u32 client_index; u32 context; + u8 is_add; + u8 is_multipath; + vl_api_ip_mroute_t route; }; - -/** \brief IP Multicast FIB table response - @param table_id - IP fib table id - @address_length - mask length - @grp_address - Group address/prefix - @src_address - Source address - @param count - the number of fib_path in path - @param path - array of of fib_path structures -*/ -typedef mfib_path -{ - vl_api_fib_path_t path; - u32 itf_flags; -}; - -manual_endian manual_print define ip_mfib_details +define ip_mroute_add_del_reply { u32 context; - u32 table_id; - u32 entry_flags; - u32 rpf_id; - u8 address_length; - u8 grp_address[4]; - u8 src_address[4]; - u32 count; + i32 retval; u32 stats_index; - vl_api_mfib_path_t path[count]; }; -/** \brief Dump IP6 multicast fib table - @param client_index - opaque cookie to identify the sender +/** \brief Dump IP multicast fib table + @param table - The table from which to dump routes (ony ID an AF are needed) */ -define ip6_mfib_dump +define ip_mroute_dump { u32 client_index; u32 context; + vl_api_ip_table_t table; }; -/** \brief IP6 Multicast FIB table response - @param table_id - IP fib table id - @address_length - mask length - @grp_address - Group address/prefix - @src_address - Source address - @param count - the number of fib_path in path - @param path - array of of fib_path structures +/** \brief IP Multicast Route Details + @param route - Details of the route */ -manual_endian manual_print define ip6_mfib_details +manual_endian manual_print define ip_mroute_details { u32 context; - u32 table_id; - u8 address_length; - u8 grp_address[16]; - u8 src_address[16]; - u32 count; - vl_api_mfib_path_t path[count]; + vl_api_ip_mroute_t route; }; define ip_address_details { u32 context; - u8 ip[16]; - u8 prefix_length; u32 sw_if_index; - u8 is_ipv6; + vl_api_prefix_t prefix; }; define ip_address_dump @@ -614,9 +553,7 @@ define mfib_signal_details u32 context; u32 sw_if_index; u32 table_id; - u16 grp_address_len; - u8 grp_address[16]; - u8 src_address[16]; + vl_api_mprefix_t prefix; u16 ip_packet_len; u8 ip_packet_data[256]; }; diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c index bcbcf5ac8d4..4d2f0704ca3 100644 --- a/src/vnet/ip/ip_api.c +++ b/src/vnet/ip/ip_api.c @@ -29,18 +29,15 @@ #include <vnet/ip/ip_types_api.h> #include <vnet/ip/ip6_neighbor.h> #include <vnet/ip/ip_punt_drop.h> +#include <vnet/ip/ip_types_api.h> #include <vnet/fib/fib_table.h> #include <vnet/fib/fib_api.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/receive_dpo.h> -#include <vnet/dpo/lookup_dpo.h> -#include <vnet/dpo/classify_dpo.h> -#include <vnet/dpo/ip_null_dpo.h> #include <vnet/ethernet/arp_packet.h> #include <vnet/mfib/ip6_mfib.h> #include <vnet/mfib/ip4_mfib.h> #include <vnet/mfib/mfib_signal.h> #include <vnet/mfib/mfib_entry.h> +#include <vnet/mfib/mfib_api.h> #include <vnet/ip/ip_source_and_port_range_check.h> #include <vnet/fib/ip4_fib.h> #include <vnet/fib/ip6_fib.h> @@ -71,10 +68,10 @@ #define foreach_ip_api_msg \ -_(IP_FIB_DUMP, ip_fib_dump) \ -_(IP6_FIB_DUMP, ip6_fib_dump) \ -_(IP_MFIB_DUMP, ip_mfib_dump) \ -_(IP6_MFIB_DUMP, ip6_mfib_dump) \ +_(IP_TABLE_DUMP, ip_table_dump) \ +_(IP_ROUTE_DUMP, ip_route_dump) \ +_(IP_MTABLE_DUMP, ip_mtable_dump) \ +_(IP_MROUTE_DUMP, ip_mroute_dump) \ _(IP_NEIGHBOR_DUMP, ip_neighbor_dump) \ _(IP_MROUTE_ADD_DEL, ip_mroute_add_del) \ _(MFIB_SIGNAL_DUMP, mfib_signal_dump) \ @@ -93,7 +90,7 @@ _(PROXY_ARP_DUMP, proxy_arp_dump) \ _(PROXY_ARP_INTFC_ENABLE_DISABLE, proxy_arp_intfc_enable_disable) \ _(PROXY_ARP_INTFC_DUMP, proxy_arp_intfc_dump) \ _(RESET_FIB, reset_fib) \ -_(IP_ADD_DEL_ROUTE, ip_add_del_route) \ +_(IP_ROUTE_ADD_DEL, ip_route_add_del) \ _(IP_TABLE_ADD_DEL, ip_table_add_del) \ _(IP_PUNT_POLICE, ip_punt_police) \ _(IP_PUNT_REDIRECT, ip_punt_redirect) \ @@ -211,137 +208,104 @@ vl_api_ip_neighbor_dump_t_handler (vl_api_ip_neighbor_dump_t * mp) } static void -send_ip_fib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - 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; - fib_route_path_encode_t *api_rpath; - vl_api_fib_path_t *fp; - int path_count; +send_ip_table_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, const fib_table_t * table) +{ + vl_api_ip_table_details_t *mp; - path_count = vec_len (api_rpaths); - mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); + mp = vl_msg_api_alloc (sizeof (*mp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_TABLE_DETAILS); mp->context = context; - 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)); - mp->stats_index = - htonl (fib_table_entry_get_stats_index (table->ft_index, pfx)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) - { - fib_api_path_encode (api_rpath, fp); - fp++; - } + mp->table.is_ip6 = (table->ft_proto == FIB_PROTOCOL_IP6); + mp->table.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))); vl_api_send_msg (reg, (u8 *) mp); } -typedef struct vl_api_ip_fib_dump_walk_ctx_t_ -{ - fib_node_index_t *feis; -} vl_api_ip_fib_dump_walk_ctx_t; - -static fib_table_walk_rc_t -vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; - - vec_add1 (ctx->feis, fei); - - return (FIB_TABLE_WALK_CONTINUE); -} - static void -vl_api_ip_fib_dump_t_handler (vl_api_ip_fib_dump_t * mp) +vl_api_ip_table_dump_t_handler (vl_api_ip_table_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip4_main_t *im = &ip4_main; fib_table_t *fib_table; - fib_node_index_t *lfeip; - const fib_prefix_t *pfx; - u32 fib_index; - fib_route_path_encode_t *api_rpaths; - vl_api_ip_fib_dump_walk_ctx_t ctx = { - .feis = NULL, - }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ - pool_foreach (fib_table, im->fibs, + pool_foreach (fib_table, ip4_main.fibs, ({ - fib_table_walk(fib_table->ft_index, - FIB_PROTOCOL_IP4, - vl_api_ip_fib_dump_walk, - &ctx); + send_ip_table_details(am, reg, mp->context, fib_table); + })); + pool_foreach (fib_table, ip6_main.fibs, + ({ + /* don't send link locals */ + if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) + continue; + send_ip_table_details(am, reg, mp->context, fib_table); })); /* *INDENT-ON* */ +} - vec_sort_with_function (ctx.feis, fib_entry_cmp_for_sort); +typedef struct vl_api_ip_fib_dump_walk_ctx_t_ +{ + fib_node_index_t *feis; +} vl_api_ip_fib_dump_walk_ctx_t; - vec_foreach (lfeip, ctx.feis) - { - pfx = fib_entry_get_prefix (*lfeip); - fib_index = fib_entry_get_fib_index (*lfeip); - fib_table = fib_table_get (fib_index, pfx->fp_proto); - api_rpaths = NULL; - fib_entry_encode (*lfeip, &api_rpaths); - send_ip_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context); - vec_free (api_rpaths); - } +static fib_table_walk_rc_t +vl_api_ip_fib_dump_walk (fib_node_index_t fei, void *arg) +{ + vl_api_ip_fib_dump_walk_ctx_t *ctx = arg; - vec_free (ctx.feis); + vec_add1 (ctx->feis, fei); + + return (FIB_TABLE_WALK_CONTINUE); } static void -send_ip6_fib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - const fib_table_t * table, - const fib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) -{ - vl_api_ip6_fib_details_t *mp; - fib_route_path_encode_t *api_rpath; +send_ip_route_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, fib_node_index_t fib_entry_index) +{ + fib_route_path_t *rpaths, *rpath; + vl_api_ip_route_details_t *mp; + const fib_prefix_t *pfx; vl_api_fib_path_t *fp; int path_count; - path_count = vec_len (api_rpaths); + rpaths = NULL; + pfx = fib_entry_get_prefix (fib_entry_index); + rpaths = fib_entry_encode (fib_entry_index); + + path_count = vec_len (rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP6_FIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_ROUTE_DETAILS); mp->context = context; - mp->table_id = htonl (table->ft_table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->address, &pfx->fp_addr.ip6, sizeof (pfx->fp_addr.ip6)); - memcpy (mp->table_name, table->ft_desc, - clib_min (vec_len (table->ft_desc), sizeof (mp->table_name))); - mp->stats_index = - htonl (fib_table_entry_get_stats_index (table->ft_index, pfx)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + ip_prefix_encode (pfx, &mp->route.prefix); + mp->route.table_id = + htonl (fib_table_get_table_id + (fib_entry_get_fib_index (fib_entry_index), pfx->fp_proto)); + mp->route.n_paths = path_count; + mp->route.stats_index = + htonl (fib_table_entry_get_stats_index + (fib_entry_get_fib_index (fib_entry_index), pfx)); + + fp = mp->route.paths; + vec_foreach (rpath, rpaths) { - fib_api_path_encode (api_rpath, fp); + fib_api_path_encode (rpath, fp); fp++; } @@ -353,232 +317,144 @@ typedef struct apt_ip6_fib_show_ctx_t_ fib_node_index_t *entries; } api_ip6_fib_show_ctx_t; -static fib_table_walk_rc_t -api_ip6_fib_table_put_entries (fib_node_index_t fei, void *arg) -{ - api_ip6_fib_show_ctx_t *ctx = arg; - - vec_add1 (ctx->entries, fei); - - return (FIB_TABLE_WALK_CONTINUE); -} - static void -api_ip6_fib_table_get_all (vl_api_registration_t * reg, - vl_api_ip6_fib_dump_t * mp, - fib_table_t * fib_table) +vl_api_ip_route_dump_t_handler (vl_api_ip_route_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; fib_node_index_t *fib_entry_index; - api_ip6_fib_show_ctx_t ctx = { - .entries = NULL, - }; - fib_route_path_encode_t *api_rpaths; - const fib_prefix_t *pfx; - - ip6_fib_table_walk (fib_table->ft_index, - api_ip6_fib_table_put_entries, &ctx); - - vec_sort_with_function (ctx.entries, fib_entry_cmp_for_sort); - - vec_foreach (fib_entry_index, ctx.entries) - { - pfx = fib_entry_get_prefix (*fib_entry_index); - api_rpaths = NULL; - fib_entry_encode (*fib_entry_index, &api_rpaths); - send_ip6_fib_details (am, reg, fib_table, pfx, api_rpaths, mp->context); - vec_free (api_rpaths); - } - - vec_free (ctx.entries); -} - -static void -vl_api_ip6_fib_dump_t_handler (vl_api_ip6_fib_dump_t * mp) -{ vl_api_registration_t *reg; - ip6_main_t *im6 = &ip6_main; - fib_table_t *fib_table; + fib_protocol_t fproto; + u32 fib_index; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; - /* *INDENT-OFF* */ - pool_foreach (fib_table, im6->fibs, - ({ - /* don't send link locals */ - if (fib_table->ft_flags & FIB_TABLE_FLAG_IP6_LL) - continue; - - api_ip6_fib_table_get_all(reg, mp, fib_table); - })); - /* *INDENT-ON* */ -} - -static void -send_ip_mfib_details (vl_api_registration_t * reg, - u32 context, u32 table_id, fib_node_index_t mfei) -{ - fib_route_path_encode_t *api_rpath, *api_rpaths = NULL; - vl_api_ip_mfib_details_t *mp; - const mfib_prefix_t *pfx; - mfib_entry_t *mfib_entry; - vl_api_mfib_path_t *fp; - int path_count; + vl_api_ip_fib_dump_walk_ctx_t ctx = { + .feis = NULL, + }; - mfib_entry = mfib_entry_get (mfei); - pfx = mfib_entry_get_prefix (mfei); - mfib_entry_encode (mfei, &api_rpaths); + fproto = (mp->table.is_ip6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + fib_index = fib_table_find (fproto, ntohl (mp->table.table_id)); - path_count = vec_len (api_rpaths); - mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); - if (!mp) + if (INDEX_INVALID == fib_index) return; - clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP_MFIB_DETAILS); - mp->context = context; - mp->rpf_id = mfib_entry->mfe_rpf_id; - mp->entry_flags = mfib_entry->mfe_flags; - mp->table_id = htonl (table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->grp_address, &pfx->fp_grp_addr.ip4, - sizeof (pfx->fp_grp_addr.ip4)); - memcpy (mp->src_address, &pfx->fp_src_addr.ip4, - sizeof (pfx->fp_src_addr.ip4)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + fib_table_walk (fib_index, fproto, vl_api_ip_fib_dump_walk, &ctx); + + vec_foreach (fib_entry_index, ctx.feis) { - fib_api_path_encode (api_rpath, &fp->path); - fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags); - fp++; + send_ip_route_details (am, reg, mp->context, *fib_entry_index); } - vec_free (api_rpaths); - vl_api_send_msg (reg, (u8 *) mp); + vec_free (ctx.feis); } -typedef struct vl_api_ip_mfib_dump_ctc_t_ +static void +send_ip_mtable_details (vl_api_registration_t * reg, + u32 context, const mfib_table_t * mfib_table) { - fib_node_index_t *entries; -} vl_api_ip_mfib_dump_ctc_t; + vl_api_ip_mtable_details_t *mp; -static int -vl_api_ip_mfib_table_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip_mfib_dump_ctc_t *ctx = arg; + mp = vl_msg_api_alloc (sizeof (*mp)); + if (!mp) + return; + memset (mp, 0, sizeof (*mp)); + mp->_vl_msg_id = ntohs (VL_API_IP_MTABLE_DETAILS); + mp->context = context; - vec_add1 (ctx->entries, fei); + mp->table.table_id = htonl (mfib_table->mft_table_id); + mp->table.is_ip6 = (FIB_PROTOCOL_IP6 == mfib_table->mft_proto); - return (0); + vl_api_send_msg (reg, (u8 *) mp); } static void -vl_api_ip_mfib_dump_t_handler (vl_api_ip_mfib_dump_t * mp) +vl_api_ip_mtable_dump_t_handler (vl_api_ip_mtable_dump_t * mp) { vl_api_registration_t *reg; - ip4_main_t *im = &ip4_main; mfib_table_t *mfib_table; - fib_node_index_t *mfeip; - vl_api_ip_mfib_dump_ctc_t ctx = { - .entries = NULL, - }; reg = vl_api_client_index_to_registration (mp->client_index); if (!reg) return; /* *INDENT-OFF* */ - pool_foreach (mfib_table, im->mfibs, + pool_foreach (mfib_table, ip4_main.mfibs, + ({ + send_ip_mtable_details (reg, mp->context, mfib_table); + })); + pool_foreach (mfib_table, ip6_main.mfibs, ({ - ip4_mfib_table_walk(&mfib_table->v4, - vl_api_ip_mfib_table_dump_walk, - &ctx); + send_ip_mtable_details (reg, mp->context, mfib_table); + })); + /* *INDENT-ON* */ +} - vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); +typedef struct vl_api_ip_mfib_dump_ctx_t_ +{ + fib_node_index_t *entries; +} vl_api_ip_mfib_dump_ctx_t; - vec_foreach (mfeip, ctx.entries) - { - send_ip_mfib_details (reg, mp->context, - mfib_table->mft_table_id, - *mfeip); - } - vec_reset_length (ctx.entries); +static int +mfib_route_dump_walk (fib_node_index_t fei, void *arg) +{ + vl_api_ip_mfib_dump_ctx_t *ctx = arg; - })); - /* *INDENT-ON* */ + vec_add1 (ctx->entries, fei); - vec_free (ctx.entries); + return (0); } static void -send_ip6_mfib_details (vpe_api_main_t * am, - vl_api_registration_t * reg, - u32 table_id, - const mfib_prefix_t * pfx, - fib_route_path_encode_t * api_rpaths, u32 context) +send_ip_mroute_details (vpe_api_main_t * am, + vl_api_registration_t * reg, + u32 context, fib_node_index_t mfib_entry_index) { - vl_api_ip6_mfib_details_t *mp; - fib_route_path_encode_t *api_rpath; + fib_route_path_t *rpaths, *rpath; + vl_api_ip_mroute_details_t *mp; + const mfib_prefix_t *pfx; vl_api_mfib_path_t *fp; int path_count; - path_count = vec_len (api_rpaths); + rpaths = NULL; + pfx = mfib_entry_get_prefix (mfib_entry_index); + rpaths = mfib_entry_encode (mfib_entry_index); + + path_count = vec_len (rpaths); mp = vl_msg_api_alloc (sizeof (*mp) + path_count * sizeof (*fp)); if (!mp) return; clib_memset (mp, 0, sizeof (*mp)); - mp->_vl_msg_id = ntohs (VL_API_IP6_MFIB_DETAILS); + mp->_vl_msg_id = ntohs (VL_API_IP_MROUTE_DETAILS); mp->context = context; - mp->table_id = htonl (table_id); - mp->address_length = pfx->fp_len; - memcpy (mp->grp_address, &pfx->fp_grp_addr.ip6, - sizeof (pfx->fp_grp_addr.ip6)); - memcpy (mp->src_address, &pfx->fp_src_addr.ip6, - sizeof (pfx->fp_src_addr.ip6)); - - mp->count = htonl (path_count); - fp = mp->path; - vec_foreach (api_rpath, api_rpaths) + ip_mprefix_encode (pfx, &mp->route.prefix); + mp->route.table_id = + htonl (mfib_table_get_table_id + (mfib_entry_get_fib_index (mfib_entry_index), pfx->fp_proto)); + mp->route.n_paths = htonl (path_count); + fp = mp->route.paths; + vec_foreach (rpath, rpaths) { - fib_api_path_encode (api_rpath, &fp->path); - fp->itf_flags = ntohl (api_rpath->rpath.frp_mitf_flags); + mfib_api_path_encode (rpath, fp); fp++; } vl_api_send_msg (reg, (u8 *) mp); -} - -typedef struct vl_api_ip6_mfib_dump_ctc_t_ -{ - fib_node_index_t *entries; -} vl_api_ip6_mfib_dump_ctc_t; - -static int -vl_api_ip6_mfib_table_dump_walk (fib_node_index_t fei, void *arg) -{ - vl_api_ip6_mfib_dump_ctc_t *ctx = arg; - - vec_add1 (ctx->entries, fei); - - return (0); + vec_free (rpaths); } static void -vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) +vl_api_ip_mroute_dump_t_handler (vl_api_ip_mroute_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip6_main_t *im = &ip6_main; - mfib_table_t *mfib_table; - const mfib_prefix_t *pfx; fib_node_index_t *mfeip; - fib_route_path_encode_t *api_rpaths = NULL; - vl_api_ip6_mfib_dump_ctc_t ctx = { + fib_protocol_t fproto; + u32 fib_index; + + vl_api_ip_mfib_dump_ctx_t ctx = { .entries = NULL, }; @@ -586,33 +462,22 @@ vl_api_ip6_mfib_dump_t_handler (vl_api_ip6_mfib_dump_t * mp) if (!reg) return; + fproto = fib_ip_proto (mp->table.is_ip6); + fib_index = mfib_table_find (fproto, ntohl (mp->table.table_id)); - /* *INDENT-OFF* */ - pool_foreach (mfib_table, im->mfibs, - ({ - ip6_mfib_table_walk(&mfib_table->v6, - vl_api_ip6_mfib_table_dump_walk, - &ctx); + if (INDEX_INVALID == fib_index) + return; - vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); + mfib_table_walk (fib_index, fproto, mfib_route_dump_walk, &ctx); - vec_foreach(mfeip, ctx.entries) - { - pfx = mfib_entry_get_prefix (*mfeip); - mfib_entry_encode (*mfeip, &api_rpaths); - send_ip6_mfib_details (am, reg, - mfib_table->mft_table_id, - pfx, api_rpaths, - mp->context); - } - vec_reset_length (api_rpaths); - vec_reset_length (ctx.entries); + vec_sort_with_function (ctx.entries, mfib_entry_cmp_for_sort); - })); - /* *INDENT-ON* */ + vec_foreach (mfeip, ctx.entries) + { + send_ip_mroute_details (am, reg, mp->context, *mfeip); + } vec_free (ctx.entries); - vec_free (api_rpaths); } static void @@ -698,7 +563,7 @@ vl_api_ip_neighbor_add_del_t_handler (vl_api_ip_neighbor_add_del_t * mp, ip46_address_t ip; mac_address_t mac; ip46_type_t type; - int rv = 0; + int rv; VALIDATE_SW_IF_INDEX ((&mp->neighbor)); @@ -767,13 +632,14 @@ 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); + fib_protocol_t fproto = (mp->table.is_ip6 ? + FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); + u32 table_id = ntohl (mp->table.table_id); int rv = 0; if (mp->is_add) { - ip_table_create (fproto, table_id, 1, mp->name); + ip_table_create (fproto, table_id, 1, mp->table.name); } else { @@ -783,398 +649,71 @@ vl_api_ip_table_add_del_t_handler (vl_api_ip_table_add_del_t * mp) REPLY_MACRO (VL_API_IP_TABLE_ADD_DEL_REPLY); } -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_multicast, - u8 is_classify, - u32 classify_table_index, - u8 is_resolve_host, - u8 is_resolve_attached, - u8 is_interface_rx, - u8 is_rpf_id, - u8 is_dvr, - u8 is_source_lookup, - u8 is_udp_encap, - u32 fib_index, - const fib_prefix_t * prefix, - dpo_proto_t next_hop_proto, - const ip46_address_t * next_hop, - u32 next_hop_id, - u32 next_hop_sw_if_index, - u8 next_hop_fib_index, - u16 next_hop_weight, - u16 next_hop_preference, - mpls_label_t next_hop_via_label, - fib_mpls_label_t * next_hop_out_label_stack) -{ - 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, - .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_preference = next_hop_preference, - .frp_label_stack = next_hop_out_label_stack, - }; - fib_route_path_t *paths = NULL; - fib_entry_flag_t entry_flags = FIB_ENTRY_FLAG_NONE; - - /* - * the special INVALID label means 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 = DPO_PROTO_MPLS; - path.frp_local_label = next_hop_via_label; - path.frp_eos = MPLS_NON_EOS; - } - if (is_local) - { - path_flags |= FIB_ROUTE_PATH_LOCAL; - if (~0 != next_hop_sw_if_index) - { - entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL); - } - } - if (is_dvr) - path_flags |= FIB_ROUTE_PATH_DVR; - if (is_resolve_host) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_HOST; - if (is_resolve_attached) - path_flags |= FIB_ROUTE_PATH_RESOLVE_VIA_ATTACHED; - if (is_interface_rx) - 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; - if (is_udp_encap) - { - path_flags |= FIB_ROUTE_PATH_UDP_ENCAP; - path.frp_udp_encap_id = next_hop_id; - } - if (path.frp_sw_if_index == ~0 && ip46_address_is_zero (&path.frp_addr) - && path.frp_fib_index != ~0) - { - path_flags |= FIB_ROUTE_PATH_DEAG; - } - - path.frp_flags = path_flags; - - if (is_drop || (is_local && (~0 == next_hop_sw_if_index)) || - 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))) - { - return VNET_API_ERROR_NO_SUCH_TABLE; - } - - dpo_set (&dpo, DPO_CLASSIFY, dproto, - classify_dpo_create (dproto, - ntohl (classify_table_index))); - } - else - { - 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_multipath) - { - vec_add1 (paths, path); - - if (is_add) - fib_table_entry_path_add2 (fib_index, - prefix, - FIB_SOURCE_API, entry_flags, paths); - else - fib_table_entry_path_remove2 (fib_index, - prefix, FIB_SOURCE_API, paths); - - vec_free (paths); - } - else - { - if (is_add) - { - vec_add1 (paths, path); - fib_table_entry_update (fib_index, - prefix, FIB_SOURCE_API, entry_flags, paths); - vec_free (paths); - } - else - { - fib_table_entry_delete (fib_index, prefix, FIB_SOURCE_API); - } - } - - return (0); -} - -int -add_del_route_check (fib_protocol_t table_proto, - u32 table_id, - u32 next_hop_sw_if_index, - dpo_proto_t next_hop_table_proto, - u32 next_hop_table_id, - u8 is_rpf_id, 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) - { - /* No such VRF, and we weren't asked to create one */ - return VNET_API_ERROR_NO_SUCH_FIB; - } - - if (!is_rpf_id && ~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 - { - 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 (fib_nh_proto, - ntohl (next_hop_table_id)); - else - *next_hop_fib_index = fib_table_find (fib_nh_proto, - ntohl (next_hop_table_id)); - - if (~0 == *next_hop_fib_index) - { - /* 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 * stats_index) +ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp, u32 * stats_index) { - u32 fib_index, next_hop_fib_index; - fib_mpls_label_t *label_stack = NULL; - int rv, ii, n_labels;; + fib_route_path_t *rpaths = NULL, *rpath; + fib_entry_flag_t entry_flags; + vl_api_fib_path_t *apath; + fib_prefix_t pfx; + u32 fib_index; + int rv, ii; - rv = add_del_route_check (FIB_PROTOCOL_IP4, - mp->table_id, - mp->next_hop_sw_if_index, - DPO_PROTO_IP4, - mp->next_hop_table_id, - 0, &fib_index, &next_hop_fib_index); + entry_flags = FIB_ENTRY_FLAG_NONE; + ip_prefix_decode (&mp->route.prefix, &pfx); + rv = fib_api_table_id_decode (pfx.fp_proto, + ntohl (mp->route.table_id), &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; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip4, mp->next_hop_address, sizeof (nh.ip4)); + goto out; - n_labels = mp->next_hop_n_out_labels; - if (n_labels == 0) - ; - else + if (0 == mp->route.n_paths) { - vec_validate (label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - label_stack[ii].fml_value = - ntohl (mp->next_hop_out_label_stack[ii].label); - label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl; - label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp; - label_stack[ii].fml_mode = - (mp->next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE); - } + rv = VNET_API_ERROR_NO_PATHS_IN_ROUTE; + goto out; } - rv = add_del_route_t_handler (mp->is_multipath, - mp->is_add, - mp->is_drop, - mp->is_unreach, - mp->is_prohibit, - mp->is_local, 0, - mp->is_classify, - mp->classify_table_index, - mp->is_resolve_host, - mp->is_resolve_attached, 0, 0, - mp->is_dvr, - mp->is_source_lookup, - mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP4, - &nh, - ntohl (mp->next_hop_id), - ntohl (mp->next_hop_sw_if_index), - next_hop_fib_index, - mp->next_hop_weight, - mp->next_hop_preference, - ntohl (mp->next_hop_via_label), label_stack); - - if (mp->is_add && 0 == rv) - *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx); - - return (rv); -} - -static int -ip6_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp, - u32 * stats_index) -{ - fib_mpls_label_t *label_stack = NULL; - u32 fib_index, next_hop_fib_index; - int rv, ii, n_labels;; + vec_validate (rpaths, mp->route.n_paths - 1); - rv = add_del_route_check (FIB_PROTOCOL_IP6, - mp->table_id, - mp->next_hop_sw_if_index, - DPO_PROTO_IP6, - mp->next_hop_table_id, - 0, &fib_index, &next_hop_fib_index); + for (ii = 0; ii < mp->route.n_paths; ii++) + { + apath = &mp->route.paths[ii]; + rpath = &rpaths[ii]; - if (0 != rv) - return (rv); + rv = fib_api_path_decode (apath, rpath); - 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; - clib_memset (&nh, 0, sizeof (nh)); - memcpy (&nh.ip6, mp->next_hop_address, sizeof (nh.ip6)); + if ((rpath->frp_flags & FIB_ROUTE_PATH_LOCAL) && + (~0 == rpath->frp_sw_if_index)) + entry_flags |= (FIB_ENTRY_FLAG_CONNECTED | FIB_ENTRY_FLAG_LOCAL); - n_labels = mp->next_hop_n_out_labels; - if (n_labels == 0) - ; - else - { - vec_validate (label_stack, n_labels - 1); - for (ii = 0; ii < n_labels; ii++) - { - label_stack[ii].fml_value = - ntohl (mp->next_hop_out_label_stack[ii].label); - label_stack[ii].fml_ttl = mp->next_hop_out_label_stack[ii].ttl; - label_stack[ii].fml_exp = mp->next_hop_out_label_stack[ii].exp; - label_stack[ii].fml_mode = - (mp->next_hop_out_label_stack[ii].is_uniform ? - FIB_MPLS_LSP_MODE_UNIFORM : FIB_MPLS_LSP_MODE_PIPE); - } + if (0 != rv) + goto out; } - rv = add_del_route_t_handler (mp->is_multipath, - mp->is_add, - mp->is_drop, - mp->is_unreach, - mp->is_prohibit, - mp->is_local, 0, - mp->is_classify, - mp->classify_table_index, - mp->is_resolve_host, - mp->is_resolve_attached, 0, 0, - mp->is_dvr, - mp->is_source_lookup, - mp->is_udp_encap, - fib_index, &pfx, DPO_PROTO_IP6, - &nh, ntohl (mp->next_hop_id), - ntohl (mp->next_hop_sw_if_index), - next_hop_fib_index, - mp->next_hop_weight, - mp->next_hop_preference, - ntohl (mp->next_hop_via_label), label_stack); + fib_api_route_add_del (mp->is_add, + mp->is_multipath, + fib_index, &pfx, entry_flags, rpaths); if (mp->is_add && 0 == rv) *stats_index = fib_table_entry_get_stats_index (fib_index, &pfx); +out: + vec_free (rpaths); + return (rv); } void -vl_api_ip_add_del_route_t_handler (vl_api_ip_add_del_route_t * mp) +vl_api_ip_route_add_del_t_handler (vl_api_ip_route_add_del_t * mp) { - vl_api_ip_add_del_route_reply_t *rmp; - u32 stats_index; + vl_api_ip_route_add_del_reply_t *rmp; + u32 stats_index = ~0; int rv; - vnet_main_t *vnm = vnet_get_main (); - - vnm->api_errno = 0; - stats_index = ~0; - if (mp->is_ipv6) - rv = ip6_add_del_route_t_handler (mp, &stats_index); - else - rv = ip4_add_del_route_t_handler (mp, &stats_index); - - rv = (rv == 0) ? vnm->api_errno : rv; + rv = ip_route_add_del_t_handler (mp, &stats_index); /* *INDENT-OFF* */ - REPLY_MACRO2 (VL_API_IP_ADD_DEL_ROUTE_REPLY, + REPLY_MACRO2 (VL_API_IP_ROUTE_ADD_DEL_REPLY, ({ rmp->stats_index = htonl (stats_index); })) @@ -1221,80 +760,37 @@ ip_table_create (fib_protocol_t fproto, } } -static int -add_del_mroute_check (fib_protocol_t table_proto, - u32 table_id, - 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) - { - /* No such table */ - 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; - } - } - - return (0); -} - -static fib_node_index_t +static u32 mroute_add_del_handler (u8 is_add, - u8 is_local, + u8 is_multipath, u32 fib_index, const mfib_prefix_t * prefix, - dpo_proto_t nh_proto, u32 entry_flags, - fib_rpf_id_t rpf_id, - u32 next_hop_sw_if_index, - ip46_address_t * nh, u32 itf_flags, u32 bier_imp) + u32 rpf_id, fib_route_path_t * rpaths) { - fib_node_index_t mfib_entry_index = ~0; - - fib_route_path_t path = { - .frp_sw_if_index = next_hop_sw_if_index, - .frp_proto = nh_proto, - .frp_addr = *nh, - }; + u32 mfib_entry_index = ~0; - if (is_local) - path.frp_flags |= FIB_ROUTE_PATH_LOCAL; - - if (DPO_PROTO_BIER == nh_proto) - { - path.frp_bier_imp = bier_imp; - path.frp_flags = FIB_ROUTE_PATH_BIER_IMP; - } - else if (!is_local && ~0 == next_hop_sw_if_index) + if (0 == vec_len (rpaths)) { mfib_entry_index = mfib_table_entry_update (fib_index, prefix, MFIB_SOURCE_API, rpf_id, entry_flags); - goto done; - } - - if (is_add) - { - mfib_entry_index = mfib_table_entry_path_update (fib_index, prefix, - MFIB_SOURCE_API, - &path, itf_flags); } else { - mfib_table_entry_path_remove (fib_index, prefix, - MFIB_SOURCE_API, &path); + if (is_add) + { + mfib_entry_index = + mfib_table_entry_paths_update (fib_index, prefix, + MFIB_SOURCE_API, rpaths); + } + else + { + mfib_table_entry_paths_remove (fib_index, prefix, + MFIB_SOURCE_API, rpaths); + } } -done: return (mfib_entry_index); } @@ -1302,64 +798,43 @@ static int api_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp, u32 * stats_index) { + fib_route_path_t *rpath, *rpaths = NULL; fib_node_index_t mfib_entry_index; - fib_protocol_t fproto; - dpo_proto_t nh_proto; - ip46_address_t nh; + mfib_prefix_t pfx; u32 fib_index; int rv; + u16 ii; - nh_proto = mp->next_hop_afi; - fproto = (mp->is_ipv6 ? FIB_PROTOCOL_IP6 : FIB_PROTOCOL_IP4); - rv = add_del_mroute_check (fproto, - mp->table_id, - mp->next_hop_sw_if_index, - mp->is_local, &fib_index); + ip_mprefix_decode (&mp->route.prefix, &pfx); + rv = mfib_api_table_id_decode (pfx.fp_proto, + ntohl (mp->route.table_id), &fib_index); if (0 != rv) - return (rv); + goto out; - mfib_prefix_t pfx = { - .fp_len = ntohs (mp->grp_address_length), - .fp_proto = fproto, - }; + vec_validate (rpaths, mp->route.n_paths - 1); - if (FIB_PROTOCOL_IP4 == fproto) - { - clib_memcpy (&pfx.fp_grp_addr.ip4, mp->grp_address, - sizeof (pfx.fp_grp_addr.ip4)); - clib_memcpy (&pfx.fp_src_addr.ip4, mp->src_address, - sizeof (pfx.fp_src_addr.ip4)); - clib_memset (&nh.ip6, 0, sizeof (nh.ip6)); - clib_memcpy (&nh.ip4, mp->nh_address, sizeof (nh.ip4)); - if (!ip46_address_is_zero (&pfx.fp_src_addr)) - pfx.fp_len = 64; - } - else + for (ii = 0; ii < mp->route.n_paths; ii++) { - clib_memcpy (&pfx.fp_grp_addr.ip6, mp->grp_address, - sizeof (pfx.fp_grp_addr.ip6)); - clib_memcpy (&pfx.fp_src_addr.ip6, mp->src_address, - sizeof (pfx.fp_src_addr.ip6)); - clib_memcpy (&nh.ip6, mp->nh_address, sizeof (nh.ip6)); - if (!ip46_address_is_zero (&pfx.fp_src_addr)) - pfx.fp_len = 256; + rpath = &rpaths[ii]; + + rv = mfib_api_path_decode (&mp->route.paths[ii], rpath); + + if (0 != rv) + goto out; } mfib_entry_index = mroute_add_del_handler (mp->is_add, - mp->is_local, + mp->is_add, fib_index, &pfx, - nh_proto, - ntohl (mp->entry_flags), - ntohl (mp->rpf_id), - ntohl (mp->next_hop_sw_if_index), - &nh, - ntohl (mp->itf_flags), - ntohl (mp->bier_imp)); + ntohl (mp->route.entry_flags), + ntohl (mp->route.rpf_id), + rpaths); if (~0 != mfib_entry_index) *stats_index = mfib_entry_get_stats_index (mfib_entry_index); +out: return (rv); } @@ -1367,14 +842,9 @@ void vl_api_ip_mroute_add_del_t_handler (vl_api_ip_mroute_add_del_t * mp) { vl_api_ip_mroute_add_del_reply_t *rmp; - vnet_main_t *vnm; - u32 stats_index; + u32 stats_index = ~0; int rv; - vnm = vnet_get_main (); - vnm->api_errno = 0; - stats_index = ~0; - rv = api_mroute_add_del_t_handler (mp, &stats_index); /* *INDENT-OFF* */ @@ -1406,8 +876,8 @@ send_ip_details (vpe_api_main_t * am, static void send_ip_address_details (vpe_api_main_t * am, vl_api_registration_t * reg, - u8 * ip, u16 prefix_length, - u32 sw_if_index, u8 is_ipv6, u32 context) + const fib_prefix_t * pfx, + u32 sw_if_index, u32 context) { vl_api_ip_address_details_t *mp; @@ -1415,19 +885,9 @@ send_ip_address_details (vpe_api_main_t * am, clib_memset (mp, 0, sizeof (*mp)); mp->_vl_msg_id = ntohs (VL_API_IP_ADDRESS_DETAILS); - if (is_ipv6) - { - clib_memcpy (&mp->ip, ip, sizeof (mp->ip)); - } - else - { - u32 *tp = (u32 *) mp->ip; - *tp = *(u32 *) ip; - } - mp->prefix_length = prefix_length; + ip_prefix_encode (pfx, &mp->prefix); mp->context = context; mp->sw_if_index = htonl (sw_if_index); - mp->is_ipv6 = is_ipv6; vl_api_send_msg (reg, (u8 *) mp); } @@ -1437,8 +897,6 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) { vpe_api_main_t *am = &vpe_api_main; vl_api_registration_t *reg; - ip6_address_t *r6; - ip4_address_t *r4; ip6_main_t *im6 = &ip6_main; ip4_main_t *im4 = &ip4_main; ip_lookup_main_t *lm6 = &im6->lookup_main; @@ -1464,10 +922,12 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) * than one interface */ foreach_ip_interface_address (lm6, ia, sw_if_index, 0, ({ - r6 = ip_interface_address_get_address (lm6, ia); - u16 prefix_length = ia->address_length; - send_ip_address_details(am, reg, (u8*)r6, prefix_length, - sw_if_index, 1, mp->context); + fib_prefix_t pfx = { + .fp_addr.ip6 = *(ip6_address_t *)ip_interface_address_get_address (lm6, ia), + .fp_len = ia->address_length, + .fp_proto = FIB_PROTOCOL_IP6, + }; + send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context); })); /* *INDENT-ON* */ } @@ -1476,10 +936,13 @@ vl_api_ip_address_dump_t_handler (vl_api_ip_address_dump_t * mp) /* *INDENT-OFF* */ foreach_ip_interface_address (lm4, ia, sw_if_index, 0, ({ - r4 = ip_interface_address_get_address (lm4, ia); - u16 prefix_length = ia->address_length; - send_ip_address_details(am, reg, (u8*)r4, prefix_length, - sw_if_index, 0, mp->context); + fib_prefix_t pfx = { + .fp_addr.ip4 = *(ip4_address_t *)ip_interface_address_get_address (lm4, ia), + .fp_len = ia->address_length, + .fp_proto = FIB_PROTOCOL_IP4, + }; + + send_ip_address_details(am, reg, &pfx, sw_if_index, mp->context); })); /* *INDENT-ON* */ } @@ -1883,22 +1346,7 @@ vl_mfib_signal_send_one (vl_api_registration_t * reg, mp->table_id = ntohl (mfib->mft_table_id); mp->sw_if_index = ntohl (mfi->mfi_sw_if_index); - if (FIB_PROTOCOL_IP4 == prefix->fp_proto) - { - mp->grp_address_len = ntohs (prefix->fp_len); - - memcpy (mp->grp_address, &prefix->fp_grp_addr.ip4, 4); - if (prefix->fp_len > 32) - { - memcpy (mp->src_address, &prefix->fp_src_addr.ip4, 4); - } - } - else - { - mp->grp_address_len = ntohs (prefix->fp_len); - - ASSERT (0); - } + ip_mprefix_encode (prefix, &mp->prefix); if (0 != mfs->mfs_buffer_len) { @@ -3369,9 +2817,11 @@ static walk_rc_t send_ip_punt_redirect_details (u32 rx_sw_if_index, const ip_punt_redirect_rx_t * ipr, void *arg) { - fib_route_path_encode_t *api_rpaths = NULL; ip_punt_redirect_walk_ctx_t *ctx = arg; vl_api_ip_punt_redirect_details_t *mp; + fib_path_encode_ctx_t path_ctx = { + .rpaths = NULL, + }; mp = vl_msg_api_alloc (sizeof (*mp)); if (!mp) @@ -3381,17 +2831,17 @@ send_ip_punt_redirect_details (u32 rx_sw_if_index, mp->_vl_msg_id = ntohs (VL_API_IP_PUNT_REDIRECT_DETAILS); mp->context = ctx->context; - fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &api_rpaths); + fib_path_list_walk_w_ext (ipr->pl, NULL, fib_path_encode, &path_ctx); mp->punt.rx_sw_if_index = htonl (rx_sw_if_index); - mp->punt.tx_sw_if_index = htonl (api_rpaths[0].rpath.frp_sw_if_index); + mp->punt.tx_sw_if_index = htonl (path_ctx.rpaths[0].frp_sw_if_index); - ip_address_encode (&api_rpaths[0].rpath.frp_addr, + ip_address_encode (&path_ctx.rpaths[0].frp_addr, fib_proto_to_ip46 (ipr->fproto), &mp->punt.nh); vl_api_send_msg (ctx->reg, (u8 *) mp); - vec_free (api_rpaths); + vec_free (path_ctx.rpaths); return (WALK_CONTINUE); } @@ -3461,8 +2911,8 @@ ip_api_hookup (vlib_main_t * vm) /* * Mark the route add/del API as MP safe */ - am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE] = 1; - am->is_mp_safe[VL_API_IP_ADD_DEL_ROUTE_REPLY] = 1; + am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL] = 1; + am->is_mp_safe[VL_API_IP_ROUTE_ADD_DEL_REPLY] = 1; /* * Set up the (msg_name, crc, message-id) table diff --git a/src/vnet/ip/ip_types_api.c b/src/vnet/ip/ip_types_api.c index fd8d24f36fe..6ad2c366dff 100644 --- a/src/vnet/ip/ip_types_api.c +++ b/src/vnet/ip/ip_types_api.c @@ -229,6 +229,9 @@ ip_mprefix_decode (const vl_api_mprefix_t * in, mfib_prefix_t * out) ip_address_union_decode (&in->grp_address, in->af, &out->fp_grp_addr); ip_address_union_decode (&in->src_address, in->af, &out->fp_src_addr); + + if (!ip46_address_is_zero (&out->fp_src_addr)) + out->fp_len = (out->fp_proto == FIB_PROTOCOL_IP6 ? 256 : 64); } /* diff --git a/src/vnet/ip/lookup.c b/src/vnet/ip/lookup.c index 5c6fec1810b..8c89ed4f490 100644 --- a/src/vnet/ip/lookup.c +++ b/src/vnet/ip/lookup.c @@ -441,7 +441,7 @@ vnet_ip_route_cmd (vlib_main_t * vm, } else if (0 < vec_len (rpaths)) { - u32 k, j, n, incr; + u32 k, n, incr; ip46_address_t dst = prefixs[i].fp_addr; f64 t[2]; n = count; @@ -451,25 +451,20 @@ vnet_ip_route_cmd (vlib_main_t * vm, for (k = 0; k < n; k++) { - for (j = 0; j < vec_len (rpaths); j++) - { - fib_prefix_t rpfx = { - .fp_len = prefixs[i].fp_len, - .fp_proto = prefixs[i].fp_proto, - .fp_addr = dst, - }; - - if (is_del) - fib_table_entry_path_remove2 (fib_index, - &rpfx, - FIB_SOURCE_CLI, &rpaths[j]); - else - fib_table_entry_path_add2 (fib_index, - &rpfx, - FIB_SOURCE_CLI, - FIB_ENTRY_FLAG_NONE, - &rpaths[j]); - } + fib_prefix_t rpfx = { + .fp_len = prefixs[i].fp_len, + .fp_proto = prefixs[i].fp_proto, + .fp_addr = dst, + }; + + if (is_del) + fib_table_entry_path_remove2 (fib_index, + &rpfx, FIB_SOURCE_CLI, rpaths); + else + fib_table_entry_path_add2 (fib_index, + &rpfx, + FIB_SOURCE_CLI, + FIB_ENTRY_FLAG_NONE, rpaths); if (FIB_PROTOCOL_IP4 == prefixs[0].fp_proto) { @@ -485,9 +480,9 @@ vnet_ip_route_cmd (vlib_main_t * vm, clib_host_to_net_u64 (incr + clib_net_to_host_u64 (dst.ip6.as_u64 [bucket])); - } } + t[1] = vlib_time_now (vm); if (count > 1) vlib_cli_output (vm, "%.6e routes/sec", count / (t[1] - t[0])); @@ -499,7 +494,6 @@ vnet_ip_route_cmd (vlib_main_t * vm, } } - done: vec_free (dpos); vec_free (prefixs); @@ -805,20 +799,17 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, unformat_input_t * main_input, vlib_cli_command_t * cmd) { unformat_input_t _line_input, *line_input = &_line_input; + fib_route_path_t rpath, *rpaths = NULL; clib_error_t *error = NULL; - fib_route_path_t rpath; - u32 table_id, is_del; - vnet_main_t *vnm; + u32 table_id, is_del, payload_proto; mfib_prefix_t pfx; u32 fib_index; - mfib_itf_flags_t iflags = 0; mfib_entry_flags_t eflags = 0; u32 gcount, scount, ss, gg, incr; f64 timet[2]; u32 rpf_id = MFIB_RPF_ID_NONE; gcount = scount = 1; - vnm = vnet_get_main (); is_del = 0; table_id = 0; clib_memset (&pfx, 0, sizeof (pfx)); @@ -887,51 +878,6 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, pfx.fp_proto = FIB_PROTOCOL_IP6; pfx.fp_len = 128; } - else if (unformat (line_input, "via %U %U %U", - unformat_ip4_address, &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U %U", - unformat_ip6_address, &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index, - unformat_mfib_itf_flags, &iflags)) - { - clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_ip4_address, &rpath.frp_addr.ip4, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U %U", - unformat_ip6_address, &rpath.frp_addr.ip6, - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - rpath.frp_weight = 1; - } - else if (unformat (line_input, "via %U", - unformat_vnet_sw_interface, vnm, - &rpath.frp_sw_if_index)) - { - clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); - rpath.frp_weight = 1; - } else if (unformat (line_input, "via local Forward")) { clib_memset (&rpath.frp_addr, 0, sizeof (rpath.frp_addr)); @@ -942,9 +888,17 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, * set the path proto appropriately for the prefix */ rpath.frp_proto = fib_proto_to_dpo (pfx.fp_proto); - iflags = MFIB_ITF_FLAG_FORWARD; + rpath.frp_mitf_flags = MFIB_ITF_FLAG_FORWARD; + } + else if (unformat (line_input, "via %U", + unformat_fib_route_path, &rpath, &payload_proto)) + { + vec_add1 (rpaths, rpath); } else if (unformat (line_input, "%U", + unformat_mfib_itf_flags, &rpath.frp_mitf_flags)) + ; + else if (unformat (line_input, "%U", unformat_mfib_entry_flags, &eflags)) ; else @@ -987,7 +941,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, { for (gg = 0; gg < gcount; gg++) { - if (is_del && 0 == rpath.frp_weight) + if (is_del && 0 == vec_len (rpaths)) { /* no path provided => route delete */ mfib_table_entry_delete (fib_index, &pfx, MFIB_SOURCE_CLI); @@ -1001,11 +955,10 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, { if (is_del) mfib_table_entry_path_remove (fib_index, - &pfx, MFIB_SOURCE_CLI, &rpath); + &pfx, MFIB_SOURCE_CLI, rpaths); else mfib_table_entry_path_update (fib_index, - &pfx, MFIB_SOURCE_CLI, &rpath, - iflags); + &pfx, MFIB_SOURCE_CLI, rpaths); } if (FIB_PROTOCOL_IP4 == pfx.fp_proto) @@ -1050,6 +1003,7 @@ vnet_ip_mroute_cmd (vlib_main_t * vm, (scount * gcount) / (timet[1] - timet[0])); done: + vec_free (rpaths); unformat_free (line_input); return error; |