diff options
author | Neale Ranns <nranns@cisco.com> | 2016-10-03 09:40:25 +0100 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2016-10-03 11:45:15 +0000 |
commit | 5e575b1d59a5a4c1590ca09d6383a876fb9fdd25 (patch) | |
tree | fcba6d058fe32d9b32fe246577565020d10455ff /vnet/vnet/lisp-gpe/lisp_gpe.c | |
parent | 553d808fc44e61846e4cda108083dd88beb338e3 (diff) |
L2 over LISP and GRE (VPP-457)
Change-Id: I0d7f9c7f41a9f9e0acb0950adedb90d45df08c2a
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'vnet/vnet/lisp-gpe/lisp_gpe.c')
-rw-r--r-- | vnet/vnet/lisp-gpe/lisp_gpe.c | 593 |
1 files changed, 10 insertions, 583 deletions
diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.c b/vnet/vnet/lisp-gpe/lisp_gpe.c index d0ab37e9637..fbda8687c3b 100644 --- a/vnet/vnet/lisp-gpe/lisp_gpe.c +++ b/vnet/vnet/lisp-gpe/lisp_gpe.c @@ -19,475 +19,13 @@ */ #include <vnet/lisp-gpe/lisp_gpe.h> +#include <vnet/lisp-gpe/lisp_gpe_fwd_entry.h> #include <vnet/lisp-gpe/lisp_gpe_adjacency.h> -#include <vnet/adj/adj_midchain.h> -#include <vnet/fib/fib_table.h> -#include <vnet/fib/fib_entry.h> -#include <vnet/fib/fib_path_list.h> -#include <vnet/dpo/drop_dpo.h> -#include <vnet/dpo/load_balance.h> +#include <vnet/lisp-gpe/lisp_gpe_tenant.h> /** LISP-GPE global state */ lisp_gpe_main_t lisp_gpe_main; -/** - * @brief A Pool of all LISP forwarding entries - */ -static lisp_fwd_entry_t *lisp_fwd_entry_pool; - -/** - * DB of all forwarding entries. The Key is:{l-EID,r-EID,vni} - * where the EID encodes L2 or L3 - */ -static uword *lisp_gpe_fwd_entries; - -static void -create_fib_entries (lisp_fwd_entry_t * lfe) -{ - dpo_proto_t dproto; - - dproto = (ip_prefix_version (&lfe->key->rmt.ippref) == IP4 ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - - lfe->src_fib_index = ip_dst_fib_add_route (lfe->eid_fib_index, - &lfe->key->rmt.ippref); - - if (LISP_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - dpo_id_t dpo = DPO_NULL; - - switch (lfe->action) - { - case LISP_NO_ACTION: - /* TODO update timers? */ - case LISP_FORWARD_NATIVE: - /* TODO check if route/next-hop for eid exists in fib and add - * more specific for the eid with the next-hop found */ - case LISP_SEND_MAP_REQUEST: - /* insert tunnel that always sends map-request */ - dpo_set (&dpo, DPO_LISP_CP, 0, dproto); - break; - case LISP_DROP: - /* for drop fwd entries, just add route, no need to add encap tunnel */ - dpo_copy (&dpo, drop_dpo_get (dproto)); - break; - } - ip_src_fib_add_route_w_dpo (lfe->src_fib_index, - &lfe->key->lcl.ippref, &dpo); - dpo_reset (&dpo); - } - else - { - ip_src_fib_add_route (lfe->src_fib_index, - &lfe->key->lcl.ippref, lfe->paths); - } -} - -static void -delete_fib_entries (lisp_fwd_entry_t * lfe) -{ - ip_src_dst_fib_del_route (lfe->src_fib_index, - &lfe->key->lcl.ippref, - lfe->eid_fib_index, &lfe->key->rmt.ippref); -} - -static void -gid_to_dp_address (gid_address_t * g, dp_address_t * d) -{ - switch (gid_address_type (g)) - { - case GID_ADDR_IP_PREFIX: - case GID_ADDR_SRC_DST: - ip_prefix_copy (&d->ippref, &gid_address_ippref (g)); - d->type = FID_ADDR_IP_PREF; - break; - case GID_ADDR_MAC: - default: - mac_copy (&d->mac, &gid_address_mac (g)); - d->type = FID_ADDR_MAC; - break; - } -} - -static lisp_fwd_entry_t * -find_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - lisp_gpe_fwd_entry_key_t * key) -{ - uword *p; - - memset (key, 0, sizeof (*key)); - - if (GID_ADDR_IP_PREFIX == gid_address_type (&a->rmt_eid)) - { - /* - * the ip version of the source is not set to ip6 when the - * source is all zeros. force it. - */ - ip_prefix_version (&gid_address_ippref (&a->lcl_eid)) = - ip_prefix_version (&gid_address_ippref (&a->rmt_eid)); - } - - gid_to_dp_address (&a->rmt_eid, &key->rmt); - gid_to_dp_address (&a->lcl_eid, &key->lcl); - key->vni = a->vni; - - p = hash_get_mem (lisp_gpe_fwd_entries, key); - - if (NULL != p) - { - return (pool_elt_at_index (lisp_fwd_entry_pool, p[0])); - } - return (NULL); -} - -static int -lisp_gpe_fwd_entry_path_sort (void *a1, void *a2) -{ - lisp_fwd_path_t *p1 = a1, *p2 = a2; - - return (p1->priority - p2->priority); -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * creation of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_fwd_entry_t *lfe; - fib_protocol_t fproto; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL != lfe) - /* don't support updates */ - return VNET_API_ERROR_INVALID_VALUE; - - pool_get (lisp_fwd_entry_pool, lfe); - memset (lfe, 0, sizeof (*lfe)); - lfe->key = clib_mem_alloc (sizeof (key)); - memcpy (lfe->key, &key, sizeof (key)); - - hash_set_mem (lisp_gpe_fwd_entries, lfe->key, lfe - lisp_fwd_entry_pool); - - fproto = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - - lfe->type = (a->is_negative ? - LISP_FWD_ENTRY_TYPE_NEGATIVE : LISP_FWD_ENTRY_TYPE_NORMAL); - lfe->eid_table_id = a->table_id; - lfe->eid_fib_index = fib_table_find_or_create_and_lock (fproto, - lfe->eid_table_id); - - if (LISP_FWD_ENTRY_TYPE_NEGATIVE != lfe->type) - { - lisp_fwd_path_t *path; - u32 index; - - vec_validate (lfe->paths, vec_len (a->locator_pairs) - 1); - - vec_foreach_index (index, a->locator_pairs) - { - path = &lfe->paths[index]; - - path->priority = a->locator_pairs[index].priority; - path->weight = a->locator_pairs[index].weight; - - path->lisp_adj = - lisp_gpe_adjacency_find_or_create_and_lock (&a->locator_pairs - [index], - lfe->eid_table_id, - lfe->key->vni); - } - vec_sort_with_function (lfe->paths, lisp_gpe_fwd_entry_path_sort); - } - - create_fib_entries (lfe); - - return (0); -} - -static void -del_ip_fwd_entry_i (lisp_fwd_entry_t * lfe) -{ - lisp_fwd_path_t *path; - fib_protocol_t fproto; - - vec_foreach (path, lfe->paths) - { - lisp_gpe_adjacency_unlock (path->lisp_adj); - } - - delete_fib_entries (lfe); - - fproto = (IP4 == ip_prefix_version (&fid_addr_ippref (&lfe->key->rmt)) ? - FIB_PROTOCOL_IP4 : FIB_PROTOCOL_IP6); - fib_table_unlock (lfe->eid_fib_index, fproto); - - hash_unset_mem (lisp_gpe_fwd_entries, lfe->key); - clib_mem_free (lfe->key); - pool_put (lisp_fwd_entry_pool, lfe); -} - -/** - * @brief Add/Delete LISP IP forwarding entry. - * - * removal of forwarding entries for IP LISP overlay: - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -del_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - lisp_gpe_fwd_entry_key_t key; - lisp_fwd_entry_t *lfe; - - lfe = find_fwd_entry (lgm, a, &key); - - if (NULL == lfe) - /* no such entry */ - return VNET_API_ERROR_INVALID_VALUE; - - del_ip_fwd_entry_i (lfe); - - return (0); -} - -static void -make_mac_fib_key (BVT (clib_bihash_kv) * kv, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - kv->key[0] = (((u64) bd_index) << 48) | mac_to_u64 (dst_mac); - kv->key[1] = mac_to_u64 (src_mac); - kv->key[2] = 0; -} - -/** - * @brief Lookup L2 SD FIB entry - * - * Does a vni + dest + source lookup in the L2 LISP FIB. If the lookup fails - * it tries a second time with source set to 0 (i.e., a simple dest lookup). - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * - * @return index of mapping matching the lookup key. - */ -index_t -lisp_l2_fib_lookup (lisp_gpe_main_t * lgm, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6]) -{ - int rv; - BVT (clib_bihash_kv) kv, value; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - - /* no match, try with src 0, catch all for dst */ - if (rv != 0) - { - kv.key[1] = 0; - rv = BV (clib_bihash_search_inline_2) (&lgm->l2_fib, &kv, &value); - if (rv == 0) - return value.value; - } - - return lisp_gpe_main.l2_lb_miss; -} - -/** - * @brief Add/del L2 SD FIB entry - * - * Inserts value in L2 FIB keyed by vni + dest + source. If entry is - * overwritten the associated value is returned. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] bd_index Bridge domain index. - * @param[in] src_mac Source mac address. - * @param[in] dst_mac Destination mac address. - * @param[in] val Value to add. - * @param[in] is_add Add/del flag. - * - * @return ~0 or value of overwritten entry. - */ -u32 -lisp_l2_fib_add_del_entry (lisp_gpe_main_t * lgm, u16 bd_index, u8 src_mac[6], - u8 dst_mac[6], u32 val, u8 is_add) -{ - BVT (clib_bihash_kv) kv, value; - u32 old_val = ~0; - - make_mac_fib_key (&kv, bd_index, src_mac, dst_mac); - - if (BV (clib_bihash_search) (&lgm->l2_fib, &kv, &value) == 0) - old_val = value.value; - - if (!is_add) - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 0 /* is_add */ ); - else - { - kv.value = val; - BV (clib_bihash_add_del) (&lgm->l2_fib, &kv, 1 /* is_add */ ); - } - return old_val; -} - -static void -l2_fib_init (lisp_gpe_main_t * lgm) -{ - BV (clib_bihash_init) (&lgm->l2_fib, "l2 fib", - 1 << max_log2 (L2_FIB_DEFAULT_HASH_NUM_BUCKETS), - L2_FIB_DEFAULT_HASH_MEMORY_SIZE); - - /* - * the result from a 'miss' in a L2 Table - */ - lgm->l2_lb_miss = load_balance_create (1, DPO_PROTO_IP4, 0); - load_balance_set_bucket (lgm->l2_lb_miss, 0, drop_dpo_get (DPO_PROTO_IP4)); -} - -/** - * @brief Add/Delete LISP L2 forwarding entry. - * - * Coordinates the creation/removal of forwarding entries for L2 LISP overlay: - * creates lisp-gpe tunnel and injects new entry in Source/Dest L2 FIB. - * - * @param[in] lgm Reference to @ref lisp_gpe_main_t. - * @param[in] a Parameters for building the forwarding entry. - * - * @return 0 on success. - */ -static int -add_del_l2_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - /* lisp_gpe_fwd_entry_key_t key; */ - /* lisp_fwd_entry_t *lfe; */ - /* fib_protocol_t fproto; */ - /* uword *bd_indexp; */ - - /* bd_indexp = hash_get (bdm->bd_index_by_bd_id, a->bd_id); */ - /* if (!bd_indexp) */ - /* { */ - /* clib_warning ("bridge domain %d doesn't exist", a->bd_id); */ - /* return -1; */ - /* } */ - - /* lfe = find_fwd_entry(lgm, a, &key); */ - - /* if (NULL != lfe) */ - /* /\* don't support updates *\/ */ - /* return VNET_API_ERROR_INVALID_VALUE; */ - - /* int rv; */ - /* u32 tun_index; */ - /* fib_node_index_t old_path_list; */ - /* bd_main_t *bdm = &bd_main; */ - /* fib_route_path_t *rpaths; */ - /* lisp_gpe_tunnel_t *t; */ - /* const dpo_id_t *dpo; */ - /* index_t lbi; */ - - /* /\* create tunnel *\/ */ - /* rv = add_del_ip_tunnel (a, 1 /\* is_l2 *\/ , &tun_index, NULL); */ - /* if (rv) */ - /* return rv; */ - - /* bd_indexp = hash_get (bdm->bd_index_by_bd_id, a->bd_id); */ - /* if (!bd_indexp) */ - /* { */ - /* clib_warning ("bridge domain %d doesn't exist", a->bd_id); */ - /* return -1; */ - /* } */ - - /* t = pool_elt_at_index (lgm->tunnels, tun_index); */ - /* old_path_list = t->l2_path_list; */ - - /* if (LISP_NO_ACTION == t->action) */ - /* { */ - /* rpaths = lisp_gpe_mk_paths_for_sub_tunnels (t); */ - - /* t->l2_path_list = fib_path_list_create (FIB_PATH_LIST_FLAG_NONE, */ - /* rpaths); */ - - /* vec_free (rpaths); */ - /* fib_path_list_lock (t->l2_path_list); */ - - /* dpo = fib_path_list_contribute_forwarding (t->l2_path_list, */ - /* FIB_FORW_CHAIN_TYPE_UNICAST_IP); */ - /* lbi = dpo->dpoi_index; */ - /* } */ - /* else if (LISP_SEND_MAP_REQUEST == t->action) */ - /* { */ - /* lbi = lgm->l2_lb_cp_lkup; */ - /* } */ - /* else */ - /* { */ - /* lbi = lgm->l2_lb_miss; */ - /* } */ - /* fib_path_list_unlock (old_path_list); */ - - /* /\* add entry to l2 lisp fib *\/ */ - /* lisp_l2_fib_add_del_entry (lgm, bd_indexp[0], gid_address_mac (&a->lcl_eid), */ - /* gid_address_mac (&a->rmt_eid), lbi, a->is_add); */ - return 0; -} - -/** - * @brief Forwarding entry create/remove dispatcher. - * - * Calls l2 or l3 forwarding entry add/del function based on input data. - * - * @param[in] a Forwarding entry parameters. - * @param[out] hw_if_indexp NOT USED - * - * @return 0 on success. - */ -int -vnet_lisp_gpe_add_del_fwd_entry (vnet_lisp_gpe_add_del_fwd_entry_args_t * a, - u32 * hw_if_indexp) -{ - lisp_gpe_main_t *lgm = &lisp_gpe_main; - u8 type; - - if (vnet_lisp_gpe_enable_disable_status () == 0) - { - clib_warning ("LISP is disabled!"); - return VNET_API_ERROR_LISP_DISABLED; - } - - type = gid_address_type (&a->rmt_eid); - switch (type) - { - case GID_ADDR_IP_PREFIX: - if (a->is_add) - return add_ip_fwd_entry (lgm, a); - else - return del_ip_fwd_entry (lgm, a); - break; - case GID_ADDR_MAC: - return add_del_l2_fwd_entry (lgm, a); - default: - clib_warning ("Forwarding entries for type %d not supported!", type); - return -1; - } -} /** CLI command to add/del forwarding entry. */ static clib_error_t * @@ -533,6 +71,10 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, { vrf_set = 1; } + else if (unformat (line_input, "bd %u", &vrf)) + { + vrf_set = 1; + } else if (unformat (line_input, "negative action %U", unformat_negative_mapping_action, &action)) { @@ -627,72 +169,6 @@ VLIB_CLI_COMMAND (lisp_gpe_add_del_fwd_entry_command, static) = { }; /* *INDENT-ON* */ -static u8 * -format_lisp_fwd_path (u8 * s, va_list ap) -{ - lisp_fwd_path_t *lfp = va_arg (ap, lisp_fwd_path_t *); - - s = format (s, "pirority:%d weight:%d ", lfp->priority, lfp->weight); - s = format (s, "adj:[%U]\n", - format_lisp_gpe_adjacency, - lisp_gpe_adjacency_get (lfp->lisp_adj), - LISP_GPE_ADJ_FORMAT_FLAG_NONE); - - return (s); -} - -static u8 * -format_lisp_gpe_fwd_entry (u8 * s, va_list ap) -{ - lisp_fwd_entry_t *lfe = va_arg (ap, lisp_fwd_entry_t *); - - s = format (s, "VNI:%d VRF:%d EID: %U -> %U", - lfe->key->vni, lfe->eid_table_id, - format_fid_address, &lfe->key->lcl, - format_fid_address, &lfe->key->rmt); - if (LISP_FWD_ENTRY_TYPE_NEGATIVE == lfe->type) - { - s = format (s, "\n Negative - action:%U", - format_negative_mapping_action, lfe->action); - } - else - { - lisp_fwd_path_t *path; - - s = format (s, "\n via:"); - vec_foreach (path, lfe->paths) - { - s = format (s, "\n %U", format_lisp_fwd_path, path); - } - } - - return (s); -} - -static clib_error_t * -lisp_gpe_fwd_entry_show (vlib_main_t * vm, - unformat_input_t * input, vlib_cli_command_t * cmd) -{ - lisp_fwd_entry_t *lfe; - -/* *INDENT-OFF* */ - pool_foreach (lfe, lisp_fwd_entry_pool, - ({ - vlib_cli_output (vm, "%U", format_lisp_gpe_fwd_entry, lfe); - })); -/* *INDENT-ON* */ - - return (NULL); -} - -/* *INDENT-OFF* */ -VLIB_CLI_COMMAND (lisp_gpe_fwd_entry_show_command, static) = { - .path = "show lisp gpe entry", - .short_help = "show lisp gpe entry vni <vni> vrf <vrf> [leid <leid>] reid <reid>", - .function = lisp_gpe_fwd_entry_show, -}; -/* *INDENT-ON* */ - /** Check if LISP-GPE is enabled. */ u8 vnet_lisp_gpe_enable_disable_status (void) @@ -714,58 +190,12 @@ vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a) } else { - CLIB_UNUSED (uword * val); - hash_pair_t *p; - u32 *dp_tables = 0, *dp_table; - vnet_lisp_gpe_add_del_iface_args_t _ai, *ai = &_ai; - lisp_fwd_entry_t *lfe; - /* remove all entries */ - /* *INDENT-OFF* */ - pool_foreach (lfe, lisp_fwd_entry_pool, - ({ - del_ip_fwd_entry_i (lfe); - })); - /* *INDENT-ON* */ + vnet_lisp_gpe_fwd_entry_flush (); /* disable all l3 ifaces */ + lisp_gpe_tenant_flush (); - /* *INDENT-OFF* */ - hash_foreach_pair(p, lgm->l3_ifaces.hw_if_index_by_dp_table, ({ - vec_add1(dp_tables, p->key); - })); - /* *INDENT-ON* */ - - vec_foreach (dp_table, dp_tables) - { - ai->is_add = 0; - ai->table_id = dp_table[0]; - ai->is_l2 = 0; - - /* disables interface and removes defaults */ - vnet_lisp_gpe_add_del_iface (ai, 0); - } - - /* disable all l2 ifaces */ - _vec_len (dp_tables) = 0; - - /* *INDENT-OFF* */ - hash_foreach_pair(p, lgm->l2_ifaces.hw_if_index_by_dp_table, ({ - vec_add1(dp_tables, p->key); - })); - /* *INDENT-ON* */ - - vec_foreach (dp_table, dp_tables) - { - ai->is_add = 0; - ai->bd_id = dp_table[0]; - ai->is_l2 = 1; - - /* disables interface and removes defaults */ - vnet_lisp_gpe_add_del_iface (ai, 0); - } - - vec_free (dp_tables); lgm->is_en = 0; } @@ -876,11 +306,8 @@ lisp_gpe_init (vlib_main_t * vm) lgm->lm4 = &ip4_main.lookup_main; lgm->lm6 = &ip6_main.lookup_main; - lisp_gpe_fwd_entries = hash_create_mem (0, - sizeof (lisp_gpe_fwd_entry_key_t), - sizeof (uword)); - - l2_fib_init (lgm); + lgm->lisp_gpe_fwd_entries = + hash_create_mem (0, sizeof (lisp_gpe_fwd_entry_key_t), sizeof (uword)); udp_register_dst_port (vm, UDP_DST_PORT_lisp_gpe, lisp_gpe_ip4_input_node.index, 1 /* is_ip4 */ ); |