api: ip: add IP_ROUTE_LOOKUP API
Add an IP_ROUTE_LOOKUP function that does either an exact match or
longest prefix match in a given fib table for a given prefix
returning the match if present.
Add API test.
Type: improvement
Signed-off-by: Christian Hopps <chopps@labn.net>
Change-ID: I67ec5a61079f4acf1349a9c646185f91f5f11806
diff --git a/src/vnet/ip/ip.api b/src/vnet/ip/ip.api
index 5624bcf..42371c4 100644
--- a/src/vnet/ip/ip.api
+++ b/src/vnet/ip/ip.api
@@ -190,6 +190,32 @@
vl_api_ip_route_t route;
};
+/** \brief Lookup IP route from a table
+ @param client_index - opaque cookie to identify the sender
+ @param table_id - The IP table to look the route up in
+ @param exact - 0 for normal route lookup, 1 for exact match only
+ @param prefix - The prefix (or host) for route lookup.
+*/
+define ip_route_lookup
+{
+ u32 client_index;
+ u32 context;
+ u32 table_id;
+ u8 exact;
+ vl_api_prefix_t prefix;
+};
+
+/** \brief IP FIB table lookup response
+ @param retval - return code of the lookup
+ @param route - The route entry in the table if found
+*/
+define ip_route_lookup_reply
+{
+ u32 context;
+ i32 retval;
+ vl_api_ip_route_t route;
+};
+
/** \brief Set the ip flow hash config for a fib request
@param client_index - opaque cookie to identify the sender
@param context - sender context, to match reply w/ request
diff --git a/src/vnet/ip/ip_api.c b/src/vnet/ip/ip_api.c
index d5fa2d3..b976eae 100644
--- a/src/vnet/ip/ip_api.c
+++ b/src/vnet/ip/ip_api.c
@@ -82,6 +82,7 @@
_(IP_TABLE_REPLACE_END, ip_table_replace_end) \
_(IP_TABLE_FLUSH, ip_table_flush) \
_(IP_ROUTE_ADD_DEL, ip_route_add_del) \
+_(IP_ROUTE_LOOKUP, ip_route_lookup) \
_(IP_TABLE_ADD_DEL, ip_table_add_del) \
_(IP_PUNT_POLICE, ip_punt_police) \
_(IP_PUNT_REDIRECT, ip_punt_redirect) \
@@ -574,6 +575,62 @@
}
void
+vl_api_ip_route_lookup_t_handler (vl_api_ip_route_lookup_t * mp)
+{
+ vl_api_ip_route_lookup_reply_t *rmp = NULL;
+ fib_route_path_t *rpaths = NULL, *rpath;
+ const fib_prefix_t *pfx = NULL;
+ fib_prefix_t lookup;
+ vl_api_fib_path_t *fp;
+ fib_node_index_t fib_entry_index;
+ u32 fib_index;
+ int npaths = 0;
+ int rv;
+
+ ip_prefix_decode (&mp->prefix, &lookup);
+ rv = fib_api_table_id_decode (lookup.fp_proto, ntohl (mp->table_id),
+ &fib_index);
+ if (PREDICT_TRUE (!rv))
+ {
+ if (mp->exact)
+ fib_entry_index = fib_table_lookup_exact_match (fib_index, &lookup);
+ else
+ fib_entry_index = fib_table_lookup (fib_index, &lookup);
+ if (fib_entry_index == FIB_NODE_INDEX_INVALID)
+ rv = VNET_API_ERROR_NO_SUCH_ENTRY;
+ else
+ {
+ pfx = fib_entry_get_prefix (fib_entry_index);
+ rpaths = fib_entry_encode (fib_entry_index);
+ npaths = vec_len (rpaths);
+ }
+ }
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO3_ZERO(VL_API_IP_ROUTE_LOOKUP_REPLY,
+ npaths * sizeof (*fp),
+ ({
+ if (!rv)
+ {
+ ip_prefix_encode (pfx, &rmp->route.prefix);
+ rmp->route.table_id = mp->table_id;
+ rmp->route.n_paths = npaths;
+ rmp->route.stats_index = fib_table_entry_get_stats_index (fib_index, pfx);
+ rmp->route.stats_index = htonl (rmp->route.stats_index);
+
+ fp = rmp->route.paths;
+ vec_foreach (rpath, rpaths)
+ {
+ fib_api_path_encode (rpath, fp);
+ fp++;
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+ vec_free (rpaths);
+}
+
+void
ip_table_create (fib_protocol_t fproto,
u32 table_id, u8 is_api, const u8 * name)
{