From beceab90520d38aa0b90427d0c829d67ca843161 Mon Sep 17 00:00:00 2001 From: Filip Tehlar Date: Wed, 20 Apr 2016 17:21:55 +0200 Subject: [PATCH] Add support for LCAF Instance ID Change-Id: Ifce3f2bdcba099157a42d0b694f3161b9f700ed2 Signed-off-by: Filip Tehlar --- vnet/test/lisp-cp/test_cp_serdes.c | 287 ++++++++++++++++++++++++---- vnet/test/lisp-cp/test_lisp_types.c | 260 +++++++++++++++++++++++++- vnet/vnet/lisp-cp/control.c | 43 +++-- vnet/vnet/lisp-cp/gid_dictionary.c | 4 +- vnet/vnet/lisp-cp/lisp_cp_messages.h | 27 +++ vnet/vnet/lisp-cp/lisp_msg_serdes.c | 31 +-- vnet/vnet/lisp-cp/lisp_msg_serdes.h | 2 +- vnet/vnet/lisp-cp/lisp_types.c | 352 +++++++++++++++++++++++++++++++++-- vnet/vnet/lisp-cp/lisp_types.h | 66 ++++++- vnet/vnet/lisp-gpe/lisp_gpe.c | 2 +- vpp/api/api.c | 4 +- 11 files changed, 976 insertions(+), 102 deletions(-) diff --git a/vnet/test/lisp-cp/test_cp_serdes.c b/vnet/test/lisp-cp/test_cp_serdes.c index d77c294d70f..2ca391e35b7 100644 --- a/vnet/test/lisp-cp/test_cp_serdes.c +++ b/vnet/test/lisp-cp/test_cp_serdes.c @@ -65,7 +65,7 @@ static clib_error_t * test_lisp_msg_push_ecm () clib_error_t * error = 0; gid_address_t la, ra; vlib_buffer_t * b = 0; - u32 buff_len = 500; + u32 buff_len = 900; int lp = 0x15, rp = 0x14; b = clib_mem_alloc (buff_len); @@ -74,11 +74,11 @@ static clib_error_t * test_lisp_msg_push_ecm () b->current_data = sizeof(udp_header_t) + sizeof(ip4_header_t) + sizeof(ecm_hdr_t) + 1; - la.type = IP_PREFIX; + la.type = GID_ADDR_IP_PREFIX; la.ippref.addr.ip.v4.as_u32 = 0xa1b2c3d4; la.ippref.addr.version = IP4; - ra.type = IP_PREFIX; + ra.type = GID_ADDR_IP_PREFIX; ra.ippref.addr.ip.v4.as_u32 = 0x90817263; ra.ippref.addr.version = IP4; @@ -96,7 +96,7 @@ static clib_error_t * test_lisp_msg_push_ecm () u8 expected_ip4_hdr[] = { 0x45, /* version; IHL */ 0x00, /* services */ - 0x02, 0x10, /* total length */ + 0x03, 0xa0, /* total length */ 0x00, 0x00, /* identification */ 0x40, 0x00, /* flags; fragment offset*/ 0xff, /* TTL */ @@ -114,7 +114,7 @@ static clib_error_t * test_lisp_msg_push_ecm () u8 expected_udp_hdr[] = { 0x00, 0x15, /* src port */ 0x00, 0x14, /* dst port */ - 0x01, 0xfc, /* length */ + 0x03, 0x8c, /* length */ 0x00, 0x00, /* checksum */ }; _assert(0 == memcmp(uh, expected_udp_hdr, sizeof(expected_udp_hdr))); @@ -161,7 +161,7 @@ static clib_error_t * test_lisp_msg_parse_mapping_record () _assert(eid.ippref.addr.ip.v4.as_u32 == 0x66554433); _assert(locs[0].local == 0); _assert(locs[0].address.ippref.addr.ip.v4.as_u32 == 0xddccbbaa); - _assert(locs[0].address.type == IP_PREFIX); + _assert(locs[0].address.type == GID_ADDR_IP_PREFIX); _assert(locs[0].priority == 0xa); _assert(locs[0].weight == 0xb); _assert(locs[0].mpriority == 0xc); @@ -175,35 +175,25 @@ done: } static map_request_hdr_t * -build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b) +build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b, + gid_address_t * rlocs) { gid_address_t _seid, * seid = &_seid; gid_address_t _deid, * deid = &_deid; u8 is_smr_invoked = 1; u64 nonce = 0; - map_request_hdr_t *h; - ip_address_t * rlocs = 0; - ip_address_t _addr, * addr = &_addr; + map_request_hdr_t * h = 0; - gid_address_type(seid) = IP_PREFIX; - gid_address_ip(seid).ip.v4.as_u32 = 0x12345678; + gid_address_type (seid) = GID_ADDR_IP_PREFIX; + ip_address_t * ip_addr = &gid_address_ip (seid); + ip_addr_v4 (ip_addr).as_u32 = 0x12345678; seid->ippref.addr.version = IP4; - gid_address_type(deid) = IP_PREFIX; - gid_address_ip(deid).ip.v4.as_u32 = 0x9abcdef0; + gid_address_type (deid) = GID_ADDR_IP_PREFIX; + ip_address_t * ip_addr2 = &gid_address_ip (deid); + ip_addr_v4 (ip_addr2).as_u32 = 0x9abcdef0; deid->ippref.addr.version = IP4; - gid_address_ippref_len(deid) = 24; - - ip_addr_version(addr) = IP4; - ip_addr_v4(addr).data_u32 = 0x10203040; - vec_add1(rlocs, addr[0]); - - ip_addr_v6(addr).as_u32[0] = 0xffeeddcc; - ip_addr_v6(addr).as_u32[1] = 0xbbaa9988; - ip_addr_v6(addr).as_u32[2] = 0x77665544; - ip_addr_v6(addr).as_u32[3] = 0x33221100; - ip_addr_version(addr) = IP6; - vec_add1(rlocs, addr[0]); + gid_address_ippref_len (deid) = 24; h = lisp_msg_put_mreq (lcm, b, seid, deid, rlocs, is_smr_invoked, &nonce); @@ -211,6 +201,26 @@ build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b) return h; } +static void +generate_rlocs (gid_address_t **rlocs, u32 * count) +{ + gid_address_t gid_addr_data, * gid_addr = &gid_addr_data; + ip_address_t * addr = &gid_address_ip (gid_addr); + + gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX; + + ip_addr_version (addr) = IP4; + ip_addr_v4 (addr).data_u32 = 0x10203040; + vec_add1 (rlocs[0], gid_addr[0]); + + ip_addr_v6 (addr).as_u32[0] = 0xffeeddcc; + ip_addr_v6 (addr).as_u32[1] = 0xbbaa9988; + ip_addr_v6 (addr).as_u32[2] = 0x77665544; + ip_addr_v6 (addr).as_u32[3] = 0x33221100; + ip_addr_version (addr) = IP6; + vec_add1 (rlocs[0], gid_addr[0]); +} + static clib_error_t * test_lisp_msg_parse () { gid_address_t eid; @@ -219,13 +229,15 @@ static clib_error_t * test_lisp_msg_parse () gid_address_t gid; clib_error_t * error = 0; vlib_buffer_t * b; - gid_address_t * rlocs = 0; + gid_address_t * rlocs_decode = 0, * rlocs = 0; + u32 rloc_count_parse = 0; u8 * data = clib_mem_alloc(500); memset(data, 0, 500); b = (vlib_buffer_t *) data; - h = build_map_request (lcm, b); + generate_rlocs (&rlocs_decode, &rloc_count_parse); + h = build_map_request (lcm, b, rlocs_decode); vlib_buffer_pull(b, sizeof(*h)); u32 len = lisp_msg_parse_addr(b, &gid); @@ -259,16 +271,95 @@ done: return error; } +static clib_error_t * test_lisp_msg_put_mreq_with_lcaf () +{ + lisp_cp_main_t * lcm = vnet_lisp_cp_get_main (); + 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 = + { + .type = GID_ADDR_IP_PREFIX, + .ippref = ippref + }; + + 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); + + u8 * data = clib_mem_alloc (500); + memset (data, 0, 500); + + h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs); + + /* clear Nonce to simplify comparison */ + memset ((u8 *)h + 4, 0, 8); + + u8 expected_data[] = + { + 0x10, 0x40, 0x00, 0x01, /* type; flags; IRC; REC count */ + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, /* nonce */ + 0x00, 0x01, /* Source-EID-AFI */ + 0x78, 0x56, 0x34, 0x12, /* Source EID Address */ + + /* RLOCs */ + 0x40, 0x03, /* AFI = LCAF*/ + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x17, /* IID mask-len */ + 0x00, 0x0a, /* iid length + next AFI lenght */ + 0x90, 0x91, 0x92, 0x93, /* IID / VNI */ + + 0x00, 0x01, /* AFI = ipv4 */ + 0x44, 0x33, 0x22, 0x11, /* ITR-RLOC Address 1 */ + + /* record */ + 0x00, /* reserved */ + 0x18, /* EID mask-len */ + 0x00, 0x01, /* EID-prefix-AFI */ + 0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */ + }; + + _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data))); +done: + clib_mem_free (data); + return error; +} + static clib_error_t * test_lisp_msg_put_mreq () { lisp_cp_main_t * lcm = vnet_lisp_cp_get_main(); clib_error_t * error = 0; map_request_hdr_t *h; + gid_address_t * rlocs = 0; + u32 rloc_count = 0; u8 * data = clib_mem_alloc(500); memset(data, 0, 500); - h = build_map_request (lcm, (vlib_buffer_t *)data); + generate_rlocs (&rlocs, &rloc_count); + h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs); /* clear Nonce to simplify comparison */ memset((u8 *)h + 4, 0, 8); @@ -297,19 +388,149 @@ static clib_error_t * test_lisp_msg_put_mreq () 0x00, 0x01, /* EID-prefix-AFI */ 0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */ }; + _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data))); + +done: + clib_mem_free (data); + return error; +} + +static clib_error_t * +test_lisp_parse_lcaf () +{ + int i; + clib_error_t * error = 0; + gid_address_t eid; + locator_t * locs = 0; + locator_t probed; + vlib_buffer_t * b = 0; + u32 buff_len = 500; + + b = clib_mem_alloc (buff_len); + memset ((u8 *)b, 0, buff_len); + + u8 map_reply_records[] = + { + /* 1. record */ + 0x01, 0x02, 0x03, 0x04, /* record TTL */ + 0x03, /* locator count */ + 0x00, 0x00, 0x00, /* eid-mask-len; ... */ + 0x00, 0x00, /* reserved; map-version num */ + 0x00, 0x01, /* EID-Prefix-AFI */ + 0x33, 0x44, 0x55, 0x66, /* eid-prefix */ + + /* 1st locator */ + 0x0a, /* prority */ + 0x0b, /* weight */ + 0x0c, /* m-prority */ + 0x0d, /* m-weight */ + 0x00, 0x00, /* unused flags */ + 0x40, 0x03, /* Loc-AFI = LCAF*/ + + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x18, /* IID mask-len */ + 0x0a, 0x00, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x00, 0x00, 0x00, 0x09, /* iid */ + 0x00, 0x01, /* AFI = ipv4 */ + 0x10, 0xbb, 0xcc, 0xdd, /* ipv4 loator address */ + + /* 2nd locator */ + 0x07, /* prority */ + 0x06, /* weight */ + 0x05, /* m-prority */ + 0x04, /* m-weight */ + 0x00, 0x00, /* unused flags */ + 0x40, 0x03, /* Loc-AFI = LCAF*/ + + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x18, /* IID mask-len */ + 0x00, 0x16, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x22, 0x44, 0x66, 0x88, /* iid */ + 0x00, 0x02, /* AFI = ipv6 */ + 0xcc, 0xdd, 0xee, 0xff, + 0x88, 0x99, 0xaa, 0xbb, + 0x44, 0x55, 0x66, 0x77, + 0x00, 0x11, 0x22, 0x33, /* ipv6 locator address */ + + /* 3rd locator */ + 0x0a, /* prority */ + 0x0b, /* weight */ + 0x0c, /* m-prority */ + 0x0d, /* m-weight */ + 0x00, 0x00, /* unused flags */ + 0x00, 0x01, /* Loc-AFI */ + 0xaa, 0xbb, 0xcc, 0xdd, /* Loator */ + }; + + b->current_length = buff_len; + memcpy (b->data, map_reply_records, sizeof (map_reply_records)); - int r = memcmp(expected_data, (u8 *)h, sizeof(expected_data)); - error = CLIB_ERROR_ASSERT (r == 0); + lisp_msg_parse_mapping_record (b, &eid, &locs, &probed); + _assert (vec_len (locs) == 3); + _assert (eid.ippref.addr.ip.v4.as_u32 == 0x66554433); + + /* check 1st locator - an LCAF with ipv4 */ + _assert (locs[0].local == 0); + _assert (locs[0].priority == 0xa); + _assert (locs[0].weight == 0xb); + _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 (IP4 == ip_prefix_version (ip_pref)); + + /* 2nd locator - LCAF entry with ipv6 address */ + _assert (locs[1].local == 0); + _assert (locs[1].priority == 0x7); + _assert (locs[1].weight == 0x6); + _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 (IP6 == ip_prefix_version (ip_pref)); + + /* 3rd locator - simple ipv4 address */ + _assert (gid_address_type (&locs[2].address) == GID_ADDR_IP_PREFIX); +done: + clib_mem_free (b); - clib_mem_free(data); + for (i = 0; i < 3; i++) + locator_free (&locs[i]); + vec_free (locs); return error; } #define foreach_test_case \ _(lisp_msg_put_mreq) \ + _(lisp_msg_put_mreq_with_lcaf) \ _(lisp_msg_push_ecm) \ _(lisp_msg_parse) \ - _(lisp_msg_parse_mapping_record) + _(lisp_msg_parse_mapping_record) \ + _(lisp_parse_lcaf) int run_tests (void) { diff --git a/vnet/test/lisp-cp/test_lisp_types.c b/vnet/test/lisp-cp/test_lisp_types.c index efd87222d49..b846cf64ca4 100644 --- a/vnet/test/lisp-cp/test_lisp_types.c +++ b/vnet/test/lisp-cp/test_lisp_types.c @@ -26,11 +26,15 @@ static clib_error_t * test_locator_type (void) { clib_error_t * error = 0; - gid_address_t _gid_addr, * gid_addr = &_gid_addr; - gid_address_type(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; + gid_address_t _gid_addr, * gid = &_gid_addr; + ip_prefix_t * ippref; + gid_address_type (gid) = GID_ADDR_IP_PREFIX; + gid_address_ippref_len (gid) = 24; + ippref = &gid_address_ippref (gid); + ip_prefix_version (ippref) = IP4; + ip_prefix_len (ippref) = 0; + ip4_address_t * ip4 = &ip_prefix_v4 (ippref); + ip4->as_u32 = 0x20304050; /* local locator */ locator_t loc1, loc2 = { @@ -47,18 +51,193 @@ static clib_error_t * test_locator_type (void) /* remote locator */ loc2.local = 0; - loc2.address = gid_addr[0]; + + ip_prefix_t nested_ippref; + ip_prefix_version (&nested_ippref) = IP4; + ip_prefix_len (&nested_ippref) = 0; + ip4 = &ip_prefix_v4 (&nested_ippref); + ip4->as_u32 = 0x33882299; + gid_address_t nested_gid = + { + .type = GID_ADDR_IP_PREFIX, + .ippref = nested_ippref + }; + + lcaf_t lcaf = + { + .type = LCAF_INSTANCE_ID, + .uni = + { + .vni_mask_len = 5, + .vni = 0xa1b2c3d4, + .gid_addr = &nested_gid + } + }; + gid_address_type (gid) = GID_ADDR_LCAF; + gid_address_lcaf (gid) = lcaf; + + loc2.address = gid[0]; locator_copy(&loc1, &loc2); _assert (0 == locator_cmp (&loc1, &loc2)); +done: + locator_free (&loc1); + return error; +} + +static clib_error_t * test_gid_parse_ip_pref () +{ + clib_error_t * error = 0; + gid_address_t _gid_addr, * gid_addr = &_gid_addr; + gid_address_t _gid_addr_copy, * gid_addr_copy = &_gid_addr_copy; + u8 data[] = + { + 0x00, 0x01, /* AFI = IPv4 */ + 0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */ + }; + + u32 len = gid_address_parse (data, gid_addr); + _assert (6 == len); + gid_address_copy (gid_addr_copy, gid_addr); + _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr)); done: return error; } -static clib_error_t * test_gid_parse () +static clib_error_t * test_gid_parse_lcaf () { clib_error_t * error = 0; + gid_address_t _gid_addr, * gid_addr = &_gid_addr; + gid_address_t _gid_addr_copy, * gid_addr_copy = &_gid_addr_copy; + + memset (gid_addr, 0, sizeof (gid_addr[0])); + memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0])); + + u8 data[] = + { + 0x40, 0x03, /* AFI = LCAF*/ + + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x18, /* IID mask-len */ + 0x00, 0x0a, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x00, 0x00, 0x00, 0x09, /* iid */ + 0x00, 0x01, /* AFI = ipv4 */ + 0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */ + }; + u32 len = gid_address_parse (data, gid_addr); + _assert (18 == len); + gid_address_copy (gid_addr_copy, gid_addr); + _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr)); + + 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; +} + +static clib_error_t * test_gid_parse_lcaf_complex () +{ + clib_error_t * error = 0; + gid_address_t _gid_addr, * gid_addr = &_gid_addr; + gid_address_t _gid_addr_copy, * gid_addr_copy = &_gid_addr_copy; + + memset (gid_addr, 0, sizeof (gid_addr[0])); + memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0])); + + u8 data[] = + { + 0x40, 0x03, /* AFI = LCAF*/ + + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x18, /* IID mask-len */ + 0x00, 0x0a, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x00, 0x00, 0x00, 0x0b, /* iid */ + + 0x40, 0x03, /* AFI = LCAF*/ + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x17, /* IID mask-len */ + 0x00, 0x0a, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x00, 0x00, 0x00, 0x0c, /* iid */ + + 0x40, 0x03, /* AFI = LCAF*/ + /* LCAF header*/ + 0x00, 0x00, /* reserved1, flags */ + 0x02, /* type = Instance ID */ + 0x16, /* IID mask-len */ + 0x00, 0x16, /* iid length + next AFI lenght */ + /* LCAF Instance ID */ + 0x00, 0x00, 0x00, 0x0d, /* iid */ + + 0x00, 0x02, /* AFI = IPv6 */ + + 0x10, 0xbb, 0xcc, 0xdd, + 0x10, 0xbb, 0xcc, 0xdd, + 0x10, 0xbb, 0xcc, 0xdd, + 0x10, 0xbb, 0xcc, 0xdd, /* ipv6 address */ + }; + u32 len = gid_address_parse (data, gid_addr); + _assert (54 == len); + _assert (gid_addr->type == GID_ADDR_LCAF); + gid_address_copy (gid_addr_copy, gid_addr); + _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr)); + _assert (gid_addr_copy->type == GID_ADDR_LCAF); + + lcaf_t * lcaf = &gid_address_lcaf (gid_addr_copy); + _assert (lcaf->type == LCAF_INSTANCE_ID); + vni_t * v = (vni_t *) lcaf; + _assert (v->vni == 0x0b); + _assert (v->vni_mask_len == 0x18); + + gid_address_t * tmp = vni_gid (v); + _assert (gid_address_type (tmp) == GID_ADDR_LCAF); + lcaf = &gid_address_lcaf (tmp); + _assert (lcaf->type == LCAF_INSTANCE_ID); + + v = (vni_t *) lcaf; + _assert (v->vni == 0x0c); + _assert (v->vni_mask_len == 0x17); + + tmp = vni_gid (v); + _assert (gid_address_type (tmp) == GID_ADDR_LCAF); + lcaf = &gid_address_lcaf (tmp); + + _assert (lcaf->type == LCAF_INSTANCE_ID); + v = (vni_t *) lcaf; + _assert (v->vni == 0x0d); + _assert (v->vni_mask_len == 0x16); + + tmp = vni_gid (v); + _assert (gid_address_type (tmp) == GID_ADDR_IP_PREFIX); + + ip_prefix_t * ip_pref = &gid_address_ippref (tmp); + ip6_address_t * ip6 = &ip_prefix_v6 (ip_pref); + _assert (ip6->as_u32[0] == 0xddccbb10); + _assert (ip6->as_u32[1] == 0xddccbb10); + _assert (ip6->as_u32[2] == 0xddccbb10); + _assert (ip6->as_u32[3] == 0xddccbb10); + _assert (ip_prefix_version (ip_pref) == IP6); + +done: + gid_address_free (gid_addr); + gid_address_free (gid_addr_copy); return error; } @@ -72,7 +251,7 @@ static clib_error_t * test_format_unformat_gid_address (void) gid_address_t unformated_gid; /* format/unformat IPv4 global ID address */ - gid_address_type(gid_addr) = IP_PREFIX; + 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; @@ -90,7 +269,7 @@ static clib_error_t * test_format_unformat_gid_address (void) s = 0; /* format/unformat IPv6 global ID address */ - gid_address_type(gid_addr) = IP_PREFIX; + 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}; @@ -115,10 +294,71 @@ done: return error; } +static clib_error_t * test_gid_address_write (void) +{ + clib_error_t * error = 0; + ip_prefix_t ippref_data, * ippref = &ippref_data; + + u8 * b = clib_mem_alloc(500); + memset(b, 0, 500); + + ip_prefix_version (ippref) = IP4; + ip4_address_t * ip4 = &ip_prefix_v4 (ippref); + ip4->as_u32 = 0xaabbccdd; + + gid_address_t nested_gid = + { + .ippref = ippref[0], + .type = GID_ADDR_IP_PREFIX, + }; + + 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)); + + u16 write_len = gid_address_put (b, &gid); + _assert (18 == write_len); + + u8 expected_gid_data[] = + { + 0x40, 0x03, /* AFI = LCAF */ + 0x00, /* reserved1 */ + 0x00, /* flags */ + 0x02, /* LCAF type = Instance ID */ + 0x18, /* IID/VNI mask len */ + 0x00, 0x0a, /* length */ + 0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */ + + 0x00, 0x01, /* AFI = IPv4 */ + 0xdd, 0xcc, 0xbb, 0xaa, /* ipv4 addr */ + }; + _assert (0 == memcmp (expected_gid_data, b, sizeof (expected_gid_data))); +done: + clib_mem_free (b); + return error; +} + #define foreach_test_case \ _(format_unformat_gid_address) \ _(locator_type) \ - _(gid_parse) + _(gid_parse_ip_pref) \ + _(gid_parse_lcaf) \ + _(gid_parse_lcaf_complex) \ + _(gid_address_write) int run_tests (void) { diff --git a/vnet/vnet/lisp-cp/control.c b/vnet/vnet/lisp-cp/control.c index 3eabf36861e..9a88402e417 100644 --- a/vnet/vnet/lisp-cp/control.c +++ b/vnet/vnet/lisp-cp/control.c @@ -194,7 +194,7 @@ 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; - gid_address_type (&eid) = IP_PREFIX; + gid_address_type (&eid) = GID_ADDR_IP_PREFIX; /* Get a line of input. */ if (! unformat_user (input, unformat_line_input, line_input)) @@ -972,7 +972,7 @@ get_local_iface_ip_for_dst (lisp_cp_main_t *lcm, ip_address_t * dst, } -static ip_address_t * +static gid_address_t * build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) { ip4_address_t * l4; @@ -981,9 +981,12 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) locator_t * loc; u32 * loc_indexp; ip_interface_address_t * ia = 0; - ip_address_t * rlocs = 0; - ip_address_t _rloc, * rloc = &_rloc; + gid_address_t gid_data, * gid = &gid_data; + gid_address_t * rlocs = 0; + ip_prefix_t * ippref = &gid_address_ippref (gid); + ip_address_t * rloc = &ip_prefix_addr (ippref); + gid_address_type (gid) = GID_ADDR_IP_PREFIX; for (i = 0; i < vec_len(loc_set->locator_indices); i++) { loc_indexp = vec_elt_at_index(loc_set->locator_indices, i); @@ -995,8 +998,8 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) loc->sw_if_index, 1 /* unnumbered */, ({ l4 = ip_interface_address_get_address (&lcm->im4->lookup_main, ia); - ip_addr_v4(rloc) = l4[0]; - vec_add1(rlocs, rloc[0]); + ip_addr_v4 (rloc) = l4[0]; + vec_add1 (rlocs, gid[0]); })); ip_addr_version(rloc) = IP6; @@ -1004,9 +1007,9 @@ build_itr_rloc_list (lisp_cp_main_t * lcm, locator_set_t * loc_set) foreach_ip_interface_address (&lcm->im6->lookup_main, ia, loc->sw_if_index, 1 /* unnumbered */, ({ - l6 = ip_interface_address_get_address (&lcm->im6->lookup_main, ia); - ip_addr_v6(rloc) = l6[0]; - vec_add1(rlocs, rloc[0]); + l6 = ip_interface_address_get_address (&lcm->im6->lookup_main, ia); + ip_addr_v6 (rloc) = l6[0]; + vec_add1 (rlocs, gid[0]); })); } return rlocs; @@ -1021,7 +1024,7 @@ build_encapsulated_map_request (vlib_main_t * vm, lisp_cp_main_t *lcm, vlib_buffer_t * b; u32 bi; ip_address_t * mr_ip, sloc; - ip_address_t * rlocs = 0; + gid_address_t * rlocs = 0; if (vlib_buffer_alloc (vm, &bi, 1) != 1) { @@ -1168,9 +1171,9 @@ lisp_cp_lookup (vlib_main_t * vm, vlib_node_runtime_t * node, gid_address_t src, dst; ip_prefix_t * spref, * dpref; - gid_address_type (&src) = IP_PREFIX; + gid_address_type (&src) = GID_ADDR_IP_PREFIX; spref = &gid_address_ippref(&src); - gid_address_type (&dst) = IP_PREFIX; + gid_address_type (&dst) = GID_ADDR_IP_PREFIX; dpref = &gid_address_ippref(&dst); pi0 = from[0]; @@ -1356,7 +1359,8 @@ add_fwd_entry (lisp_cp_main_t* lcm, u32 src_map_index, u32 dst_map_index) { u32 li = vec_elt (dst_ls->locator_indices, i); locator_t * l = pool_elt_at_index (lcm->locator_pool, li); - if (l->priority < minp && gid_address_type(&l->address) == IP_PREFIX) + if (l->priority < minp && gid_address_type(&l->address) + == GID_ADDR_IP_PREFIX) { minp = l->priority; dl = l; @@ -1456,6 +1460,7 @@ compare_locators (lisp_cp_main_t *lcm, u32 * old_ls_indexes, void process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b) { + locator_t * loc; u32 len = 0, i, ls_index = 0; void * h; vnet_lisp_add_del_locator_set_args_t _ls_arg, * ls_arg = &_ls_arg; @@ -1496,6 +1501,10 @@ process_map_reply (lisp_cp_main_t * lcm, vlib_buffer_t * b) if (len == ~0) { clib_warning ("Failed to parse mapping record!"); + vec_foreach (loc, ls_arg->locators) + { + locator_free (loc); + } vec_free(ls_arg->locators); return; } @@ -1559,7 +1568,7 @@ process_map_request (vlib_main_t * vm, lisp_cp_main_t * lcm, vlib_buffer_t * b) gid_address_t src, dst; // u64 nonce; u32 i, len = 0; - gid_address_t * itr_rlocs = 0; + gid_address_t * itr_rlocs = 0, * rloc; mreq_hdr = vlib_buffer_get_current (b); vlib_buffer_pull (b, sizeof(*mreq_hdr)); @@ -1581,6 +1590,12 @@ process_map_request (vlib_main_t * vm, lisp_cp_main_t * lcm, vlib_buffer_t * b) if (len == ~0) return; + /* TODO: RLOCs are currently unused, so free them for now */ + vec_foreach (rloc, itr_rlocs) + { + gid_address_free (rloc); + } + /* parse eid records and send SMR-invoked map-requests */ for (i = 0; i < MREQ_REC_COUNT(mreq_hdr); i++) { diff --git a/vnet/vnet/lisp-cp/gid_dictionary.c b/vnet/vnet/lisp-cp/gid_dictionary.c index 4da520344e3..8dc3fd4302d 100644 --- a/vnet/vnet/lisp-cp/gid_dictionary.c +++ b/vnet/vnet/lisp-cp/gid_dictionary.c @@ -100,7 +100,7 @@ gid_dictionary_lookup (gid_dictionary_t * db, gid_address_t * key) /* XXX for now this only works with ip-prefixes, no lcafs */ switch (gid_address_type (key)) { - case IP_PREFIX: + case GID_ADDR_IP_PREFIX: return ip_lookup (db, 0, &gid_address_ippref(key)); break; default: @@ -264,7 +264,7 @@ gid_dictionary_add_del (gid_dictionary_t *db, gid_address_t *key, u32 value, /* XXX for now this only works with ip-prefixes, no lcafs */ switch (gid_address_type (key)) { - case IP_PREFIX: + case GID_ADDR_IP_PREFIX: return gid_dictionary_add_del_ip (db, 0, &gid_address_ippref(key), value, is_add); break; diff --git a/vnet/vnet/lisp-cp/lisp_cp_messages.h b/vnet/vnet/lisp-cp/lisp_cp_messages.h index 6142a0479d3..742e7fa0a09 100644 --- a/vnet/vnet/lisp-cp/lisp_cp_messages.h +++ b/vnet/vnet/lisp-cp/lisp_cp_messages.h @@ -430,4 +430,31 @@ typedef enum lisp_authoritative A_AUTHORITATIVE } lisp_authoritative_e; +/* + * LISP Canonical Address Format Encodings + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | AFI = 16387 | Rsvd1 | Flags | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Type | Rsvd2 | Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ + +typedef struct _lcaf_hdr_t +{ + u8 reserved1; + u8 flags; + u8 type; + u8 reserved2; + u16 len; +} __attribute__ ((__packed__)) lcaf_hdr_t; + +#define LCAF_TYPE(h) ((lcaf_hdr_t *)(h))->type +#define LCAF_LENGTH(h) ((lcaf_hdr_t *)(h))->len +#define LCAF_RES2(h) ((lcaf_hdr_t *)(h))->reserved2 +#define LCAF_FLAGS(h) ((lcaf_hdr_t *)(h))->flags +#define LCAF_PAYLOAD(h) (u8 *)(h)+sizeof(lcaf_hdr_t) + #endif /* VNET_LISP_GPE_LISP_CP_MESSAGES_H_ */ diff --git a/vnet/vnet/lisp-cp/lisp_msg_serdes.c b/vnet/vnet/lisp-cp/lisp_msg_serdes.c index 48e40cffa86..6c5546014b1 100644 --- a/vnet/vnet/lisp-cp/lisp_msg_serdes.c +++ b/vnet/vnet/lisp-cp/lisp_msg_serdes.c @@ -25,32 +25,19 @@ lisp_msg_put_gid (vlib_buffer_t * b, gid_address_t * gid) return p; } -void * +static void * lisp_msg_put_itr_rlocs (lisp_cp_main_t * lcm, vlib_buffer_t * b, - ip_address_t * rlocs, u8 * locs_put) + gid_address_t * rlocs, u8 * locs_put) { - u8 * p, * bp, count = 0; + u8 * bp, count = 0; u32 i; - ip_address_t * addr; - bp = vlib_buffer_get_current(b); - for (i = 0; i < vec_len(rlocs); i++) - { - addr = &rlocs[i]; - switch (ip_addr_version(addr)) + bp = vlib_buffer_get_current (b); + for (i = 0; i < vec_len (rlocs); i++) { - case IP4: - p = vlib_buffer_put_uninit (b, ip4_address_size_to_put()); - ip4_address_put (p, &ip_addr_v4(addr)); - count++; - break; - case IP6: - p = vlib_buffer_put_uninit (b, ip6_address_size_to_put()); - ip6_address_put (p, &ip_addr_v6(addr)); + lisp_msg_put_gid (b, &rlocs[i]); count++; - break; } - } *locs_put = count-1; return bp; @@ -92,8 +79,8 @@ nonce_build (u32 seed) void * lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b, - gid_address_t * seid, gid_address_t * deid, - ip_address_t * rlocs, u8 is_smr_invoked, u64 * nonce) + gid_address_t * seid, gid_address_t * deid, + gid_address_t * rlocs, u8 is_smr_invoked, u64 * nonce) { u8 loc_count = 0; @@ -127,7 +114,7 @@ lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t *b, int lp, int rp, gid_address_t *la, gid_address_t *ra) { ecm_hdr_t *h; - ASSERT(gid_address_type(la) == IP_PREFIX); + ASSERT(gid_address_type(la) == GID_ADDR_IP_PREFIX); /* Push inner ip and udp */ pkt_push_udp_and_ip (vm, b, lp, rp, &gid_address_ip(la), diff --git a/vnet/vnet/lisp-cp/lisp_msg_serdes.h b/vnet/vnet/lisp-cp/lisp_msg_serdes.h index d7eeb35d321..4c222699f02 100644 --- a/vnet/vnet/lisp-cp/lisp_msg_serdes.h +++ b/vnet/vnet/lisp-cp/lisp_msg_serdes.h @@ -23,7 +23,7 @@ void * lisp_msg_put_mreq (lisp_cp_main_t * lcm, vlib_buffer_t * b, gid_address_t * seid, gid_address_t * deid, - ip_address_t * rlocs, u8 is_smr_invoked, u64 * nonce); + gid_address_t * rlocs, u8 is_smr_invoked, u64 * nonce); void * lisp_msg_push_ecm (vlib_main_t * vm, vlib_buffer_t *b, int lp, int rp, diff --git a/vnet/vnet/lisp-cp/lisp_types.c b/vnet/vnet/lisp-cp/lisp_types.c index 1234c7caf95..c9f4405901b 100644 --- a/vnet/vnet/lisp-cp/lisp_types.c +++ b/vnet/vnet/lisp-cp/lisp_types.c @@ -17,20 +17,87 @@ typedef u16 (*size_to_write_fct)(void *); typedef void * (*cast_fct)(gid_address_t *); -typedef u16 (*write_fct)(u8 *, void *); +typedef u16 (*serdes_fct)(u8 *, void *); typedef u8 (*addr_len_fct)(void *); typedef void (*copy_fct)(void *, void *); +typedef void (*free_fct)(void *); +typedef int (*cmp_fct)(void *, void *); + +u16 vni_write (u8 * p, void * a); +u16 vni_parse (u8 * p, void * a); +u16 vni_size_to_write (void * a); +void vni_free (void * a); +void vni_copy (void * dst, void * src); +u16 vni_length (void * a); +int vni_cmp (void *, void *); + +u16 no_addr_size_to_write (void *); +u16 no_addr_write (u8 * p, void * a); +u16 no_addr_parse (u8 * p, void * a); +void no_addr_free (void * a); +void no_addr_copy (void *, void *); +u16 no_addr_length (void * a); +int no_addr_cmp (void * a1, void * a2); size_to_write_fct size_to_write_fcts[GID_ADDR_TYPES] = - { ip_prefix_size_to_write }; -write_fct write_fcts[GID_ADDR_TYPES] = - { ip_prefix_write }; + { ip_prefix_size_to_write, lcaf_size_to_write }; +serdes_fct write_fcts[GID_ADDR_TYPES] = + { ip_prefix_write, lcaf_write }; cast_fct cast_fcts[GID_ADDR_TYPES] = - { ip_prefix_cast }; + { ip_prefix_cast, lcaf_cast }; addr_len_fct addr_len_fcts[GID_ADDR_TYPES] = - { ip_prefix_length }; + { ip_prefix_length, lcaf_prefix_length }; copy_fct copy_fcts[GID_ADDR_TYPES] = - { ip_prefix_copy }; + { ip_prefix_copy, lcaf_copy }; + +cmp_fct lcaf_cmp_fcts[LCAF_TYPES] = + { + no_addr_cmp, + NULL, + vni_cmp + }; + +size_to_write_fct lcaf_body_length_fcts[LCAF_TYPES] = + { + no_addr_length, + NULL, + vni_length + }; + +copy_fct lcaf_copy_fcts[LCAF_TYPES] = + { + no_addr_copy, + NULL, + vni_copy + }; + +free_fct lcaf_free_fcts[LCAF_TYPES] = + { + no_addr_free, + NULL, + vni_free + }; + +size_to_write_fct lcaf_size_to_write_fcts[LCAF_TYPES] = + { + no_addr_size_to_write, + NULL, + vni_size_to_write + }; + +serdes_fct lcaf_write_fcts[LCAF_TYPES] = + { + no_addr_write, + NULL, + vni_write + }; + +serdes_fct lcaf_parse_fcts[LCAF_TYPES] = + { + no_addr_parse, + NULL, + vni_parse + }; u8 * format_ip_address (u8 * s, va_list * args) @@ -87,7 +154,7 @@ format_gid_address (u8 * s, va_list * args) u8 type = gid_address_type(a); switch (type) { - case IP_PREFIX: + case GID_ADDR_IP_PREFIX: return format (s, "%U", format_ip_prefix, &gid_address_ippref(a)); default: clib_warning("Can't format gid type %d", type); @@ -100,7 +167,7 @@ unformat_gid_address (unformat_input_t * input, va_list * args) { gid_address_t * a = va_arg(*args, gid_address_t *); if (unformat (input, "%U", unformat_ip_prefix, &gid_address_ippref(a))) - gid_address_type(a) = IP_PREFIX; + gid_address_type(a) = GID_ADDR_IP_PREFIX; else return 0; return 1; @@ -250,6 +317,88 @@ ip_address_parse(void * offset, u16 iana_afi, ip_address_t *dst) return(sizeof(u16) + size); } +u32 +lcaf_hdr_parse (void * offset, lcaf_t * lcaf) +{ + lcaf_hdr_t * lh = offset; + lcaf->type = lh->type; + + /* this is a bit of hack: since the LCAF Instance ID is the + only message that uses reserved2 field, we can set it here. + If any LCAF format starts using reserved2 field as well this needs + to be moved elsewhere */ + lcaf_vni_len (lcaf) = lh->reserved2; + + return sizeof (lh[0]); +} + +u16 +vni_parse (u8 * p, void * a) +{ + vni_t * v = 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])); + + size += gid_address_parse (p + size, gid); + return size; +} + +u16 +no_addr_parse (u8 * p, void * a) +{ + /* do nothing */ + return 0; +} + +u32 +lcaf_parse (void * offset, gid_address_t *addr) +{ + /* skip AFI type */ + offset += sizeof (u16); + lcaf_t * lcaf = &gid_address_lcaf (addr); + + u32 size = lcaf_hdr_parse (offset, lcaf); + u8 type = lcaf_type (lcaf); + + if (!lcaf_parse_fcts[type]) + { + clib_warning ("Unsupported LCAF type: %u", type); + return ~0; + } + size += (*lcaf_parse_fcts[type])(offset + size, lcaf); + return sizeof (u16) + size; +} + +void +vni_free (void * a) +{ + vni_t * v = a; + gid_address_free (vni_gid (v)); + clib_mem_free (vni_gid (v)); +} + +void +no_addr_free (void * a) +{ + /* nothing to do */ +} + +void +gid_address_free (gid_address_t *a) +{ + if (gid_address_type (a) != GID_ADDR_LCAF) + return; + + lcaf_t * lcaf = &gid_address_lcaf (a); + u8 lcaf_type = lcaf_type (lcaf); + (*lcaf_free_fcts[lcaf_type])(lcaf); +} + int ip_address_cmp (ip_address_t * ip1, ip_address_t * ip2) { @@ -339,6 +488,143 @@ ip_prefix_cmp(ip_prefix_t * p1, ip_prefix_t * p2) return cmp; } +void +no_addr_copy (void * dst, void * src) +{ + /* nothing to do */ +} + +void +vni_copy (void * dst, void * src) +{ + vni_t * vd = dst; + vni_t * vs = src; + + clib_memcpy (vd, vs, sizeof (vd[0])); + vni_gid (vd) = clib_mem_alloc (sizeof (gid_address_t)); + gid_address_copy (vni_gid (vd), vni_gid (vs)); +} + +void +lcaf_copy (void * dst , void * src) +{ + lcaf_t * lcaf_dst = dst; + lcaf_t * lcaf_src = src; + + lcaf_type (lcaf_dst) = lcaf_type (lcaf_src); + (*lcaf_copy_fcts[lcaf_type (lcaf_src)])(dst, src); +} + +u8 +lcaf_prefix_length (void *a) +{ + return 0; +} + +void * +lcaf_cast (gid_address_t * a) +{ + return &gid_address_lcaf (a); +} + +u16 +no_addr_length (void * a) +{ + return 0; +} + +u16 +vni_length (void * a) +{ + vni_t * v = a; + return (sizeof (u32) /* VNI size */ + + gid_address_size_to_put (vni_gid (v)) /* vni body size*/); +} + +u16 +lcaf_write (u8 * p, void * a) +{ + u16 size = 0, len; + lcaf_t * lcaf = a; + u8 type = lcaf_type (lcaf); + lcaf_hdr_t _h, *h = &_h; + + *(u16 *) p = clib_host_to_net_u16 (LISP_AFI_LCAF); + size += sizeof (u16); + memset (h, 0, sizeof (h[0])); + LCAF_TYPE (h) = type; + 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); + + if (~0 == len) + return ~0; + + return size + len; +} + +u16 +vni_write (u8 * p, void * a) +{ + vni_t * v = a; + u16 size = 0, len; + + *(u32 *)p = clib_host_to_net_u32 (vni_vni (v)); + size += sizeof (u32); + len = gid_address_put (p + size, vni_gid (v)); + + if (~0 == len) + return ~0; + + return size + len; +} + +u16 +no_addr_write (u8 * p, void * a) +{ + /* do nothing; return AFI field size */ + return sizeof (u16); +} + +u16 +no_addr_size_to_write (void * a) +{ + return sizeof (u16); /* AFI field length */ +} + +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)); +} + +u16 +lcaf_size_to_write (void * a) +{ + lcaf_t * lcaf = (lcaf_t *) a; + u32 size = 0, len; + u8 type = lcaf_type (lcaf); + + size += sizeof (u16); /* AFI size */ + + len = (*lcaf_size_to_write_fcts[type])(lcaf); + if (~0 == len) + return ~0; + + return size + len; +} + u8 gid_address_len (gid_address_t *a) { @@ -389,21 +675,24 @@ gid_address_parse (u8 * offset, gid_address_t *a) { case LISP_AFI_NO_ADDR: len = sizeof(u16); - gid_address_type(a) = NO_ADDRESS; + gid_address_type(a) = GID_ADDR_NO_ADDRESS; break; case LISP_AFI_IP: len = ip_address_parse (offset, afi, &gid_address_ip(a)); - gid_address_type(a) = IP_PREFIX; + gid_address_type(a) = GID_ADDR_IP_PREFIX; /* this should be modified outside if needed*/ gid_address_ippref_len(a) = 32; break; case LISP_AFI_IP6: len = ip_address_parse (offset, afi, &gid_address_ip(a)); - gid_address_type(a) = IP_PREFIX; + gid_address_type(a) = GID_ADDR_IP_PREFIX; /* this should be modified outside if needed*/ gid_address_ippref_len(a) = 128; break; case LISP_AFI_LCAF: + len = lcaf_parse (offset, a); + gid_address_type(a) = GID_ADDR_LCAF; + break; default: clib_warning("LISP AFI %d not supported!", afi); return ~0; @@ -411,6 +700,25 @@ gid_address_parse (u8 * offset, gid_address_t *a) return len; } +int +no_addr_cmp (void * a1, void * a2) +{ + return 0; +} + +int +vni_cmp (void * a1, void * a2) +{ + vni_t * v1 = a1; + vni_t * v2 = a2; + + if (vni_mask_len (v1) != vni_mask_len (v2)) + return -1; + if (vni_vni (v1) != vni_vni (v2)) + return -1; + return gid_address_cmp (vni_gid (v1), vni_gid (v2)); +} + /* Compare two gid_address_t. * Returns: * -1: If they are from different afi @@ -421,6 +729,7 @@ gid_address_parse (u8 * offset, gid_address_t *a) int gid_address_cmp (gid_address_t * a1, gid_address_t * a2) { + lcaf_t * lcaf1, * lcaf2; int cmp = -1; if (!a1 || !a2) return -1; @@ -429,15 +738,21 @@ gid_address_cmp (gid_address_t * a1, gid_address_t * a2) switch (gid_address_type(a1)) { - case NO_ADDRESS: + case GID_ADDR_NO_ADDRESS: if (a1 == a2) cmp = 0; else cmp = 2; break; - case IP_PREFIX: + case GID_ADDR_IP_PREFIX: cmp = ip_prefix_cmp (&gid_address_ippref(a1), &gid_address_ippref(a2)); break; + case GID_ADDR_LCAF: + lcaf1 = &gid_address_lcaf (a1); + lcaf2 = &gid_address_lcaf (a2); + if (lcaf_type (lcaf1) == lcaf_type (lcaf2)) + cmp = (*lcaf_cmp_fcts[lcaf_type (lcaf1)])(lcaf1, lcaf2); + break; default: break; } @@ -476,6 +791,8 @@ locator_copy (locator_t * dst, locator_t * src) { /* TODO if gid become more complex, this will need to be changed! */ clib_memcpy (dst, src, sizeof(*dst)); + if (!src->local) + gid_address_copy (&dst->address, &src->address); } u32 @@ -495,3 +812,10 @@ locator_cmp (locator_t * l1, locator_t * l2) return 1; return 0; } + +void +locator_free (locator_t * l) +{ + if (!l->local) + gid_address_free (&l->address); +} diff --git a/vnet/vnet/lisp-cp/lisp_types.h b/vnet/vnet/lisp-cp/lisp_types.h index 0aba9fb1f5e..8db3cfe7338 100644 --- a/vnet/vnet/lisp-cp/lisp_types.h +++ b/vnet/vnet/lisp-cp/lisp_types.h @@ -60,17 +60,65 @@ typedef enum { /* NOTE: ip addresses are left out on purpose. Use max masked ip-prefixes * instead */ - IP_PREFIX, - NO_ADDRESS, + GID_ADDR_IP_PREFIX, + GID_ADDR_LCAF, + GID_ADDR_NO_ADDRESS, GID_ADDR_TYPES } gid_address_type_t; -/* might want to expand this in the future :) */ +typedef enum +{ + /* make sure that values corresponds with RFC */ + LCAF_NULL_BODY = 0, + LCAF_AFI_LIST_TYPE, + LCAF_INSTANCE_ID, + LCAF_TYPES +} lcaf_type_t; + +struct _gid_address_t; + typedef struct +{ + u8 vni_mask_len; + u32 vni; + struct _gid_address_t *gid_addr; +} vni_t; + +#define vni_vni(_a) (_a)->vni +#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! */ + union + { + source_dest_t sd; + vni_t uni; + }; + u8 type; +} lcaf_t; + +#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 { union { ip_prefix_t ippref; + lcaf_t lcaf; }; u8 type; } gid_address_t; @@ -101,6 +149,7 @@ typedef enum { u8 *format_gid_address (u8 * s, va_list * args); uword unformat_gid_address (unformat_input_t * input, va_list * args); int gid_address_cmp (gid_address_t * a1, gid_address_t * a2); +void gid_address_free (gid_address_t *a); u16 gid_address_size_to_put (gid_address_t * a); u16 gid_address_put (u8 * b, gid_address_t * gid); @@ -113,6 +162,9 @@ u32 gid_address_parse (u8 * offset, gid_address_t *a); #define gid_address_ippref(_a) (_a)->ippref #define gid_address_ippref_len(_a) (_a)->ippref.len #define gid_address_ip(_a) ip_prefix_addr(&gid_address_ippref(_a)) +#define gid_address_lcaf(_a) (_a)->lcaf +#define gid_address_vni(_a) ( (GID_ADDR_LCAF == gid_address_type(_a)) ? \ + lcaf_vni(&gid_address_lcaf(_a)) : 0) /* 'sub'address functions */ u16 ip_prefix_size_to_write (void * pref); @@ -121,6 +173,13 @@ u8 ip_prefix_length (void *a); void *ip_prefix_cast (gid_address_t * a); void ip_prefix_copy (void * dst , void * src); +int lcaf_cmp (lcaf_t * lcaf1, lcaf_t * lcaf2); +u16 lcaf_size_to_write (void * pref); +u16 lcaf_write (u8 * p, void * pref); +u8 lcaf_prefix_length (void *a); +void *lcaf_cast (gid_address_t * a); +void lcaf_copy (void * dst , void * src); + typedef struct { /* mark locator as local as opposed to remote */ @@ -139,6 +198,7 @@ typedef struct u32 locator_parse (void * ptr, locator_t * loc); void locator_copy (locator_t * dst, locator_t * src); u32 locator_cmp (locator_t * l1, locator_t * l2); +void locator_free (locator_t * l); typedef struct { diff --git a/vnet/vnet/lisp-gpe/lisp_gpe.c b/vnet/vnet/lisp-gpe/lisp_gpe.c index 129bfc4cd1b..76a7fa25e9f 100644 --- a/vnet/vnet/lisp-gpe/lisp_gpe.c +++ b/vnet/vnet/lisp-gpe/lisp_gpe.c @@ -484,7 +484,7 @@ vnet_lisp_gpe_enable_disable (vnet_lisp_gpe_enable_disable_args_t * a) vec_foreach(tunnel, tunnels) { memset(at, 0, sizeof(at[0])); at->is_add = 0; - gid_address_type(&at->deid) = IP_PREFIX; + gid_address_type(&at->deid) = GID_ADDR_IP_PREFIX; ip_prefix_copy(&gid_address_ippref(&at->deid), &tunnel->eid); ip_address_copy(&at->dlocator, &tunnel->dst_loc); vnet_lisp_gpe_add_del_fwd_entry (at, 0); diff --git a/vpp/api/api.c b/vpp/api/api.c index bc2f64cde9f..9c988a18172 100644 --- a/vpp/api/api.c +++ b/vpp/api/api.c @@ -4583,7 +4583,7 @@ vl_api_lisp_add_del_local_eid_t_handler( prefp = &gid_address_ippref(&eid); ip_eid = &ip_prefix_addr(prefp); - gid_address_type (&eid) = IP_PREFIX; + gid_address_type (&eid) = GID_ADDR_IP_PREFIX; if (mp->is_ipv6) { clib_memcpy(&ip_addr_v6(ip_eid), mp->ip_address, @@ -4802,7 +4802,7 @@ send_lisp_local_eid_table_details (mapping_t *mapit, gid = &mapit->eid; type = gid_address_type(gid); - if (type != IP_PREFIX) { + if (type != GID_ADDR_IP_PREFIX) { return; } -- 2.16.6