#include <openssl/evp.h>
#include <openssl/hmac.h>
+#define MAX_VALUE_U24 0xffffff
+
lisp_cp_main_t lisp_control_main;
u8 *format_lisp_cp_input_trace (u8 * s, va_list * args);
mapping_t *m, *old_map;
u32 **eid_indexes;
+ if (gid_address_type (&a->eid) == GID_ADDR_NSH)
+ {
+ if (gid_address_vni (&a->eid) != 0)
+ {
+ clib_warning ("Supported only default VNI for NSH!");
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+ if (gid_address_nsh_spi (&a->eid) > MAX_VALUE_U24)
+ {
+ clib_warning ("SPI is greater than 24bit!");
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+ }
+ }
+
mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->eid);
old_map = mi != ~0 ? pool_elt_at_index (lcm->mapping_pool, mi) : 0;
if (a->is_add)
else if (GID_ADDR_MAC == type)
dp_table = hash_get (lcm->bd_id_by_vni, vni);
- if (!dp_table)
+ if (!dp_table && GID_ADDR_NSH != type)
{
clib_warning ("vni %d not associated to a %s!", vni,
GID_ADDR_IP_PREFIX == type ? "vrf" : "bd");
{
/* check if source eid has an associated mapping. If pitr mode is on,
* just use the pitr's mapping */
- local_mi = lcm->lisp_pitr ? lcm->pitr_map_index :
- gid_dictionary_lookup (&lcm->mapping_index_by_gid, &a->leid);
+ if (lcm->lisp_pitr)
+ local_mi = lcm->pitr_map_index;
+ else
+ {
+ if (gid_address_type (&a->reid) == GID_ADDR_NSH)
+ {
+ if (lcm->nsh_map_index == ~0)
+ local_mi = GID_LOOKUP_MISS;
+ else
+ local_mi = lcm->nsh_map_index;
+ }
+ else
+ {
+ local_mi = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
+ &a->leid);
+ }
+ }
if (GID_LOOKUP_MISS == local_mi)
{
return 0;
}
+int
+vnet_lisp_nsh_set_locator_set (u8 * locator_set_name, u8 is_add)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_gpe_main_t *lgm = vnet_lisp_gpe_get_main ();
+ u32 locator_set_index = ~0;
+ mapping_t *m;
+ uword *p;
+
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ if (is_add)
+ {
+ if (lcm->nsh_map_index == (u32) ~ 0)
+ {
+ p = hash_get_mem (lcm->locator_set_index_by_name, locator_set_name);
+ if (!p)
+ {
+ clib_warning ("locator-set %v doesn't exist", locator_set_name);
+ return -1;
+ }
+ locator_set_index = p[0];
+
+ pool_get (lcm->mapping_pool, m);
+ memset (m, 0, sizeof *m);
+ m->locator_set_index = locator_set_index;
+ m->local = 1;
+ m->nsh_set = 1;
+ lcm->nsh_map_index = m - lcm->mapping_pool;
+
+ if (~0 == vnet_lisp_gpe_add_nsh_iface (lgm))
+ return -1;
+ }
+ }
+ else
+ {
+ if (lcm->nsh_map_index != (u32) ~ 0)
+ {
+ /* remove NSH mapping */
+ pool_put_index (lcm->mapping_pool, lcm->nsh_map_index);
+ lcm->nsh_map_index = ~0;
+ vnet_lisp_gpe_del_nsh_iface (lgm);
+ }
+ }
+ return 0;
+}
+
int
vnet_lisp_pitr_set_locator_set (u8 * locator_set_name, u8 is_add)
{
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- rloc);
+ rloc, 1);
bi_res[0] = bi;
}
b = vlib_get_buffer (vm, bi);
+ b->flags = 0;
/* leave some space for the encap headers */
vlib_buffer_make_headroom (b, MAX_LISP_MSG_ENCAP_LEN);
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- mr_ip);
+ mr_ip, 1);
bi_res[0] = bi;
/* push outer ip header */
pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, LISP_CONTROL_PORT, sloc,
- ms_ip);
+ ms_ip, 1);
bi_res[0] = bi;
return b;
}
/* get locator-set for seid */
- if (!lcm->lisp_pitr)
+ if (!lcm->lisp_pitr && gid_address_type (deid) != GID_ADDR_NSH)
{
map_index = gid_dictionary_lookup (&lcm->mapping_index_by_gid, seid);
if (map_index == ~0)
}
else
{
- map_index = lcm->pitr_map_index;
- map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
- ls_index = map->locator_set_index;
+ if (lcm->lisp_pitr)
+ {
+ map = pool_elt_at_index (lcm->mapping_pool, lcm->pitr_map_index);
+ ls_index = map->locator_set_index;
+ }
+ else
+ {
+ if (lcm->nsh_map_index == (u32) ~ 0)
+ {
+ clib_warning ("No locator-set defined for NSH!");
+ return -1;
+ }
+ else
+ {
+ map = pool_elt_at_index (lcm->mapping_pool, lcm->nsh_map_index);
+ ls_index = map->locator_set_index;
+ }
+ }
}
/* overwrite locator set if map-request itr-rlocs configured */
gid_address_t * src, gid_address_t * dst,
u16 type)
{
+ ethernet_header_t *eh;
u32 vni = 0;
memset (src, 0, sizeof (*src));
}
else if (LISP_AFI_MAC == type)
{
- ethernet_header_t *eh;
ethernet_arp_header_t *ah;
eh = vlib_buffer_get_current (b);
}
else if (LISP_AFI_LCAF == type)
{
- /* Eventually extend this to support NSH and other */
- ASSERT (0);
+ lisp_nsh_hdr_t *nh;
+ eh = vlib_buffer_get_current (b);
+
+ if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_NSH)
+ {
+ nh = (lisp_nsh_hdr_t *) (((u8 *) eh) + sizeof (*eh));
+ u32 spi = clib_net_to_host_u32 (nh->spi_si << 8);
+ u8 si = (u8) clib_net_to_host_u32 (nh->spi_si);
+ gid_address_nsh_spi (dst) = spi;
+ gid_address_nsh_si (dst) = si;
+
+ gid_address_type (dst) = GID_ADDR_NSH;
+ }
}
}
}
else
{
- si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
- &src);
+ if (GID_ADDR_NSH != gid_address_type (&dst))
+ {
+ si = gid_dictionary_lookup (&lcm->mapping_index_by_gid,
+ &src);
+ }
+ else
+ si = lcm->nsh_map_index;
+
if (~0 != si)
{
dp_add_fwd_entry_from_mt (si, di);
static void
map_records_arg_free (map_records_arg_t * a)
{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
mapping_t *m;
vec_foreach (m, a->mappings)
{
vec_free (m->locators);
gid_address_free (&m->eid);
}
-
- clib_mem_free (a);
+ pool_put (lcm->map_records_args_pool[vlib_get_thread_index ()], a);
}
void *
pool_put (lcm->pending_map_requests_pool, pmr);
done:
- map_records_arg_free (a);
+ a->is_free = 1;
return 0;
}
return;
}
- map_records_arg_free (a);
+ a->is_free = 1;
hash_unset (lcm->map_register_messages_by_nonce, a->nonce);
}
return 0;
}
+static map_records_arg_t *
+map_record_args_get ()
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ map_records_arg_t *rec;
+
+ /* Cleanup first */
+ /* *INDENT-OFF* */
+ pool_foreach (rec, lcm->map_records_args_pool[vlib_get_thread_index()], ({
+ if (rec->is_free)
+ map_records_arg_free (rec);
+ }));
+ /* *INDENT-ON* */
+
+ pool_get (lcm->map_records_args_pool[vlib_get_thread_index ()], rec);
+ return rec;
+}
+
static map_records_arg_t *
parse_map_notify (vlib_buffer_t * b)
{
gid_address_t deid;
u16 auth_data_len = 0;
u8 record_count;
- map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
+ map_records_arg_t *a;
+ a = map_record_args_get ();
memset (a, 0, sizeof (*a));
mnotif_hdr = vlib_buffer_get_current (b);
vlib_buffer_pull (b, sizeof (*mnotif_hdr));
lisp_msg_put_map_reply (b, records, nonce, probe_bit);
/* push outer ip header */
- pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst);
+ pkt_push_udp_and_ip (vm, b, LISP_CONTROL_PORT, dst_port, sloc, dst, 1);
bi_res[0] = bi;
return b;
static void
find_ip_header (vlib_buffer_t * b, u8 ** ip_hdr)
{
- const i32 start = vnet_buffer (b)->ip.start_of_ip_header;
+ const i32 start = vnet_buffer (b)->l3_hdr_offset;
if (start < 0 && start < -sizeof (b->pre_data))
{
*ip_hdr = 0;
u32 i, len = 0;
mapping_t m;
map_reply_hdr_t *mrep_hdr;
- map_records_arg_t *a = clib_mem_alloc (sizeof (*a));
+ map_records_arg_t *a;
+
+ a = map_record_args_get ();
memset (a, 0, sizeof (*a));
+
locator_t *locators;
mrep_hdr = vlib_buffer_get_current (b);
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
clib_error_t *error = 0;
+ vlib_thread_main_t *vtm = vlib_get_thread_main ();
+ u32 num_threads;
if ((error = vlib_call_init_function (vm, lisp_gpe_init)))
return error;
lcm->do_map_resolver_election = 1;
lcm->map_request_mode = MR_MODE_DST_ONLY;
+ num_threads = 1 /* main thread */ + vtm->n_threads;
+ vec_validate (lcm->map_records_args_pool, num_threads - 1);
+
/* default vrf mapped to vni 0 */
hash_set (lcm->table_id_by_vni, 0, 0);
hash_set (lcm->vni_by_table_id, 0, 0);
u64 now = clib_cpu_time_now ();
timing_wheel_init (&lcm->wheel, now, vm->clib_time.clocks_per_second);
+ lcm->nsh_map_index = ~0;
return 0;
}