diff options
Diffstat (limited to 'vnet/vnet/lisp-cp/control.c')
-rw-r--r-- | vnet/vnet/lisp-cp/control.c | 100 |
1 files changed, 88 insertions, 12 deletions
diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index 3448fb3e..f067cf6d 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -18,7 +18,8 @@ #include <vnet/lisp-cp/lisp_msg_serdes.h> #include <vnet/lisp-gpe/lisp_gpe.h> -/* Adds mapping to map-cache but does NOT program LISP forwarding */ +/* Stores mapping in map-cache. It does NOT program data plane forwarding for + * remote/learned mappings. */ int vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, u32 * map_index_result) @@ -32,11 +33,12 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, if (a->is_add) { /* TODO check if overwriting and take appropriate actions */ - if (mi != GID_LOOKUP_MISS) { + if (mi != GID_LOOKUP_MISS) + { clib_warning("eid %U found in the eid-table", format_ip_address, &a->deid); return VNET_API_ERROR_VALUE_EXIST; - } + } pool_get(lcm->mapping_pool, m); m->eid = a->deid; @@ -65,18 +67,17 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, { /* mark as local */ vec_add1(lcm->local_mappings_indexes, map_index); - - /* XXX do something else? */ } map_index_result[0] = map_index; } else { - if (mi == GID_LOOKUP_MISS) { + if (mi == GID_LOOKUP_MISS) + { clib_warning("eid %U not found in the eid-table", format_ip_address, &a->deid); return VNET_API_ERROR_INVALID_VALUE; - } + } /* clear locator-set to eids binding */ eid_indexes = vec_elt_at_index(lcm->locator_set_to_eids, @@ -115,6 +116,66 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, return 0; } +/* Stores mapping in map-cache and programs data plane for local mappings. */ +int +vnet_lisp_add_del_local_mapping (vnet_lisp_add_del_mapping_args_t * a, + u32 * map_index_result) +{ + uword * table_id, * refc; + u32 rv; + vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai; + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); + + /* store/remove mapping from map-cache */ + rv = vnet_lisp_add_del_mapping (a, map_index_result); + if (rv) + return rv; + + table_id = hash_get(lcm->table_id_by_vni, /* default for now */ 0); + + if (!table_id) + { + clib_warning ("vni %d not associated to a vrf!", 0); + return VNET_API_ERROR_INVALID_VALUE; + } + + refc = hash_get(lcm->dp_if_refcount_by_vni, 0); + + /* enable/disable data-plane interface */ + if (a->is_add) + { + /* create interface or update refcount */ + if (!refc) + { + ai->is_add = 1; + ai->vni = 0; /* default for now, pass vni as parameter */ + ai->table_id = table_id[0]; + vnet_lisp_gpe_add_del_iface (ai, 0); + } + else + { + refc[0]++; + } + } + else + { + /* since this is a remove for an existing eid, the iface should exist */ + ASSERT(refc != 0); + refc[0]--; + + /* remove iface if needed */ + if (refc[0] == 0) + { + ai->is_add = 0; + ai->vni = 0; /* default for now, pass vni as parameter */ + ai->table_id = table_id[0]; + vnet_lisp_gpe_add_del_iface (ai, 0); + } + } + + return rv; +} + static clib_error_t * lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -171,7 +232,7 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, a->locator_set_index = locator_set_index; a->local = 1; - vnet_lisp_add_del_mapping (a, &map_index); + vnet_lisp_add_del_local_mapping (a, &map_index); done: vec_free(eids); return error; @@ -650,7 +711,8 @@ lisp_add_del_locator_set_command_fn (vlib_main_t * vm, unformat_input_t * input, VLIB_CLI_COMMAND (lisp_cp_add_del_locator_set_command) = { .path = "lisp locator-set", - .short_help = "lisp locator-set add/del <name> <iface-name> <priority> <weight>", + .short_help = "lisp locator-set add/del <name> iface <iface-name> " + "<priority> <weight>", .function = lisp_add_del_locator_set_command_fn, }; @@ -1251,7 +1313,7 @@ del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, a->is_add = 0; a->dlocator = fe->dst_loc; a->slocator = fe->src_loc; - a->iid = 0; // XXX should be part of mapping/eid + a->vni = 0; // XXX should be part of mapping/eid gid_address_copy(&a->deid, &fe->deid); vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index); @@ -1268,8 +1330,9 @@ add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index) locator_set_t * dst_ls, * src_ls; u32 i, minp = ~0; locator_t * dl = 0; - uword * feip = 0; + uword * feip = 0, * tidp; vnet_lisp_gpe_add_del_fwd_entry_args_t _a, * a = &_a; + memset (a, 0, sizeof(*a)); /* remove entry if it already exists */ @@ -1334,10 +1397,20 @@ add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index) } gid_address_copy (&a->deid, &dst_map->eid); - a->iid = 0; // XXX should be part of mapping/eid + a->vni = 0; // XXX should be part of mapping/eid + + tidp = hash_get(lcm->table_id_by_vni, a->vni); + if (!tidp) + { + clib_warning("vni %d not associated to a vrf!", a->vni); + return; + } + a->table_id = tidp[0]; + u8 ipver = ip_prefix_version(&gid_address_ippref(&a->deid)); a->decap_next_index = (ipver == IP4) ? LISP_GPE_INPUT_NEXT_IP4_INPUT : LISP_GPE_INPUT_NEXT_IP6_INPUT; + /* XXX tunnels work only with IP4 now */ vnet_lisp_gpe_add_del_fwd_entry (a, &sw_if_index); @@ -1611,6 +1684,9 @@ lisp_cp_init (vlib_main_t *vm) gid_dictionary_init (&lcm->mapping_index_by_gid); gid_dictionary_init (&lcm->mapping_index_by_gid); + /* default vrf mapped to vni 0 */ + hash_set(lcm->table_id_by_vni, 0, 0); + udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, lisp_cp_input_node.index, 1 /* is_ip4 */); udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp6, |