aboutsummaryrefslogtreecommitdiffstats
path: root/vnet/vnet/lisp-cp/control.c
diff options
context:
space:
mode:
authorFilip Tehlar <ftehlar@cisco.com>2016-10-17 16:20:18 +0200
committerFlorin Coras <florin.coras@gmail.com>2016-10-25 09:07:10 +0000
commitd5fcc468f33189c64c638c146812c534bcecac61 (patch)
treed5ccee7779af3e56ca238612a7f7025d754da9d1 /vnet/vnet/lisp-cp/control.c
parent0c38ea3e7bac5577698f0dcf5c0b493a97d2a9ce (diff)
Fix LISP src/dst based policy
Change-Id: Ibcc58ad50e33cd26367fd28f60334e29f45a094c Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
Diffstat (limited to 'vnet/vnet/lisp-cp/control.c')
-rw-r--r--vnet/vnet/lisp-cp/control.c106
1 files changed, 99 insertions, 7 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c
index 8dc42078..3b843a01 100644
--- a/vnet/vnet/lisp-cp/control.c
+++ b/vnet/vnet/lisp-cp/control.c
@@ -230,6 +230,8 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index)
a->locator_pairs = fe->locator_pairs;
a->vni = gid_address_vni (&fe->reid);
gid_address_copy (&a->rmt_eid, &fe->reid);
+ if (fe->is_src_dst)
+ gid_address_copy (&a->lcl_eid, &fe->leid);
vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index);
@@ -386,12 +388,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;
- if (GID_ADDR_SRC_DST == gid_address_type (&dst_map->eid))
+ if (MR_MODE_SRC_DST == lcm->map_request_mode)
{
- 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));
+ 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);
+ gid_address_copy (&a->lcl_eid, &src_map->eid);
+ }
is_src_dst = 1;
}
else
@@ -873,6 +883,85 @@ compare_locators (lisp_cp_main_t * lcm, u32 * old_ls_indexes,
return 0;
}
+typedef struct
+{
+ u8 is_negative;
+ void *lcm;
+ gid_address_t *eids_to_be_deleted;
+} remove_mapping_args_t;
+
+/**
+ * Callback invoked when a sub-prefix is found
+ */
+static void
+remove_mapping_if_needed (u32 mi, void *arg)
+{
+ u8 delete = 0;
+ remove_mapping_args_t *a = arg;
+ lisp_cp_main_t *lcm = a->lcm;
+ mapping_t *m;
+ locator_set_t *ls;
+
+ m = pool_elt_at_index (lcm->mapping_pool, mi);
+ if (!m)
+ return;
+
+ ls = pool_elt_at_index (lcm->locator_set_pool, m->locator_set_index);
+
+ if (a->is_negative)
+ {
+ if (0 != vec_len (ls->locator_indices))
+ delete = 1;
+ }
+ else
+ {
+ if (0 == vec_len (ls->locator_indices))
+ delete = 1;
+ }
+
+ if (delete)
+ vec_add1 (a->eids_to_be_deleted, m->eid);
+}
+
+/**
+ * This function searches map cache and looks for IP prefixes that are subset
+ * of the provided one. If such prefix is found depending on 'is_negative'
+ * it does follows:
+ *
+ * 1) if is_negative is true and found prefix points to positive mapping,
+ * then the mapping is removed
+ * 2) if is_negative is false and found prefix points to negative mapping,
+ * then the mapping is removed
+ */
+static void
+remove_overlapping_sub_prefixes (lisp_cp_main_t * lcm, gid_address_t * eid,
+ u8 is_negative)
+{
+ gid_address_t *e;
+ remove_mapping_args_t a;
+ memset (&a, 0, sizeof (a));
+
+ /* do this only in src/dst mode ... */
+ if (MR_MODE_SRC_DST != lcm->map_request_mode)
+ return;
+
+ /* ... and only for IP prefix */
+ if (GID_ADDR_SRC_DST != gid_address_type (eid)
+ || (FID_ADDR_IP_PREF != gid_address_sd_dst_type (eid)))
+ return;
+
+ a.is_negative = is_negative;
+ a.lcm = lcm;
+
+ gid_dict_foreach_subprefix (&lcm->mapping_index_by_gid, eid,
+ remove_mapping_if_needed, &a);
+
+ vec_foreach (e, a.eids_to_be_deleted)
+ vnet_lisp_add_del_mapping (e, 0, 0, 0, 0, 0 /* is add */ , 0, 0);
+
+ vec_free (a.eids_to_be_deleted);
+}
+
/**
* Adds/removes/updates mapping. Does not program forwarding.
*
@@ -925,7 +1014,7 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
/* do not overwrite local or static remote mappings */
clib_warning ("mapping %U rejected due to collision with local "
"or static remote mapping!", format_gid_address,
- &eid);
+ eid);
return 0;
}
@@ -952,6 +1041,8 @@ vnet_lisp_add_del_mapping (gid_address_t * eid, locator_t * rlocs, u8 action,
/* new mapping */
else
{
+ remove_overlapping_sub_prefixes (lcm, eid, 0 == ls_args->locators);
+
ls_args->is_add = 1;
ls_args->index = ~0;
@@ -2843,7 +2934,8 @@ build_encapsulated_map_request (lisp_cp_main_t * lcm,
/* get rlocs */
rlocs = build_itr_rloc_list (lcm, loc_set);
- if (MR_MODE_SRC_DST == lcm->map_request_mode)
+ if (MR_MODE_SRC_DST == lcm->map_request_mode
+ && GID_ADDR_SRC_DST != gid_address_type (deid))
{
gid_address_t sd;
memset (&sd, 0, sizeof (sd));