From bb5c22f1b6f48cb53fa2d0e5abcac7248318f8e0 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 2 Aug 2016 02:31:03 +0200 Subject: LISP multihoming API changes and cleanup Change-Id: I106352a6da0fad2b91dc8593f8d6d664af3113a8 Signed-off-by: Florin Coras --- vnet/vnet/lisp-cp/control.c | 24 ++--- vnet/vnet/lisp-cp/control.h | 3 +- vnet/vnet/lisp-cp/lisp_types.c | 5 +- vnet/vnet/lisp-cp/lisp_types.h | 21 ++++ vnet/vnet/lisp-gpe/lisp_gpe.c | 229 +++++++++++++++++++++-------------------- vnet/vnet/lisp-gpe/lisp_gpe.h | 14 +-- 6 files changed, 155 insertions(+), 141 deletions(-) (limited to 'vnet') diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index 9b86da5c8f1..4424b60199a 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -221,8 +221,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) /* delete dp fwd entry */ u32 sw_if_index; a->is_add = 0; - a->rmt_loc = fe->dst_loc; - a->lcl_loc = fe->src_loc; + a->locator_pairs = fe->locator_pairs; a->vni = gid_address_vni(&a->rmt_eid); gid_address_copy(&a->rmt_eid, &fe->deid); @@ -230,6 +229,7 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) /* delete entry in fwd table */ hash_unset(lcm->fwd_entry_by_mapping_index, dst_map_index); + vec_free(fe->locator_pairs); pool_put(lcm->fwd_entry_pool, fe); } @@ -240,13 +240,14 @@ dp_del_fwd_entry (lisp_cp_main_t * lcm, u32 src_map_index, u32 dst_map_index) */ static u32 get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map, - ip_address_t * lcl_loc, ip_address_t * rmt_loc) + locator_pair_t ** locator_pairs) { u32 i, minp = ~0, limitp = 0, li, check_index = 0, done = 0, esi; locator_set_t * rmt_ls, * lcl_ls; ip_address_t _lcl, * lcl = &_lcl; locator_t * l, * rmt = 0; uword * checked = 0; + locator_pair_t pair; rmt_ls = pool_elt_at_index(lcm->locator_set_pool, rmt_map->locator_set_index); lcl_ls = pool_elt_at_index(lcm->locator_set_pool, lcl_map->locator_set_index); @@ -299,8 +300,10 @@ get_locator_pair (lisp_cp_main_t* lcm, mapping_t * lcl_map, mapping_t * rmt_map, gid_address_ip_version(&rmt->address), lcl)) continue; - ip_address_copy(rmt_loc, &gid_address_ip(&rmt->address)); - ip_address_copy(lcl_loc, lcl); + memset(&pair, 0, sizeof(pair)); + ip_address_copy(&pair.rmt_loc, &gid_address_ip(&rmt->address)); + ip_address_copy(&pair.lcl_loc, lcl); + vec_add1(locator_pairs[0], pair); done = 2; } } @@ -366,7 +369,7 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index) } /* find best locator pair that 1) verifies LISP policy 2) are connected */ - if (0 == get_locator_pair (lcm, src_map, dst_map, &a->lcl_loc, &a->rmt_loc)) + if (0 == get_locator_pair (lcm, src_map, dst_map, &a->locator_pairs)) { /* negative entry */ a->is_negative = 1; @@ -382,8 +385,7 @@ dp_add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index) /* add tunnel to fwd entry table XXX check return value from DP insertion */ pool_get (lcm->fwd_entry_pool, fe); - fe->dst_loc = a->rmt_loc; - fe->src_loc = a->lcl_loc; + fe->locator_pairs = a->locator_pairs; gid_address_copy (&fe->deid, &a->rmt_eid); hash_set (lcm->fwd_entry_by_mapping_index, dst_map_index, fe - lcm->fwd_entry_pool); @@ -985,7 +987,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, is_add = 0; else if (unformat (line_input, "add")) ; - else if (unformat (line_input, "%U", unformat_gid_address, &eid)) + else if (unformat (line_input, "eid %U", unformat_gid_address, &eid)) eid_set = 1; else if (unformat (line_input, "vni %u", &vni)) { @@ -1002,7 +1004,7 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, curr_rloc->weight = w; } else if (unformat (line_input, "rloc %U", unformat_ip_address, - &rloc.address)) + &gid_address_ip(&rloc.address))) { vec_add1 (rlocs, rloc); curr_rloc = &rlocs[vec_len (rlocs) - 1]; @@ -1025,8 +1027,6 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, if (!del_all) { - - if (is_add && (~0 == action) && 0 == vec_len (rlocs)) { diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h index 74ade39cc58..ff722feb8f4 100644 --- a/vnet/vnet/lisp-cp/control.h +++ b/vnet/vnet/lisp-cp/control.h @@ -30,8 +30,7 @@ typedef struct { gid_address_t seid; gid_address_t deid; - ip_address_t src_loc; - ip_address_t dst_loc; + locator_pair_t * locator_pairs; } fwd_entry_t; typedef enum diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c index e62edb93875..ad420a46c7c 100644 --- a/vnet/vnet/lisp-cp/lisp_types.c +++ b/vnet/vnet/lisp-cp/lisp_types.c @@ -210,16 +210,15 @@ unformat_gid_address (unformat_input_t * input, va_list * args) ip_prefix_t ippref; memset (&ippref, 0, sizeof (ippref)); - memset(a, 0, sizeof(a[0])); if (unformat (input, "%U", unformat_ip_prefix, &ippref)) { - clib_memcpy (&gid_address_ippref(a), &ippref, sizeof(ippref)); + ip_prefix_copy (&gid_address_ippref(a), &ippref); gid_address_type(a) = GID_ADDR_IP_PREFIX; } else if (unformat (input, "%U", unformat_mac_address, mac)) { - clib_memcpy (gid_address_mac(a), mac, sizeof(mac)); + mac_copy (gid_address_mac(a), mac); gid_address_type(a) = GID_ADDR_MAC; } else if (unformat (input, "[%d]", &vni)) diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h index b1b4b9db3f0..6542b009ffd 100644 --- a/vnet/vnet/lisp-cp/lisp_types.h +++ b/vnet/vnet/lisp-cp/lisp_types.h @@ -252,4 +252,25 @@ typedef struct uword unformat_negative_mapping_action (unformat_input_t * input, va_list * args); +/* dp works with a subset of ids */ +typedef struct lisp_dp_address +{ + union + { + ip_prefix_t ippref; + u8 mac[6]; + }; + u8 type; +} dp_address_t; + +typedef struct locator_pair +{ + /* local and remote locators (underlay attachment points) */ + ip_address_t lcl_loc; + ip_address_t rmt_loc; + + u8 priority; + u8 weight; +} locator_pair_t; + #endif /* VNET_LISP_GPE_LISP_TYPES_H_ */ diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.c b/vnet/vnet/lisp-gpe/lisp_gpe.c index 812e0aed7ad..ae3a5e0f7fd 100644 --- a/vnet/vnet/lisp-gpe/lisp_gpe.c +++ b/vnet/vnet/lisp-gpe/lisp_gpe.c @@ -113,12 +113,10 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2, /* fill in the key's remote eid */ if (!is_l2) - ip_prefix_copy (&key.rmt_ippref, &gid_address_ippref(&a->rmt_eid)); + ip_prefix_copy (&key.rmt.ippref, &gid_address_ippref(&a->rmt_eid)); else - mac_copy (&key.rmt_mac, &gid_address_mac(&a->rmt_eid)); + mac_copy (&key.rmt.mac, &gid_address_mac(&a->rmt_eid)); - - ip_address_copy(&key.rmt_loc, &a->rmt_loc); key.vni = clib_host_to_net_u32 (a->vni); p = mhash_get (&lgm->lisp_gpe_tunnel_by_key, &key); @@ -140,8 +138,12 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2, foreach_copy_field; #undef _ - ip_address_copy(&t->src, &a->lcl_loc); - ip_address_copy(&t->dst, &a->rmt_loc); + /* TODO multihoming */ + if (!a->is_negative) + { + ip_address_copy (&t->src, &a->locator_pairs[0].lcl_loc); + ip_address_copy (&t->dst, &a->locator_pairs[0].rmt_loc); + } /* if vni is non-default */ if (a->vni) @@ -152,7 +154,7 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2, /* next proto */ if (!is_l2) - t->next_protocol = ip_prefix_version(&key.rmt_ippref) == IP4 ? + t->next_protocol = ip_prefix_version(&key.rmt.ippref) == IP4 ? LISP_GPE_NEXT_PROTO_IP4 : LISP_GPE_NEXT_PROTO_IP6; else t->next_protocol = LISP_GPE_NEXT_PROTO_ETHERNET; @@ -194,94 +196,29 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, u8 is_l2, } static int -add_del_negative_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) -{ - ip_adjacency_t adj; - ip_prefix_t * dpref = &gid_address_ippref(&a->rmt_eid); - ip_prefix_t * spref = &gid_address_ippref(&a->lcl_eid); - - /* setup adjacency for eid */ - memset (&adj, 0, sizeof(adj)); - adj.n_adj = 1; - - /* fill in 'legal' data to avoid issues */ - adj.lookup_next_index = (ip_prefix_version(dpref) == IP4) ? - lgm->ip4_lookup_next_lgpe_ip4_lookup : - lgm->ip6_lookup_next_lgpe_ip6_lookup; - - adj.rewrite_header.sw_if_index = ~0; - adj.rewrite_header.next_index = ~0; - - switch (a->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 */ - adj.explicit_fib_index = (ip_prefix_version(dpref) == IP4) ? - LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP: - LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP; - /* add/delete route for prefix */ - return ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj, - a->is_add); - case LISP_DROP: - /* for drop fwd entries, just add route, no need to add encap tunnel */ - adj.explicit_fib_index = (ip_prefix_version(dpref) == IP4 ? - LGPE_IP4_LOOKUP_NEXT_DROP : LGPE_IP6_LOOKUP_NEXT_DROP); - - /* add/delete route for prefix */ - return ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj, - a->is_add); - default: - return -1; - } -} - -static int -add_del_ip_fwd_entry (lisp_gpe_main_t * lgm, - vnet_lisp_gpe_add_del_fwd_entry_args_t * a) +build_ip_adjacency (lisp_gpe_main_t * lgm, ip_adjacency_t * adj, u32 table_id, + u32 vni, u32 tun_index, u8 is_negative, u8 action, + u8 ip_ver) { - ip_adjacency_t adj, * adjp; - u32 adj_index, rv, tun_index = ~0; - ip_prefix_t * dpref, * spref; uword * lookup_next_index, * lgpe_sw_if_index, * lnip; - u8 ip_ver; - - /* treat negative fwd entries separately */ - if (a->is_negative) - return add_del_negative_ip_fwd_entry (lgm, a); - - /* add/del tunnel to tunnels pool and prepares rewrite */ - rv = add_del_ip_tunnel (a, 0 /* is_l2 */, &tun_index); - if (rv) - return rv; - - dpref = &gid_address_ippref(&a->rmt_eid); - spref = &gid_address_ippref(&a->lcl_eid); - ip_ver = ip_prefix_version(dpref); - - /* setup adjacency for eid */ - memset (&adj, 0, sizeof(adj)); - adj.n_adj = 1; + memset(adj, 0, sizeof(adj[0])); + adj->n_adj = 1; /* fill in lookup_next_index with a 'legal' value to avoid problems */ - adj.lookup_next_index = (ip_ver == IP4) ? + adj->lookup_next_index = (ip_ver == IP4) ? lgm->ip4_lookup_next_lgpe_ip4_lookup : lgm->ip6_lookup_next_lgpe_ip6_lookup; - if (a->is_add) + /* positive mapping */ + if (!is_negative) { /* send packets that hit this adj to lisp-gpe interface output node in * requested vrf. */ lnip = (ip_ver == IP4) ? lgm->lgpe_ip4_lookup_next_index_by_table_id : lgm->lgpe_ip6_lookup_next_index_by_table_id; - lookup_next_index = hash_get(lnip, a->table_id); - lgpe_sw_if_index = hash_get(lgm->l3_ifaces.sw_if_index_by_vni, a->vni); + lookup_next_index = hash_get(lnip, table_id); + lgpe_sw_if_index = hash_get(lgm->l3_ifaces.sw_if_index_by_vni, vni); /* the assumption is that the interface must've been created before * programming the dp */ @@ -290,19 +227,84 @@ add_del_ip_fwd_entry (lisp_gpe_main_t * lgm, /* hijack explicit fib index to store lisp interface node index and * if_address_index for the tunnel index */ - adj.explicit_fib_index = lookup_next_index[0]; - adj.if_address_index = tun_index; - adj.rewrite_header.sw_if_index = lgpe_sw_if_index[0]; + adj->explicit_fib_index = lookup_next_index[0]; + adj->if_address_index = tun_index; + adj->rewrite_header.sw_if_index = lgpe_sw_if_index[0]; + } + /* negative mapping */ + else + { + adj->rewrite_header.sw_if_index = ~0; + adj->rewrite_header.next_index = ~0; + + switch (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 */ + adj->explicit_fib_index = (ip_ver == IP4) ? + LGPE_IP4_LOOKUP_NEXT_LISP_CP_LOOKUP: + LGPE_IP6_LOOKUP_NEXT_LISP_CP_LOOKUP; + break; + case LISP_DROP: + /* for drop fwd entries, just add route, no need to add encap tunnel */ + adj->explicit_fib_index = (ip_ver == IP4 ? + LGPE_IP4_LOOKUP_NEXT_DROP : LGPE_IP6_LOOKUP_NEXT_DROP); + break; + default: + return -1; + } + } + return 0; +} + +static int +add_del_ip_fwd_entry (lisp_gpe_main_t * lgm, + vnet_lisp_gpe_add_del_fwd_entry_args_t * a) +{ + ip_adjacency_t adj, * adjp; + u32 rv, tun_index = ~0; + ip_prefix_t * rmt_pref, * lcl_pref; + u8 ip_ver; + + rmt_pref = &gid_address_ippref(&a->rmt_eid); + lcl_pref = &gid_address_ippref(&a->lcl_eid); + ip_ver = ip_prefix_version(rmt_pref); + + /* add/del tunnel to tunnels pool and prepares rewrite */ + if (!a->is_negative) + { + rv = add_del_ip_tunnel (a, 0 /* is_l2 */, &tun_index); + if (rv) + { + clib_warning ("failed to build tunnel!"); + return rv; + } } - /* add/delete route for prefix */ - rv = ip_sd_fib_add_del_route (lgm, dpref, spref, a->table_id, &adj, + /* setup adjacency for eid */ + rv = build_ip_adjacency (lgm, &adj, a->table_id, a->vni, tun_index, + a->is_negative, a->action, ip_ver); + + /* add/delete route for eid */ + rv |= ip_sd_fib_add_del_route (lgm, rmt_pref, lcl_pref, a->table_id, &adj, a->is_add); + if (rv) + { + clib_warning ("failed to insert route for tunnel!"); + return rv; + } + /* check that everything worked */ if (CLIB_DEBUG && a->is_add) { - adj_index = ip_sd_fib_get_route (lgm, dpref, spref, a->table_id); + u32 adj_index; + adj_index = ip_sd_fib_get_route (lgm, rmt_pref, lcl_pref, a->table_id); ASSERT(adj_index != 0); adjp = ip_get_adjacency ((ip_ver == IP4) ? lgm->lm4 : lgm->lm6, @@ -438,11 +440,12 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, { unformat_input_t _line_input, * line_input = &_line_input; u8 is_add = 1; - ip_address_t lloc, rloc, *llocs = 0, *rlocs = 0; + ip_address_t lloc, rloc; clib_error_t * error = 0; gid_address_t _reid, * reid = &_reid, _leid, * leid = &_leid; u8 reid_set = 0, leid_set = 0, is_negative = 0, vrf_set = 0, vni_set = 0; - u32 vni, vrf, action = ~0; + u32 vni, vrf, action = ~0, p, w; + locator_pair_t pair, * pairs = 0; int rv; /* Get a line of input. */ @@ -480,13 +483,15 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, { is_negative = 1; } - else if (unformat (line_input, "lloc %U rloc %U", + else if (unformat (line_input, "loc-pair %U %U p %d w %d", unformat_ip_address, &lloc, - unformat_ip_address, &rloc)) + unformat_ip_address, &rloc, &p, &w)) { - /* TODO: support p and w */ - vec_add1 (llocs, lloc); - vec_add1 (rlocs, rloc); + pair.lcl_loc = lloc; + pair.rmt_loc = rloc; + pair.priority = p; + pair.weight = w; + vec_add1(pairs, pair); } else { @@ -518,17 +523,11 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, } else { - if (vec_len (llocs) == 0) + if (vec_len (pairs) == 0) { error = clib_error_return (0, "expected ip4/ip6 locators."); goto done; } - - if (vec_len (llocs) != 1) - { - error = clib_error_return (0, "multihoming not supported for now!"); - goto done; - } } @@ -550,12 +549,7 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, a->table_id = vrf; gid_address_copy(&a->lcl_eid, leid); gid_address_copy(&a->rmt_eid, reid); - - if (!is_negative) - { - a->lcl_loc = llocs[0]; - a->rmt_loc = rlocs[0]; - } + a->locator_pairs = pairs; rv = vnet_lisp_gpe_add_del_fwd_entry (a, 0); if (0 != rv) @@ -565,8 +559,7 @@ lisp_gpe_add_del_fwd_entry_command_fn (vlib_main_t * vm, } done: - vec_free(llocs); - vec_free(rlocs); + vec_free(pairs); return error; } @@ -699,12 +692,20 @@ vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a) vec_add1(tunnels, tunnel[0]); })); - vec_foreach(tunnel, tunnels) { + vec_foreach(tunnel, tunnels) + { memset(at, 0, sizeof(at[0])); at->is_add = 0; - gid_address_type(&at->rmt_eid) = GID_ADDR_IP_PREFIX; - ip_prefix_copy(&gid_address_ippref(&at->rmt_eid), &tunnel->rmt_ippref); - ip_address_copy(&at->rmt_loc, &tunnel->rmt_loc); + if (tunnel->rmt.type == GID_ADDR_IP_PREFIX) + { + gid_address_type(&at->rmt_eid) = GID_ADDR_IP_PREFIX; + ip_prefix_copy(&gid_address_ippref(&at->rmt_eid), &tunnel->rmt.ippref); + } + else + { + gid_address_type(&at->rmt_eid) = GID_ADDR_MAC; + mac_copy(&gid_address_mac(&at->rmt_eid), &tunnel->rmt.mac); + } vnet_lisp_gpe_add_del_fwd_entry (at, 0); } vec_free(tunnels); diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.h b/vnet/vnet/lisp-gpe/lisp_gpe.h index c3f024229e3..f3e75772ee7 100644 --- a/vnet/vnet/lisp-gpe/lisp_gpe.h +++ b/vnet/vnet/lisp-gpe/lisp_gpe.h @@ -46,13 +46,8 @@ typedef struct { struct { - /* within the dp only ip and mac can be eids */ - union - { - ip_prefix_t rmt_ippref; - u8 rmt_mac[6]; - }; - ip_address_t rmt_loc; + dp_address_t rmt; + dp_address_t lcl; u32 vni; }; u8 as_u8[40]; @@ -246,9 +241,8 @@ typedef struct gid_address_t lcl_eid; gid_address_t rmt_eid; - /* local and remote locators (underlay attachment points) */ - ip_address_t lcl_loc; - ip_address_t rmt_loc; + /* vector of locator pairs */ + locator_pair_t * locator_pairs; /* FIB indices to lookup remote locator at encap and inner IP at decap */ u32 encap_fib_index; -- cgit 1.2.3-korg