summaryrefslogtreecommitdiffstats
path: root/vnet
diff options
context:
space:
mode:
Diffstat (limited to 'vnet')
-rw-r--r--vnet/vnet/lisp-cp/control.c161
-rw-r--r--vnet/vnet/lisp-cp/control.h12
-rw-r--r--vnet/vnet/lisp-cp/gid_dictionary.c450
-rw-r--r--vnet/vnet/lisp-cp/gid_dictionary.h30
-rw-r--r--vnet/vnet/lisp-cp/lisp_msg_serdes.c3
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.c44
-rw-r--r--vnet/vnet/lisp-cp/lisp_types.h7
7 files changed, 592 insertions, 115 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c
index 618acf25166..2e89286ddc4 100644
--- a/vnet/vnet/lisp-cp/control.c
+++ b/vnet/vnet/lisp-cp/control.c
@@ -29,6 +29,13 @@ typedef struct
u8 smr_invoked;
} map_request_args_t;
+u8
+vnet_lisp_get_map_request_mode (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ return lcm->map_request_mode;
+}
+
static int
queue_map_request (gid_address_t * seid, gid_address_t * deid,
u8 smr_invoked, u8 is_resend);
@@ -347,6 +354,30 @@ get_locator_pairs (lisp_cp_main_t * lcm, mapping_t * lcl_map,
}
static void
+gid_address_sd_to_flat (gid_address_t * dst, gid_address_t * src,
+ fid_address_t * fid)
+{
+ ASSERT (GID_ADDR_SRC_DST == gid_address_type (src));
+
+ dst[0] = src[0];
+
+ switch (fid_addr_type (fid))
+ {
+ case FID_ADDR_IP_PREF:
+ gid_address_type (dst) = GID_ADDR_IP_PREFIX;
+ gid_address_ippref (dst) = fid_addr_ippref (fid);
+ break;
+ case FID_ADDR_MAC:
+ gid_address_type (dst) = GID_ADDR_MAC;
+ mac_copy (gid_address_mac (dst), fid_addr_mac (fid));
+ break;
+ default:
+ clib_warning ("Unsupported fid type %d!", fid_addr_type (fid));
+ break;
+ }
+}
+
+static void
dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
{
vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
@@ -369,11 +400,20 @@ dp_add_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
/* insert data plane forwarding entry */
a->is_add = 1;
- gid_address_copy (&a->rmt_eid, &dst_map->eid);
+ if (GID_ADDR_SRC_DST == gid_address_type (&dst_map->eid))
+ {
+ gid_address_sd_to_flat (&a->rmt_eid, &dst_map->eid,
+ &gid_address_sd_dst (&dst_map->eid));
+ gid_address_sd_to_flat (&a->lcl_eid, &dst_map->eid,
+ &gid_address_sd_src (&dst_map->eid));
+ }
+ else
+ gid_address_copy (&a->rmt_eid, &dst_map->eid);
+
a->vni = gid_address_vni (&a->rmt_eid);
/* get vrf or bd_index associated to vni */
- type = gid_address_type (&dst_map->eid);
+ type = gid_address_type (&a->rmt_eid);
if (GID_ADDR_IP_PREFIX == type)
{
dpid = hash_get (lcm->table_id_by_vni, a->vni);
@@ -1256,6 +1296,104 @@ VLIB_CLI_COMMAND (lisp_add_del_adjacency_command) = {
};
/* *INDENT-ON* */
+int
+vnet_lisp_set_map_request_mode (u8 mode)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ if (mode >= _MR_MODE_MAX)
+ {
+ clib_warning ("Invalid LISP map request mode %d!", mode);
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+
+ lcm->map_request_mode = mode;
+ return 0;
+}
+
+static clib_error_t *
+lisp_map_request_mode_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ unformat_input_t _i, *i = &_i;
+ map_request_mode_t mr_mode = _MR_MODE_MAX;
+
+ /* Get a line of input. */
+ if (!unformat_user (input, unformat_line_input, i))
+ return 0;
+
+ while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
+ {
+ if (unformat (i, "dst-only"))
+ mr_mode = MR_MODE_DST_ONLY;
+ else if (unformat (i, "src-dst"))
+ mr_mode = MR_MODE_SRC_DST;
+ else
+ {
+ clib_warning ("parse error '%U'", format_unformat_error, i);
+ goto done;
+ }
+ }
+
+ if (_MR_MODE_MAX == mr_mode)
+ {
+ clib_warning ("No LISP map request mode entered!");
+ return 0;
+ }
+
+ vnet_lisp_set_map_request_mode (mr_mode);
+done:
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (lisp_map_request_mode_command) = {
+ .path = "lisp map-request mode",
+ .short_help = "lisp map-request mode dst-only|src-dst",
+ .function = lisp_map_request_mode_command_fn,
+};
+/* *INDENT-ON* */
+
+static u8 *
+format_lisp_map_request_mode (u8 * s, va_list * args)
+{
+ u32 mode = va_arg (*args, u32);
+
+ switch (mode)
+ {
+ case 0:
+ return format (0, "dst-only");
+ case 1:
+ return format (0, "src-dst");
+ }
+ return 0;
+}
+
+static clib_error_t *
+lisp_show_map_request_mode_command_fn (vlib_main_t * vm,
+ unformat_input_t * input,
+ vlib_cli_command_t * cmd)
+{
+ vlib_cli_output (vm, "map-request mode: %U", format_lisp_map_request_mode,
+ vnet_lisp_get_map_request_mode ());
+ return 0;
+}
+
+/* *INDENT-OFF* */
+VLIB_CLI_COMMAND (lisp_show_map_request_mode_command) = {
+ .path = "show lisp map-request mode",
+ .short_help = "show lisp map-request mode",
+ .function = lisp_show_map_request_mode_command_fn,
+};
+/* *INDENT-ON* */
+
static clib_error_t *
lisp_show_map_resolvers_command_fn (vlib_main_t * vm,
unformat_input_t * input,
@@ -2657,8 +2795,19 @@ build_encapsulated_map_request (lisp_cp_main_t * lcm,
/* get rlocs */
rlocs = build_itr_rloc_list (lcm, loc_set);
- /* put lisp msg */
- lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked, nonce_res);
+ if (MR_MODE_SRC_DST == lcm->map_request_mode)
+ {
+ gid_address_t sd;
+ memset (&sd, 0, sizeof (sd));
+ build_src_dst (&sd, seid, deid);
+ lisp_msg_put_mreq (lcm, b, seid, &sd, rlocs, is_smr_invoked, nonce_res);
+ }
+ else
+ {
+ /* put lisp msg */
+ lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked,
+ nonce_res);
+ }
/* push ecm: udp-ip-lisp */
lisp_msg_push_ecm (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, seid, deid);
@@ -3007,7 +3156,8 @@ lisp_cp_lookup_inline (vlib_main_t * vm,
/* if we have remote mapping for destination already in map-chache
add forwarding tunnel directly. If not send a map-request */
- di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
+ di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst,
+ &src);
if (~0 != di)
{
mapping_t *m = vec_elt_at_index (lcm->mapping_pool, di);
@@ -3408,6 +3558,7 @@ lisp_cp_init (vlib_main_t * vm)
lcm->pending_map_request_lock[0] = 0;
gid_dictionary_init (&lcm->mapping_index_by_gid);
lcm->do_map_resolver_election = 1;
+ lcm->map_request_mode = MR_MODE_DST_ONLY;
/* default vrf mapped to vni 0 */
hash_set (lcm->table_id_by_vni, 0, 0);
diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h
index 02efd046170..1c8abfb359b 100644
--- a/vnet/vnet/lisp-cp/control.h
+++ b/vnet/vnet/lisp-cp/control.h
@@ -63,6 +63,13 @@ typedef struct
miss_packet_type_t type;
} miss_packet_t;
+typedef enum
+{
+ MR_MODE_DST_ONLY = 0,
+ MR_MODE_SRC_DST,
+ _MR_MODE_MAX
+} map_request_mode_t;
+
typedef struct
{
/* LISP feature status */
@@ -138,6 +145,9 @@ typedef struct
/* LISP PITR mode */
u8 lisp_pitr;
+ /* map request mode */
+ u8 map_request_mode;
+
/* commodity */
ip4_main_t *im4;
ip6_main_t *im6;
@@ -240,6 +250,8 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a);
int vnet_lisp_clear_all_remote_adjacencies (void);
int vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_l2, u8 is_add);
+int vnet_lisp_set_map_request_mode (u8 mode);
+u8 vnet_lisp_get_map_request_mode (void);
static inline void
lisp_pending_map_request_lock (lisp_cp_main_t * lcm)
diff --git a/vnet/vnet/lisp-cp/gid_dictionary.c b/vnet/vnet/lisp-cp/gid_dictionary.c
index fc95c88c30f..a422b247a06 100644
--- a/vnet/vnet/lisp-cp/gid_dictionary.c
+++ b/vnet/vnet/lisp-cp/gid_dictionary.c
@@ -15,25 +15,41 @@
#include <vnet/lisp-cp/gid_dictionary.h>
+static void
+make_mac_sd_key (BVT (clib_bihash_kv) * kv, u32 vni, u8 src_mac[6],
+ u8 dst_mac[6])
+{
+ kv->key[0] = (u64) vni;
+ kv->key[1] = mac_to_u64 (dst_mac);
+ kv->key[2] = src_mac ? mac_to_u64 (src_mac) : (u64) 0;
+}
+
static u32
-mac_lookup (gid_dictionary_t * db, u32 vni, u8 * key)
+mac_sd_lookup (gid_mac_table_t * db, u32 vni, u8 * dst, u8 * src)
{
int rv;
BVT (clib_bihash_kv) kv, value;
- kv.key[0] = mac_to_u64 (key);
- kv.key[1] = (u64) vni;
- kv.key[2] = 0;
-
+ make_mac_sd_key (&kv, vni, src, dst);
rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv, &value);
- if (rv == 0)
+
+ /* no match, try with src 0, catch all for dst */
+ if (rv != 0)
+ {
+ kv.key[2] = 0;
+ rv = BV (clib_bihash_search_inline_2) (&db->mac_lookup_table, &kv,
+ &value);
+ if (rv == 0)
+ return value.value;
+ }
+ else
return value.value;
return GID_LOOKUP_MISS;
}
static u32
-ip4_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
+ip4_lookup (gid_ip4_table_t * db, u32 vni, ip_prefix_t * key)
{
int i, len;
int rv;
@@ -65,7 +81,7 @@ ip4_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
}
static u32
-ip6_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
+ip6_lookup (gid_ip6_table_t * db, u32 vni, ip_prefix_t * key)
{
int i, len;
int rv;
@@ -96,35 +112,88 @@ ip6_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
}
static u32
-ip_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * key)
+ip_sd_lookup (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst,
+ ip_prefix_t * src)
{
- /* XXX for now this only works with ip-prefixes, no lcafs */
- switch (ip_prefix_version (key))
+ u32 sfi;
+ gid_ip4_table_t *sfib4;
+ gid_ip6_table_t *sfib6;
+
+ switch (ip_prefix_version (dst))
{
case IP4:
- return ip4_lookup (db, vni, key);
+ sfi = ip4_lookup (&db->dst_ip4_table, vni, dst);
+ if (GID_LOOKUP_MISS != sfi)
+ sfib4 = pool_elt_at_index (db->src_ip4_table_pool, sfi);
+ else
+ return GID_LOOKUP_MISS;
+
+ if (!src)
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ return ip4_lookup (sfib4, 0, &sp);
+ }
+ else
+ return ip4_lookup (sfib4, 0, src);
+
break;
case IP6:
- return ip6_lookup (db, vni, key);
+ sfi = ip6_lookup (&db->dst_ip6_table, vni, dst);
+ if (GID_LOOKUP_MISS != sfi)
+ sfib6 = pool_elt_at_index (db->src_ip6_table_pool, sfi);
+ else
+ return GID_LOOKUP_MISS;
+
+ if (!src)
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ ip_prefix_version (&sp) = IP6;
+ return ip6_lookup (sfib6, 0, &sp);
+ }
+ else
+ return ip6_lookup (sfib6, 0, src);
+
break;
default:
clib_warning ("address type %d not supported!",
- ip_prefix_version (key));
+ ip_prefix_version (dst));
break;
}
- return ~0;
+ return GID_LOOKUP_MISS;
}
u32
gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
{
- /* XXX for now this only works with ip-prefixes, no lcafs */
switch (gid_address_type (key))
{
case GID_ADDR_IP_PREFIX:
- return ip_lookup (db, gid_address_vni (key), &gid_address_ippref (key));
+ return ip_sd_lookup (db, gid_address_vni (key),
+ &gid_address_ippref (key), 0);
case GID_ADDR_MAC:
- return mac_lookup (db, gid_address_vni (key), gid_address_mac (key));
+ return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
+ gid_address_mac (key), 0);
+ case GID_ADDR_SRC_DST:
+ switch (gid_address_sd_dst_type (key))
+ {
+ case FID_ADDR_IP_PREF:
+ return ip_sd_lookup (db, gid_address_vni (key),
+ &gid_address_sd_dst_ippref (key),
+ &gid_address_sd_src_ippref (key));
+ break;
+ case FID_ADDR_MAC:
+ return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (key),
+ gid_address_sd_dst_mac (key),
+ gid_address_sd_src_mac (key));
+ break;
+ default:
+ clib_warning ("Source/Dest address type %d not supported!",
+ gid_address_sd_dst_type (key));
+ break;
+ }
+ break;
default:
clib_warning ("address type %d not supported!", gid_address_type (key));
break;
@@ -132,8 +201,28 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key)
return GID_LOOKUP_MISS;
}
+u32
+gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst,
+ gid_address_t * src)
+{
+ switch (gid_address_type (dst))
+ {
+ case GID_ADDR_IP_PREFIX:
+ return ip_sd_lookup (db, gid_address_vni (dst),
+ &gid_address_ippref (dst),
+ &gid_address_ippref (src));
+ case GID_ADDR_MAC:
+ return mac_sd_lookup (&db->sd_mac_table, gid_address_vni (dst),
+ gid_address_mac (dst), gid_address_mac (src));
+ default:
+ clib_warning ("address type %d not supported!", gid_address_type (dst));
+ break;
+ }
+ return GID_LOOKUP_MISS;
+}
+
static void
-ip4_compute_prefix_lengths_in_search_order (gid_dictionary_t * db)
+ip4_compute_prefix_lengths_in_search_order (gid_ip4_table_t * db)
{
int i;
vec_reset_length (db->ip4_prefix_lengths_in_search_order);
@@ -150,7 +239,7 @@ ip4_compute_prefix_lengths_in_search_order (gid_dictionary_t * db)
}
static u32
-add_del_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
+add_del_ip4_key (gid_ip4_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
u8 is_add)
{
BVT (clib_bihash_kv) kv, value;
@@ -202,7 +291,105 @@ add_del_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
}
static void
-ip6_compute_prefix_lengths_in_search_order (gid_dictionary_t * db)
+ip4_lookup_init (gid_ip4_table_t * db)
+{
+ uword i;
+
+ memset (db->ip4_prefix_len_refcount, 0,
+ sizeof (db->ip4_prefix_len_refcount));
+
+ for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
+ {
+ u32 m;
+
+ if (i < 32)
+ m = pow2_mask (i) << (32 - i);
+ else
+ m = ~0;
+ db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
+ }
+ if (db->ip4_lookup_table_nbuckets == 0)
+ db->ip4_lookup_table_nbuckets = IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
+
+ db->ip4_lookup_table_nbuckets =
+ 1 << max_log2 (db->ip4_lookup_table_nbuckets);
+
+ if (db->ip4_lookup_table_size == 0)
+ db->ip4_lookup_table_size = IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
+
+ BV (clib_bihash_init) (&db->ip4_lookup_table, "ip4 lookup table",
+ db->ip4_lookup_table_nbuckets,
+ db->ip4_lookup_table_size);
+}
+
+static u32
+add_del_sd_ip4_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
+ ip_prefix_t * src_pref, u32 val, u8 is_add)
+{
+ u32 sfi, old_val = ~0;
+ gid_ip4_table_t *sfib;
+
+ sfi = ip4_lookup (&db->dst_ip4_table, vni, dst_pref);
+
+ if (is_add)
+ {
+ if (GID_LOOKUP_MISS == sfi)
+ {
+ pool_get (db->src_ip4_table_pool, sfib);
+ ip4_lookup_init (sfib);
+ add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref,
+ sfib - db->src_ip4_table_pool, is_add);
+ if (src_pref)
+ add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
+ }
+ }
+ else
+ {
+ ASSERT (!pool_is_free_index (db->src_ip4_table_pool, sfi));
+ sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
+ if (src_pref)
+ {
+ old_val = ip4_lookup (sfib, 0, src_pref);
+ add_del_ip4_key (sfib, 0 /* vni */ , src_pref, val, is_add);
+ }
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ old_val =
+ add_del_ip4_key (sfib, 0 /* vni */ , &sp, val, is_add);
+ }
+ }
+ }
+ else
+ {
+ if (GID_LOOKUP_MISS != sfi)
+ {
+ add_del_ip4_key (&db->dst_ip4_table, vni, dst_pref, 0, is_add);
+ sfib = pool_elt_at_index (db->src_ip4_table_pool, sfi);
+ if (src_pref)
+ old_val = add_del_ip4_key (sfib, 0, src_pref, 0, is_add);
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ old_val = add_del_ip4_key (sfib, 0, &sp, 0, is_add);
+ }
+ }
+ else
+ clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
+ dst_pref);
+ }
+ return old_val;
+}
+
+static void
+ip6_compute_prefix_lengths_in_search_order (gid_ip6_table_t * db)
{
int i;
vec_reset_length (db->ip6_prefix_lengths_in_search_order);
@@ -218,7 +405,7 @@ ip6_compute_prefix_lengths_in_search_order (gid_dictionary_t * db)
}
static u32
-add_del_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
+add_del_ip6_key (gid_ip6_table_t * db, u32 vni, ip_prefix_t * pref, u32 val,
u8 is_add)
{
BVT (clib_bihash_kv) kv, value;
@@ -270,14 +457,13 @@ add_del_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * pref, u32 val,
}
static u32
-add_del_mac (gid_dictionary_t * db, u32 vni, u8 * mac, u32 val, u8 is_add)
+add_del_mac (gid_mac_table_t * db, u32 vni, u8 * dst_mac, u8 * src_mac,
+ u32 val, u8 is_add)
{
BVT (clib_bihash_kv) kv, value;
u32 old_val = ~0;
- kv.key[0] = ((u64 *) mac)[0];
- kv.key[1] = (u64) vni;
- kv.key[2] = 0;
+ make_mac_sd_key (&kv, vni, src_mac, dst_mac);
if (BV (clib_bihash_search) (&db->mac_lookup_table, &kv, &value) == 0)
old_val = value.value;
@@ -292,80 +478,8 @@ add_del_mac (gid_dictionary_t * db, u32 vni, u8 * mac, u32 val, u8 is_add)
return old_val;
}
-static u32
-add_del_ip (gid_dictionary_t * db, u32 vni, ip_prefix_t * key, u32 value,
- u8 is_add)
-{
- switch (ip_prefix_version (key))
- {
- case IP4:
- return add_del_ip4_key (db, vni, key, value, is_add);
- break;
- case IP6:
- return add_del_ip6_key (db, vni, key, value, is_add);
- break;
- default:
- clib_warning ("address type %d not supported!",
- ip_prefix_version (key));
- break;
- }
- return ~0;
-}
-
-u32
-gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value,
- u8 is_add)
-{
- /* XXX for now this only works with ip-prefixes, no lcafs */
- switch (gid_address_type (key))
- {
- case GID_ADDR_IP_PREFIX:
- return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
- value, is_add);
- case GID_ADDR_MAC:
- return add_del_mac (db, gid_address_vni (key), gid_address_mac (key),
- value, is_add);
- default:
- clib_warning ("address type %d not supported!", gid_address_type (key));
- break;
- }
- return ~0;
-}
-
-static void
-ip4_lookup_init (gid_dictionary_t * db)
-{
- uword i;
-
- memset (db->ip4_prefix_len_refcount, 0,
- sizeof (db->ip4_prefix_len_refcount));
-
- for (i = 0; i < ARRAY_LEN (db->ip4_fib_masks); i++)
- {
- u32 m;
-
- if (i < 32)
- m = pow2_mask (i) << (32 - i);
- else
- m = ~0;
- db->ip4_fib_masks[i].as_u32 = clib_host_to_net_u32 (m);
- }
- if (db->ip4_lookup_table_nbuckets == 0)
- db->ip4_lookup_table_nbuckets = IP4_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
-
- db->ip4_lookup_table_nbuckets =
- 1 << max_log2 (db->ip4_lookup_table_nbuckets);
-
- if (db->ip4_lookup_table_size == 0)
- db->ip4_lookup_table_size = IP4_LOOKUP_DEFAULT_HASH_MEMORY_SIZE;
-
- BV (clib_bihash_init) (&db->ip4_lookup_table, "ip4 lookup table",
- db->ip4_lookup_table_nbuckets,
- db->ip4_lookup_table_size);
-}
-
static void
-ip6_lookup_init (gid_dictionary_t * db)
+ip6_lookup_init (gid_ip6_table_t * db)
{
uword i;
@@ -401,8 +515,138 @@ ip6_lookup_init (gid_dictionary_t * db)
db->ip6_lookup_table_size);
}
+static u32
+add_del_sd_ip6_key (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_pref,
+ ip_prefix_t * src_pref, u32 val, u8 is_add)
+{
+ u32 sfi, old_val = ~0;
+ gid_ip6_table_t *sfib;
+
+ sfi = ip6_lookup (&db->dst_ip6_table, vni, dst_pref);
+
+ if (is_add)
+ {
+ if (GID_LOOKUP_MISS == sfi)
+ {
+ pool_get (db->src_ip6_table_pool, sfib);
+ ip6_lookup_init (sfib);
+ add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref,
+ sfib - db->src_ip6_table_pool, is_add);
+ if (src_pref)
+ add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
+ }
+ }
+ else
+ {
+ ASSERT (!pool_is_free_index (db->src_ip6_table_pool, sfi));
+ sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
+ if (src_pref)
+ {
+ old_val = ip6_lookup (sfib, 0, src_pref);
+ add_del_ip6_key (sfib, 0 /* vni */ , src_pref, val, is_add);
+ }
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ old_val =
+ add_del_ip6_key (sfib, 0 /* vni */ , &sp, val, is_add);
+ }
+ }
+ }
+ else
+ {
+ if (GID_LOOKUP_MISS != sfi)
+ {
+ add_del_ip6_key (&db->dst_ip6_table, vni, dst_pref, 0, is_add);
+ sfib = pool_elt_at_index (db->src_ip6_table_pool, sfi);
+ if (src_pref)
+ old_val = add_del_ip6_key (sfib, 0, src_pref, 0, is_add);
+ else
+ {
+ ip_prefix_t sp;
+ memset (&sp, 0, sizeof (sp));
+ old_val = add_del_ip6_key (sfib, 0, &sp, 0, is_add);
+ }
+ }
+ else
+ clib_warning ("cannot delete dst mapping %U!", format_ip_prefix,
+ dst_pref);
+ }
+ return old_val;
+}
+
+static u32
+add_del_ip (gid_dictionary_t * db, u32 vni, ip_prefix_t * dst_key,
+ ip_prefix_t * src_key, u32 value, u8 is_add)
+{
+ switch (ip_prefix_version (dst_key))
+ {
+ case IP4:
+ return add_del_sd_ip4_key (db, vni, dst_key, src_key, value, is_add);
+ break;
+ case IP6:
+ return add_del_sd_ip6_key (db, vni, dst_key, src_key, value, is_add);
+ break;
+ default:
+ clib_warning ("address type %d not supported!",
+ ip_prefix_version (dst_key));
+ break;
+ }
+ return ~0;
+}
+
+static u32
+add_del_sd (gid_dictionary_t * db, u32 vni, source_dest_t * key, u32 value,
+ u8 is_add)
+{
+ switch (sd_dst_type (key))
+ {
+ case FID_ADDR_IP_PREF:
+ add_del_ip (db, vni, &sd_dst_ippref (key), &sd_src_ippref (key),
+ value, is_add);
+
+ case FID_ADDR_MAC:
+ return add_del_mac (&db->sd_mac_table, vni, sd_dst_mac (key),
+ sd_src_mac (key), value, is_add);
+
+ default:
+ clib_warning ("SD address type %d not supprted!", sd_dst_type (key));
+ break;
+ }
+
+ return ~0;
+}
+
+u32
+gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value,
+ u8 is_add)
+{
+ switch (gid_address_type (key))
+ {
+ case GID_ADDR_IP_PREFIX:
+ return add_del_ip (db, gid_address_vni (key), &gid_address_ippref (key),
+ 0, value, is_add);
+ case GID_ADDR_MAC:
+ return add_del_mac (&db->sd_mac_table, gid_address_vni (key),
+ gid_address_mac (key), 0, value, is_add);
+ case GID_ADDR_SRC_DST:
+ return add_del_sd (db, gid_address_vni (key), &gid_address_sd (key),
+ value, is_add);
+ default:
+ clib_warning ("address type %d not supported!", gid_address_type (key));
+ break;
+ }
+ return ~0;
+}
+
static void
-mac_lookup_init (gid_dictionary_t * db)
+mac_lookup_init (gid_mac_table_t * db)
{
if (db->mac_lookup_table_nbuckets == 0)
db->mac_lookup_table_nbuckets = MAC_LOOKUP_DEFAULT_HASH_NUM_BUCKETS;
@@ -421,9 +665,9 @@ mac_lookup_init (gid_dictionary_t * db)
void
gid_dictionary_init (gid_dictionary_t * db)
{
- ip4_lookup_init (db);
- ip6_lookup_init (db);
- mac_lookup_init (db);
+ ip4_lookup_init (&db->dst_ip4_table);
+ ip6_lookup_init (&db->dst_ip6_table);
+ mac_lookup_init (&db->sd_mac_table);
}
/*
diff --git a/vnet/vnet/lisp-cp/gid_dictionary.h b/vnet/vnet/lisp-cp/gid_dictionary.h
index d9a857fbaac..6544cca1b18 100644
--- a/vnet/vnet/lisp-cp/gid_dictionary.h
+++ b/vnet/vnet/lisp-cp/gid_dictionary.h
@@ -48,8 +48,11 @@ typedef struct
/* ip4 lookup table config parameters */
u32 ip4_lookup_table_nbuckets;
uword ip4_lookup_table_size;
+} gid_ip4_table_t;
- BVT (clib_bihash) ip6_lookup_table;
+typedef struct
+{
+ BVT (clib_bihash) ip6_lookup_table;
/* bitmap/vector of mask widths to search */
uword *ip6_non_empty_dst_address_length_bitmap;
@@ -60,12 +63,33 @@ typedef struct
/* ip6 lookup table config parameters */
u32 ip6_lookup_table_nbuckets;
uword ip6_lookup_table_size;
+} gid_ip6_table_t;
- BVT (clib_bihash) mac_lookup_table;
+typedef struct gid_mac_table
+{
+ BVT (clib_bihash) mac_lookup_table;
/* mac lookup table config parameters */
u32 mac_lookup_table_nbuckets;
uword mac_lookup_table_size;
+} gid_mac_table_t;
+
+typedef struct
+{
+ /** destination IP LPM ip4 lookup table */
+ gid_ip4_table_t dst_ip4_table;
+
+ /** pool of source IP LPM ip4 lookup tables */
+ gid_ip4_table_t *src_ip4_table_pool;
+
+ /** destination IP LPM ip6 lookup table */
+ gid_ip6_table_t dst_ip6_table;
+
+ /** pool of source IP LPM ip6 lookup tables */
+ gid_ip6_table_t *src_ip6_table_pool;
+
+ /** flat source/dest mac lookup table */
+ gid_mac_table_t sd_mac_table;
} gid_dictionary_t;
@@ -74,6 +98,8 @@ gid_dictionary_add_del (gid_dictionary_t * db, gid_address_t * key, u32 value,
u8 is_add);
u32 gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key);
+u32 gid_dictionary_sd_lookup (gid_dictionary_t * db, gid_address_t * dst,
+ gid_address_t * src);
void gid_dictionary_init (gid_dictionary_t * db);
diff --git a/vnet/vnet/lisp-cp/lisp_msg_serdes.c b/vnet/vnet/lisp-cp/lisp_msg_serdes.c
index d170efdd59a..de9a4f5b121 100644
--- a/vnet/vnet/lisp-cp/lisp_msg_serdes.c
+++ b/vnet/vnet/lisp-cp/lisp_msg_serdes.c
@@ -233,7 +233,8 @@ lisp_msg_parse_mapping_record (vlib_buffer_t * b, gid_address_t * eid,
return len;
vlib_buffer_pull (b, len);
- gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
+ if (GID_ADDR_IP_PREFIX == gid_address_type (eid))
+ gid_address_ippref_len (eid) = MAP_REC_EID_PLEN (h);
for (i = 0; i < MAP_REC_LOC_COUNT (h); i++)
{
diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c
index a2edb487cca..1f527d6e92e 100644
--- a/vnet/vnet/lisp-cp/lisp_types.c
+++ b/vnet/vnet/lisp-cp/lisp_types.c
@@ -213,7 +213,7 @@ format_fid_address (u8 * s, va_list * args)
return format (s, "%U", format_ip_prefix, &fid_addr_ippref (a));
case FID_ADDR_MAC:
- return format (s, "%U", format_ip_prefix, &fid_addr_mac (a));
+ return format (s, "%U", format_mac_address, &fid_addr_mac (a));
default:
clib_warning ("Can't format fid address type %d!", fid_addr_type (a));
@@ -1303,6 +1303,12 @@ vni_cmp (void *a1, void *a2)
}
static int
+mac_cmp (void *a1, void *a2)
+{
+ return memcmp (a1, a2, 6);
+}
+
+static int
fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
{
if (fid_addr_type (a1) != fid_addr_type (a2))
@@ -1314,7 +1320,7 @@ fid_addr_cmp (fid_address_t * a1, fid_address_t * a2)
return ip_prefix_cmp (&fid_addr_ippref (a1), &fid_addr_ippref (a2));
case FID_ADDR_MAC:
- return memcmp (&fid_addr_mac (a1), &fid_addr_mac (a2), 6);
+ return mac_cmp (fid_addr_mac (a1), fid_addr_mac (a2));
default:
return -1;
@@ -1375,8 +1381,7 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2)
cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)]) (lcaf1, lcaf2);
break;
case GID_ADDR_MAC:
- cmp = memcmp (gid_address_mac (a1), gid_address_mac (a2),
- sizeof (gid_address_mac (a1)));
+ cmp = mac_cmp (gid_address_mac (a1), gid_address_mac (a2));
break;
case GID_ADDR_SRC_DST:
@@ -1448,6 +1453,37 @@ locator_free (locator_t * l)
gid_address_free (&l->address);
}
+void
+build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst)
+{
+ memset (sd, 0, sizeof (*sd));
+ gid_address_type (sd) = GID_ADDR_SRC_DST;
+ gid_address_vni (sd) = gid_address_vni (dst);
+ gid_address_vni_mask (sd) = gid_address_vni_mask (dst);
+
+ switch (gid_address_type (dst))
+ {
+ case GID_ADDR_IP_PREFIX:
+ gid_address_sd_src_type (sd) = FID_ADDR_IP_PREF;
+ gid_address_sd_dst_type (sd) = FID_ADDR_IP_PREF;
+ ip_prefix_copy (&gid_address_sd_src_ippref (sd),
+ &gid_address_ippref (src));
+ ip_prefix_copy (&gid_address_sd_dst_ippref (sd),
+ &gid_address_ippref (dst));
+ break;
+ case GID_ADDR_MAC:
+ gid_address_sd_src_type (sd) = FID_ADDR_MAC;
+ gid_address_sd_dst_type (sd) = FID_ADDR_MAC;
+ mac_copy (gid_address_sd_src_mac (sd), gid_address_mac (src));
+ mac_copy (gid_address_sd_dst_mac (sd), gid_address_mac (dst));
+ break;
+ default:
+ clib_warning ("Unsupported gid type %d while conversion!",
+ gid_address_type (dst));
+ break;
+ }
+}
+
/*
* fd.io coding-style-patch-verification: ON
*
diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h
index cd1d1b9a642..e6811f0187e 100644
--- a/vnet/vnet/lisp-cp/lisp_types.h
+++ b/vnet/vnet/lisp-cp/lisp_types.h
@@ -126,6 +126,8 @@ typedef struct
#define sd_dst_ippref(_a) fid_addr_ippref(&sd_dst(_a))
#define sd_src_mac(_a) fid_addr_mac(&sd_src(_a))
#define sd_dst_mac(_a) fid_addr_mac(&sd_dst(_a))
+#define sd_src_type(_a) fid_addr_type(&sd_src(_a))
+#define sd_dst_type(_a) fid_addr_type(&sd_dst(_a))
typedef struct
{
@@ -224,6 +226,8 @@ void gid_address_ip_set (gid_address_t * dst, void *src, u8 version);
#define gid_address_sd(_a) (_a)->sd
#define gid_address_sd_src(_a) sd_src(&gid_address_sd(_a))
#define gid_address_sd_dst(_a) sd_dst(&gid_address_sd(_a))
+#define gid_address_sd_src_type(_a) sd_src_type(&gid_address_sd(_a))
+#define gid_address_sd_dst_type(_a) sd_dst_type(&gid_address_sd(_a))
/* 'sub'address functions */
#define foreach_gid_address_type_fcns \
@@ -311,6 +315,9 @@ typedef struct locator_pair
u8 weight;
} locator_pair_t;
+void
+build_src_dst (gid_address_t * sd, gid_address_t * src, gid_address_t * dst);
+
#endif /* VNET_LISP_GPE_LISP_TYPES_H_ */
/*