From 68660906e60416dcb573402bff5a40b26c2213c2 Mon Sep 17 00:00:00 2001 From: Andrej Kozemcak Date: Thu, 26 May 2016 12:20:08 +0200 Subject: ONE-15: Fix duplicate locator, refactoring locator Check duplication locator and clean after locator when remove it. Refactoring locator_set code. Change-Id: Ib83cbcddc7a363a60fa5b6a366203d0dc0ea7ca6 Signed-off-by: Andrej Kozemcak --- vnet/vnet/lisp-cp/control.c | 394 +++++++++++++++++--------------------------- vnet/vnet/lisp-cp/control.h | 5 +- vpp/api/api.c | 4 +- 3 files changed, 157 insertions(+), 246 deletions(-) diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index 39aad6cafbc..8492ecd14f7 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -550,187 +550,172 @@ clean_locator_to_locator_set (lisp_cp_main_t * lcm, u32 lsi) pool_put_index(lcm->locator_pool, loc_indexp[0]); } } -int -vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a, - u32 * ls_result) + +static inline +uword *get_locator_set_index(vnet_lisp_add_del_locator_set_args_t * a, + uword * p) { lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); - locator_set_t * ls; - locator_t * loc, * itloc; - uword _p = (u32)~0, * p = &_p; - u32 loc_index, ls_index, ** ls_indexes; - u32 **eid_indexes; - if (a->is_add) - { - /* check if overwrite */ - if (a->local) - p = hash_get_mem(lcm->locator_set_index_by_name, a->name); - else - *p = a->index; + ASSERT(a != NULL); + ASSERT(p != NULL); - /* overwrite */ - if (p && p[0] != (u32)~0) - { - ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); - if (!ls) - { - clib_warning("locator-set %d to be overwritten doesn't exist!", - p[0]); - return -1; - } + /* find locator-set */ + if (a->local) + { + p = hash_get_mem(lcm->locator_set_index_by_name, a->name); + } + else + { + *p = a->index; + } - /* clean locator to locator-set vectors and remove locators if - * they're not part of another locator-set */ - clean_locator_to_locator_set (lcm, p[0]); + return p; +} - /* remove locator indices from locator set */ - vec_free(ls->locator_indices); +static inline +int is_locator_in_locator_set(lisp_cp_main_t * lcm, locator_set_t * ls, + locator_t * loc) +{ + locator_t * itloc; + u32 * locit; - ls_index = p[0]; + ASSERT(ls != NULL); + ASSERT(loc != NULL); - if (ls_result) - ls_result[0] = p[0]; - } - /* new locator-set */ - else + vec_foreach(locit, ls->locator_indices) + { + itloc = pool_elt_at_index(lcm->locator_pool, locit[0]); + if (itloc->sw_if_index == loc->sw_if_index || + !gid_address_cmp(&itloc->address, &loc->address)) { - pool_get(lcm->locator_set_pool, ls); - ls_index = ls - lcm->locator_set_pool; + clib_warning("Duplicate locator"); + return VNET_API_ERROR_VALUE_EXIST; + } + } - if (a->local) - { - ls->name = vec_dup(a->name); + return 0; +} - if (!lcm->locator_set_index_by_name) - lcm->locator_set_index_by_name = hash_create_vec( - /* size */0, sizeof(ls->name[0]), sizeof(uword)); - hash_set_mem(lcm->locator_set_index_by_name, ls->name, ls_index); +static inline +void remove_locator_from_locator_set(locator_set_t * ls, u32 * locit, + u32 ls_index, u32 loc_id) +{ + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); + u32 ** ls_indexes = NULL; - /* mark as local locator-set */ - vec_add1(lcm->local_locator_set_indexes, ls_index); - } - ls->local = a->local; - if (ls_result) - ls_result[0] = ls_index; - } + ASSERT(ls != NULL); + ASSERT(locit != NULL); - /* allocate locators */ - vec_foreach (itloc, a->locators) - { - pool_get(lcm->locator_pool, loc); - loc[0] = itloc[0]; - loc_index = loc - lcm->locator_pool; + ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets, + locit[0]); + pool_put_index(lcm->locator_pool, locit[0]); + vec_del1(ls->locator_indices, loc_id); + vec_del1(ls_indexes[0], ls_index); +} + +int +vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a, + locator_set_t * ls, u32 * ls_result) +{ + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); + locator_t * loc = NULL, *itloc = NULL; + uword _p = (u32)~0, * p = &_p; + u32 loc_index = ~0, ls_index = ~0, * locit = NULL, ** ls_indexes = NULL; + u32 loc_id = ~0; + int ret = 0; - vec_add1(ls->locator_indices, loc_index); + ASSERT(a != NULL); - vec_validate (lcm->locator_to_locator_sets, loc_index); - ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets, - loc_index); - vec_add1(ls_indexes[0], ls_index); - } - } - else + p = get_locator_set_index(a, p); + if (!p) { - /* find locator-set */ - if (a->local) - { - p = hash_get_mem(lcm->locator_set_index_by_name, a->name); - if (!p) - { - clib_warning("locator-set %v doesn't exists", a->name); - return -1; - } - } - else - *p = a->index; + clib_warning("locator-set %v doesn't exist", a->name); + return VNET_API_ERROR_INVALID_ARGUMENT; + } + if (ls == 0) + { ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); if (!ls) { - clib_warning("locator-set with index %d doesn't exists", p[0]); - return -1; + clib_warning("locator-set %d to be overwritten doesn't exist!", + p[0]); + return VNET_API_ERROR_INVALID_ARGUMENT; } -// /* XXX what happens when a mapping is configured to use the loc-set ? */ -// if (vec_len (vec_elt_at_index(lcm->locator_set_to_eids, p[0])) != 0) -// { -// clib_warning ("Can't delete a locator that supports a mapping!"); -// return -1; -// } - - if (vec_len(lcm->locator_set_to_eids) != 0) - { - eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids, p[0]); - if (vec_len(eid_indexes[0]) != 0) - { - clib_warning ("Can't delete a locator that supports a mapping!"); - return -1; - } - } + } - /* clean locator to locator-sets data */ - clean_locator_to_locator_set (lcm, p[0]); + if (a->is_add) + { - if (ls->local) - { - u32 it, lsi; + if (ls_result) + ls_result[0] = p[0]; - vec_foreach_index(it, lcm->local_locator_set_indexes) + /* allocate locators */ + vec_foreach (itloc, a->locators) { - lsi = vec_elt(lcm->local_locator_set_indexes, it); - if (lsi == p[0]) + ret = is_locator_in_locator_set(lcm, ls, itloc); + if (0 != ret) { - vec_del1(lcm->local_locator_set_indexes, it); - break; + return ret; } + + pool_get(lcm->locator_pool, loc); + loc[0] = itloc[0]; + loc_index = loc - lcm->locator_pool; + + vec_add1(ls->locator_indices, loc_index); + + vec_validate (lcm->locator_to_locator_sets, loc_index); + ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets, + loc_index); + vec_add1(ls_indexes[0], ls_index); } - hash_unset_mem(lcm->locator_set_index_by_name, ls->name); - vec_free(ls->name); - } - pool_put(lcm->locator_set_pool, ls); - } - return 0; -} + } + else + { + ls_index = p[0]; -static inline -uword *vnet_lisp_get_locator(vnet_lisp_add_del_locator_set_args_t * a, - uword *p) -{ - lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); + itloc = a->locators; + loc_id = 0; + vec_foreach (locit, ls->locator_indices) + { + loc = pool_elt_at_index(lcm->locator_pool, locit[0]); - ASSERT(a != NULL); - ASSERT(p != NULL); + 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); + } - /* find locator-set */ - if (a->local) - { - p = hash_get_mem(lcm->locator_set_index_by_name, a->name); - } - else - { - *p = a->index; - } + loc_id++; + } + } - return p; + return 0; } int -vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, - u32 * ls_result) +vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a, + u32 * ls_result) { lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); locator_set_t * ls; uword _p = (u32)~0, * p = &_p; - u32 ls_index = ~0; - u32 **eid_indexes = NULL; - - ASSERT(a != NULL); - ASSERT(ls_result != NULL); - - p = vnet_lisp_get_locator(a, p); + u32 ls_index; + u32 ** eid_indexes; + int ret = 0; if (a->is_add) { + p = get_locator_set_index(a, p); + /* overwrite */ if (p && p[0] != (u32)~0) { @@ -739,7 +724,7 @@ vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, { clib_warning("locator-set %d to be overwritten doesn't exist!", p[0]); - return VNET_API_ERROR_UNSPECIFIED; + return -1; } /* clean locator to locator-set vectors and remove locators if @@ -758,6 +743,7 @@ vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, else { pool_get(lcm->locator_set_pool, ls); + memset(ls, 0, sizeof(*ls)); ls_index = ls - lcm->locator_set_pool; if (a->local) @@ -773,25 +759,31 @@ vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, vec_add1(lcm->local_locator_set_indexes, ls_index); } ls->local = a->local; - ls->locator_indices = NULL; if (ls_result) ls_result[0] = ls_index; } + + ret = vnet_lisp_add_del_locator(a, ls, NULL); + if (0 != ret) + { + return ret; + } } else { - if (!p) - { - clib_warning("locator-set %v doesn't exists", a->name); - return VNET_API_ERROR_INVALID_ARGUMENT; - } - - ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); - if (!ls) - { - clib_warning("locator-set with index %d doesn't exists", p[0]); - return VNET_API_ERROR_INVALID_ARGUMENT; - } + p = get_locator_set_index(a, p); + if (!p) + { + clib_warning("locator-set %v doesn't exists", a->name); + return -1; + } + + ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); + if (!ls) + { + clib_warning("locator-set with index %d doesn't exists", p[0]); + return -1; + } if (vec_len(lcm->locator_set_to_eids) != 0) { @@ -811,97 +803,19 @@ vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, u32 it, lsi; vec_foreach_index(it, lcm->local_locator_set_indexes) - { - lsi = vec_elt(lcm->local_locator_set_indexes, it); - if (lsi == p[0]) - { - vec_del1(lcm->local_locator_set_indexes, it); - break; - } - } - hash_unset_mem(lcm->locator_set_index_by_name, ls->name); - vec_free(ls->name); - } - pool_put(lcm->locator_set_pool, ls); - } - return 0; -} - -int -vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t *a, - u32 *ls_result) -{ - lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); - locator_set_t *ls = NULL; - locator_t *loc = NULL, *itloc = NULL; - uword _p = (u32)~0, * p = &_p; - u32 loc_index = ~0, ls_index = ~0, *locit = NULL, **ls_indexes = NULL; - u32 i = ~0; - - ASSERT(a != NULL); - ASSERT(ls_result != NULL); - - p = vnet_lisp_get_locator(a, p); - if (!p) { - clib_warning("locator-set %v doesn't exists", a->name); - return VNET_API_ERROR_INVALID_ARGUMENT; - } - - ls_index = p[0]; - - if (a->is_add) - { - ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); - if (!ls) - { - clib_warning("locator-set %d to be overwritten doesn't exist!", - p[0]); - return VNET_API_ERROR_INVALID_ARGUMENT; - } - - if (ls_result) - ls_result[0] = p[0]; - - /* allocate locators */ - itloc = a->locators; - pool_get(lcm->locator_pool, loc); - loc[0] = itloc[0]; - loc_index = loc - lcm->locator_pool; - - vec_add1(ls->locator_indices, loc_index); - - vec_validate (lcm->locator_to_locator_sets, loc_index); - ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets, - loc_index); - vec_add1(ls_indexes[0], ls_index); - } - else - { - ls = pool_elt_at_index(lcm->locator_set_pool, p[0]); - if (!ls) - { - clib_warning("locator-set with index %d doesn't exists", p[0]); - return VNET_API_ERROR_INVALID_ARGUMENT; - } - - if (ls->local) - { - itloc = a->locators; - i = 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) + lsi = vec_elt(lcm->local_locator_set_indexes, it); + if (lsi == p[0]) { - ls_indexes = vec_elt_at_index(lcm->locator_to_locator_sets, - locit[0]); - pool_put_index(lcm->locator_pool, locit[0]); - vec_del1(ls->locator_indices, i); - vec_del1(ls_indexes[0], ls_index); + vec_del1(lcm->local_locator_set_indexes, it); + break; } - i++; } - } + hash_unset_mem(lcm->locator_set_index_by_name, ls->name); + } + vec_free(ls->name); + vec_free(ls->locator_indices); + pool_put(lcm->locator_set_pool, ls); } return 0; } diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h index ecab1dba091..705bd5a0287 100644 --- a/vnet/vnet/lisp-cp/control.h +++ b/vnet/vnet/lisp-cp/control.h @@ -132,11 +132,8 @@ int vnet_lisp_add_del_locator_set (vnet_lisp_add_del_locator_set_args_t * a, u32 * ls_index); int -vnet_lisp_add_del_locator_set_name (vnet_lisp_add_del_locator_set_args_t * a, - u32 * ls_index); -int vnet_lisp_add_del_locator (vnet_lisp_add_del_locator_set_args_t * a, - u32 * ls_index); + locator_set_t * ls, u32 * ls_index); typedef struct { diff --git a/vpp/api/api.c b/vpp/api/api.c index ae8ddf9de13..7aa898c6e30 100644 --- a/vpp/api/api.c +++ b/vpp/api/api.c @@ -4600,7 +4600,7 @@ vl_api_lisp_add_del_locator_set_t_handler(vl_api_lisp_add_del_locator_set_t *mp) a->is_add = mp->is_add; a->local = 1; - rv = vnet_lisp_add_del_locator_set_name(a, &ls_index); + rv = vnet_lisp_add_del_locator_set(a, &ls_index); vec_free(locator_name); @@ -4634,7 +4634,7 @@ vl_api_lisp_add_del_locator_t_handler( a->is_add = mp->is_add; a->local = 1; - rv = vnet_lisp_add_del_locator(a, &ls_index); + rv = vnet_lisp_add_del_locator(a, NULL, &ls_index); vec_free(locators); vec_free(locator_name); -- cgit 1.2.3-korg