}
static void
-dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
+dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 dst_map_index)
{
vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
fwd_entry_t *fe = 0;
vnet_lisp_gpe_add_del_fwd_entry_args_t _a, *a = &_a;
gid_address_t *rmt_eid, *lcl_eid;
mapping_t *lcl_map, *rmt_map;
- u32 sw_if_index;
- uword *feip = 0, *dpid;
+ u32 sw_if_index, **rmts, rmts_idx;
+ uword *feip = 0, *dpid, *rmts_stored_idxp = 0;
fwd_entry_t *fe;
u8 type, is_src_dst = 0;
int rv;
/* remove entry if it already exists */
feip = hash_get (lcm->fwd_entry_by_mapping_index, dst_map_index);
if (feip)
- dp_del_fwd_entry (lcm, src_map_index, dst_map_index);
+ dp_del_fwd_entry (lcm, dst_map_index);
/*
* Determine local mapping and eid
fe->is_src_dst = is_src_dst;
hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index,
fe - lcm->fwd_entry_pool);
+
+ /* Add rmt mapping to the vector of adjacent mappings to lcl mapping */
+ rmts_stored_idxp =
+ hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index);
+ if (!rmts_stored_idxp)
+ {
+ pool_get (lcm->lcl_to_rmt_adjacencies, rmts);
+ memset (rmts, 0, sizeof (*rmts));
+ rmts_idx = rmts - lcm->lcl_to_rmt_adjacencies;
+ hash_set (lcm->lcl_to_rmt_adjs_by_lcl_idx, src_map_index, rmts_idx);
+ }
+ else
+ {
+ rmts_idx = (u32) (*rmts_stored_idxp);
+ rmts = pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idx);
+ }
+ vec_add1 (rmts[0], dst_map_index);
}
typedef struct
{
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
u32 mi, *map_indexp, map_index, i;
+ u32 **rmts = 0, *remote_idxp, rmts_itr, remote_idx;
+ uword *rmts_idxp;
mapping_t *m, *old_map;
u32 **eid_indexes;
m = pool_elt_at_index (lcm->mapping_pool, mi);
if (m->local)
{
+ /* Remove adjacencies associated with the local mapping */
+ rmts_idxp = hash_get (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi);
+ if (rmts_idxp)
+ {
+ rmts =
+ pool_elt_at_index (lcm->lcl_to_rmt_adjacencies, rmts_idxp[0]);
+ vec_foreach (remote_idxp, rmts[0])
+ {
+ dp_del_fwd_entry (lcm, remote_idxp[0]);
+ }
+ vec_free (rmts[0]);
+ pool_put (lcm->lcl_to_rmt_adjacencies, rmts);
+ hash_unset (lcm->lcl_to_rmt_adjs_by_lcl_idx, mi);
+ }
+
u32 k, *lm_indexp;
for (k = 0; k < vec_len (lcm->local_mappings_indexes); k++)
{
}
vec_del1 (lcm->local_mappings_indexes, k);
}
+ else
+ {
+ /* Remove remote (if present) from the vectors of lcl-to-rmts
+ * TODO: Address this in a more efficient way.
+ */
+ /* *INDENT-OFF* */
+ pool_foreach (rmts, lcm->lcl_to_rmt_adjacencies,
+ ({
+ vec_foreach_index (rmts_itr, rmts[0])
+ {
+ remote_idx = vec_elt (rmts[0], rmts_itr);
+ if (mi == remote_idx)
+ {
+ vec_del1 (rmts[0], rmts_itr);
+ break;
+ }
+ }
+ }));
+ /* *INDENT-ON* */
+ }
/* remove mapping from dictionary */
gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->eid, 0, 0);
add_l2_arp_bd (BVT (clib_bihash_kv) * kvp, void *arg)
{
u32 **ht = arg;
- u32 bd = (u32) kvp->key[0];
+ u32 version = (u32) kvp->key[0];
+ if (IP6 == version)
+ return;
+
+ u32 bd = (u32) (kvp->key[0] >> 32);
hash_set (ht[0], bd, 0);
}
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);
+ gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid,
+ add_l2_arp_bd, &bds);
+ return bds;
+}
+
+static void
+add_ndp_bd (BVT (clib_bihash_kv) * kvp, void *arg)
+{
+ u32 **ht = arg;
+ u32 version = (u32) kvp->key[0];
+ if (IP4 == version)
+ return;
+
+ u32 bd = (u32) (kvp->key[0] >> 32);
+ hash_set (ht[0], bd, 0);
+}
+
+u32 *
+vnet_lisp_ndp_bds_get (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ u32 *bds = 0;
+
+ gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid,
+ add_ndp_bd, &bds);
return bds;
}
{
void *vector;
u32 bd;
-} lisp_add_l2_arp_args_t;
+} lisp_add_l2_arp_ndp_args_t;
static void
add_l2_arp_entry (BVT (clib_bihash_kv) * kvp, void *arg)
{
- lisp_add_l2_arp_args_t *a = arg;
+ lisp_add_l2_arp_ndp_args_t *a = arg;
lisp_api_l2_arp_entry_t **vector = a->vector, e;
- if ((u32) kvp->key[0] == a->bd)
+ u32 version = (u32) kvp->key[0];
+ if (IP6 == version)
+ return;
+
+ u32 bd = (u32) (kvp->key[0] >> 32);
+
+ if (bd == a->bd)
{
mac_copy (e.mac, (void *) &kvp->value);
e.ip4 = (u32) kvp->key[1];
{
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;
+ lisp_add_l2_arp_ndp_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);
+ gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid,
+ add_l2_arp_entry, &a);
+ return entries;
+}
+
+static void
+add_ndp_entry (BVT (clib_bihash_kv) * kvp, void *arg)
+{
+ lisp_add_l2_arp_ndp_args_t *a = arg;
+ lisp_api_ndp_entry_t **vector = a->vector, e;
+
+ u32 version = (u32) kvp->key[0];
+ if (IP4 == version)
+ return;
+
+ u32 bd = (u32) (kvp->key[0] >> 32);
+
+ if (bd == a->bd)
+ {
+ mac_copy (e.mac, (void *) &kvp->value);
+ clib_memcpy (e.ip6, &kvp->key[1], 16);
+ vec_add1 (vector[0], e);
+ }
+}
+
+lisp_api_ndp_entry_t *
+vnet_lisp_ndp_entries_get_by_bd (u32 bd)
+{
+ lisp_api_ndp_entry_t *entries = 0;
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ lisp_add_l2_arp_ndp_args_t a;
+
+ a.vector = &entries;
+ a.bd = bd;
+
+ gid_dict_foreach_l2_arp_ndp_entry (&lcm->mapping_index_by_gid,
+ add_ndp_entry, &a);
return entries;
}
int
-vnet_lisp_add_del_l2_arp_entry (gid_address_t * key, u8 * mac, u8 is_add)
+vnet_lisp_add_del_l2_arp_ndp_entry (gid_address_t * key, u8 * mac, u8 is_add)
{
if (vnet_lisp_enable_disable_status () == 0)
{
{
if (res == GID_LOOKUP_MISS_L2)
{
- clib_warning ("ONE ARP entry %U not found - cannot delete!",
+ clib_warning ("ONE entry %U not found - cannot delete!",
format_gid_address, key);
return -1;
}
mapping_t *old_map;
u32 mi;
+ memset (ls_args, 0, sizeof (ls_args[0]));
memset (m_args, 0, sizeof (m_args[0]));
if (res_map_index)
res_map_index[0] = ~0;
mapping_t *map = pool_elt_at_index (lcm->mapping_pool, map_indexp[0]);
if (!map->local)
{
- dp_del_fwd_entry (lcm, 0, map_indexp[0]);
+ dp_del_fwd_entry (lcm, map_indexp[0]);
dm_args->is_add = 0;
gid_address_copy (&dm_args->eid, &map->eid);
dp_add_fwd_entry (lcm, local_mi, remote_mi);
}
else
- dp_del_fwd_entry (lcm, 0, remote_mi);
+ dp_del_fwd_entry (lcm, remote_mi);
return 0;
}
/* find locator-set */
if (a->local)
{
+ ASSERT (a->name);
p = hash_get_mem (lcm->locator_set_index_by_name, a->name);
}
else
clib_error_t *
vnet_lisp_enable_disable (u8 is_enable)
{
- u32 vni, dp_table;
+ u32 vni, dp_table, **rmts;
clib_error_t *error = 0;
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
vnet_lisp_gpe_enable_disable_args_t _a, *a = &_a;
/* clear interface table */
hash_free (lcm->fwd_entry_by_mapping_index);
pool_free (lcm->fwd_entry_pool);
+ /* Clear state tracking rmt-lcl fwd entries */
+ /* *INDENT-OFF* */
+ pool_foreach(rmts, lcm->lcl_to_rmt_adjacencies,
+ {
+ vec_free(rmts[0]);
+ });
+ /* *INDENT-ON* */
+ hash_free (lcm->lcl_to_rmt_adjs_by_lcl_idx);
+ pool_free (lcm->lcl_to_rmt_adjacencies);
}
/* update global flag */
#define foreach_lisp_cp_lookup_error \
_(DROP, "drop") \
_(MAP_REQUESTS_SENT, "map-request sent") \
-_(ARP_REPLY_TX, "ARP replies sent")
+_(ARP_REPLY_TX, "ARP replies sent") \
+_(NDP_NEIGHBOR_ADVERTISEMENT_TX, \
+ "neighbor advertisement 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_NEXT_ARP_NDP_REPLY_TX,
LISP_CP_LOOKUP_N_NEXT,
} lisp_cp_lookup_next_t;
{
ethernet_header_t *eh;
u32 vni = 0;
+ icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt;
memset (src, 0, sizeof (*src));
memset (dst, 0, sizeof (*dst));
}
else
{
+ if (clib_net_to_host_u16 (eh->type) == ETHERNET_TYPE_IP6)
+ {
+ ip6_header_t *ip;
+ ip = (ip6_header_t *) (eh + 1);
+
+ if (IP_PROTOCOL_ICMP6 == ip->protocol)
+ {
+ icmp6_neighbor_solicitation_or_advertisement_header_t *ndh;
+ ndh = ip6_next_header (ip);
+ if (ndh->icmp.type == ICMP6_neighbor_solicitation)
+ {
+ opt = (void *) (ndh + 1);
+ if ((opt->header.type !=
+ ICMP6_NEIGHBOR_DISCOVERY_OPTION_source_link_layer_address)
+ || (opt->header.n_data_u64s != 1))
+ return; /* source link layer address option not present */
+
+ gid_address_type (dst) = GID_ADDR_NDP;
+ gid_address_ndp_bd (dst) =
+ lisp_get_bd_from_buffer_eth (b);
+ ip_address_set (&gid_address_arp_ndp_ip (dst),
+ &ndh->target_address, IP6);
+ return;
+ }
+ }
+ }
+
gid_address_type (src) = GID_ADDR_MAC;
gid_address_type (dst) = GID_ADDR_MAC;
mac_copy (&gid_address_mac (src), eh->src_address);
vlib_node_runtime_t * node,
vlib_frame_t * from_frame, int overlay)
{
+ icmp6_neighbor_discovery_ethernet_link_layer_address_option_t *opt;
u32 *from, *to_next, di, si;
lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
u32 pkts_mapped = 0, next_index;
ethernet_arp_header_t *arp0;
ethernet_header_t *eth0;
vnet_hw_interface_t *hw_if0;
+ ethernet_header_t *eh0;
+ icmp6_neighbor_solicitation_or_advertisement_header_t *ndh;
+ ip6_header_t *ip0;
pi0 = from[0];
from += 1;
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;
- }
- goto done;
+ if (GID_LOOKUP_MISS_L2 == mac0)
+ goto drop;
+
+ /* 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_NDP_REPLY_TX;
+ goto enqueue;
+ }
+ else if (gid_address_type (&dst) == GID_ADDR_NDP)
+ {
+ mac0 = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst);
+ if (GID_LOOKUP_MISS_L2 == mac0)
+ goto drop;
+
+ sw_if_index0 = vnet_buffer (b0)->sw_if_index[VLIB_RX];
+ vnet_buffer (b0)->sw_if_index[VLIB_TX] = sw_if_index0;
+
+ eh0 = vlib_buffer_get_current (b0);
+ ip0 = (ip6_header_t *) (eh0 + 1);
+ ndh = ip6_next_header (ip0);
+ int bogus_length;
+ ip0->dst_address = ip0->src_address;
+ ip0->src_address = ndh->target_address;
+ ip0->hop_limit = 255;
+ opt = (void *) (ndh + 1);
+ opt->header.type =
+ ICMP6_NEIGHBOR_DISCOVERY_OPTION_target_link_layer_address;
+ clib_memcpy (opt->ethernet_address, (u8 *) & mac0, 6);
+ ndh->icmp.type = ICMP6_neighbor_advertisement;
+ ndh->advertisement_flags = clib_host_to_net_u32
+ (ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_SOLICITED |
+ ICMP6_NEIGHBOR_ADVERTISEMENT_FLAG_OVERRIDE);
+ ndh->icmp.checksum = 0;
+ ndh->icmp.checksum =
+ ip6_tcp_udp_icmp_compute_checksum (vm, b0, ip0,
+ &bogus_length);
+ clib_memcpy (eh0->dst_address, eh0->src_address, 6);
+ clib_memcpy (eh0->src_address, (u8 *) & mac0, 6);
+ b0->error =
+ node->errors
+ [LISP_CP_LOOKUP_ERROR_NDP_NEIGHBOR_ADVERTISEMENT_TX];
+ next0 = LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX;
+ goto enqueue;
}
/* if we have remote mapping for destination already in map-chache
pkts_mapped++;
}
- done:
+ drop:
b0->error = node->errors[LISP_CP_LOOKUP_ERROR_DROP];
+ next0 = LISP_CP_LOOKUP_NEXT_DROP;
+ enqueue:
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);
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
- [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
+ [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
- [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
+ [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
- [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
+ [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
.next_nodes = {
[LISP_CP_LOOKUP_NEXT_DROP] = "error-drop",
- [LISP_CP_LOOKUP_NEXT_ARP_REPLY_TX] = "interface-output",
+ [LISP_CP_LOOKUP_NEXT_ARP_NDP_REPLY_TX] = "interface-output",
},
};
/* *INDENT-ON* */
lcm->map_register_ttl = MAP_REGISTER_DEFAULT_TTL;
lcm->max_expired_map_registers = MAX_EXPIRED_MAP_REGISTERS_DEFAULT;
lcm->expired_map_registers = 0;
+ lcm->transport_protocol = LISP_TRANSPORT_PROTOCOL_UDP;
return 0;
}
};
/* *INDENT-ON* */
+u32
+vnet_lisp_set_transport_protocol (u8 protocol)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+
+ if (protocol < LISP_TRANSPORT_PROTOCOL_UDP ||
+ protocol > LISP_TRANSPORT_PROTOCOL_API)
+ return VNET_API_ERROR_INVALID_ARGUMENT;
+
+ lcm->transport_protocol = protocol;
+ return 0;
+}
+
+lisp_transport_protocol_t
+vnet_lisp_get_transport_protocol (void)
+{
+ lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
+ return lcm->transport_protocol;
+}
+
VLIB_INIT_FUNCTION (lisp_cp_init);
/*