aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorin Coras <fcoras@cisco.com>2017-06-07 21:50:57 -0700
committerDamjan Marion <dmarion.lists@gmail.com>2017-06-08 17:43:56 +0000
commita4e63e5593d53692b8085dc666f8670ece135f32 (patch)
tree42cc0326c181351c7dcd0ce08a478dc076858d86
parent6899a30bd70f219cfd182dfb0e9ac96faf5d9892 (diff)
Add gpe native-forward static route support
Change-Id: I744e7d64d94dbb302f2c1246663480f720672ee2 Signed-off-by: Florin Coras <fcoras@cisco.com>
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.api56
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.c191
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe.h12
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_api.c108
-rw-r--r--src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c51
5 files changed, 402 insertions, 16 deletions
diff --git a/src/vnet/lisp-gpe/lisp_gpe.api b/src/vnet/lisp-gpe/lisp_gpe.api
index 706f20d4..17ce579f 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.api
+++ b/src/vnet/lisp-gpe/lisp_gpe.api
@@ -186,6 +186,62 @@ define gpe_get_encap_mode_reply
u8 encap_mode;
};
+/** \brief Add native fwd rpath
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+ @param is_add - flag to indicate add or del
+ @param table_id - table id for route path
+ @param nh_sw_if_index - next-hop sw_if_index (~0 if not set)
+ @param is_ip4 - flag to indicate if nh is ip4
+ @param nh_addr - next hop ip address
+*/
+autoreply define gpe_add_del_native_fwd_rpath
+{
+ u32 client_index;
+ u32 context;
+ u8 is_add;
+ u32 table_id;
+ u32 nh_sw_if_index;
+ u8 is_ip4;
+ u8 nh_addr[16];
+};
+
+/** \brief get GPE native fwd rpath
+ @param client_index - opaque cookie to identify the sender
+ @param context - sender context, to match reply w/ request
+*/
+define gpe_native_fwd_rpaths_get
+{
+ u32 client_index;
+ u32 context;
+ u8 is_ip4;
+};
+
+/** \brief Reply for get native fwd rpath
+ @param context - returned sender context, to match reply w/ request
+ @param retval - return code
+ @param table_id - table id for route path
+ @param nh_sw_if_index - next-hop sw_if_index (~0 if not set)
+ @param nh_addr - next hop address
+*/
+typeonly manual_print manual_endian define gpe_native_fwd_rpath
+{
+ u32 context;
+ i32 retval;
+ u32 fib_index;
+ u32 nh_sw_if_index;
+ u8 is_ip4;
+ u8 nh_addr[16];
+};
+
+manual_print manual_endian define gpe_native_fwd_rpaths_get_reply
+{
+ u32 context;
+ i32 retval;
+ u32 count;
+ vl_api_gpe_native_fwd_rpath_t entries[count];
+};
+
/*
* Local Variables:
* eval: (c-set-style "gnu")
diff --git a/src/vnet/lisp-gpe/lisp_gpe.c b/src/vnet/lisp-gpe/lisp_gpe.c
index 052410e2..ea6c143d 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.c
+++ b/src/vnet/lisp-gpe/lisp_gpe.c
@@ -22,6 +22,9 @@
#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
#include <vnet/lisp-gpe/lisp_gpe_adjacency.h>
#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
+#include <vnet/fib/fib_path_list.h>
+#include <vnet/fib/fib_table.h>
+#include <vnet/fib/fib_internal.h>
/** LISP-GPE global state */
lisp_gpe_main_t lisp_gpe_main;
@@ -387,6 +390,194 @@ VLIB_CLI_COMMAND (lisp_show_iface_command) = {
};
/* *INDENT-ON* */
+/** CLI command to show GPE fwd native route path. */
+static clib_error_t *
+gpe_show_native_fwd_rpath_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ lisp_gpe_main_t *lgm = &lisp_gpe_main;
+ fib_route_path_t *rpath;
+
+ if (vec_len (lgm->native_fwd_rpath[IP4]))
+ {
+ vec_foreach (rpath, lgm->native_fwd_rpath[IP4])
+ {
+ vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u",
+ format_ip46_address, &rpath->frp_addr, 1,
+ rpath->frp_fib_index, rpath->frp_sw_if_index);
+ }
+ }
+ if (vec_len (lgm->native_fwd_rpath[IP6]))
+ {
+ vec_foreach (rpath, lgm->native_fwd_rpath[IP6])
+ {
+ vlib_cli_output (vm, "nh: %U fib_index %u sw_if_index %u",
+ format_ip46_address, &rpath->frp_addr, 1,
+ rpath->frp_fib_index, rpath->frp_sw_if_index);
+ }
+ }
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (gpe_show_native_fwd_rpath_command) = {
+ .path = "show gpe native-forward",
+ .short_help = "show gpe native-forward",
+ .function = gpe_show_native_fwd_rpath_command_fn,
+};
+/* *INDENT-ON* */
+
+void
+gpe_update_native_fwd_path (u8 ip_version)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ lisp_gpe_fwd_entry_t *lfe;
+ fib_prefix_t fib_prefix;
+ u32 *lfei;
+
+ vec_foreach (lfei, lgm->native_fwd_lfes[ip_version])
+ {
+ lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]);
+ ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix);
+ fib_table_entry_update (lfe->eid_fib_index, &fib_prefix, FIB_SOURCE_LISP,
+ FIB_ENTRY_FLAG_NONE,
+ lgm->native_fwd_rpath[ip_version]);
+ }
+}
+
+int
+vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ fib_route_path_t *rpath;
+ u8 ip_version;
+
+ ip_version = a->rpath.frp_proto == FIB_PROTOCOL_IP4 ? IP4 : IP6;
+
+ if (a->is_add)
+ {
+ vec_add1 (lgm->native_fwd_rpath[ip_version], a->rpath);
+ }
+ else
+ {
+ vec_foreach (rpath, lgm->native_fwd_rpath[ip_version])
+ {
+ if (!fib_route_path_cmp (rpath, &a->rpath))
+ {
+ vec_del1 (lgm->native_fwd_rpath[ip_version],
+ rpath - lgm->native_fwd_rpath[ip_version]);
+ break;
+ }
+ }
+ }
+ gpe_update_native_fwd_path (ip_version);
+ return 0;
+}
+
+/**
+ * CLI command to add action for native forward.
+ */
+static clib_error_t *
+gpe_native_forward_command_fn (vlib_main_t * vm, unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vnet_main_t *vnm = vnet_get_main ();
+ unformat_input_t _line_input, *line_input = &_line_input;
+ vnet_api_error_t rv;
+ fib_route_path_t rpath;
+ u32 table_id = ~0;
+ vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a;
+ u8 is_add = 1;
+ clib_error_t *error = 0;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, line_input))
+ return 0;
+
+ memset (&rpath, 0, sizeof (rpath));
+
+ while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (line_input, "table %d", &table_id))
+ ;
+ else if (unformat (line_input, "del"))
+ is_add = 0;
+ 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;
+ rpath.frp_proto = FIB_PROTOCOL_IP4;
+ }
+ 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;
+ rpath.frp_proto = FIB_PROTOCOL_IP6;
+ }
+ else if (unformat (line_input, "via %U",
+ unformat_ip4_address, &rpath.frp_addr.ip4))
+ {
+ rpath.frp_weight = 1;
+ rpath.frp_sw_if_index = ~0;
+ rpath.frp_proto = FIB_PROTOCOL_IP4;
+ }
+ else if (unformat (line_input, "via %U",
+ unformat_ip6_address, &rpath.frp_addr.ip6))
+ {
+ rpath.frp_weight = 1;
+ rpath.frp_sw_if_index = ~0;
+ rpath.frp_proto = FIB_PROTOCOL_IP6;
+ }
+ else
+ {
+ return clib_error_return (0, "parse error: '%U'",
+ format_unformat_error, line_input);
+ }
+ }
+
+ if ((u32) ~ 0 == table_id)
+ {
+ rpath.frp_fib_index = 0;
+ }
+ else
+ {
+ rpath.frp_fib_index = fib_table_find (rpath.frp_proto, table_id);
+ if ((u32) ~ 0 == rpath.frp_fib_index)
+ {
+ error = clib_error_return (0, "Nonexistent table id %d", table_id);
+ goto done;
+ }
+ }
+
+ a->rpath = rpath;
+ a->is_add = is_add;
+
+ rv = vnet_gpe_add_del_native_fwd_rpath (a);
+ if (rv)
+ {
+ return clib_error_return (0, "Error: couldn't add path!");
+ }
+
+done:
+ return error;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (gpe_native_forward_command) = {
+ .path = "gpe native-forward",
+ .short_help = "gpe native-forward [del] via <nh-ip-addr> [iface] "
+ "[table <table>]",
+ .function = gpe_native_forward_command_fn,
+};
+/* *INDENT-ON* */
+
/** Format LISP-GPE status. */
u8 *
format_vnet_lisp_gpe_status (u8 * s, va_list * args)
diff --git a/src/vnet/lisp-gpe/lisp_gpe.h b/src/vnet/lisp-gpe/lisp_gpe.h
index f0405644..660f8a66 100644
--- a/src/vnet/lisp-gpe/lisp_gpe.h
+++ b/src/vnet/lisp-gpe/lisp_gpe.h
@@ -163,6 +163,10 @@ typedef struct lisp_gpe_main
uword *lisp_stats_index_by_key;
vlib_combined_counter_main_t counters;
+ /** Native fwd data structures */
+ fib_route_path_t *native_fwd_rpath[2];
+ u32 *native_fwd_lfes[2];
+
/** convenience */
vlib_main_t *vlib_main;
vnet_main_t *vnet_main;
@@ -271,6 +275,12 @@ typedef struct
typedef struct
{
+ fib_route_path_t rpath;
+ u8 is_add;
+} vnet_gpe_native_fwd_rpath_args_t;
+
+typedef struct
+{
u32 fwd_entry_index;
u32 dp_table;
u32 vni;
@@ -313,7 +323,7 @@ u8 vnet_lisp_stats_enable_disable_state (void);
vnet_api_error_t vnet_lisp_stats_enable_disable (u8 enable);
lisp_api_stats_t *vnet_lisp_get_stats (void);
int vnet_lisp_flush_stats (void);
-
+int vnet_gpe_add_del_native_fwd_rpath (vnet_gpe_native_fwd_rpath_args_t * a);
#endif /* included_vnet_lisp_gpe_h */
/*
diff --git a/src/vnet/lisp-gpe/lisp_gpe_api.c b/src/vnet/lisp-gpe/lisp_gpe_api.c
index ab081b35..4df743cd 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_api.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_api.c
@@ -27,7 +27,7 @@
#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h>
#include <vnet/lisp-gpe/lisp_gpe_tenant.h>
-
+#include <vnet/fib/fib_table.h>
#include <vnet/vnet_msg_enum.h>
#define vl_api_gpe_locator_pair_t_endian vl_noop_handler
@@ -51,15 +51,17 @@
#include <vlibapi/api_helper_macros.h>
-#define foreach_vpe_api_msg \
-_(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry) \
-_(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get) \
-_(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump) \
-_(GPE_ENABLE_DISABLE, gpe_enable_disable) \
-_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \
-_(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get) \
-_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \
-_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode)
+#define foreach_vpe_api_msg \
+_(GPE_ADD_DEL_FWD_ENTRY, gpe_add_del_fwd_entry) \
+_(GPE_FWD_ENTRIES_GET, gpe_fwd_entries_get) \
+_(GPE_FWD_ENTRY_PATH_DUMP, gpe_fwd_entry_path_dump) \
+_(GPE_ENABLE_DISABLE, gpe_enable_disable) \
+_(GPE_ADD_DEL_IFACE, gpe_add_del_iface) \
+_(GPE_FWD_ENTRY_VNIS_GET, gpe_fwd_entry_vnis_get) \
+_(GPE_SET_ENCAP_MODE, gpe_set_encap_mode) \
+_(GPE_GET_ENCAP_MODE, gpe_get_encap_mode) \
+_(GPE_ADD_DEL_NATIVE_FWD_RPATH, gpe_add_del_native_fwd_rpath) \
+_(GPE_NATIVE_FWD_RPATHS_GET, gpe_native_fwd_rpaths_get)
static locator_pair_t *
unformat_gpe_loc_pairs (void *locs, u32 rloc_num)
@@ -435,6 +437,92 @@ vl_api_gpe_get_encap_mode_t_handler (vl_api_gpe_get_encap_mode_t * mp)
/* *INDENT-ON* */
}
+static void
+ vl_api_gpe_add_del_native_fwd_rpath_t_handler
+ (vl_api_gpe_add_del_native_fwd_rpath_t * mp)
+{
+ vl_api_gpe_add_del_fwd_entry_reply_t *rmp;
+ vnet_gpe_native_fwd_rpath_args_t _a, *a = &_a;
+ int rv = 0;
+
+ memset (a, 0, sizeof (a[0]));
+
+ if (mp->is_ip4)
+ clib_memcpy (&a->rpath.frp_addr, mp->nh_addr, sizeof (ip4_address_t));
+ else
+ clib_memcpy (&a->rpath.frp_addr, mp->nh_addr, sizeof (ip6_address_t));
+
+ a->is_add = mp->is_add;
+ a->rpath.frp_proto = mp->is_ip4 ? FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6;
+ a->rpath.frp_fib_index = fib_table_find (a->rpath.frp_proto,
+ clib_net_to_host_u32
+ (mp->table_id));
+ a->rpath.frp_sw_if_index = clib_net_to_host_u32 (mp->nh_sw_if_index);
+ a->rpath.frp_weight = 1;
+
+ rv = vnet_gpe_add_del_native_fwd_rpath (a);
+ REPLY_MACRO (VL_API_GPE_ADD_DEL_NATIVE_FWD_RPATH_REPLY);
+}
+
+static void
+gpe_native_fwd_rpaths_copy (vl_api_gpe_native_fwd_rpath_t * dst,
+ fib_route_path_t * src)
+{
+ fib_route_path_t *e;
+ u32 i = 0;
+
+ vec_foreach (e, src)
+ {
+ memset (&dst[i], 0, sizeof (*dst));
+ clib_memcpy (&dst[i], e, sizeof (fib_route_path_t *));
+ }
+}
+
+static void
+gpe_native_fwd_rpath_t_host_to_net (vl_api_gpe_native_fwd_rpath_t * e)
+{
+ e->fib_index = clib_host_to_net_u32 (e->fib_index);
+ e->nh_sw_if_index = clib_host_to_net_u32 (e->nh_sw_if_index);
+}
+
+static void
+ gpe_native_fwd_rpaths_get_reply_t_host_to_net
+ (vl_api_gpe_native_fwd_rpaths_get_reply_t * mp)
+{
+ u32 i;
+ vl_api_gpe_native_fwd_rpath_t *e;
+
+ for (i = 0; i < mp->count; i++)
+ {
+ e = &mp->entries[i];
+ gpe_native_fwd_rpath_t_host_to_net (e);
+ }
+ mp->count = clib_host_to_net_u32 (mp->count);
+}
+
+static void
+vl_api_gpe_native_fwd_rpaths_get_t_handler (vl_api_gpe_native_fwd_rpaths_get_t
+ * mp)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ vl_api_gpe_native_fwd_rpaths_get_reply_t *rmp;
+ u32 size = 0;
+ int rv = 0;
+
+ size = vec_len (lgm->native_fwd_rpath[mp->is_ip4])
+ * sizeof (vl_api_gpe_native_fwd_rpath_t);
+
+ /* *INDENT-OFF* */
+ REPLY_MACRO4 (VL_API_GPE_NATIVE_FWD_RPATHS_GET_REPLY, size,
+ {
+ rmp->count = vec_len (lgm->native_fwd_rpath[mp->is_ip4]);
+ gpe_native_fwd_rpaths_copy (rmp->entries,
+ lgm->native_fwd_rpath[mp->is_ip4]);
+ gpe_native_fwd_rpaths_get_reply_t_host_to_net (rmp);
+ });
+ /* *INDENT-ON* */
+}
+
/*
* gpe_api_hookup
* Add vpe's API message handlers to the table.
diff --git a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
index 0b7b0fef..395b493a 100644
--- a/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
+++ b/src/vnet/lisp-gpe/lisp_gpe_fwd_entry.c
@@ -279,14 +279,46 @@ ip_src_fib_add_route (u32 src_fib_index,
vec_free (rpaths);
}
+static void
+gpe_native_fwd_add_del_lfe (lisp_gpe_fwd_entry_t * lfe, u8 is_add)
+{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ u8 found = 0, ip_version;
+ u32 *lfei, new_lfei;
+ ip_version = ip_prefix_version (&lfe->key->rmt.ippref);
+
+ new_lfei = lfe - lgm->lisp_fwd_entry_pool;
+ vec_foreach (lfei, lgm->native_fwd_lfes[ip_version])
+ {
+ lfe = pool_elt_at_index (lgm->lisp_fwd_entry_pool, lfei[0]);
+ if (lfei[0] == new_lfei)
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (is_add)
+ {
+ if (!found)
+ vec_add1 (lgm->native_fwd_lfes[ip_version], new_lfei);
+ }
+ else
+ {
+ if (found)
+ vec_del1 (lgm->native_fwd_lfes[ip_version], lfei[0]);
+ }
+}
static void
create_fib_entries (lisp_gpe_fwd_entry_t * lfe)
{
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
dpo_proto_t dproto;
ip_prefix_t ippref;
- dproto = (ip_prefix_version (&lfe->key->rmt.ippref) == IP4 ?
- DPO_PROTO_IP4 : DPO_PROTO_IP6);
+ fib_prefix_t fib_prefix;
+ u8 ip_version = ip_prefix_version (&lfe->key->rmt.ippref);
+ dproto = (ip_version == IP4 ? DPO_PROTO_IP4 : DPO_PROTO_IP6);
if (lfe->is_src_dst)
{
@@ -306,11 +338,19 @@ create_fib_entries (lisp_gpe_fwd_entry_t * lfe)
switch (lfe->action)
{
+ case LISP_FORWARD_NATIVE:
+ /* TODO handle route overlaps with fib and default route */
+ if (vec_len (lgm->native_fwd_rpath[ip_version]))
+ {
+ ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &fib_prefix);
+ fib_table_entry_update (lfe->eid_fib_index, &fib_prefix,
+ FIB_SOURCE_LISP, FIB_ENTRY_FLAG_NONE,
+ lgm->native_fwd_rpath[ip_version]);
+ gpe_native_fwd_add_del_lfe (lfe, 1);
+ break;
+ }
case LISP_NO_ACTION:
/* TODO update timers? */
- case LISP_FORWARD_NATIVE:
- /* TODO check if route/next-hop for eid exists in fib and add
- * more specific for the eid with the next-hop found */
case LISP_SEND_MAP_REQUEST:
/* insert tunnel that always sends map-request */
dpo_copy (&dpo, lisp_cp_dpo_get (dproto));
@@ -343,6 +383,7 @@ delete_fib_entries (lisp_gpe_fwd_entry_t * lfe)
ip_prefix_to_fib_prefix (&lfe->key->rmt.ippref, &dst_fib_prefix);
fib_table_entry_delete (lfe->src_fib_index, &dst_fib_prefix,
FIB_SOURCE_LISP);
+ gpe_native_fwd_add_del_lfe (lfe, 0);
}
}