#include <vnet/lisp-gpe/lisp_gpe_tunnel.h>
#include <vnet/fib/fib_entry.h>
#include <vnet/fib/fib_table.h>
+#include <vnet/ethernet/arp_packet.h>
+#include <vnet/ethernet/packet.h>
#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);
u8 smr_invoked;
} map_request_args_t;
-typedef struct
-{
- u64 nonce;
- u8 is_rloc_probe;
- mapping_t *mappings;
-} map_records_arg_t;
-
u8
vnet_lisp_get_map_request_mode (void)
{
if (fe->is_src_dst)
gid_address_copy (&a->lcl_eid, &fe->leid);
- vnet_lisp_del_fwd_stats (a, feip[0]);
+ vnet_lisp_gpe_del_fwd_counters (a, feip[0]);
vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
/* delete entry in fwd table */
a->action = rmt_map->action;
}
- vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
+ rv = vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
+ if (rv)
+ {
+ if (a->locator_pairs)
+ vec_free (a->locator_pairs);
+ return;
+ }
- /* add tunnel to fwd entry table XXX check return value from DP insertion */
+ /* add tunnel to fwd entry table */
pool_get (lcm->fwd_entry_pool, fe);
+ vnet_lisp_gpe_add_fwd_counters (a, fe - lcm->fwd_entry_pool);
+
fe->locator_pairs = a->locator_pairs;
gid_address_copy (&fe->reid, &a->rmt_eid);
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");
return vnet_lisp_map_cache_add_del (a, map_index_result);
}
+static void
+add_l2_arp_bd (BVT (clib_bihash_kv) * kvp, void *arg)
+{
+ u32 **ht = arg;
+ u32 bd = (u32) kvp->key[0];
+ hash_set (ht[0], bd, 0);
+}
+
+u32 *
+vnet_lisp_l2_arp_bds_get (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ u32 *bds = 0;
+
+ gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid,
+ add_l2_arp_bd, &bds);
+ return bds;
+}
+
+typedef struct
+{
+ void *vector;
+ u32 bd;
+} lisp_add_l2_arp_args_t;
+
+static void
+add_l2_arp_entry (BVT (clib_bihash_kv) * kvp, void *arg)
+{
+ lisp_add_l2_arp_args_t *a = arg;
+ lisp_api_l2_arp_entry_t **vector = a->vector, e;
+
+ if ((u32) kvp->key[0] == a->bd)
+ {
+ mac_copy (e.mac, (void *) &kvp->value);
+ e.ip4 = (u32) kvp->key[1];
+ vec_add1 (vector[0], e);
+ }
+}
+
+lisp_api_l2_arp_entry_t *
+vnet_lisp_l2_arp_entries_get_by_bd (u32 bd)
+{
+ lisp_api_l2_arp_entry_t *entries = 0;
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_add_l2_arp_args_t a;
+
+ a.vector = &entries;
+ a.bd = bd;
+
+ gid_dict_foreach_l2_arp_entry (&lcm->mapping_index_by_gid,
+ add_l2_arp_entry, &a);
+ return entries;
+}
+
+int
+vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add)
+{
+ if (vnet_lisp_enable_disable_status () == 0)
+ {
+ clib_warning ("LISP is disabled!");
+ return VNET_API_ERROR_LISP_DISABLED;
+ }
+
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ int rc = 0;
+
+ u64 res = gid_dictionary_lookup (&lcm->mapping_index_by_gid, key);
+ if (is_add)
+ {
+ if (res != GID_LOOKUP_MISS_L2)
+ {
+ clib_warning ("Entry %U exists in DB!", format_gid_address, key);
+ return VNET_API_ERROR_ENTRY_ALREADY_EXISTS;
+ }
+ u64 val = mac_to_u64 (mac);
+ gid_dictionary_add_del (&lcm->mapping_index_by_gid, key, val,
+ 1 /* is_add */ );
+ }
+ else
+ {
+ if (res == GID_LOOKUP_MISS_L2)
+ {
+ clib_warning ("ONE ARP entry %U not found - cannot delete!",
+ format_gid_address, key);
+ return -1;
+ }
+ gid_dictionary_add_del (&lcm->mapping_index_by_gid, key, 0,
+ 0 /* is_add */ );
+ }
+
+ return rc;
+}
+
int
vnet_lisp_eid_table_map (u32 vni, u32 dp_id, u8 is_l2, u8 is_add)
{
if (vnet_lisp_enable_disable_status () == 0)
{
clib_warning ("LISP is disabled!");
- return -1;
+ return VNET_API_ERROR_LISP_DISABLED;
}
dp_table_by_vni = is_l2 ? &lcm->bd_id_by_vni : &lcm->table_id_by_vni;
"mapping!", vni, dp_id);
return -1;
}
- hash_unset (dp_table_by_vni[0], vni);
- hash_unset (vni_by_dp_table[0], dp_id);
-
/* remove dp iface */
dp_add_del_iface (lcm, vni, is_l2, 0);
+
+ hash_unset (dp_table_by_vni[0], vni);
+ hash_unset (vni_by_dp_table[0], dp_id);
}
return 0;
{
/* 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)
{
return 0;
}
+static void
+update_adjacencies_by_map_index (lisp_cp_main_t * lcm, u8 is_local,
+ u32 mapping_index, u8 remove_only)
+{
+ fwd_entry_t *fwd;
+ mapping_t *map;
+ vnet_lisp_add_del_adjacency_args_t _a, *a = &_a;
+
+ map = pool_elt_at_index (lcm->mapping_pool, mapping_index);
+
+ /* *INDENT-OFF* */
+ pool_foreach(fwd, lcm->fwd_entry_pool,
+ ({
+ if ((is_local && 0 == gid_address_cmp (&map->eid, &fwd->leid)) ||
+ (!is_local && 0 == gid_address_cmp (&map->eid, &fwd->reid)))
+ {
+ a->is_add = 0;
+ gid_address_copy (&a->leid, &fwd->leid);
+ gid_address_copy (&a->reid, &fwd->reid);
+
+ vnet_lisp_add_del_adjacency (a);
+
+ if (!remove_only)
+ {
+ a->is_add = 1;
+ vnet_lisp_add_del_adjacency (a);
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+}
+
+static void
+update_fwd_entries_by_locator_set (lisp_cp_main_t * lcm, u8 is_local,
+ u32 ls_index, u8 remove_only)
+{
+ u32 i, *map_indexp;
+ u32 **eid_indexes;
+
+ if (vec_len (lcm->locator_set_to_eids) <= ls_index)
+ return;
+
+ eid_indexes = vec_elt_at_index (lcm->locator_set_to_eids, ls_index);
+
+ for (i = 0; i < vec_len (eid_indexes[0]); i++)
+ {
+ map_indexp = vec_elt_at_index (eid_indexes[0], i);
+ update_adjacencies_by_map_index (lcm, is_local, map_indexp[0],
+ remove_only);
+ }
+}
+
static inline void
remove_locator_from_locator_set (locator_set_t * ls, u32 * locit,
u32 ls_index, u32 loc_id)
else
{
ls_index = p[0];
+ u8 removed;
- itloc = a->locators;
- loc_id = 0;
- vec_foreach (locit, ls->locator_indices)
+ vec_foreach (itloc, a->locators)
{
- loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
+ removed = 0;
+ loc_id = 0;
+ vec_foreach (locit, ls->locator_indices)
+ {
+ loc = pool_elt_at_index (lcm->locator_pool, locit[0]);
- if (loc->local && loc->sw_if_index == itloc->sw_if_index)
- {
- remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
- }
- if (0 == loc->local &&
- !gid_address_cmp (&loc->address, &itloc->address))
- {
- remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
- }
+ if (loc->local && loc->sw_if_index == itloc->sw_if_index)
+ {
+ removed = 1;
+ remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
+ }
+ if (0 == loc->local &&
+ !gid_address_cmp (&loc->address, &itloc->address))
+ {
+ removed = 1;
+ remove_locator_from_locator_set (ls, locit, ls_index, loc_id);
+ }
- loc_id++;
+ if (removed)
+ {
+ /* update fwd entries using this locator in DP */
+ update_fwd_entries_by_locator_set (lcm, loc->local, ls_index,
+ vec_len (ls->locator_indices)
+ == 0);
+ }
+
+ loc_id++;
+ }
}
}
return 0;
}
+int
+vnet_lisp_map_register_set_ttl (u32 ttl)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lcm->map_register_ttl = ttl;
+ return 0;
+}
+
+u32
+vnet_lisp_map_register_get_ttl (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ return lcm->map_register_ttl;
+}
+
int
vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a)
{
/* Statistics (not really errors) */
#define foreach_lisp_cp_lookup_error \
_(DROP, "drop") \
-_(MAP_REQUESTS_SENT, "map-request sent")
+_(MAP_REQUESTS_SENT, "map-request sent") \
+_(ARP_REPLY_TX, "ARP replies sent")
static char *lisp_cp_lookup_error_strings[] = {
#define _(sym,string) string,
typedef enum
{
LISP_CP_LOOKUP_NEXT_DROP,
+ LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX,
LISP_CP_LOOKUP_N_NEXT,
} lisp_cp_lookup_next_t;
/* 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;
u64 nonce = 0;
u32 next_index, *to_next;
ip_address_t *ms = 0;
- mapping_t *records, *r, *g;
+ mapping_t *records, *r, *group, *k;
// TODO: support multiple map servers and do election
if (0 == vec_len (lcm->map_servers))
if (!key)
continue; /* no secret key -> map-register cannot be sent */
- g = 0;
- // TODO: group mappings that share common key
- vec_add1 (g, r[0]);
- b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, g,
+ group = 0;
+ vec_add1 (group, r[0]);
+
+ /* group mappings that share common key */
+ for (k = r + 1; k < vec_end (records); k++)
+ {
+ if (k->key_id != r->key_id)
+ continue;
+
+ if (vec_is_equal (k->key, r->key))
+ {
+ vec_add1 (group, k[0]);
+ k->key = 0; /* don't process this mapping again */
+ }
+ }
+
+ b = build_map_register (lcm, &sloc, ms, &nonce, want_map_notif, group,
key_id, key, &bi);
- vec_free (g);
+ vec_free (group);
if (!b)
continue;
}
/* 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 */
}
always_inline u32
-lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
+lisp_get_bd_from_buffer_eth (vlib_buffer_t * b)
{
- uword *vnip;
- u32 vni = ~0;
u32 sw_if_index0;
l2input_main_t *l2im = &l2input_main;
config = vec_elt_at_index (l2im->configs, sw_if_index0);
bd_config = vec_elt_at_index (l2im->bd_configs, config->bd_index);
- vnip = hash_get (lcm->vni_by_bd_id, bd_config->bd_id);
+ return bd_config->bd_id;
+}
+
+always_inline u32
+lisp_get_vni_from_buffer_eth (lisp_cp_main_t * lcm, vlib_buffer_t * b)
+{
+ uword *vnip;
+ u32 vni = ~0;
+ u32 bd = lisp_get_bd_from_buffer_eth (b);
+
+ vnip = hash_get (lcm->vni_by_bd_id, bd);
if (vnip)
vni = vnip[0];
else
- clib_warning ("bridge domain %d is not mapped to any vni!",
- config->bd_index);
+ clib_warning ("bridge domain %d is not mapped to any vni!", bd);
return vni;
}
gid_address_t * src, gid_address_t * dst,
u16 type)
{
+ ethernet_header_t *eh;
u32 vni = 0;
memset (src, 0, sizeof (*src));
memset (dst, 0, sizeof (*dst));
+ gid_address_type (dst) = GID_ADDR_NO_ADDRESS;
+ gid_address_type (src) = GID_ADDR_NO_ADDRESS;
+
if (LISP_AFI_IP == type || LISP_AFI_IP6 == type)
{
ip4_header_t *ip;
}
else if (LISP_AFI_MAC == type)
{
- ethernet_header_t *eh;
+ ethernet_arp_header_t *ah;
eh = vlib_buffer_get_current (b);
- gid_address_type (src) = GID_ADDR_MAC;
- gid_address_type (dst) = GID_ADDR_MAC;
- mac_copy (&gid_address_mac (src), eh->src_address);
- mac_copy (&gid_address_mac (dst), eh->dst_address);
+ if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_ARP)
+ {
+ ah = (ethernet_arp_header_t *) (((u8 *) eh) + sizeof (*eh));
+ if (clib_net_to_host_u16 (ah->opcode)
+ != ETHERNET_ARP_OPCODE_request)
+ return;
+
+ gid_address_type (dst) = GID_ADDR_ARP;
+ gid_address_arp_bd (dst) = lisp_get_bd_from_buffer_eth (b);
+ clib_memcpy (&gid_address_arp_ip4 (dst),
+ &ah->ip4_over_ethernet[1].ip4, 4);
+ }
+ else
+ {
+ gid_address_type (src) = GID_ADDR_MAC;
+ gid_address_type (dst) = GID_ADDR_MAC;
+ mac_copy (&gid_address_mac (src), eh->src_address);
+ mac_copy (&gid_address_mac (dst), eh->dst_address);
- /* get vni */
- vni = lisp_get_vni_from_buffer_eth (lcm, b);
+ /* get vni */
+ vni = lisp_get_vni_from_buffer_eth (lcm, b);
- gid_address_vni (dst) = vni;
- gid_address_vni (src) = vni;
+ gid_address_vni (dst) = vni;
+ gid_address_vni (src) = vni;
+ }
}
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;
+ }
}
}
vlib_node_runtime_t * node,
vlib_frame_t * from_frame, int overlay)
{
- u32 *from, *to_next_drop, di, si;
+ u32 *from, *to_next, di, si;
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
- u32 pkts_mapped = 0;
- uword n_left_from, n_left_to_next_drop;
+ u32 pkts_mapped = 0, next_index;
+ uword n_left_from, n_left_to_next;
+ vnet_main_t *vnm = vnet_get_main ();
from = vlib_frame_vector_args (from_frame);
n_left_from = from_frame->n_vectors;
+ next_index = node->cached_next_index;
while (n_left_from > 0)
{
- vlib_get_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
- to_next_drop, n_left_to_next_drop);
+ vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
- while (n_left_from > 0 && n_left_to_next_drop > 0)
+ while (n_left_from > 0 && n_left_to_next > 0)
{
- u32 pi0;
+ u32 pi0, sw_if_index0, next0;
+ u64 mac0;
vlib_buffer_t *b0;
gid_address_t src, dst;
+ ethernet_arp_header_t *arp0;
+ ethernet_header_t *eth0;
+ vnet_hw_interface_t *hw_if0;
pi0 = from[0];
from += 1;
n_left_from -= 1;
- to_next_drop[0] = pi0;
- to_next_drop += 1;
- n_left_to_next_drop -= 1;
+ to_next[0] = pi0;
+ to_next += 1;
+ n_left_to_next -= 1;
b0 = vlib_get_buffer (vm, pi0);
- b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
/* src/dst eid pair */
get_src_and_dst_eids_from_buffer (lcm, b0, &src, &dst, overlay);
+ if (gid_address_type (&dst) == GID_ADDR_ARP)
+ {
+ mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
+ if (GID_LOOKUP_MISS_L2 != mac0)
+ {
+ /* send ARP reply */
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
+
+ hw_if0 = vnet_get_sup_hw_interface (vnm, sw_if_index0);
+
+ eth0 = vlib_buffer_get_current (b0);
+ arp0 = (ethernet_arp_header_t *) (((u8 *) eth0)
+ + sizeof (*eth0));
+ arp0->opcode =
+ clib_host_to_net_u16 (ETHERNET_ARP_OPCODE_reply);
+ arp0->ip4_over_ethernet[1] = arp0->ip4_over_ethernet[0];
+ clib_memcpy (arp0->ip4_over_ethernet[0].ethernet,
+ (u8 *) & mac0, 6);
+ clib_memcpy (&arp0->ip4_over_ethernet[0].ip4,
+ &gid_address_arp_ip4 (&dst), 4);
+
+ /* Hardware must be ethernet-like. */
+ ASSERT (vec_len (hw_if0->hw_address) == 6);
+
+ clib_memcpy (eth0->dst_address, eth0->src_address, 6);
+ clib_memcpy (eth0->src_address, hw_if0->hw_address, 6);
+
+ b0->error = node->errors[LISP_CP_LOOKUP_ERROR_ARP_REPLY_TX];
+ next0 = LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX;
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next,
+ n_left_to_next, pi0,
+ next0);
+ }
+ continue;
+ }
+
/* if we have remote mapping for destination already in map-chache
add forwarding tunnel directly. If not send a map-request */
di = gid_dictionary_sd_lookup (&lcm->mapping_index_by_gid, &dst,
}
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);
pkts_mapped++;
}
+ b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
if (PREDICT_FALSE (b0->flags & VLIB_BUFFER_IS_TRACED))
{
lisp_cp_lookup_trace_t *tr = vlib_add_trace (vm, node, b0,
}
gid_address_free (&dst);
gid_address_free (&src);
+ next0 = LISP_CP_LOOKUP_NEXT_DROP;
+ vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
+ to_next,
+ n_left_to_next, pi0, next0);
}
- vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP,
- n_left_to_next_drop);
+ vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}
vlib_node_increment_counter (vm, node->node_index,
LISP_CP_LOOKUP_ERROR_MAP_REQUESTS_SENT,
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
+ [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
+ [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
+ [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
+ [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
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);
}
mapping_t m;
locator_t *loc;
+ memset (&m, 0, sizeof (m));
+
/* parse record eid */
for (i = 0; i < count; i++)
{
+ locators = 0;
len = lisp_msg_parse_mapping_record (b, &deid, &locators, NULL);
if (len == ~0)
{
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;
vec_free (itr_rlocs);
}
-static map_records_arg_t *
+map_records_arg_t *
parse_map_reply (vlib_buffer_t * b)
{
locator_t probed;
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);
a->nonce = MREP_NONCE (mrep_hdr);
a->is_rloc_probe = MREP_RLOC_PROBE (mrep_hdr);
+ if (!vlib_buffer_has_space (b, sizeof (*mrep_hdr)))
+ {
+ clib_mem_free (a);
+ return 0;
+ }
vlib_buffer_pull (b, sizeof (*mrep_hdr));
for (i = 0; i < MREP_REC_COUNT (mrep_hdr); i++)
{
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;
+ lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL;
return 0;
}
lisp_api_stats_t * stat, lisp_stats_key_t * key,
u32 stats_index)
{
- lisp_stats_t *s;
+ vlib_counter_t v;
+ vlib_combined_counter_main_t *cm = &lgm->counters;
lisp_gpe_fwd_entry_key_t fwd_key;
const lisp_gpe_tunnel_t *lgt;
fwd_entry_t *fe;
stat->loc_rloc = lgt->key->lcl;
stat->rmt_rloc = lgt->key->rmt;
- s = pool_elt_at_index (lgm->lisp_stats_pool, stats_index);
- stat->stats = *s;
+ vlib_get_combined_counter (cm, stats_index, &v);
+ stat->counters = v;
return 1;
}