lisp: Move to plugin
[vpp.git] / src / plugins / lisp / test / 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 <lisp/lisp-cp/lisp_cp_messages.h>
19 #include <lisp/lisp-cp/control.h>
20 #include <lisp/lisp-cp/lisp_msg_serdes.h>
21 #include <vlibapi/api.h>
22 #include <lisp/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.ip4.as_u32 = 0xa1b2c3d4;
85   la.ippref.addr.version = AF_IP4;
86
87   ra.type = GID_ADDR_IP_PREFIX;
88   ra.ippref.addr.ip.ip4.as_u32 = 0x90817263;
89   ra.ippref.addr.version = AF_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.ip4.as_u32 == 0x66554433);
178   _assert (locs[0].local == 0);
179   _assert (locs[0].address.ippref.addr.ip.ip4.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 = AF_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 = AF_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) = AF_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) = AF_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.ip4.as_u32 == 0x12345678);
268   _assert (gid.ippref.addr.version == AF_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.ip4.as_u32 == 0x10203040);
275   _assert (rlocs[0].ippref.addr.version == AF_IP4);
276
277   _assert (rlocs[1].ippref.addr.ip.ip6.as_u32[0] == 0xffeeddcc);
278   _assert (rlocs[1].ippref.addr.ip.ip6.as_u32[1] == 0xbbaa9988);
279   _assert (rlocs[1].ippref.addr.ip.ip6.as_u32[2] == 0x77665544);
280   _assert (rlocs[1].ippref.addr.ip.ip6.as_u32[3] == 0x33221100);
281   _assert (rlocs[1].ippref.addr.version == AF_IP6);
282
283   lisp_msg_parse_eid_rec (b, &eid);
284   _assert (eid.ippref.addr.ip.ip4.as_u32 == 0x9abcdef0);
285   _assert (eid.ippref.addr.version == AF_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) = AF_IP4;
305   ip4_address_t *ip = &ip_prefix_v4 (&ippref);
306   ip->as_u32 = 0x11223344;
307   ippref.len = 32;
308
309   gid_address_t g = {
310     .type = GID_ADDR_IP_PREFIX,
311     .ippref = ippref,
312     .vni = 0x90919293,
313     .vni_mask = 0x17
314   };
315   vec_add1 (rlocs, g);
316
317   u8 *data = clib_mem_alloc (500);
318   clib_memset (data, 0, 500);
319
320   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
321
322   /* clear Nonce to simplify comparison */
323   clib_memset ((u8 *) h + 4, 0, 8);
324
325   /* *INDENT-OFF* */
326   u8 expected_data[] =
327     {
328       0x10, 0x40, 0x00, 0x01, /* type; flags; IRC; REC count */
329       0x00, 0x00, 0x00, 0x00,
330       0x00, 0x00, 0x00, 0x00, /* nonce */
331       0x00, 0x01,             /* Source-EID-AFI */
332       0x78, 0x56, 0x34, 0x12, /* Source EID Address */
333
334       /* RLOCs */
335       0x40, 0x03,             /* AFI = LCAF*/
336       /* LCAF header*/
337       0x00, 0x00,             /* reserved1, flags */
338       0x02,                   /* type = Instance ID */
339       0x17,                   /* IID mask-len */
340       0x00, 0x0a,             /* lenght */
341       0x90, 0x91, 0x92, 0x93, /* IID / VNI */
342
343       0x00, 0x01,             /* AFI = ipv4 */
344       0x44, 0x33, 0x22, 0x11, /* ITR-RLOC Address 1 */
345
346       /* record */
347       0x00,                   /* reserved */
348       0x18,                   /* EID mask-len */
349       0x00, 0x01,             /* EID-prefix-AFI */
350       0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
351     };
352   /* *INDENT-ON* */
353
354   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
355 done:
356   clib_mem_free (data);
357   return error;
358 }
359
360 static clib_error_t *
361 test_lisp_msg_put_mreq ()
362 {
363   lisp_cp_main_t *lcm = vnet_lisp_cp_get_main ();
364   clib_error_t *error = 0;
365   map_request_hdr_t *h;
366   gid_address_t *rlocs = 0;
367   u32 rloc_count = 0;
368
369   u8 *data = clib_mem_alloc (500);
370   clib_memset (data, 0, 500);
371
372   generate_rlocs (&rlocs, &rloc_count);
373   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
374
375   /* clear Nonce to simplify comparison */
376   clib_memset ((u8 *) h + 4, 0, 8);
377
378   print_map_request (h);
379
380   /* *INDENT-OFF* */
381   u8 expected_data[50] = {
382     0x10, 0x40, 0x01, 0x01, /* type; flags; IRC; REC count */
383     0x00, 0x00, 0x00, 0x00,
384     0x00, 0x00, 0x00, 0x00, /* nonce */
385     0x00, 0x01,             /* Source-EID-AFI */
386     0x78, 0x56, 0x34, 0x12, /* Source EID Address */
387
388     /* RLOCs */
389     0x00, 0x01,             /* ITR-RLOC-AFI 1 */
390     0x40, 0x30, 0x20, 0x10, /* ITR-RLOC Address 1 */
391     0x00, 0x02,             /* ITR-RLOC-AFI 2 */
392     0xcc, 0xdd, 0xee, 0xff,
393     0x88, 0x99, 0xaa, 0xbb,
394     0x44, 0x55, 0x66, 0x77,
395     0x00, 0x11, 0x22, 0x33, /* ITR-RLOC Address 2 */
396
397     /* record */
398     0x00,                   /* reserved */
399     0x18,                   /* EID mask-len */
400     0x00, 0x01,             /* EID-prefix-AFI */
401     0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
402   };
403   /* *INDENT-ON* */
404
405   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
406
407 done:
408   clib_mem_free (data);
409   return error;
410 }
411
412 /* generate a vector of eid records */
413 static mapping_t *
414 build_test_map_records ()
415 {
416   mapping_t *records = 0;
417
418   /* *INDENT-OFF* */
419   mapping_t r = {
420     .ttl = MAP_REGISTER_DEFAULT_TTL,
421     .eid = {
422       .type = GID_ADDR_MAC,
423       .mac = {1, 2, 3, 4, 5, 6},
424       .vni = 0x0
425     }
426   };
427
428   locator_t loc = {
429     .weight = 1,
430     .priority = 2,
431     .local = 1,
432     .address = {
433       .type = GID_ADDR_IP_PREFIX,
434       .ippref = {
435         .addr = {
436           .ip.ip4.as_u32 = 0x99887766,
437           .version = AF_IP4
438         }
439       }
440     }
441   };
442   /* *INDENT-ON* */
443
444   vec_add1 (r.locators, loc);
445   vec_add1 (records, r);
446
447   return records;
448 }
449
450 static void
451 free_test_map_records (mapping_t * maps)
452 {
453   mapping_t *map;
454   vec_foreach (map, maps)
455   {
456     vec_free (map->locators);
457   }
458   vec_free (maps);
459 }
460
461 static clib_error_t *
462 test_lisp_map_register ()
463 {
464   vlib_buffer_t *b;
465   clib_error_t *error = 0;
466   u64 nonce;
467   u32 msg_len = 0;
468   mapping_t *records = build_test_map_records ();
469
470   u8 *data = clib_mem_alloc (500);
471   clib_memset (data, 0, 500);
472   b = (vlib_buffer_t *) data;
473
474   lisp_msg_put_map_register (b, records, 1 /* want map notify */ ,
475                              20 /* length of HMAC_SHA_1_96 */ ,
476                              &nonce, &msg_len);
477   free_test_map_records (records);
478
479   /* clear Nonce to simplify comparison */
480   clib_memset ((u8 *) b->data + 4, 0, 8);
481
482   /* clear authentication data */
483   clib_memset ((u8 *) b->data + 16, 0, 20);
484
485   /* *INDENT-OFF* */
486   u8 expected_data[] = {
487     0x30, 0x00, 0x01, 0x01, /* type; rsvd; want notify; REC count */
488     0x00, 0x00, 0x00, 0x00,
489     0x00, 0x00, 0x00, 0x00, /* nonce */
490     0x00, 0x00, 0x00, 0x00, /* key id, auth data length:
491                               both are zeroes because those are set in another
492                               function (see auth_data_len_by_key_id())*/
493     0x00, 0x00, 0x00, 0x00,
494     0x00, 0x00, 0x00, 0x00,
495     0x00, 0x00, 0x00, 0x00,
496     0x00, 0x00, 0x00, 0x00,
497     0x00, 0x00, 0x00, 0x00, /* auth data */
498
499     /* first record */
500     /* 0x00, 0x00, 0x03, 0x84, */ /* default ttl (15 minues) */
501     0x00, 0x01, 0x51, 0x80, /* default ttl (24h = 86400s) */
502     0x01, 0x00, 0x00, 0x00, /* loc count, eid len, ACT, A */
503     0x00, 0x00, 0x40, 0x05, /* rsvd, map ver num, AFI = MAC */
504     0x01, 0x02, 0x03, 0x04,
505     0x05, 0x06,             /* MAC EID */
506
507     /* locator 1 */
508     0x02, 0x01, 0x00, 0x00, /* prio, weight, mprio, mweight */
509     0x00, 0x04, 0x00, 0x01, /* flags, AFI = ipv4 */
510     0x66, 0x77, 0x88, 0x99, /* ipv4 locator address */
511   };
512   /* *INDENT-ON* */
513
514   _assert (0 == memcmp (expected_data, b->data, sizeof (expected_data)));
515 done:
516   clib_mem_free (data);
517   return error;
518 }
519
520 static vlib_buffer_t *
521 create_buffer (u8 * data, u32 data_len)
522 {
523   vlib_buffer_t *b;
524
525   u8 *buf_data = clib_mem_alloc (500);
526   clib_memset (buf_data, 0, 500);
527   b = (vlib_buffer_t *) buf_data;
528
529   u8 *p = vlib_buffer_put_uninit (b, data_len);
530   clib_memcpy (p, data, data_len);
531
532   return b;
533 }
534
535 static clib_error_t *
536 test_lisp_parse_map_reply ()
537 {
538   clib_error_t *error = 0;
539
540   /* *INDENT-OFF* */
541   u8 map_reply_data[] =
542     {
543       0x00, 0x00, 0x00, 0x01, /* type; rsvd; mapping count */
544       0x00, 0x00, 0x00, 0x00,
545     };
546   /* *INDENT-ON* */
547
548   vlib_buffer_t *b = create_buffer (map_reply_data, sizeof (map_reply_data));
549   map_records_arg_t *mrecs = parse_map_reply (b);
550   _assert (0 == mrecs);
551   clib_mem_free (b);
552
553   /* *INDENT-OFF* */
554   u8 map_reply_data2[] =
555     {
556       0x00, 0x00, 0x00, 0x01, /* type; rsvd */
557       0x00, 0x00, 0x00, 0x00,
558       0x00, 0x00, 0x00, 0x00, /* nonce */
559
560       /* 1. record  - incomplete */
561       0x01, 0x02, 0x03, 0x04, /* record TTL */
562       0x01,                   /* locator count */
563     };
564   /* *INDENT-ON* */
565
566   b = create_buffer (map_reply_data2, sizeof (map_reply_data2));
567   mrecs = parse_map_reply (b);
568   _assert (0 == mrecs);
569 done:
570   clib_mem_free (b);
571   return error;
572 }
573
574 static clib_error_t *
575 test_lisp_parse_lcaf ()
576 {
577   int i;
578   clib_error_t *error = 0;
579   gid_address_t eid;
580   locator_t *locs = 0;
581   locator_t probed;
582   vlib_buffer_t *b = 0;
583   u32 buff_len = 500;
584
585   b = clib_mem_alloc (buff_len);
586   clib_memset ((u8 *) b, 0, buff_len);
587
588   /* *INDENT-OFF* */
589   u8 map_reply_records[] =
590     {
591       /* 1. record */
592       0x01, 0x02, 0x03, 0x04, /* record TTL */
593       0x03,                   /* locator count */
594       0x00, 0x00, 0x00,       /* eid-mask-len; ... */
595       0x00, 0x00,             /* reserved; map-version num */
596       0x00, 0x01,             /* EID-Prefix-AFI */
597       0x33, 0x44, 0x55, 0x66, /* eid-prefix */
598
599       /* 1st locator */
600       0x0a,                   /* prority */
601       0x0b,                   /* weight */
602       0x0c,                   /* m-prority */
603       0x0d,                   /* m-weight */
604       0x00, 0x00,             /* unused flags */
605       0x40, 0x03,             /* Loc-AFI = LCAF*/
606
607       /* LCAF header*/
608       0x00, 0x00,             /* reserved1, flags */
609       0x02,                   /* type = Instance ID */
610       0x18,                   /* IID mask-len */
611       0x00, 0x0a,             /* lenght */
612       /* LCAF Instance ID */
613       0x00, 0x00, 0x00, 0x09, /* iid */
614       0x00, 0x01,             /* AFI = ipv4 */
615       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 loator address */
616
617       /* 2nd locator */
618       0x07,                   /* prority */
619       0x06,                   /* weight */
620       0x05,                   /* m-prority */
621       0x04,                   /* m-weight */
622       0x00, 0x00,             /* unused flags */
623       0x40, 0x03,             /* Loc-AFI = LCAF*/
624
625       /* LCAF header*/
626       0x00, 0x00,             /* reserved1, flags */
627       0x02,                   /* type = Instance ID */
628       0x18,                   /* IID mask-len */
629       0x00, 0x16,             /* iid length + next AFI lenght */
630       /* LCAF Instance ID */
631       0x22, 0x44, 0x66, 0x88, /* iid */
632       0x00, 0x02,             /* AFI = ipv6 */
633       0xcc, 0xdd, 0xee, 0xff,
634       0x88, 0x99, 0xaa, 0xbb,
635       0x44, 0x55, 0x66, 0x77,
636       0x00, 0x11, 0x22, 0x33, /* ipv6 locator address */
637
638       /* 3rd locator */
639       0x0a,                   /* prority */
640       0x0b,                   /* weight */
641       0x0c,                   /* m-prority */
642       0x0d,                   /* m-weight */
643       0x00, 0x00,             /* unused flags */
644       0x00, 0x01,             /* Loc-AFI */
645       0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
646     };
647   /* *INDENT-ON* */
648
649   b->current_length = buff_len;
650   memcpy (b->data, map_reply_records, sizeof (map_reply_records));
651
652   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
653   _assert (vec_len (locs) == 3);
654   _assert (eid.ippref.addr.ip.ip4.as_u32 == 0x66554433);
655
656   /* check 1st locator - an LCAF with ipv4 */
657   _assert (locs[0].local == 0);
658   _assert (locs[0].priority == 0xa);
659   _assert (locs[0].weight == 0xb);
660   _assert (locs[0].mpriority == 0xc);
661   _assert (locs[0].mweight == 0xd);
662
663   _assert (gid_address_type (&locs[0].address) == GID_ADDR_IP_PREFIX);
664   _assert (gid_address_vni (&locs[0].address) == 0x09);
665   ip_prefix_t *ip_pref = &gid_address_ippref (&locs[0].address);
666   _assert (AF_IP4 == ip_prefix_version (ip_pref));
667
668   /* 2nd locator - LCAF entry with ipv6 address */
669   _assert (locs[1].local == 0);
670   _assert (locs[1].priority == 0x7);
671   _assert (locs[1].weight == 0x6);
672   _assert (locs[1].mpriority == 0x5);
673   _assert (locs[1].mweight == 0x4);
674
675   _assert (gid_address_type (&locs[1].address) == GID_ADDR_IP_PREFIX);
676   _assert (0x22446688 == gid_address_vni (&locs[1].address));
677   ip_pref = &gid_address_ippref (&locs[1].address);
678   _assert (AF_IP6 == ip_prefix_version (ip_pref));
679
680   /* 3rd locator - simple ipv4 address */
681   _assert (gid_address_type (&locs[2].address) == GID_ADDR_IP_PREFIX);
682 done:
683   clib_mem_free (b);
684
685   for (i = 0; i < 3; i++)
686     locator_free (&locs[i]);
687   vec_free (locs);
688   return error;
689 }
690
691 #define foreach_test_case                 \
692   _(lisp_msg_put_mreq)                    \
693   _(lisp_msg_put_mreq_with_lcaf)          \
694   _(lisp_msg_push_ecm)                    \
695   _(lisp_msg_parse)                       \
696   _(lisp_msg_parse_mapping_record)        \
697   _(lisp_parse_map_reply)                 \
698   _(lisp_parse_lcaf)                      \
699   _(lisp_map_register)
700
701 static int
702 lisp_cp_serdes_tests (vlib_main_t * vm, unformat_input_t * input)
703 {
704   clib_error_t *error;
705
706 #define _(_test_name)                                   \
707   error = test_ ## _test_name ();                       \
708   if (error)                                            \
709     {                                                   \
710       fformat (stderr, "FAIL: test_" #_test_name "\n"); \
711       return -1;                                        \
712     }                                                   \
713   else                                                  \
714       fformat (stderr, "PASS: test_" #_test_name "\n"); \
715
716   foreach_test_case
717 #undef _
718     return 0;
719 }
720
721 static clib_error_t *
722 test_locator_type (void)
723 {
724   clib_error_t *error = 0;
725   gid_address_t _gid_addr, *gid = &_gid_addr;
726   ip_prefix_t *ippref;
727   gid_address_type (gid) = GID_ADDR_IP_PREFIX;
728   gid_address_ippref_len (gid) = 24;
729   ippref = &gid_address_ippref (gid);
730   ip_prefix_version (ippref) = AF_IP4;
731   ip_prefix_len (ippref) = 0;
732   ip4_address_t *ip4 = &ip_prefix_v4 (ippref);
733   ip4->as_u32 = 0x20304050;
734
735   /* local locator */
736   locator_t loc1, loc2 = {
737     .local = 1,
738     .state = 2,
739     .sw_if_index = 8,
740     .priority = 3,
741     .weight = 100,
742     .mpriority = 4,
743     .mweight = 101
744   };
745   locator_copy (&loc1, &loc2);
746   _assert (0 == locator_cmp (&loc1, &loc2));
747
748   /* remote locator */
749   loc2.local = 0;
750
751   ip_prefix_t nested_ippref;
752   ip_prefix_version (&nested_ippref) = AF_IP4;
753   ip_prefix_len (&nested_ippref) = 0;
754   ip4 = &ip_prefix_v4 (&nested_ippref);
755   ip4->as_u32 = 0x33882299;
756   gid_address_t nested_gid = {
757     .type = GID_ADDR_IP_PREFIX,
758     .ippref = nested_ippref
759   };
760
761   lcaf_t lcaf = {
762     .type = LCAF_INSTANCE_ID,
763     .uni = {
764             .vni_mask_len = 5,
765             .vni = 0xa1b2c3d4,
766             .gid_addr = &nested_gid}
767   };
768   gid_address_type (gid) = GID_ADDR_LCAF;
769   gid_address_lcaf (gid) = lcaf;
770
771   loc2.address = gid[0];
772   locator_copy (&loc1, &loc2);
773
774   _assert (0 == locator_cmp (&loc1, &loc2));
775
776 done:
777   locator_free (&loc1);
778   return error;
779 }
780
781 static clib_error_t *
782 test_gid_parse_ip_pref ()
783 {
784   clib_error_t *error = 0;
785   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
786   gid_address_t _gid_addr_copy, *copy = &_gid_addr_copy;
787
788   /* *INDENT-OFF* */
789   u8 data[] =
790     {
791       0x00, 0x01,             /* AFI = IPv4 */
792       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */
793     };
794   /* *INDENT-ON* */
795
796   u32 len = gid_address_parse (data, gid_addr);
797   _assert (6 == len);
798   gid_address_copy (copy, gid_addr);
799   _assert (0 == gid_address_cmp (copy, gid_addr));
800 done:
801   return error;
802 }
803
804 static clib_error_t *
805 test_gid_parse_mac ()
806 {
807   clib_error_t *error = 0;
808   gid_address_t _gid, *gid = &_gid;
809   gid_address_t _gid_copy, *gid_copy = &_gid_copy;
810
811   /* *INDENT-OFF* */
812   u8 data[] =
813     {
814       0x40, 0x05,             /* AFI = MAC address */
815       0x10, 0xbb, 0xcc, 0xdd, /* MAC */
816       0x77, 0x99,
817     };
818   /* *INDENT-ON* */
819
820   u32 len = gid_address_parse (data, gid);
821   _assert (8 == len);
822   _assert (GID_ADDR_MAC == gid_address_type (gid));
823   gid_address_copy (gid_copy, gid);
824   _assert (0 == gid_address_cmp (gid_copy, gid));
825 done:
826   return error;
827 }
828
829 static clib_error_t *
830 test_gid_write_nsh (void)
831 {
832   clib_error_t *error = 0;
833
834   u8 *b = clib_mem_alloc (500);
835   clib_memset (b, 0, 500);
836
837   gid_address_t g = {
838     .vni = 0,
839     .nsh.spi = 0x112233,
840     .nsh.si = 0x42,
841     .type = GID_ADDR_NSH,
842   };
843
844   u16 len = gid_address_put (b, &g);
845
846   /* *INDENT-OFF* */
847   u8 expected[] =
848     {
849       0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
850       0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
851
852       /* Service Path ID, Service index */
853       0x11, 0x22, 0x33, 0x42, /* SPI, SI */
854     };
855   /* *INDENT-ON* */
856
857   _assert (sizeof (expected) == len);
858   _assert (0 == memcmp (expected, b, len));
859 done:
860   clib_mem_free (b);
861   return error;
862 }
863
864 static clib_error_t *
865 test_gid_parse_nsh ()
866 {
867   clib_error_t *error = 0;
868   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
869   gid_address_t _gid_addr_copy, *copy = &_gid_addr_copy;
870
871   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
872   clib_memset (copy, 0, sizeof (copy[0]));
873
874   /* *INDENT-OFF* */
875   u8 data[] =
876     {
877       0x40, 0x03, 0x00, 0x00, /* AFI = LCAF*/
878       0x11, 0x00, 0x00, 0x04, /* type = SPI LCAF, length = 4 */
879
880       /* Service Path ID, Service index */
881       0x55, 0x99, 0x42, 0x09, /* SPI, SI */
882     };
883   /* *INDENT-ON* */
884
885   u32 len = gid_address_parse (data, gid_addr);
886   _assert (sizeof (data) == len);
887   gid_address_copy (copy, gid_addr);
888   _assert (0 == gid_address_cmp (gid_addr, copy));
889   _assert (GID_ADDR_NSH == gid_address_type (copy));
890   _assert (0 == gid_address_vni (copy));
891   _assert (gid_address_nsh_spi (copy) == 0x559942);
892   _assert (gid_address_nsh_si (copy) == 0x09);
893
894 done:
895   gid_address_free (copy);
896   gid_address_free (gid_addr);
897   return error;
898 }
899
900 static clib_error_t *
901 test_gid_parse_lcaf ()
902 {
903   clib_error_t *error = 0;
904   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
905   gid_address_t _gid_addr_copy, *gid_addr_copy = &_gid_addr_copy;
906
907   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
908   clib_memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0]));
909
910   /* *INDENT-OFF* */
911   u8 data[] =
912     {
913       0x40, 0x03,             /* AFI = LCAF*/
914
915       /* LCAF header*/
916       0x00, 0x00,             /* reserved1, flags */
917       0x02,                   /* type = Instance ID */
918       0x18,                   /* IID mask-len */
919       0x00, 0x0a,             /* iid length + next AFI lenght */
920       /* LCAF Instance ID */
921       0x00, 0x00, 0x00, 0x09, /* iid */
922       0x00, 0x01,             /* AFI = ipv4 */
923       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 address */
924     };
925   /* *INDENT-ON* */
926
927   u32 len = gid_address_parse (data, gid_addr);
928   _assert (18 == len);
929   gid_address_copy (gid_addr_copy, gid_addr);
930   _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
931   _assert (GID_ADDR_IP_PREFIX == gid_address_type (gid_addr));
932   _assert (9 == gid_address_vni (gid_addr));
933   _assert (0x18 == gid_address_vni_mask (gid_addr));
934   _assert (0xddccbb10 == gid_addr->ippref.addr.ip.ip4.as_u32);
935
936 done:
937   gid_address_free (gid_addr);
938   gid_address_free (gid_addr_copy);
939   return error;
940 }
941
942 /* recursive LCAFs are not supported */
943 #if 0
944 static clib_error_t *
945 test_gid_parse_lcaf_complex ()
946 {
947   clib_error_t *error = 0;
948   gid_address_t _gid_addr, *gid_addr = &_gid_addr;
949   gid_address_t _gid_addr_copy, *gid_addr_copy = &_gid_addr_copy;
950
951   clib_memset (gid_addr, 0, sizeof (gid_addr[0]));
952   clib_memset (gid_addr_copy, 0, sizeof (gid_addr_copy[0]));
953
954   /* *INDENT-OFF* */
955   u8 data[] = {
956     0x40, 0x03,                 /* AFI = LCAF */
957
958     /* LCAF header */
959     0x00, 0x00,                 /* reserved1, flags */
960     0x02,                       /* type = Instance ID */
961     0x18,                       /* IID mask-len */
962     0x00, 0x0a,                 /* iid length + next AFI lenght */
963     /* LCAF Instance ID */
964     0x00, 0x00, 0x00, 0x0b,     /* iid */
965
966     0x40, 0x03,                 /* AFI = LCAF */
967     /* LCAF header */
968     0x00, 0x00,                 /* reserved1, flags */
969     0x02,                       /* type = Instance ID */
970     0x17,                       /* IID mask-len */
971     0x00, 0x0a,                 /* iid length + next AFI lenght */
972     /* LCAF Instance ID */
973     0x00, 0x00, 0x00, 0x0c,     /* iid */
974
975     0x40, 0x03,                 /* AFI = LCAF */
976     /* LCAF header */
977     0x00, 0x00,                 /* reserved1, flags */
978     0x02,                       /* type = Instance ID */
979     0x16,                       /* IID mask-len */
980     0x00, 0x16,                 /* iid length + next AFI lenght */
981     /* LCAF Instance ID */
982     0x00, 0x00, 0x00, 0x0d,     /* iid */
983
984     0x00, 0x02,                 /* AFI = IPv6 */
985
986     0x10, 0xbb, 0xcc, 0xdd,
987     0x10, 0xbb, 0xcc, 0xdd,
988     0x10, 0xbb, 0xcc, 0xdd,
989     0x10, 0xbb, 0xcc, 0xdd,     /* ipv6 address */
990   };
991   /* *INDENT-ON* */
992
993   u32 len = gid_address_parse (data, gid_addr);
994   _assert (54 == len);
995   _assert (gid_addr->type == GID_ADDR_LCAF);
996   gid_address_copy (gid_addr_copy, gid_addr);
997   _assert (0 == gid_address_cmp (gid_addr_copy, gid_addr));
998   _assert (gid_addr_copy->type == GID_ADDR_LCAF);
999
1000   lcaf_t *lcaf = &gid_address_lcaf (gid_addr_copy);
1001   _assert (lcaf->type == LCAF_INSTANCE_ID);
1002   vni_t *v = (vni_t *) lcaf;
1003   _assert (v->vni == 0x0b);
1004   _assert (v->vni_mask_len == 0x18);
1005
1006   gid_address_t *tmp = vni_gid (v);
1007   _assert (gid_address_type (tmp) == GID_ADDR_LCAF);
1008   lcaf = &gid_address_lcaf (tmp);
1009   _assert (lcaf->type == LCAF_INSTANCE_ID);
1010
1011   v = (vni_t *) lcaf;
1012   _assert (v->vni == 0x0c);
1013   _assert (v->vni_mask_len == 0x17);
1014
1015   tmp = vni_gid (v);
1016   _assert (gid_address_type (tmp) == GID_ADDR_LCAF);
1017   lcaf = &gid_address_lcaf (tmp);
1018
1019   _assert (lcaf->type == LCAF_INSTANCE_ID);
1020   v = (vni_t *) lcaf;
1021   _assert (v->vni == 0x0d);
1022   _assert (v->vni_mask_len == 0x16);
1023
1024   tmp = vni_gid (v);
1025   _assert (gid_address_type (tmp) == GID_ADDR_IP_PREFIX);
1026
1027   ip_prefix_t *ip_pref = &gid_address_ippref (tmp);
1028   ip6_address_t *ip6 = &ip_prefix_v6 (ip_pref);
1029   _assert (ip6->as_u32[0] == 0xddccbb10);
1030   _assert (ip6->as_u32[1] == 0xddccbb10);
1031   _assert (ip6->as_u32[2] == 0xddccbb10);
1032   _assert (ip6->as_u32[3] == 0xddccbb10);
1033   _assert (ip_prefix_version (ip_pref) == AF_IP6);
1034
1035 done:
1036   gid_address_free (gid_addr);
1037   gid_address_free (gid_addr_copy);
1038   return error;
1039 }
1040 #endif
1041
1042 static clib_error_t *
1043 test_write_mac_in_lcaf (void)
1044 {
1045   clib_error_t *error = 0;
1046
1047   u8 *b = clib_mem_alloc (500);
1048   clib_memset (b, 0, 500);
1049
1050   gid_address_t g = {
1051     .mac = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6},
1052     .vni = 0x01020304,
1053     .vni_mask = 0x10,
1054     .type = GID_ADDR_MAC,
1055   };
1056
1057   u16 len = gid_address_put (b, &g);
1058
1059   /* *INDENT-OFF* */
1060   u8 expected[] =
1061     {
1062       0x40, 0x03,             /* AFI = LCAF */
1063       0x00,                   /* reserved1 */
1064       0x00,                   /* flags */
1065       0x02,                   /* LCAF type = Instance ID */
1066       0x10,                   /* IID/IID mask len */
1067       0x00, 0x0c,             /* length */
1068       0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */
1069
1070       0x40, 0x05,             /* AFI = MAC */
1071       0x01, 0x02, 0x03, 0x04,
1072       0x05, 0x06              /* MAC */
1073     };
1074   /* *INDENT-ON* */
1075
1076   _assert (sizeof (expected) == len);
1077   _assert (0 == memcmp (expected, b, len));
1078 done:
1079   clib_mem_free (b);
1080   return error;
1081 }
1082
1083 static clib_error_t *
1084 test_mac_address_write (void)
1085 {
1086   clib_error_t *error = 0;
1087
1088   u8 *b = clib_mem_alloc (500);
1089   clib_memset (b, 0, 500);
1090
1091   gid_address_t g = {
1092     .mac = {0x1, 0x2, 0x3, 0x4, 0x5, 0x6},
1093     .type = GID_ADDR_MAC,
1094   };
1095
1096   u16 len = gid_address_put (b, &g);
1097   _assert (8 == len);
1098
1099   /* *INDENT-OFF* */
1100   u8 expected[] =
1101     {
1102       0x40, 0x05,             /* AFI = MAC */
1103       0x01, 0x02, 0x03, 0x04,
1104       0x05, 0x06              /* MAC */
1105     };
1106   /* *INDENT-ON* */
1107
1108   _assert (0 == memcmp (expected, b, len));
1109 done:
1110   clib_mem_free (b);
1111   return error;
1112 }
1113
1114 static clib_error_t *
1115 test_src_dst_with_vni_serdes (void)
1116 {
1117   clib_error_t *error = 0;
1118   u8 *b = clib_mem_alloc (500);
1119   clib_memset (b, 0, 500);
1120
1121   /* *INDENT-OFF* */
1122   fid_address_t src =
1123     {
1124       .type = FID_ADDR_IP_PREF,
1125       .ippref =
1126         {
1127           .len = 24,
1128           .addr =
1129             {
1130               .version = AF_IP4,
1131               .ip.ip4.data = { 0x1, 0x2, 0x3, 0x0 }
1132             }
1133         }
1134     };
1135
1136   fid_address_t dst =
1137     {
1138       .type = FID_ADDR_IP_PREF,
1139       .ippref =
1140         {
1141           .len = 16,
1142           .addr =
1143             {
1144               .version = AF_IP4,
1145               .ip.ip4.data = { 0x9, 0x8, 0x0, 0x0 }
1146             }
1147         }
1148     };
1149
1150   source_dest_t sd =
1151     {
1152       .src = src,
1153       .dst = dst
1154     };
1155
1156   gid_address_t g =
1157     {
1158       .sd = sd,
1159       .type = GID_ADDR_SRC_DST,
1160       .vni = 0x12345678,
1161       .vni_mask = 0x9
1162     };
1163
1164   /* *INDENT-ON* */
1165
1166   u16 size_to_put = gid_address_size_to_put (&g);
1167   _assert (36 == size_to_put);
1168   _assert (0 == gid_address_len (&g));
1169
1170   u16 write_len = gid_address_put (b, &g);
1171   _assert (size_to_put == write_len);
1172
1173   /* *INDENT-OFF* */
1174   u8 expected_data[] =
1175     {
1176       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1177       0x02, 0x09, 0x00, 0x1c,  /* LCAF type = IID, IID mask-len, length */
1178       0x12, 0x34, 0x56, 0x78,  /* reserved; source-ML, Dest-ML */
1179
1180       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1181       0x0c, 0x00, 0x00, 0x10,  /* LCAF type = source/dest key, rsvd, length */
1182       0x00, 0x00, 0x18, 0x10,  /* reserved; source-ML, Dest-ML */
1183
1184       0x00, 0x01,              /* AFI = ip4 */
1185       0x01, 0x02, 0x03, 0x00,  /* source */
1186
1187       0x00, 0x01,              /* AFI = ip4 */
1188       0x09, 0x08, 0x00, 0x00,  /* destination */
1189     };
1190   /* *INDENT-ON* */
1191
1192   _assert (0 == memcmp (expected_data, b, sizeof (expected_data)));
1193
1194   gid_address_t p;
1195   clib_memset (&p, 0, sizeof (p));
1196   _assert (write_len == gid_address_parse (b, &p));
1197   _assert (0 == gid_address_cmp (&g, &p));
1198 done:
1199   clib_mem_free (b);
1200   return error;
1201 }
1202
1203 static clib_error_t *
1204 test_src_dst_deser_bad_afi (void)
1205 {
1206   clib_error_t *error = 0;
1207
1208   /* *INDENT-OFF* */
1209   u8 expected_data[] =
1210     {
1211       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1212       0x0c, 0x00, 0x00, 0x14,  /* LCAF type = source/dest key, rsvd, length */
1213       0x00, 0x00, 0x00, 0x00,  /* reserved; source-ML, Dest-ML */
1214
1215       0xde, 0xad,              /* AFI = bad value */
1216       0x11, 0x22, 0x33, 0x44,
1217       0x55, 0x66,              /* source */
1218
1219       0x40, 0x05,              /* AFI = MAC */
1220       0x10, 0x21, 0x32, 0x43,
1221       0x54, 0x65,              /* destination */
1222     };
1223   /* *INDENT-ON* */
1224
1225   gid_address_t p;
1226   _assert (~0 == gid_address_parse (expected_data, &p));
1227 done:
1228   return error;
1229 }
1230
1231 static clib_error_t *
1232 test_src_dst_serdes (void)
1233 {
1234   clib_error_t *error = 0;
1235
1236   u8 *b = clib_mem_alloc (500);
1237   clib_memset (b, 0, 500);
1238
1239   fid_address_t src = {
1240     .type = FID_ADDR_MAC,
1241     .mac = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}
1242   };
1243
1244   fid_address_t dst = {
1245     .type = FID_ADDR_MAC,
1246     .mac = {0x10, 0x21, 0x32, 0x43, 0x54, 0x65}
1247   };
1248
1249   source_dest_t sd = {
1250     .src = src,
1251     .dst = dst
1252   };
1253
1254   gid_address_t g = {
1255     .sd = sd,
1256     .type = GID_ADDR_SRC_DST,
1257     .vni = 0x0,
1258     .vni_mask = 0x0
1259   };
1260
1261   u16 size_to_put = gid_address_size_to_put (&g);
1262   _assert (28 == size_to_put);
1263   _assert (0 == gid_address_len (&g));
1264
1265   u16 write_len = gid_address_put (b, &g);
1266   _assert (size_to_put == write_len);
1267
1268   /* *INDENT-OFF* */
1269   u8 expected_data[] =
1270     {
1271       0x40, 0x03, 0x00, 0x00,  /* AFI = LCAF, reserved1, flags */
1272       0x0c, 0x00, 0x00, 0x14,  /* LCAF type = source/dest key, rsvd, length */
1273       0x00, 0x00, 0x00, 0x00,  /* reserved; source-ML, Dest-ML */
1274
1275       0x40, 0x05,              /* AFI = MAC */
1276       0x11, 0x22, 0x33, 0x44,
1277       0x55, 0x66,              /* source */
1278
1279       0x40, 0x05,              /* AFI = MAC */
1280       0x10, 0x21, 0x32, 0x43,
1281       0x54, 0x65,              /* destination */
1282     };
1283   /* *INDENT-ON* */
1284
1285   _assert (0 == memcmp (expected_data, b, sizeof (expected_data)));
1286
1287   gid_address_t p;
1288   clib_memset (&p, 0, sizeof (p));
1289   _assert (write_len == gid_address_parse (b, &p));
1290   _assert (0 == gid_address_cmp (&g, &p));
1291 done:
1292   clib_mem_free (b);
1293   return error;
1294 }
1295
1296 static clib_error_t *
1297 test_gid_address_write (void)
1298 {
1299   clib_error_t *error = 0;
1300   ip_prefix_t ippref_data, *ippref = &ippref_data;
1301
1302   u8 *b = clib_mem_alloc (500);
1303   clib_memset (b, 0, 500);
1304
1305   ip_prefix_version (ippref) = AF_IP4;
1306   ip_prefix_len (ippref) = 9;
1307   ip4_address_t *ip4 = &ip_prefix_v4 (ippref);
1308   ip4->as_u32 = 0xaabbccdd;
1309
1310   gid_address_t g = {
1311     .ippref = ippref[0],
1312     .type = GID_ADDR_IP_PREFIX,
1313     .vni = 0x01020304,
1314     .vni_mask = 0x18
1315   };
1316
1317   _assert (18 == gid_address_size_to_put (&g));
1318   _assert (gid_address_len (&g) == 9);
1319
1320   u16 write_len = gid_address_put (b, &g);
1321   _assert (18 == write_len);
1322
1323   /* *INDENT-OFF* */
1324   u8 expected_gid_data[] =
1325     {
1326       0x40, 0x03,             /* AFI = LCAF */
1327       0x00,                   /* reserved1 */
1328       0x00,                   /* flags */
1329       0x02,                   /* LCAF type = Instance ID */
1330       0x18,                   /* IID/VNI mask len */
1331       0x00, 0x0a,             /* length */
1332       0x01, 0x02, 0x03, 0x04, /* Instance ID / VNI */
1333
1334       0x00, 0x01,             /* AFI = IPv4 */
1335       0xdd, 0xcc, 0xbb, 0xaa, /* ipv4 addr */
1336     };
1337   /* *INDENT-ON* */
1338
1339   _assert (0 == memcmp (expected_gid_data, b, sizeof (expected_gid_data)));
1340 done:
1341   clib_mem_free (b);
1342   return error;
1343 }
1344
1345 #undef foreach_test_case
1346
1347 #define foreach_test_case                 \
1348   _(locator_type)                         \
1349   _(gid_parse_ip_pref)                    \
1350   _(gid_parse_mac)                        \
1351   _(gid_parse_lcaf)                       \
1352   _(gid_parse_nsh)                        \
1353   _(gid_write_nsh)                        \
1354   _(mac_address_write)                    \
1355   _(gid_address_write)                    \
1356   _(src_dst_serdes)                       \
1357   _(write_mac_in_lcaf)                    \
1358   _(src_dst_deser_bad_afi)                \
1359   _(src_dst_with_vni_serdes)
1360
1361 static int
1362 lisp_cp_types_tests (vlib_main_t * vm, unformat_input_t * input)
1363 {
1364   clib_error_t *error;
1365
1366 #define _(_test_name)                                   \
1367   error = test_ ## _test_name ();                       \
1368   if (error)                                            \
1369     {                                                   \
1370       fformat (stderr, "FAIL: test_" #_test_name "\n"); \
1371       return -1;                                        \
1372     }                                                   \
1373   else                                                  \
1374       fformat (stderr, "PASS: test_" #_test_name "\n"); \
1375
1376   foreach_test_case
1377 #undef _
1378     return 0;
1379 }
1380
1381 #undef _assert
1382
1383 static clib_error_t *
1384 lisp_cp_test (vlib_main_t * vm, unformat_input_t * input,
1385               vlib_cli_command_t * cmd_arg)
1386 {
1387   int res = 0;
1388
1389   while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
1390     {
1391       if (unformat (input, "serdes"))
1392         {
1393           res = lisp_cp_serdes_tests (vm, input);
1394         }
1395       if (unformat (input, "types"))
1396         {
1397           res = lisp_cp_types_tests (vm, input);
1398         }
1399       else if (unformat (input, "all"))
1400         {
1401           if ((res = lisp_cp_serdes_tests (vm, input)))
1402             goto done;
1403           if ((res = lisp_cp_types_tests (vm, input)))
1404             goto done;
1405         }
1406       else
1407         break;
1408     }
1409
1410 done:
1411   if (res)
1412     return clib_error_return (0, "rbtree unit test failed");
1413   return 0;
1414 }
1415
1416 /* *INDENT-OFF* */
1417 VLIB_CLI_COMMAND (lisp_cp_command, static) =
1418 {
1419   .path = "test lisp cp",
1420   .short_help = "lisp cp internal unit tests",
1421   .function = lisp_cp_test,
1422 };
1423 /* *INDENT-ON* */
1424
1425 #include <vlib/unix/plugin.h>
1426 #include <vpp/app/version.h>
1427
1428 /* *INDENT-OFF* */
1429 VLIB_PLUGIN_REGISTER () = {
1430     .version = VPP_BUILD_VER,
1431     .description = "Test Locator ID Separation Protocol (LISP)",
1432     .default_disabled = 1,
1433 };
1434 /* *INDENT-ON* */
1435
1436 /*
1437  * fd.io coding-style-patch-verification: ON
1438  *
1439  * Local Variables:
1440  * eval: (c-set-style "gnu")
1441  * End:
1442  */