From 324112fad06e0461958f22827f944595466e1891 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Thu, 2 Jun 2016 16:07:38 +0200 Subject: LISP EID virtualization support Change-Id: I892c001cfdff9d8d93e646641d96520beb3c6265 Signed-off-by: Filip Tehlar --- vnet/test/lisp-cp/test_cp_serdes.c | 53 +++-------- vnet/test/lisp-cp/test_lisp_types.c | 96 +++---------------- vnet/vnet/lisp-cp/control.c | 179 +++++++++++++++++++++++++++++++++--- vnet/vnet/lisp-cp/control.h | 5 + vnet/vnet/lisp-cp/lisp_types.c | 97 +++++++++++++------ vnet/vnet/lisp-cp/lisp_types.h | 28 +++--- vnet/vnet/lisp-gpe/decap.c | 9 +- vnet/vnet/lisp-gpe/lisp_gpe.c | 7 ++ 8 files changed, 298 insertions(+), 176 deletions(-) (limited to 'vnet') diff --git a/vnet/test/lisp-cp/test_cp_serdes.c b/vnet/test/lisp-cp/test_cp_serdes.c index 2ca391e35b7..7bfe6e35378 100644 --- a/vnet/test/lisp-cp/test_cp_serdes.c +++ b/vnet/test/lisp-cp/test_cp_serdes.c @@ -183,6 +183,8 @@ build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b, u8 is_smr_invoked = 1; u64 nonce = 0; map_request_hdr_t * h = 0; + memset (deid, 0, sizeof (deid[0])); + memset (seid, 0, sizeof (seid[0])); gid_address_type (seid) = GID_ADDR_IP_PREFIX; ip_address_t * ip_addr = &gid_address_ip (seid); @@ -205,6 +207,7 @@ static void generate_rlocs (gid_address_t **rlocs, u32 * count) { gid_address_t gid_addr_data, * gid_addr = &gid_addr_data; + memset (gid_addr, 0, sizeof (gid_addr[0])); ip_address_t * addr = &gid_address_ip (gid_addr); gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX; @@ -277,34 +280,20 @@ static clib_error_t * test_lisp_msg_put_mreq_with_lcaf () clib_error_t * error = 0; map_request_hdr_t *h = 0; gid_address_t * rlocs = 0; - gid_address_t rloc; ip_prefix_t ippref; ip_prefix_version (&ippref) = IP4; ip4_address_t * ip = &ip_prefix_v4 (&ippref); ip->as_u32 = 0x11223344; - gid_address_t gid1 = + gid_address_t g = { .type = GID_ADDR_IP_PREFIX, - .ippref = ippref + .ippref = ippref, + .vni = 0x90919293, + .vni_mask = 0x17 }; - - lcaf_t lcaf1 = - { - .type = LCAF_INSTANCE_ID, - .uni = - { - .vni_mask_len = 0x17, - .vni = 0x90919293, - .gid_addr = &gid1 - } - }; - - gid_address_type (&rloc) = GID_ADDR_LCAF; - gid_address_lcaf (&rloc) = lcaf1; - - vec_add1 (rlocs, rloc); + vec_add1 (rlocs, g); u8 * data = clib_mem_alloc (500); memset (data, 0, 500); @@ -482,16 +471,9 @@ test_lisp_parse_lcaf () _assert (locs[0].mpriority == 0xc); _assert (locs[0].mweight == 0xd); - /* check LCAF header data */ - lcaf_t * lcaf = &gid_address_lcaf (&locs[0].address); - _assert (gid_address_type (&locs[0].address) == GID_ADDR_LCAF); - _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID); - vni_t * v = (vni_t *) lcaf; - _assert (vni_vni (v) == 0x09); - - gid_address_t * nested_gid = vni_gid (v); - _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid)); - ip_prefix_t * ip_pref = &gid_address_ippref (nested_gid); + _assert (gid_address_type (&locs[0].address) == GID_ADDR_IP_PREFIX); + _assert (gid_address_vni (&locs[0].address) == 0x09); + ip_prefix_t * ip_pref = &gid_address_ippref (&locs[0].address); _assert (IP4 == ip_prefix_version (ip_pref)); /* 2nd locator - LCAF entry with ipv6 address */ @@ -501,16 +483,9 @@ test_lisp_parse_lcaf () _assert (locs[1].mpriority == 0x5); _assert (locs[1].mweight == 0x4); - /* LCAF header */ - _assert (gid_address_type (&locs[1].address) == GID_ADDR_LCAF); - lcaf = &gid_address_lcaf (&locs[1].address); - _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID); - v = (vni_t *) lcaf; - _assert (vni_vni (v) == 0x22446688); - - nested_gid = vni_gid (v); - _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid)); - ip_pref = &gid_address_ippref (nested_gid); + _assert (gid_address_type (&locs[1].address) == GID_ADDR_IP_PREFIX); + _assert (0x22446688 == gid_address_vni (&locs[1].address)); + ip_pref = &gid_address_ippref (&locs[1].address); _assert (IP6 == ip_prefix_version (ip_pref)); /* 3rd locator - simple ipv4 address */ diff --git a/vnet/test/lisp-cp/test_lisp_types.c b/vnet/test/lisp-cp/test_lisp_types.c index 5d4e2a80c60..4291bbebb20 100644 --- a/vnet/test/lisp-cp/test_lisp_types.c +++ b/vnet/test/lisp-cp/test_lisp_types.c @@ -154,21 +154,19 @@ static clib_error_t * test_gid_parse_lcaf () _assert (18 == len); gid_address_copy (gid_addr_copy, gid_addr); _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr)); + _assert (GID_ADDR_IP_PREFIX == gid_address_type (gid_addr)); + _assert (9 == gid_address_vni (gid_addr)); + _assert (0x18 == gid_address_vni_mask (gid_addr)); + _assert (0xddccbb10 == gid_addr->ippref.addr.ip.v4.as_u32); - lcaf_t * lcaf = &gid_address_lcaf (gid_addr_copy); - vni_t * vni = (vni_t *) lcaf; - _assert (lcaf->type == LCAF_INSTANCE_ID); - _assert (vni->vni == 9); - _assert (vni->vni_mask_len == 0x18); - - gid_address_t * g = vni_gid (vni); - _assert (gid_address_type (g) == GID_ADDR_IP_PREFIX); done: gid_address_free (gid_addr); gid_address_free (gid_addr_copy); return error; } +/* recursive LCAFs are not supported */ +#if 0 static clib_error_t * test_gid_parse_lcaf_complex () { clib_error_t * error = 0; @@ -262,59 +260,7 @@ done: gid_address_free (gid_addr_copy); return error; } - -static clib_error_t * test_format_unformat_gid_address (void) -{ - u8 * s = 0; - clib_error_t * error = 0; - unformat_input_t _input; - unformat_input_t * input = &_input; - gid_address_t _gid_addr, * gid_addr = &_gid_addr; - gid_address_t unformated_gid; - - /* format/unformat IPv4 global ID address */ - gid_address_type(gid_addr) = GID_ADDR_IP_PREFIX; - gid_address_ippref_len(gid_addr) = 24; - ip_prefix_version(&gid_addr->ippref) = IP4; - gid_addr->ippref.addr.ip.v4.as_u32 = 0x20304050; - - s = format(0, "%U", format_gid_address, gid_addr); - vec_add1(s, 0); - unformat_init_string(input, (char *)s, vec_len(s)); - - _assert (unformat(input, "%U", - unformat_gid_address, &unformated_gid)); - _assert (0 == gid_address_cmp (&unformated_gid, gid_addr)); - - unformat_free(input); - vec_free(s); - s = 0; - - /* format/unformat IPv6 global ID address */ - gid_address_type(gid_addr) = GID_ADDR_IP_PREFIX; - gid_address_ippref_len(gid_addr) = 64; - ip_prefix_version(&gid_addr->ippref) = IP6; - u8 ipv6[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf}; - clib_memcpy(gid_addr->ippref.addr.ip.v6.as_u8, ipv6, sizeof(ipv6)); - - s = format(0, "%U", format_gid_address, gid_addr); - vec_add1(s, 0); - unformat_init_string(input, (char *)s, vec_len(s)); - - _assert (unformat (input, "%U", unformat_gid_address, - &unformated_gid)); - _assert (0 == gid_address_cmp(&unformated_gid, gid_addr)); - - /* test address copy */ - gid_address_t gid_addr_copy; - gid_address_copy(&gid_addr_copy, gid_addr); - _assert (0 == gid_address_cmp (&gid_addr_copy, gid_addr)); - -done: - unformat_free(input); - vec_free(s); - return error; -} +#endif #if 0 /* uncomment this once VNI is supported */ static clib_error_t * test_write_mac_in_lcaf (void) @@ -393,34 +339,22 @@ static clib_error_t * test_gid_address_write (void) memset(b, 0, 500); ip_prefix_version (ippref) = IP4; + ip_prefix_len (ippref) = 9; ip4_address_t * ip4 = &ip_prefix_v4 (ippref); ip4->as_u32 = 0xaabbccdd; - gid_address_t nested_gid = + gid_address_t g = { .ippref = ippref[0], .type = GID_ADDR_IP_PREFIX, + .vni = 0x01020304, + .vni_mask = 0x18 }; - lcaf_t lcaf = - { - .type = LCAF_INSTANCE_ID, - .uni = - { - .vni_mask_len = 0x18, - .vni = 0x01020304, - .gid_addr = &nested_gid - } - }; - - gid_address_t gid = - { - .type = GID_ADDR_LCAF, - .lcaf = lcaf - }; - _assert (18 == gid_address_size_to_put (&gid)); + _assert (18 == gid_address_size_to_put (&g)); + _assert (gid_address_len (&g) == 9); - u16 write_len = gid_address_put (b, &gid); + u16 write_len = gid_address_put (b, &g); _assert (18 == write_len); u8 expected_gid_data[] = @@ -443,12 +377,10 @@ done: } #define foreach_test_case \ - _(format_unformat_gid_address) \ _(locator_type) \ _(gid_parse_ip_pref) \ _(gid_parse_mac) \ _(gid_parse_lcaf) \ - _(gid_parse_lcaf_complex) \ _(mac_address_write) \ _(gid_address_write) diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index 54a83f48752..8b3d25f8dfa 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -47,13 +47,13 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, if (mi != GID_LOOKUP_MISS && !gid_address_cmp (&old_map->eid, &a->deid)) { - clib_warning("eid %U found in the eid-table", format_ip_address, + clib_warning ("eid %U found in the eid-table", format_gid_address, &a->deid); return VNET_API_ERROR_VALUE_EXIST; } pool_get(lcm->mapping_pool, m); - m->eid = a->deid; + gid_address_copy (&m->eid, &a->deid); m->locator_set_index = a->locator_set_index; m->ttl = a->ttl; m->action = a->action; @@ -87,7 +87,7 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, { if (mi == GID_LOOKUP_MISS) { - clib_warning("eid %U not found in the eid-table", format_ip_address, + clib_warning("eid %U not found in the eid-table", format_gid_address, &a->deid); return VNET_API_ERROR_INVALID_VALUE; } @@ -123,6 +123,7 @@ vnet_lisp_add_del_mapping (vnet_lisp_add_del_mapping_args_t * a, /* remove mapping from dictionary */ gid_dictionary_add_del (&lcm->mapping_index_by_gid, &a->deid, 0, 0); + gid_address_free (&m->eid); pool_put_index (lcm->mapping_pool, mi); } @@ -217,9 +218,9 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, uword * p; vnet_lisp_add_del_mapping_args_t _a, * a = &_a; int rv = 0; + u32 vni = 0; - gid_address_type (&eid) = GID_ADDR_IP_PREFIX; - + memset (&eid, 0, sizeof (eid)); /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) return 0; @@ -230,6 +231,8 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, is_add = 1; else if (unformat (line_input, "del")) is_add = 0; + else if (unformat (line_input, "vni %d", &vni)) + gid_address_vni (&eid) = vni; else if (unformat (line_input, "eid %U", unformat_ip_prefix, prefp)) { vec_add1(eids, eid); @@ -251,8 +254,9 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, goto done; } } - /* XXX treat batch configuration */ + + gid_address_type (&eid) = GID_ADDR_IP_PREFIX; a->deid = eid; a->is_add = is_add; a->locator_set_index = locator_set_index; @@ -268,15 +272,99 @@ lisp_add_del_local_eid_command_fn (vlib_main_t * vm, unformat_input_t * input, vec_free(eids); if (locator_set_name) vec_free (locator_set_name); + gid_address_free (&a->deid); return error; } VLIB_CLI_COMMAND (lisp_add_del_local_eid_command) = { .path = "lisp eid-table", - .short_help = "lisp eid-table add/del eid locator-set ", + .short_help = "lisp eid-table add/del [vni ] eid " + "locator-set ", .function = lisp_add_del_local_eid_command_fn, }; +int +vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add) +{ + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); + uword * table_id, * vnip; + + if (vnet_lisp_enable_disable_status () == 0) + { + clib_warning ("LISP is disabled!"); + return -1; + } + + if (vni == 0 || vrf == 0) + { + clib_warning ("can't add/del default vni-vrf mapping!"); + return -1; + } + + table_id = hash_get (lcm->table_id_by_vni, vni); + vnip = hash_get (lcm->vni_by_table_id, vrf); + + if (is_add) + { + if (table_id || vnip) + { + clib_warning ("vni %d or vrf %d already used in any vrf/vni " + "mapping!", vni, vrf); + return -1; + } + hash_set (lcm->table_id_by_vni, vni, vrf); + hash_set (lcm->vni_by_table_id, vrf, vni); + } + else + { + if (!table_id || !vnip) + { + clib_warning ("vni %d or vrf %d not used in any vrf/vni! " + "mapping!", vni, vrf); + return -1; + } + hash_unset (lcm->table_id_by_vni, vni); + hash_unset (lcm->vni_by_table_id, vrf); + } + return 0; +} + +static clib_error_t * +lisp_eid_table_map_command_fn (vlib_main_t * vm, + unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + u8 is_add = 1; + u32 vni = 0, vrf = 0; + unformat_input_t _line_input, * line_input = &_line_input; + + /* Get a line of input. */ + if (! unformat_user (input, unformat_line_input, line_input)) + return 0; + + while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT) + { + if (unformat (line_input, "del")) + is_add = 0; + else if (unformat (line_input, "vni %d", &vni)) + ; + else if (unformat (line_input, "vrf %d", &vrf)) + ; + else + { + return unformat_parse_error (line_input); + } + } + vnet_lisp_eid_table_map (vni, vrf, is_add); + return 0; +} + +VLIB_CLI_COMMAND (lisp_eid_table_map_command) = { + .path = "lisp eid-table map", + .short_help = "lisp eid-table map [del] vni vrf ", + .function = lisp_eid_table_map_command_fn, +}; + static int lisp_add_del_negative_static_mapping (gid_address_t * deid, vnet_lisp_add_del_locator_set_args_t * ls, u8 action, u8 is_add) @@ -605,8 +693,8 @@ lisp_add_del_remote_mapping_command_fn (vlib_main_t * vm, } else if (unformat (line_input, "vni %u", &vni)) { - gid_address_set_vni (&seid, vni); - gid_address_set_vni (&deid, vni); + gid_address_vni (&seid) = vni; + gid_address_vni (&deid) = vni; } else if (unformat (line_input, "seid %U", unformat_ip_prefix, seid_ippref)) @@ -811,13 +899,13 @@ lisp_show_local_eid_table_command_fn (vlib_main_t * vm, lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); mapping_t * mapit; - vlib_cli_output (vm, "%=20s%=16s", "EID", "Locator"); + vlib_cli_output (vm, "%=30s%=16s", "EID", "Locator"); pool_foreach (mapit, lcm->mapping_pool, ({ u8 * msg = 0; locator_set_t * ls = pool_elt_at_index (lcm->locator_set_pool, mapit->locator_set_index); - vlib_cli_output (vm, "%-16U%16v", format_gid_address, &mapit->eid, + vlib_cli_output (vm, "%-30U%16v", format_gid_address, &mapit->eid, ls->name); vec_free (msg); })); @@ -1294,6 +1382,28 @@ VLIB_CLI_COMMAND (lisp_show_status_command) = { .short_help = "show lisp status", .function = lisp_show_status_command_fn, }; + +static clib_error_t * +lisp_show_eid_table_map_command_fn (vlib_main_t * vm, unformat_input_t * input, + vlib_cli_command_t * cmd) +{ + hash_pair_t * p; + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); + + vlib_cli_output (vm, "%=10s%=10s", "VNI", "VRF"); + hash_foreach_pair (p, lcm->table_id_by_vni, + { + vlib_cli_output (vm, "%=10d%=10d", p->key, p->value[0]); + }); + return 0; +} + +VLIB_CLI_COMMAND (lisp_show_eid_table_map_command) = { + .path = "show lisp eid-table map", + .short_help = "show lisp eid-table vni to vrf mappings", + .function = lisp_show_eid_table_map_command_fn, +}; + static clib_error_t * lisp_add_del_locator_set_command_fn (vlib_main_t * vm, unformat_input_t * input, vlib_cli_command_t * cmd) @@ -1886,6 +1996,7 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) ip_prefix_t * ippref = &gid_address_ippref (gid); ip_address_t * rloc = &ip_prefix_addr (ippref); + memset (gid, 0, sizeof (gid[0])); gid_address_type (gid) = GID_ADDR_IP_PREFIX; for (i = 0; i < vec_len(loc_set->locator_indices); i++) { @@ -2059,6 +2170,43 @@ get_src_and_dst (void *hdr, ip_address_t * src, ip_address_t *dst) } } +static u32 +lisp_get_vni_from_buffer (vlib_buffer_t * b, u8 version) +{ + uword * vnip; + u32 vni = ~0, table_id = ~0, fib_index; + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); + + if (version == IP4) + { + ip4_fib_t * fib; + ip4_main_t * im4 = &ip4_main; + fib_index = vec_elt (im4->fib_index_by_sw_if_index, + vnet_buffer (b)->sw_if_index[VLIB_RX]); + fib = find_ip4_fib_by_table_index_or_id (im4, fib_index, + IP4_ROUTE_FLAG_FIB_INDEX); + table_id = fib->table_id; + } + else + { + ip6_fib_t * fib; + ip6_main_t * im6 = &ip6_main; + fib_index = vec_elt (im6->fib_index_by_sw_if_index, + vnet_buffer (b)->sw_if_index[VLIB_RX]); + fib = find_ip6_fib_by_table_index_or_id (im6, fib_index, + IP6_ROUTE_FLAG_FIB_INDEX); + table_id = fib->table_id; + } + + vnip = hash_get (lcm->vni_by_table_id, table_id); + if (vnip) + vni = vnip[0]; + else + clib_warning ("vrf %d is not mapped to any vni!", table_id); + + return vni; +} + static uword lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * from_frame) @@ -2078,7 +2226,7 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node, while (n_left_from > 0 && n_left_to_next_drop > 0) { - u32 pi0; + u32 pi0, vni; vlib_buffer_t * p0; ip4_header_t * ip0; gid_address_t src, dst; @@ -2105,6 +2253,10 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node, ip_prefix_len(spref) = ip_address_max_len (ip_prefix_version(spref)); ip_prefix_len(dpref) = ip_address_max_len (ip_prefix_version(dpref)); + vni = lisp_get_vni_from_buffer (p0, ip_prefix_version (spref)); + gid_address_vni (&dst) = vni; + gid_address_vni (&src) = vni; + /* if we have remote mapping for destination already in map-chache add forwarding tunnel directly. If not send a map-request */ di = gid_dictionary_lookup (&lcm->mapping_index_by_gid, &dst); @@ -2150,6 +2302,8 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node, sizeof(ip_address_t)); } } + gid_address_free (&dst); + gid_address_free (&src); } vlib_put_next_frame (vm, node, LISP_CP_LOOKUP_NEXT_DROP, n_left_to_next_drop); @@ -2662,6 +2816,7 @@ lisp_cp_init (vlib_main_t *vm) /* default vrf mapped to vni 0 */ hash_set(lcm->table_id_by_vni, 0, 0); + hash_set(lcm->vni_by_table_id, 0, 0); udp_register_dst_port (vm, UDP_DST_PORT_lisp_cp, lisp_cp_input_node.index, 1 /* is_ip4 */); diff --git a/vnet/vnet/lisp-cp/control.h b/vnet/vnet/lisp-cp/control.h index 53c14dd1e01..7cf39783886 100644 --- a/vnet/vnet/lisp-cp/control.h +++ b/vnet/vnet/lisp-cp/control.h @@ -100,6 +100,9 @@ typedef struct /* Lookup vrf by vni */ uword * table_id_by_vni; + /* Lookup vni by vrf */ + uword * vni_by_table_id; + /* Number of src prefixes in a vni that use an interface */ uword * dp_if_refcount_by_vni; @@ -200,4 +203,6 @@ vnet_lisp_add_del_mreq_itr_rlocs (vnet_lisp_add_del_mreq_itr_rloc_args_t * a); int vnet_lisp_clear_all_remote_mappings (void); +int vnet_lisp_eid_table_map (u32 vni, u32 vrf, u8 is_add); + #endif /* VNET_CONTROL_H_ */ diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c index 9e1cb1f69e0..f0debc61a00 100644 --- a/vnet/vnet/lisp-cp/lisp_types.c +++ b/vnet/vnet/lisp-cp/lisp_types.c @@ -15,6 +15,9 @@ #include +static u16 gid_address_put_no_vni (u8 * b, gid_address_t * gid); +static u16 gid_address_size_to_put_no_vni (gid_address_t * gid); + typedef u16 (*size_to_write_fct)(void *); typedef void * (*cast_fct)(gid_address_t *); typedef u16 (*serdes_fct)(u8 *, void *); @@ -155,7 +158,8 @@ format_gid_address (u8 * s, va_list * args) switch (type) { case GID_ADDR_IP_PREFIX: - return format (s, "%U", format_ip_prefix, &gid_address_ippref(a)); + return format (s, "[%d] %U", gid_address_vni(a), format_ip_prefix, + &gid_address_ippref(a)); default: clib_warning("Can't format gid type %d", type); return 0; @@ -335,16 +339,17 @@ lcaf_hdr_parse (void * offset, lcaf_t * lcaf) u16 vni_parse (u8 * p, void * a) { - vni_t * v = a; + lcaf_t * lcaf = a; + gid_address_t * g = a; u16 size = 0; - vni_vni (v) = clib_net_to_host_u32 ( *(u32 *) p); - size += sizeof (u32); - vni_gid (v) = clib_mem_alloc (sizeof (gid_address_t)); - gid_address_t * gid = vni_gid (v); - memset (gid, 0, sizeof (gid[0])); + gid_address_vni (g) = clib_net_to_host_u32 ( *(u32 *) p); + size += sizeof (u32); + gid_address_vni_mask (g) = lcaf_vni_len (lcaf); - size += gid_address_parse (p + size, gid); + /* nested LCAFs are not supported - it is expected that nested AFI type is + IP address */ + size += gid_address_parse (p + size, g); return size; } @@ -448,9 +453,11 @@ ip_prefix_size_to_write (void * pref) } u16 -ip_prefix_write (u8 * p, void * pref) +ip_prefix_write (u8 * p, void * gid) { - ip_prefix_t *a = (ip_prefix_t *) pref; + gid_address_t * g = gid; + ip_prefix_t *a = &gid_address_ippref (g); + switch (ip_prefix_version (a)) { case IP4: @@ -581,9 +588,6 @@ lcaf_write (u8 * p, void * a) u16 lcaf_len = (*lcaf_body_length_fcts[type])(lcaf); LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len); - if (LCAF_INSTANCE_ID == type) - LCAF_RES2 (h) = lcaf_vni_len(lcaf); - clib_memcpy (p + size, h, sizeof (h[0])); size += sizeof (h[0]); len = (*lcaf_write_fcts[type])(p + size, lcaf); @@ -605,12 +609,30 @@ mac_write (u8 * p, void * a) u16 vni_write (u8 * p, void * a) { - vni_t * v = a; + lcaf_hdr_t _h, *h = &_h; + gid_address_t * g = a; u16 size = 0, len; - *(u32 *)p = clib_host_to_net_u32 (vni_vni (v)); + /* put lcaf header */ + *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF); + size += sizeof (u16); + memset (h, 0, sizeof (h[0])); + LCAF_TYPE (h) = LCAF_INSTANCE_ID; + u16 lcaf_len = sizeof (u32) /* Instance ID size */ + + gid_address_size_to_put_no_vni (g); + LCAF_LENGTH (h) = clib_host_to_net_u16 (lcaf_len); + LCAF_RES2 (h) = gid_address_vni_mask (g); + + /* put vni header */ + clib_memcpy (p + size, h, sizeof (h[0])); + size += sizeof (h[0]); + + u32 * afip = (u32 *)(p + size); + afip[0] = clib_host_to_net_u32 (gid_address_vni (g)); size += sizeof (u32); - len = gid_address_put (p + size, vni_gid (v)); + + /* write the actual address */ + len = gid_address_put_no_vni (p + size, g); if ((u16)~0 == len) return ~0; @@ -634,12 +656,11 @@ no_addr_size_to_write (void * a) u16 vni_size_to_write (void * a) { - vni_t * v = a; - u16 size = sizeof (vni_vni (v)); - - gid_address_t * gid = vni_gid (v); - return (size + sizeof (lcaf_hdr_t) - + gid_address_size_to_put (gid)); + gid_address_t * g = a; + return (sizeof (u32) /* vni size */ + + sizeof (u16) /* LCAF AFI field size */ + + sizeof (lcaf_hdr_t) + + gid_address_size_to_put_no_vni (g)); } u16 @@ -671,20 +692,38 @@ gid_address_len (gid_address_t *a) return (*addr_len_fcts[type])((*cast_fcts[type])(a)); } -u16 -gid_address_put (u8 * b, gid_address_t * gid) +static u16 +gid_address_put_no_vni (u8 * b, gid_address_t * gid) { gid_address_type_t type = gid_address_type (gid); return (*write_fcts[type])(b, (*cast_fcts[type])(gid)); } u16 -gid_address_size_to_put (gid_address_t * gid) +gid_address_put (u8 * b, gid_address_t * gid) +{ + if (0 != gid_address_vni (gid)) + return vni_write (b, gid); + + return gid_address_put_no_vni (b, gid); +} + +static u16 +gid_address_size_to_put_no_vni (gid_address_t * gid) { gid_address_type_t type = gid_address_type (gid); return (*size_to_write_fcts[type])((*cast_fcts[type])(gid)); } +u16 +gid_address_size_to_put (gid_address_t * gid) +{ + if (0 != gid_address_vni (gid)) + return vni_size_to_write (gid); + + return gid_address_size_to_put_no_vni (gid); +} + void * gid_address_cast (gid_address_t * gid, gid_address_type_t type) { @@ -697,6 +736,8 @@ gid_address_copy(gid_address_t * dst, gid_address_t * src) gid_address_type_t type = gid_address_type(src); (*copy_fcts[type])((*cast_fcts[type])(dst), (*cast_fcts[type])(src)); gid_address_type(dst) = type; + gid_address_vni(dst) = gid_address_vni(src); + gid_address_vni_mask(dst) = gid_address_vni_mask(src); } u32 @@ -739,8 +780,8 @@ gid_address_parse (u8 * offset, gid_address_t *a) gid_address_ippref_len(a) = 128; break; case LISP_AFI_LCAF: - len = lcaf_parse (offset, a); gid_address_type(a) = GID_ADDR_LCAF; + len = lcaf_parse (offset, a); break; case LISP_AFI_MAC: len = mac_parse (offset, a); @@ -788,6 +829,10 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2) return -1; if (gid_address_type(a1) != gid_address_type(a2)) return -1; + if (gid_address_vni(a1) != gid_address_vni(a2)) + return -1; + if (gid_address_vni_mask(a1) != gid_address_vni_mask(a2)) + return -1; switch (gid_address_type(a1)) { diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h index b80ba0b844f..235d4701d46 100644 --- a/vnet/vnet/lisp-cp/lisp_types.h +++ b/vnet/vnet/lisp-cp/lisp_types.h @@ -79,6 +79,14 @@ typedef enum struct _gid_address_t; +typedef struct +{ + u8 src_len; + u8 dst_len; + struct _gid_address_t *src; + struct _gid_address_t *dst; +} source_dest_t; + typedef struct { u8 vni_mask_len; @@ -90,14 +98,6 @@ typedef struct #define vni_mask_len(_a) (_a)->vni_mask_len #define vni_gid(_a) (_a)->gid_addr -typedef struct -{ - u8 src_len; - u8 dst_len; - struct _gid_address_t *src; - struct _gid_address_t *dst; -} source_dest_t; - typedef struct { /* the union needs to be at the beginning! */ @@ -112,7 +112,6 @@ typedef struct #define lcaf_type(_a) (_a)->type #define lcaf_vni(_a) vni_vni(& (_a)->uni) #define lcaf_vni_len(_a) vni_mask_len(& (_a)->uni) -#define lcaf_gid (_a) vni_gid(& (_a)->uni) /* might want to expand this in the future :) */ typedef struct _gid_address_t @@ -124,6 +123,8 @@ typedef struct _gid_address_t u8 mac[6]; }; u8 type; + u32 vni; + u8 vni_mask; } gid_address_t; u8 * format_ip_address (u8 * s, va_list * args); @@ -169,11 +170,8 @@ u32 gid_address_parse (u8 * offset, gid_address_t *a); #define gid_address_ip_version(_a) ip_addr_version(&gid_address_ip(_a)) #define gid_address_lcaf(_a) (_a)->lcaf #define gid_address_mac(_a) (_a)->mac -#define gid_address_vni(_a) ( (GID_ADDR_LCAF == gid_address_type(_a)) ? \ - lcaf_vni(&gid_address_lcaf(_a)) : 0) -/* setter for vni */ -#define gid_address_set_vni(_a, _val) \ - (lcaf_vni(&gid_address_lcaf(_a)) = (_val)) +#define gid_address_vni(_a) (_a)->vni +#define gid_address_vni_mask(_a) (_a)->vni_mask /* 'sub'address functions */ #define foreach_gid_address_type_fcns \ @@ -235,4 +233,6 @@ typedef struct u8 local; } mapping_t; +lcaf_t lcaf_iid_init (u32 vni); + #endif /* VNET_LISP_GPE_LISP_TYPES_H_ */ diff --git a/vnet/vnet/lisp-gpe/decap.c b/vnet/vnet/lisp-gpe/decap.c index a583666fcf4..4684c29315e 100644 --- a/vnet/vnet/lisp-gpe/decap.c +++ b/vnet/vnet/lisp-gpe/decap.c @@ -180,8 +180,10 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to * decide the rx vrf and the input features to be applied */ - si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh0->iid); - si1 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh1->iid); + si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, + clib_net_to_host_u32 (lh0->iid)); + si1 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, + clib_net_to_host_u32 (lh1->iid)); if (si0) { @@ -297,7 +299,8 @@ lisp_gpe_input_inline (vlib_main_t * vm, vlib_node_runtime_t * node, /* map iid/vni to lisp-gpe sw_if_index which is used by ipx_input to * decide the rx vrf and the input features to be applied */ - si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, lh0->iid); + si0 = hash_get(lgm->tunnel_term_sw_if_index_by_vni, + clib_net_to_host_u32 (lh0->iid)); if (si0) { diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.c b/vnet/vnet/lisp-gpe/lisp_gpe.c index c4f936eccda..0eacb385c58 100644 --- a/vnet/vnet/lisp-gpe/lisp_gpe.c +++ b/vnet/vnet/lisp-gpe/lisp_gpe.c @@ -135,6 +135,13 @@ add_del_ip_tunnel (vnet_lisp_gpe_add_del_fwd_entry_args_t *a, ip_address_copy(&t->src, &a->slocator); ip_address_copy(&t->dst, &a->dlocator); + /* if vni is non-default */ + if (a->vni) + { + t->flags = LISP_GPE_FLAGS_I; + t->vni = a->vni; + } + t->flags |= LISP_GPE_FLAGS_P; t->next_protocol = ip_prefix_version(&key.eid) == IP4 ? LISP_GPE_NEXT_PROTO_IP4 : LISP_GPE_NEXT_PROTO_IP6; -- cgit 1.2.3-korg