lisp: move cp tests to unittest
[vpp.git] / src / plugins / unittest / lisp_cp_test.c
1 /*
2  * Copyright (c) 2019 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <vnet/vnet.h>
17 #include <vppinfra/error.h>
18 #include <vnet/lisp-cp/lisp_cp_messages.h>
19 #include <vnet/lisp-cp/control.h>
20 #include <vnet/lisp-cp/lisp_msg_serdes.h>
21 #include <vlibapi/api.h>
22 #include <vnet/lisp-cp/packets.h>
23
24 #define _assert(e)                                      \
25   error = CLIB_ERROR_ASSERT (e);                        \
26   if (error)                                            \
27     {                                                   \
28       fformat(stderr, "FAIL: line %d \n\n", __LINE__);  \
29       goto done;                                        \
30     }
31
32 static void
33 print_chunk (u8 * b, int *offset, int c, char *des)
34 {
35   int i, n = offset[0] + c;;
36   for (i = offset[0]; i < n; i++)
37     {
38       printf ("0x%02x, ", b[i]);
39     }
40   printf (" // %s\n", des);
41   *offset += c;
42 }
43
44 void
45 print_map_request (map_request_hdr_t * h)
46 {
47 #define pchunk(_count, _desc) \
48   print_chunk((u8 *)h, &offset, _count, _desc)
49
50   int offset = 0;
51
52   pchunk (4, "data");
53   pchunk (8, "Nonce");
54   pchunk (2, "Source-EID-AFI");
55   pchunk (4, "Source EID Address");
56   pchunk (2, "ITR-RLOC-AFI 1");
57   pchunk (4, "ITR-RLOC Address 1");
58   pchunk (2, "ITR-RLOC-AFI 2");
59   pchunk (16, "ITR-RLOC Address 2");
60   pchunk (1, "REC: reserved");
61   pchunk (1, "REC: EID mask-len");
62   pchunk (2, "REC: EID-prefix-AFI");
63   pchunk (4, "REC: EID-prefix");
64   printf ("\n");
65 }
66
67 static clib_error_t *
68 test_lisp_msg_push_ecm ()
69 {
70   vlib_main_t *vm = vlib_get_main ();
71   clib_error_t *error = 0;
72   gid_address_t la, ra;
73   vlib_buffer_t *b = 0;
74   u32 buff_len = 900;
75   int lp = 0x15, rp = 0x14;
76
77   b = clib_mem_alloc (buff_len);
78   clib_memset ((u8 *) b, 0, buff_len);
79   b->current_length = buff_len;
80   b->current_data = sizeof (udp_header_t) + sizeof (ip4_header_t) +
81     sizeof (ecm_hdr_t) + 1;
82
83   la.type = GID_ADDR_IP_PREFIX;
84   la.ippref.addr.ip.v4.as_u32 = 0xa1b2c3d4;
85   la.ippref.addr.version = IP4;
86
87   ra.type = GID_ADDR_IP_PREFIX;
88   ra.ippref.addr.ip.v4.as_u32 = 0x90817263;
89   ra.ippref.addr.version = IP4;
90
91   ecm_hdr_t *lh = lisp_msg_push_ecm (vm, b, lp, rp, &la, &ra);
92
93   u8 expected_ecm_hdr[] = {
94     0x80, 0x00, 0x00, 0x00
95   };
96   _assert (0 == memcmp (expected_ecm_hdr, lh, sizeof (expected_ecm_hdr)));
97
98   ip4_header_t *ih = (ip4_header_t *) (lh + 1);
99   /* clear ip checksum */
100   clib_memset ((u8 *) ih + 10, 0, 2);
101
102   /* *INDENT-OFF* */
103   u8 expected_ip4_hdr[] = {
104     0x45,                   /* version; IHL */
105     0x00,                   /* services */
106     0x03, 0xa0,             /* total length */
107     0x00, 0x00,             /* identification */
108     0x40, 0x00,             /* flags; fragment offset*/
109     0xff,                   /* TTL */
110     0x11,                   /* protocol */
111     0x00, 0x00,             /* header checksum */
112     0xd4, 0xc3, 0xb2, 0xa1, /* src IP */
113     0x63, 0x72, 0x81, 0x90, /* dst IP */
114   };
115   /* *INDENT-ON* */
116
117   _assert (0 == memcmp (ih, expected_ip4_hdr, sizeof (expected_ip4_hdr)));
118
119   udp_header_t *uh = (udp_header_t *) (ih + 1);
120   /* clear udp checksum */
121   clib_memset ((u8 *) uh + 6, 0, 2);
122
123   /* *INDENT-OFF* */
124   u8 expected_udp_hdr[] = {
125     0x00, 0x15, /* src port */
126     0x00, 0x14, /* dst port */
127     0x03, 0x8c, /* length */
128     0x00, 0x00, /* checksum */
129   };
130   /* *INDENT-ON* */
131
132   _assert (0 == memcmp (uh, expected_udp_hdr, sizeof (expected_udp_hdr)));
133
134 done:
135   clib_mem_free (b);
136   return error;
137 }
138
139 static clib_error_t *
140 test_lisp_msg_parse_mapping_record ()
141 {
142   clib_error_t *error = 0;
143   locator_t probed;
144   locator_t *locs = 0;
145   vlib_buffer_t *b = 0;
146   gid_address_t eid;
147   u32 buff_len = 500;
148
149   b = clib_mem_alloc (buff_len);
150   clib_memset ((u8 *) b, 0, buff_len);
151
152   /* *INDENT-OFF* */
153   u8 map_reply_records[] = {
154     /* 1. record */
155     0x01, 0x02, 0x03, 0x04, /* record TTL */
156     0x01,                   /* locator count */
157     0x00, 0x00, 0x00,       /* eid-mask-len; ... */
158     0x00, 0x00,             /* reserved; map-version num */
159     0x00, 0x01,             /* EID-Prefix-AFI */
160     0x33, 0x44, 0x55, 0x66, /* eid-prefix */
161     /* loc */
162     0x0a,                   /* prority */
163     0x0b,                   /* weight */
164     0x0c,                   /* m-prority */
165     0x0d,                   /* m-weight */
166     0x00, 0x00,             /* unused flags */
167     0x00, 0x01,             /* Loc-AFI */
168     0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
169   };
170   /* *INDENT-ON* */
171
172   b->current_length = buff_len;
173   clib_memcpy (b->data, map_reply_records, sizeof (map_reply_records));
174
175   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
176   _assert (vec_len (locs) == 1);
177   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x66554433);
178   _assert (locs[0].local == 0);
179   _assert (locs[0].address.ippref.addr.ip.v4.as_u32 == 0xddccbbaa);
180   _assert (locs[0].address.type == GID_ADDR_IP_PREFIX);
181   _assert (locs[0].priority == 0xa);
182   _assert (locs[0].weight == 0xb);
183   _assert (locs[0].mpriority == 0xc);
184   _assert (locs[0].mweight == 0xd);
185
186 done:
187   clib_mem_free (b);
188   if (locs)
189     vec_free (locs);
190   return error;
191 }
192
193 static map_request_hdr_t *
194 build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b,
195                    gid_address_t * rlocs)
196 {
197   gid_address_t _seid, *seid = &_seid;
198   gid_address_t _deid, *deid = &_deid;
199   u8 is_smr_invoked = 1;
200   u8 rloc_probe_set = 0;
201   u64 nonce = 0;
202   map_request_hdr_t *h = 0;
203   clib_memset (deid, 0, sizeof (deid[0]));
204   clib_memset (seid, 0, sizeof (seid[0]));
205
206   gid_address_type (seid) = GID_ADDR_IP_PREFIX;
207   ip_address_t *ip_addr = &gid_address_ip (seid);
208   ip_addr_v4 (ip_addr).as_u32 = 0x12345678;
209   seid->ippref.addr.version = IP4;
210
211   gid_address_type (deid) = GID_ADDR_IP_PREFIX;
212   ip_address_t *ip_addr2 = &gid_address_ip (deid);
213   ip_addr_v4 (ip_addr2).as_u32 = 0x9abcdef0;
214   deid->ippref.addr.version = IP4;
215   gid_address_ippref_len (deid) = 24;
216
217   h = lisp_msg_put_mreq (lcm, b, seid, deid, rlocs,
218                          is_smr_invoked, rloc_probe_set, &nonce);
219   vec_free (rlocs);
220   return h;
221 }
222
223 static void
224 generate_rlocs (gid_address_t ** rlocs, u32 * count)
225 {
226   gid_address_t gid_addr_data, *gid_addr = &gid_addr_data;
227   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
228   ip_address_t *addr = &gid_address_ip (gid_addr);
229
230   gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX;
231
232   ip_addr_version (addr) = IP4;
233   ip_addr_v4 (addr).data_u32 = 0x10203040;
234   vec_add1 (rlocs[0], gid_addr[0]);
235
236   ip_addr_v6 (addr).as_u32[0] = 0xffeeddcc;
237   ip_addr_v6 (addr).as_u32[1] = 0xbbaa9988;
238   ip_addr_v6 (addr).as_u32[2] = 0x77665544;
239   ip_addr_v6 (addr).as_u32[3] = 0x33221100;
240   ip_addr_version (addr) = IP6;
241   vec_add1 (rlocs[0], gid_addr[0]);
242 }
243
244 static clib_error_t *
245 test_lisp_msg_parse ()
246 {
247   gid_address_t eid;
248   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
249   map_request_hdr_t *h;
250   gid_address_t gid;
251   clib_error_t *error = 0;
252   vlib_buffer_t *b;
253   gid_address_t *rlocs_decode = 0, *rlocs = 0;
254   u32 rloc_count_parse = 0;
255
256   u8 *data = clib_mem_alloc (500);
257   clib_memset (data, 0, 500);
258   b = (vlib_buffer_t *) data;
259
260   generate_rlocs (&rlocs_decode, &rloc_count_parse);
261   h = build_map_request (lcm, b, rlocs_decode);
262
263   vlib_buffer_pull (b, sizeof (*h));
264   u32 len = lisp_msg_parse_addr (b, &gid);
265   _assert (len == 2 + 4
266            /* Source-EID-AFI field lenght + IPv4 address length */ );
267   _assert (gid.ippref.addr.ip.v4.as_u32 == 0x12345678);
268   _assert (gid.ippref.addr.version == IP4);
269
270   u8 rloc_count = MREQ_ITR_RLOC_COUNT (h) + 1;
271   lisp_msg_parse_itr_rlocs (b, &rlocs, rloc_count);
272
273   _assert (vec_len (rlocs) == 2);
274   _assert (rlocs[0].ippref.addr.ip.v4.as_u32 == 0x10203040);
275   _assert (rlocs[0].ippref.addr.version == IP4);
276
277   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[0] == 0xffeeddcc);
278   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[1] == 0xbbaa9988);
279   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[2] == 0x77665544);
280   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[3] == 0x33221100);
281   _assert (rlocs[1].ippref.addr.version == IP6);
282
283   lisp_msg_parse_eid_rec (b, &eid);
284   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x9abcdef0);
285   _assert (eid.ippref.addr.version == IP4);
286   _assert (eid.ippref.len == 24);
287
288 done:
289   clib_mem_free (data);
290   if (rlocs)
291     vec_free (rlocs);
292   return error;
293 }
294
295 static clib_error_t *
296 test_lisp_msg_put_mreq_with_lcaf ()
297 {
298   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
299   clib_error_t *error = 0;
300   map_request_hdr_t *h = 0;
301   gid_address_t *rlocs = 0;
302
303   ip_prefix_t ippref;
304   ip_prefix_version (&ippref) = IP4;
305   ip4_address_t *ip = &ip_prefix_v4 (&ippref);
306   ip->as_u32 = 0x11223344;
307
308   gid_address_t g = {
309     .type = GID_ADDR_IP_PREFIX,
310     .ippref = ippref,
311     .vni = 0x90919293,
312     .vni_mask = 0x17
313   };
314   vec_add1 (rlocs, g);
315
316   u8 *data = clib_mem_alloc (500);
317   clib_memset (data, 0, 500);
318
319   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
320
321   /* clear Nonce to simplify comparison */
322   clib_memset ((u8 *) h + 4, 0, 8);
323
324   /* *INDENT-OFF* */
325   u8 expected_data[] =
326     {
327       0x10, 0x40, 0x00, 0x01, /* type; flags; IRC; REC count */
328       0x00, 0x00, 0x00, 0x00,
329       0x00, 0x00, 0x00, 0x00, /* nonce */
330       0x00, 0x01,             /* Source-EID-AFI */
331       0x78, 0x56, 0x34, 0x12, /* Source EID Address */
332
333       /* RLOCs */
334       0x40, 0x03,             /* AFI = LCAF*/
335       /* LCAF header*/
336       0x00, 0x00,             /* reserved1, flags */
337       0x02,                   /* type = Instance ID */
338       0x17,                   /* IID mask-len */
339       0x00, 0x0a,             /* lenght */
340       0x90, 0x91, 0x92, 0x93, /* IID / VNI */
341
342       0x00, 0x01,             /* AFI = ipv4 */
343       0x44, 0x33, 0x22, 0x11, /* ITR-RLOC Address 1 */
344
345       /* record */
346       0x00,                   /* reserved */
347       0x18,                   /* EID mask-len */
348       0x00, 0x01,             /* EID-prefix-AFI */
349       0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
350     };
351   /* *INDENT-ON* */
352
353   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
354 done:
355   clib_mem_free (data);
356   return error;
357 }
358
359 static clib_error_t *
360 test_lisp_msg_put_mreq ()
361 {
362   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
363   clib_error_t *error = 0;
364   map_request_hdr_t *h;
365   gid_address_t *rlocs = 0;
366   u32 rloc_count = 0;
367
368   u8 *data = clib_mem_alloc (500);
369   clib_memset (data, 0, 500);
370
371   generate_rlocs (&rlocs, &rloc_count);
372   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
373
374   /* clear Nonce to simplify comparison */
375   clib_memset ((u8 *) h + 4, 0, 8);
376
377   print_map_request (h);
378
379   /* *INDENT-OFF* */
380   u8 expected_data[50] = {
381     0x10, 0x40, 0x01, 0x01, /* type; flags; IRC; REC count */
382     0x00, 0x00, 0x00, 0x00,
383     0x00, 0x00, 0x00, 0x00, /* nonce */
384     0x00, 0x01,             /* Source-EID-AFI */
385     0x78, 0x56, 0x34, 0x12, /* Source EID Address */
386
387     /* RLOCs */
388     0x00, 0x01,             /* ITR-RLOC-AFI 1 */
389     0x40, 0x30, 0x20, 0x10, /* ITR-RLOC Address 1 */
390     0x00, 0x02,             /* ITR-RLOC-AFI 2 */
391     0xcc, 0xdd, 0xee, 0xff,
392     0x88, 0x99, 0xaa, 0xbb,
393     0x44, 0x55, 0x66, 0x77,
394     0x00, 0x11, 0x22, 0x33, /* ITR-RLOC Address 2 */
395
396     /* record */
397     0x00,                   /* reserved */
398     0x18,                   /* EID mask-len */
399     0x00, 0x01,             /* EID-prefix-AFI */
400     0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
401   };
402   /* *INDENT-ON* */
403
404   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
405
406 done:
407   clib_mem_free (data);
408   return error;
409 }
410
411 /* generate a vector of eid records */
412 static mapping_t *
413 build_test_map_records ()
414 {
415   mapping_t *records = 0;
416
417   /* *INDENT-OFF* */
418   mapping_t r = {
419     .ttl = MAP_REGISTER_DEFAULT_TTL,
420     .eid = {
421       .type = GID_ADDR_MAC,
422       .mac = {1, 2, 3, 4, 5, 6},
423       .vni = 0x0
424     }
425   };
426
427   locator_t loc = {
428     .weight = 1,
429     .priority = 2,
430     .local = 1,
431     .address = {
432       .type = GID_ADDR_IP_PREFIX,
433       .ippref = {
434         .addr = {
435           .ip.v4.as_u32 = 0x99887766,
436           .version = IP4
437         }
438       }
439     }
440   };
441   /* *INDENT-ON* */
442
443   vec_add1 (r.locators, loc);
444   vec_add1 (records, r);
445
446   return records;
447 }
448
449 static void
450 free_test_map_records (mapping_t * maps)
451 {
452   mapping_t *map;
453   vec_foreach (map, maps)
454   {
455     vec_free (map->locators);
456   }
457   vec_free (maps);
458 }
459
460 static clib_error_t *
461 test_lisp_map_register ()
462 {
463   vlib_buffer_t *b;
464   clib_error_t *error = 0;
465   u64 nonce;
466   u32 msg_len = 0;
467   mapping_t *records = build_test_map_records ();
468
469   u8 *data = clib_mem_alloc (500);
470   clib_memset (data, 0, 500);
471   b = (vlib_buffer_t *) data;
472
473   lisp_msg_put_map_register (b, records, 1 /* want map notify */ ,
474                              20 /* length of HMAC_SHA_1_96 */ ,
475                              &nonce, &msg_len);
476   free_test_map_records (records);
477
478   /* clear Nonce to simplify comparison */
479   clib_memset ((u8 *) b->data + 4, 0, 8);
480
481   /* clear authentication data */
482   clib_memset ((u8 *) b->data + 16, 0, 20);
483
484   /* *INDENT-OFF* */
485   u8 expected_data[] = {
486     0x30, 0x00, 0x01, 0x01, /* type; rsvd; want notify; REC count */
487     0x00, 0x00, 0x00, 0x00,
488     0x00, 0x00, 0x00, 0x00, /* nonce */
489     0x00, 0x00, 0x00, 0x00, /* key id, auth data length:
490                               both are zeroes because those are set in another
491                               function (see auth_data_len_by_key_id())*/
492     0x00, 0x00, 0x00, 0x00,
493     0x00, 0x00, 0x00, 0x00,
494     0x00, 0x00, 0x00, 0x00,
495     0x00, 0x00, 0x00, 0x00,
496     0x00, 0x00, 0x00, 0x00, /* auth data */
497
498     /* first record */
499     /* 0x00, 0x00, 0x03, 0x84, */ /* default ttl (15 minues) */
500     0x00, 0x01, 0x51, 0x80, /* default ttl (24h = 86400s) */
501     0x01, 0x00, 0x00, 0x00, /* loc count, eid len, ACT, A */
502     0x00, 0x00, 0x40, 0x05, /* rsvd, map ver num, AFI = MAC */
503     0x01, 0x02, 0x03, 0x04,
504     0x05, 0x06,             /* MAC EID */
505
506     /* locator 1 */
507     0x02, 0x01, 0x00, 0x00, /* prio, weight, mprio, mweight */
508     0x00, 0x04, 0x00, 0x01, /* flags, AFI = ipv4 */
509     0x66, 0x77, 0x88, 0x99, /* ipv4 locator address */
510   };
511   /* *INDENT-ON* */
512
513   _assert (0 == memcmp (expected_data, b->data, sizeof (expected_data)));
514 done:
515   clib_mem_free (data);
516   return error;
517 }
518
519 static vlib_buffer_t *
520 create_buffer (u8 * data, u32 data_len)
521 {
522   vlib_buffer_t *b;
523
524   u8 *buf_data = clib_mem_alloc (500);
525   clib_memset (buf_data, 0, 500);
526   b = (vlib_buffer_t *) buf_data;
527
528   u8 *p = vlib_buffer_put_uninit (b, data_len);
529   clib_memcpy (p, data, data_len);
530
531   return b;
532 }
533
534 static clib_error_t *
535 test_lisp_parse_map_reply ()
536 {
537   clib_error_t *error = 0;
538
539   /* *INDENT-OFF* */
540   u8 map_reply_data[] =
541     {
542       0x00, 0x00, 0x00, 0x01, /* type; rsvd; mapping count */
543       0x00, 0x00, 0x00, 0x00,
544     };
545   /* *INDENT-ON* */
546
547   vlib_buffer_t *b = create_buffer (map_reply_data, sizeof (map_reply_data));
548   map_records_arg_t *mrecs = parse_map_reply (b);
549   _assert (0 == mrecs);
550   clib_mem_free (b);
551
552   /* *INDENT-OFF* */
553   u8 map_reply_data2[] =
554     {
555       0x00, 0x00, 0x00, 0x01, /* type; rsvd */
556       0x00, 0x00, 0x00, 0x00,
557       0x00, 0x00, 0x00, 0x00, /* nonce */
558
559       /* 1. record  - incomplete */
560       0x01, 0x02, 0x03, 0x04, /* record TTL */
561       0x01,                   /* locator count */
562     };
563   /* *INDENT-ON* */
564
565   b = create_buffer (map_reply_data2, sizeof (map_reply_data2));
566   mrecs = parse_map_reply (b);
567   _assert (0 == mrecs);
568 done:
569   clib_mem_free (b);
570   return error;
571 }
572
573 static clib_error_t *
574 test_lisp_parse_lcaf ()
575 {
576   int i;
577   clib_error_t *error = 0;
578   gid_address_t eid;
579   locator_t *locs = 0;
580   locator_t probed;
581   vlib_buffer_t *b = 0;
582   u32 buff_len = 500;
583
584   b = clib_mem_alloc (buff_len);
585   clib_memset ((u8 *) b, 0, buff_len);
586
587   /* *INDENT-OFF* */
588   u8 map_reply_records[] =
589     {
590       /* 1. record */
591       0x01, 0x02, 0x03, 0x04, /* record TTL */
592       0x03,                   /* locator count */
593       0x00, 0x00, 0x00,       /* eid-mask-len; ... */
594       0x00, 0x00,             /* reserved; map-version num */
595       0x00, 0x01,             /* EID-Prefix-AFI */
596       0x33, 0x44, 0x55, 0x66, /* eid-prefix */
597
598       /* 1st locator */
599       0x0a,                   /* prority */
600       0x0b,                   /* weight */
601       0x0c,                   /* m-prority */
602       0x0d,                   /* m-weight */
603       0x00, 0x00,             /* unused flags */
604       0x40, 0x03,             /* Loc-AFI = LCAF*/
605
606       /* LCAF header*/
607       0x00, 0x00,             /* reserved1, flags */
608       0x02,                   /* type = Instance ID */
609       0x18,                   /* IID mask-len */
610       0x00, 0x0a,             /* lenght */
611       /* LCAF Instance ID */
612       0x00, 0x00, 0x00, 0x09, /* iid */
613       0x00, 0x01,             /* AFI = ipv4 */
614       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 loator address */
615
616       /* 2nd locator */
617       0x07,                   /* prority */
618       0x06,                   /* weight */
619       0x05,                   /* m-prority */
620       0x04,                   /* m-weight */
621       0x00, 0x00,             /* unused flags */
622       0x40, 0x03,             /* Loc-AFI = LCAF*/
623
624       /* LCAF header*/
625       0x00, 0x00,             /* reserved1, flags */
626       0x02,                   /* type = Instance ID */
627       0x18,                   /* IID mask-len */
628       0x00, 0x16,             /* iid length + next AFI lenght */
629       /* LCAF Instance ID */
630       0x22, 0x44, 0x66, 0x88, /* iid */
631       0x00, 0x02,             /* AFI = ipv6 */
632       0xcc, 0xdd, 0xee, 0xff,
633       0x88, 0x99, 0xaa, 0xbb,
634       0x44, 0x55, 0x66, 0x77,
635       0x00, 0x11, 0x22, 0x33, /* ipv6 locator address */
636
637       /* 3rd locator */
638       0x0a,                   /* prority */
639       0x0b,                   /* weight */
640       0x0c,                   /* m-prority */
641       0x0d,                   /* m-weight */
642       0x00, 0x00,             /* unused flags */
643       0x00, 0x01,             /* Loc-AFI */
644       0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
645     };
646   /* *INDENT-ON* */
647
648   b->current_length = buff_len;
649   memcpy (b->data, map_reply_records, sizeof (map_reply_records));
650
651   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
652   _assert (vec_len (locs) == 3);
653   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x66554433);
654
655   /* check 1st locator - an LCAF with ipv4 */
656   _assert (locs[0].local == 0);
657   _assert (locs[0].priority == 0xa);
658   _assert (locs[0].weight == 0xb);
659   _assert (locs[0].mpriority == 0xc);
660   _assert (locs[0].mweight == 0xd);
661
662   _assert (gid_address_type (&locs[0].address) == GID_ADDR_IP_PREFIX);
663   _assert (gid_address_vni (&locs[0].address) == 0x09);
664   ip_prefix_t *ip_pref = &gid_address_ippref (&locs[0].address);
665   _assert (IP4 == ip_prefix_version (ip_pref));
666
667   /* 2nd locator - LCAF entry with ipv6 address */
668   _assert (locs[1].local == 0);
669   _assert (locs[1].priority == 0x7);
670   _assert (locs[1].weight == 0x6);
671   _assert (locs[1].mpriority == 0x5);
672   _assert (locs[1].mweight == 0x4);
673
674   _assert (gid_address_type (&locs[1].address) == GID_ADDR_IP_PREFIX);
675   _assert (0x22446688 == gid_address_vni (&locs[1].address));
676   ip_pref = &gid_address_ippref (&locs[1].address);
677   _assert (IP6 == ip_prefix_version (ip_pref));
678
679   /* 3rd locator - simple ipv4 address */
680   _assert (gid_address_type (&locs[2].address) == GID_ADDR_IP_PREFIX);
681 done:
682   clib_mem_free (b);
683
684   for (i = 0; i < 3; i++)
685     locator_free (&locs[i]);
686   vec_free (locs);
687   return error;
688 }
689
690 #define foreach_test_case                 \
691   _(lisp_msg_put_mreq)                    \
692   _(lisp_msg_put_mreq_with_lcaf)          \
693   _(lisp_msg_push_ecm)                    \
694   _(lisp_msg_parse)                       \
695   _(lisp_msg_parse_mapping_record)        \
696   _(lisp_parse_map_reply)                 \
697   _(lisp_parse_lcaf)                      \
698   _(lisp_map_register)
699
700 static int
701 lisp_cp_serdes_tests (vlib_main_t * vm, unformat_input_t * input)
702 {
703   clib_error_t *error;
704
705 #define _(_test_name)                                   \
706   error = test_ ## _test_name ();                       \
707   if (error)                                            \
708     {                                                   \
709       fformat (stderr, "FAIL: test_" #_test_name "\n"); \
710       return -1;                                        \
711     }                                                   \
712   else                                                  \
713       fformat (stderr, "PASS: test_" #_test_name "\n"); \
714
715   foreach_test_case
716 #undef _
717     return 0;
718 }
719
720 static clib_error_t *
721 test_locator_type (void)
722 {
723   clib_error_t *error = 0;
724   gid_address_t _gid_addr, *gid = &_gid_addr;
725   ip_prefix_t *ippref;
726   gid_address_type (gid) = GID_ADDR_IP_PREFIX;
727   gid_address_ippref_len (gid) = 24;
728   ippref = &gid_address_ippref (gid);
729   ip_prefix_version (ippref) = IP4;
730   ip_prefix_len (ippref) = 0;
731   ip4_address_t *ip4 = &ip_prefix_v4 (ippref);
732   ip4->as_u32 = 0x20304050;
733
734   /* local locator */
735   locator_t loc1, loc2 = {
736     .local = 1,
737     .state = 2,
738     .sw_if_index = 8,
739     .priority = 3,
740     .weight = 100,
741     .mpriority = 4,
742     .mweight = 101
743   };
744   locator_copy (&loc1, &loc2);
745   _assert (0 == locator_cmp (&loc1, &loc2));
746
747   /* remote locator */
748   loc2.local = 0;
749
750   ip_prefix_t nested_ippref;
751   ip_prefix_version (&nested_ippref) = IP4;
752   ip_prefix_len (&nested_ippref) = 0;
753   ip4 = &ip_prefix_v4 (&nested_ippref);
754   ip4->as_u32 = 0x33882299;
755   gid_address_t nested_gid = {
756     .type = GID_ADDR_IP_PREFIX,
757     .ippref = nested_ippref
758   };
759
760   lcaf_t lcaf = {
761     .type = LCAF_INSTANCE_ID,
762     .uni = {
763             .vni_mask_len = 5,
764             .vni = 0xa1b2c3d4,
765             .gid_addr = &nested_gid}
766   };
767   gid_address_type (gid) = GID_ADDR_LCAF;
768   gid_address_lcaf (gid) = lcaf;
769
770   loc2.address = gid[0];
771   locator_copy (&loc1, &loc2);
772
773   _assert (0 == locator_cmp (&loc1, &loc2));
774
775 done:
776   locator_free (&loc1);
777   return error;
778 }
779
780 static clib_error_t *
781 test_gid_parse_ip_pref ()
782 {
783   clib_error_t *error = 0;
784   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
785   gid_address_t _gid_addr_copy, *copy = &_gid_addr_copy;
786
787   /* *INDENT-OFF* */
788   u8 data[] =
789     {
790       0x00, 0x01,             /* AFI = IPv4 */
791       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */
792     };
793   /* *INDENT-ON* */
794
795   u32 len = gid_address_parse (data, gid_addr);
796   _assert (6 == len);
797   gid_address_copy (copy, gid_addr);
798   _assert (0 == gid_address_cmp (copy, gid_addr));
799 done:
800   return error;
801 }
802
803 static clib_error_t *
804 test_gid_parse_mac ()
805 {
806   clib_error_t *error = 0;
807   gid_address_t _gid, *gid = &_gid;
808   gid_address_t _gid_copy, *gid_copy = &_gid_copy;
809
810   /* *INDENT-OFF* */
811   u8 data[] =
812     {
813       0x40, 0x05,             /* AFI = MAC address */
814       0x10, 0xbb, 0xcc, 0xdd, /* MAC */
815       0x77, 0x99,
816     };
817   /* *INDENT-ON* */
818
819   u32 len = gid_address_parse (data, gid);
820   _assert (8 == len);
821   _assert (GID_ADDR_MAC == gid_address_type (gid));
822   gid_address_copy (gid_copy, gid);
823   _assert (0 == gid_address_cmp (gid_copy, gid));
824 done:
825   return error;
826 }
827
828 static clib_error_t *
829 test_gid_write_nsh (void)
830 {
831   clib_error_t *error = 0;
832
833   u8 *b = clib_mem_alloc (500);
834   clib_memset (b, 0, 500);
835
836   gid_address_t g = {
837     .vni = 0,
838     .nsh.spi = 0x112233,
839     .nsh.si = 0x42,
840     .type = GID_ADDR_NSH,
841   };
842
843   u16 len = gid_address_put (b, &g);
844
845   /* *INDENT-OFF* */
846   u8 expected[] =
847     {
848       0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
849       0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
850
851       /* Service Path ID, Service index */
852       0x11, 0x22, 0x33, 0x42, /* SPI, SI */
853     };
854   /* *INDENT-ON* */
855
856   _assert (sizeof (expected) == len);
857   _assert (0 == memcmp (expected, b, len));
858 done:
859   clib_mem_free (b);
860   return error;
861 }
862
863 static clib_error_t *
864 test_gid_parse_nsh ()
865 {
866   clib_error_t *error = 0;
867   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
868   gid_address_t _gid_addr_copy, *copy = &_gid_addr_copy;
869
870   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
871   clib_memset (copy, 0, sizeof (copy[0]));
872
873   /* *INDENT-OFF* */
874   u8 data[] =
875     {
876       0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
877       0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
878
879       /* Service Path ID, Service index */
880       0x55, 0x99, 0x42, 0x09, /* SPI, SI */
881     };
882   /* *INDENT-ON* */
883
884   u32 len = gid_address_parse (data, gid_addr);
885   _assert (sizeof (data) == len);
886   gid_address_copy (copy, gid_addr);
887   _assert (0 == gid_address_cmp (gid_addr, copy));
888   _assert (GID_ADDR_NSH == gid_address_type (copy));
889   _assert (0 == gid_address_vni (copy));
890   _assert (gid_address_nsh_spi (copy) == 0x559942);
891   _assert (gid_address_nsh_si (copy) == 0x09);
892
893 done:
894   gid_address_free (copy);
895   gid_address_free (gid_addr);
896   return error;
897 }
898
899 static clib_error_t *
900 test_gid_parse_lcaf ()
901 {
902   clib_error_t *error = 0;
903   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
904   gid_address_t _gid_addr_copy, *gid_addr_copy = &_gid_addr_copy;
905
906   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
907   clib_memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0]));
908
909   /* *INDENT-OFF* */
910   u8 data[] =
911     {
912       0x40, 0x03,             /* AFI = LCAF*/
913
914       /* LCAF header*/
915       0x00, 0x00,             /* reserved1, flags */
916       0x02,                   /* type = Instance ID */
917       0x18,                   /* IID mask-len */
918       0x00, 0x0a,             /* iid length + next AFI lenght */
919       /* LCAF Instance ID */
920       0x00, 0x00, 0x00, 0x09, /* iid */
921       0x00, 0x01,             /* AFI = ipv4 */
922       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */
923     };
924   /* *INDENT-ON* */
925
926   u32 len = gid_address_parse (data, gid_addr);
927   _assert (18 == len);
928   gid_address_copy (gid_addr_copy, gid_addr);
929   _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
930   _assert (GID_ADDR_IP_PREFIX == gid_address_type (gid_addr));
931   _assert (9 == gid_address_vni (gid_addr));
932   _assert (0x18 == gid_address_vni_mask (gid_addr));
933   _assert (0xddccbb10 == gid_addr->ippref.addr.ip.v4.as_u32);
934
935 done:
936   gid_address_free (gid_addr);
937   gid_address_free (gid_addr_copy);
938   return error;
939 }
940
941 /* recursive LCAFs are not supported */
942 #if 0
943 static clib_error_t *
944 test_gid_parse_lcaf_complex ()
945 {
946   clib_error_t *error = 0;
947   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
948   gid_address_t _gid_addr_copy, *gid_addr_copy = &_gid_addr_copy;
949
950   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
951   clib_memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0]));
952
953   /* *INDENT-OFF* */
954   u8 data[] = {
955     0x40, 0x03,                 /* AFI = LCAF */
956
957     /* LCAF header */
958     0x00, 0x00,                 /* reserved1, flags */
959     0x02,                       /* type = Instance ID */
960     0x18,                       /* IID mask-len */
961     0x00, 0x0a,                 /* iid length + next AFI lenght */
962     /* LCAF Instance ID */
963     0x00, 0x00, 0x00, 0x0b,     /* iid */
964
965     0x40, 0x03,                 /* AFI = LCAF */
966     /* LCAF header */
967     0x00, 0x00,                 /* reserved1, flags */
968     0x02,                       /* type = Instance ID */
969     0x17,                       /* IID mask-len */
970     0x00, 0x0a,                 /* iid length + next AFI lenght */
971     /* LCAF Instance ID */
972     0x00, 0x00, 0x00, 0x0c,     /* iid */
973
974     0x40, 0x03,                 /* AFI = LCAF */
975     /* LCAF header */
976     0x00, 0x00,                 /* reserved1, flags */
977     0x02,                       /* type = Instance ID */
978     0x16,                       /* IID mask-len */
979     0x00, 0x16,                 /* iid length + next AFI lenght */
980     /* LCAF Instance ID */
981     0x00, 0x00, 0x00, 0x0d,     /* iid */
982
983     0x00, 0x02,                 /* AFI = IPv6 */
984
985     0x10, 0xbb, 0xcc, 0xdd,
986     0x10, 0xbb, 0xcc, 0xdd,
987     0x10, 0xbb, 0xcc, 0xdd,
988     0x10, 0xbb, 0xcc, 0xdd,     /* ipv6 address */
989   };
990   /* *INDENT-ON* */
991
992   u32 len = gid_address_parse (data, gid_addr);
993   _assert (54 == len);
994   _assert (gid_addr->type == GID_ADDR_LCAF);
995   gid_address_copy (gid_addr_copy, gid_addr);
996   _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
997   _assert (gid_addr_copy->type == GID_ADDR_LCAF);
998
999   lcaf_t *lcaf = &gid_address_lcaf (gid_addr_copy);
1000   _assert (lcaf->type == LCAF_INSTANCE_ID);
1001   vni_t *v = (vni_t *) lcaf;
1002   _assert (v->vni == 0x0b);
1003   _assert (v->vni_mask_len == 0x18);
1004
1005   gid_address_t *tmp = vni_gid (v);
1006   _assert (gid_address_type (tmp) == GID_ADDR_LCAF);
1007   lcaf = &gid_address_lcaf (tmp);
1008   _assert (lcaf->type == LCAF_INSTANCE_ID);
1009
1010   v = (vni_t *) lcaf;
1011   _assert (v->vni == 0x0c);
1012   _assert (v->vni_mask_len == 0x17);
1013
1014   tmp = vni_gid (v);
1015   _assert (gid_address_type (tmp) == GID_ADDR_LCAF);
1016   lcaf = &gid_address_lcaf (tmp);
1017
1018   _assert (lcaf->type == LCAF_INSTANCE_ID);
1019   v = (vni_t *) lcaf;
1020   _assert (v->vni == 0x0d);
1021   _assert (v->vni_mask_len == 0x16);
1022
1023   tmp = vni_gid (v);
1024   _assert (gid_address_type (tmp) == GID_ADDR_IP_PREFIX);
1025
1026   ip_prefix_t *ip_pref = &gid_address_ippref (tmp);
1027   ip6_address_t *ip6 = &ip_prefix_v6 (ip_pref);
1028   _assert (ip6->as_u32[0] == 0xddccbb10);
1029   _assert (ip6->as_u32[1] == 0xddccbb10);
1030   _assert (ip6->as_u32[2] == 0xddccbb10);
1031   _assert (ip6->as_u32[3] == 0xddccbb10);
1032   _assert (ip_prefix_version (ip_pref) == IP6);
1033
1034 done:
1035   gid_address_free (gid_addr);
1036   gid_address_free (gid_addr_copy);
1037   return error;
1038 }
1039 #endif
1040
1041 static clib_error_t *
1042 test_write_mac_in_lcaf (void)
1043 {
1044   clib_error_t *error = 0;
1045
1046   u8 *b = clib_mem_alloc (500);
1047   clib_memset (b, 0, 500);
1048
1049   gid_address_t g = {
1050     .mac = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6},
1051     .vni = 0x01020304,
1052     .vni_mask = 0x10,
1053     .type = GID_ADDR_MAC,
1054   };
1055
1056   u16 len = gid_address_put (b, &g);
1057
1058   /* *INDENT-OFF* */
1059   u8 expected[] =
1060     {
1061       0x40, 0x03,             /* AFI = LCAF */
1062       0x00,                   /* reserved1 */
1063       0x00,                   /* flags */
1064       0x02,                   /* LCAF type = Instance ID */
1065       0x10,                   /* IID/IID mask len */
1066       0x00, 0x0c,             /* length */
1067       0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */
1068
1069       0x40, 0x05,             /* AFI = MAC */
1070       0x01, 0x02, 0x03, 0x04,
1071       0x05, 0x06              /* MAC */
1072     };
1073   /* *INDENT-ON* */
1074
1075   _assert (sizeof (expected) == len);
1076   _assert (0 == memcmp (expected, b, len));
1077 done:
1078   clib_mem_free (b);
1079   return error;
1080 }
1081
1082 static clib_error_t *
1083 test_mac_address_write (void)
1084 {
1085   clib_error_t *error = 0;
1086
1087   u8 *b = clib_mem_alloc (500);
1088   clib_memset (b, 0, 500);
1089
1090   gid_address_t g = {
1091     .mac = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6},
1092     .type = GID_ADDR_MAC,
1093   };
1094
1095   u16 len = gid_address_put (b, &g);
1096   _assert (8 == len);
1097
1098   /* *INDENT-OFF* */
1099   u8 expected[] =
1100     {
1101       0x40, 0x05,             /* AFI = MAC */
1102       0x01, 0x02, 0x03, 0x04,
1103       0x05, 0x06              /* MAC */
1104     };
1105   /* *INDENT-ON* */
1106
1107   _assert (0 == memcmp (expected, b, len));
1108 done:
1109   clib_mem_free (b);
1110   return error;
1111 }
1112
1113 static clib_error_t *
1114 test_src_dst_with_vni_serdes (void)
1115 {
1116   clib_error_t *error = 0;
1117   u8 *b = clib_mem_alloc (500);
1118   clib_memset (b, 0, 500);
1119
1120   /* *INDENT-OFF* */
1121   fid_address_t src =
1122     {
1123       .type = FID_ADDR_IP_PREF,
1124       .ippref =
1125         {
1126           .len = 24,
1127           .addr =
1128             {
1129               .version = IP4,
1130               .ip.v4.data = { 0x1, 0x2, 0x3, 0x0 }
1131             }
1132         }
1133     };
1134
1135   fid_address_t dst =
1136     {
1137       .type = FID_ADDR_IP_PREF,
1138       .ippref =
1139         {
1140           .len = 16,
1141           .addr =
1142             {
1143               .version = IP4,
1144               .ip.v4.data = { 0x9, 0x8, 0x0, 0x0 }
1145             }
1146         }
1147     };
1148
1149   source_dest_t sd =
1150     {
1151       .src = src,
1152       .dst = dst
1153     };
1154
1155   gid_address_t g =
1156     {
1157       .sd = sd,
1158       .type = GID_ADDR_SRC_DST,
1159       .vni = 0x12345678,
1160       .vni_mask = 0x9
1161     };
1162
1163   /* *INDENT-ON* */
1164
1165   u16 size_to_put = gid_address_size_to_put (&g);
1166   _assert (36 == size_to_put);
1167   _assert (0 == gid_address_len (&g));
1168
1169   u16 write_len = gid_address_put (b, &g);
1170   _assert (size_to_put == write_len);
1171
1172   /* *INDENT-OFF* */
1173   u8 expected_data[] =
1174     {
1175       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1176       0x02, 0x09, 0x00, 0x1c,  /* LCAF type = IID, IID mask-len, length */
1177       0x12, 0x34, 0x56, 0x78,  /* reserved; source-ML, Dest-ML */
1178
1179       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1180       0x0c, 0x00, 0x00, 0x10,  /* LCAF type = source/dest key, rsvd, length */
1181       0x00, 0x00, 0x18, 0x10,  /* reserved; source-ML, Dest-ML */
1182
1183       0x00, 0x01,              /* AFI = ip4 */
1184       0x01, 0x02, 0x03, 0x00,  /* source */
1185
1186       0x00, 0x01,              /* AFI = ip4 */
1187       0x09, 0x08, 0x00, 0x00,  /* destination */
1188     };
1189   /* *INDENT-ON* */
1190
1191   _assert (0 == memcmp (expected_data, b, sizeof (expected_data)));
1192
1193   gid_address_t p;
1194   clib_memset (&p, 0, sizeof (p));
1195   _assert (write_len == gid_address_parse (b, &p));
1196   _assert (0 == gid_address_cmp (&g, &p));
1197 done:
1198   clib_mem_free (b);
1199   return error;
1200 }
1201
1202 static clib_error_t *
1203 test_src_dst_deser_bad_afi (void)
1204 {
1205   clib_error_t *error = 0;
1206
1207   /* *INDENT-OFF* */
1208   u8 expected_data[] =
1209     {
1210       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1211       0x0c, 0x00, 0x00, 0x14,  /* LCAF type = source/dest key, rsvd, length */
1212       0x00, 0x00, 0x00, 0x00,  /* reserved; source-ML, Dest-ML */
1213
1214       0xde, 0xad,              /* AFI = bad value */
1215       0x11, 0x22, 0x33, 0x44,
1216       0x55, 0x66,              /* source */
1217
1218       0x40, 0x05,              /* AFI = MAC */
1219       0x10, 0x21, 0x32, 0x43,
1220       0x54, 0x65,              /* destination */
1221     };
1222   /* *INDENT-ON* */
1223
1224   gid_address_t p;
1225   _assert (~0 == gid_address_parse (expected_data, &p));
1226 done:
1227   return error;
1228 }
1229
1230 static clib_error_t *
1231 test_src_dst_serdes (void)
1232 {
1233   clib_error_t *error = 0;
1234
1235   u8 *b = clib_mem_alloc (500);
1236   clib_memset (b, 0, 500);
1237
1238   fid_address_t src = {
1239     .type = FID_ADDR_MAC,
1240     .mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
1241   };
1242
1243   fid_address_t dst = {
1244     .type = FID_ADDR_MAC,
1245     .mac = {0x10, 0x21, 0x32, 0x43, 0x54, 0x65}
1246   };
1247
1248   source_dest_t sd = {
1249     .src = src,
1250     .dst = dst
1251   };
1252
1253   gid_address_t g = {
1254     .sd = sd,
1255     .type = GID_ADDR_SRC_DST,
1256     .vni = 0x0,
1257     .vni_mask = 0x0
1258   };
1259
1260   u16 size_to_put = gid_address_size_to_put (&g);
1261   _assert (28 == size_to_put);
1262   _assert (0 == gid_address_len (&g));
1263
1264   u16 write_len = gid_address_put (b, &g);
1265   _assert (size_to_put == write_len);
1266
1267   /* *INDENT-OFF* */
1268   u8 expected_data[] =
1269     {
1270       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1271       0x0c, 0x00, 0x00, 0x14,  /* LCAF type = source/dest key, rsvd, length */
1272       0x00, 0x00, 0x00, 0x00,  /* reserved; source-ML, Dest-ML */
1273
1274       0x40, 0x05,              /* AFI = MAC */
1275       0x11, 0x22, 0x33, 0x44,
1276       0x55, 0x66,              /* source */
1277
1278       0x40, 0x05,              /* AFI = MAC */
1279       0x10, 0x21, 0x32, 0x43,
1280       0x54, 0x65,              /* destination */
1281     };
1282   /* *INDENT-ON* */
1283
1284   _assert (0 == memcmp (expected_data, b, sizeof (expected_data)));
1285
1286   gid_address_t p;
1287   clib_memset (&p, 0, sizeof (p));
1288   _assert (write_len == gid_address_parse (b, &p));
1289   _assert (0 == gid_address_cmp (&g, &p));
1290 done:
1291   clib_mem_free (b);
1292   return error;
1293 }
1294
1295 static clib_error_t *
1296 test_gid_address_write (void)
1297 {
1298   clib_error_t *error = 0;
1299   ip_prefix_t ippref_data, *ippref = &ippref_data;
1300
1301   u8 *b = clib_mem_alloc (500);
1302   clib_memset (b, 0, 500);
1303
1304   ip_prefix_version (ippref) = IP4;
1305   ip_prefix_len (ippref) = 9;
1306   ip4_address_t *ip4 = &ip_prefix_v4 (ippref);
1307   ip4->as_u32 = 0xaabbccdd;
1308
1309   gid_address_t g = {
1310     .ippref = ippref[0],
1311     .type = GID_ADDR_IP_PREFIX,
1312     .vni = 0x01020304,
1313     .vni_mask = 0x18
1314   };
1315
1316   _assert (18 == gid_address_size_to_put (&g));
1317   _assert (gid_address_len (&g) == 9);
1318
1319   u16 write_len = gid_address_put (b, &g);
1320   _assert (18 == write_len);
1321
1322   /* *INDENT-OFF* */
1323   u8 expected_gid_data[] =
1324     {
1325       0x40, 0x03,             /* AFI = LCAF */
1326       0x00,                   /* reserved1 */
1327       0x00,                   /* flags */
1328       0x02,                   /* LCAF type = Instance ID */
1329       0x18,                   /* IID/VNI mask len */
1330       0x00, 0x0a,             /* length */
1331       0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */
1332
1333       0x00, 0x01,             /* AFI = IPv4 */
1334       0xdd, 0xcc, 0xbb, 0xaa, /* ipv4 addr */
1335     };
1336   /* *INDENT-ON* */
1337
1338   _assert (0 == memcmp (expected_gid_data, b, sizeof (expected_gid_data)));
1339 done:
1340   clib_mem_free (b);
1341   return error;
1342 }
1343
1344 #undef foreach_test_case
1345
1346 #define foreach_test_case                 \
1347   _(locator_type)                         \
1348   _(gid_parse_ip_pref)                    \
1349   _(gid_parse_mac)                        \
1350   _(gid_parse_lcaf)                       \
1351   _(gid_parse_nsh)                        \
1352   _(gid_write_nsh)                        \
1353   _(mac_address_write)                    \
1354   _(gid_address_write)                    \
1355   _(src_dst_serdes)                       \
1356   _(write_mac_in_lcaf)                    \
1357   _(src_dst_deser_bad_afi)                \
1358   _(src_dst_with_vni_serdes)
1359
1360 static int
1361 lisp_cp_types_tests (vlib_main_t * vm, unformat_input_t * input)
1362 {
1363   clib_error_t *error;
1364
1365 #define _(_test_name)                                   \
1366   error = test_ ## _test_name ();                       \
1367   if (error)                                            \
1368     {                                                   \
1369       fformat (stderr, "FAIL: test_" #_test_name "\n"); \
1370       return -1;                                        \
1371     }                                                   \
1372   else                                                  \
1373       fformat (stderr, "PASS: test_" #_test_name "\n"); \
1374
1375   foreach_test_case
1376 #undef _
1377     return 0;
1378 }
1379
1380 #undef _assert
1381
1382 static clib_error_t *
1383 lisp_cp_test (vlib_main_t * vm, unformat_input_t * input,
1384               vlib_cli_command_t * cmd_arg)
1385 {
1386   int res = 0;
1387
1388   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1389     {
1390       if (unformat (input, "serdes"))
1391         {
1392           res = lisp_cp_serdes_tests (vm, input);
1393         }
1394       if (unformat (input, "types"))
1395         {
1396           res = lisp_cp_types_tests (vm, input);
1397         }
1398       else if (unformat (input, "all"))
1399         {
1400           if ((res = lisp_cp_serdes_tests (vm, input)))
1401             goto done;
1402           if ((res = lisp_cp_types_tests (vm, input)))
1403             goto done;
1404         }
1405       else
1406         break;
1407     }
1408
1409 done:
1410   if (res)
1411     return clib_error_return (0, "rbtree unit test failed");
1412   return 0;
1413 }
1414
1415 /* *INDENT-OFF* */
1416 VLIB_CLI_COMMAND (lisp_cp_command, static) =
1417 {
1418   .path = "test lisp cp",
1419   .short_help = "lisp cp internal unit tests",
1420   .function = lisp_cp_test,
1421 };
1422 /* *INDENT-ON* */
1423
1424
1425 /*
1426  * fd.io coding-style-patch-verification: ON
1427  *
1428  * Local Variables:
1429  * eval: (c-set-style "gnu")
1430  * End:
1431  */