Add support for LCAF Instance ID 81/881/4
authorFilip Tehlar <ftehlar@cisco.com>
Wed, 20 Apr 2016 15:21:55 +0000 (17:21 +0200)
committerFilip Tehlar <ftehlar@cisco.com>
Fri, 29 Apr 2016 12:16:53 +0000 (14:16 +0200)
Change-Id: Ifce3f2bdcba099157a42d0b694f3161b9f700ed2
Signed-off-by: Filip Tehlar <ftehlar@cisco.com>
vnet/test/lisp-cp/test_cp_serdes.c
vnet/test/lisp-cp/test_lisp_types.c
vnet/vnet/lisp-cp/control.c
vnet/vnet/lisp-cp/gid_dictionary.c
vnet/vnet/lisp-cp/lisp_cp_messages.h
vnet/vnet/lisp-cp/lisp_msg_serdes.c
vnet/vnet/lisp-cp/lisp_msg_serdes.h
vnet/vnet/lisp-cp/lisp_types.c
vnet/vnet/lisp-cp/lisp_types.h
vnet/vnet/lisp-gpe/lisp_gpe.c
vpp/api/api.c

index d77c294..2ca391e 100644 (file)
@@ -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)
 {
index efd8722..b846cf6 100644 (file)
 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)
 {
index 3eabf36..9a88402 100644 (file)
@@ -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++)
     {
index 4da5203..8dc3fd4 100644 (file)
@@ -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;
index 6142a04..742e7fa 100644 (file)
@@ -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_ */
index 48e40cf..6c55460 100644 (file)
@@ -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),
index d7eeb35..4c22269 100644 (file)
@@ -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,
index 1234c7c..c9f4405 100644 (file)
 
 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);
+}
index 0aba9fb..8db3cfe 100644 (file)
@@ -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
 {
index 129bfc4..76a7fa2 100644 (file)
@@ -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);
index bc2f64c..9c988a1 100644 (file)
@@ -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;
     }