2ca391e35b7061cf2533c3fc482b8e6c753608b4
[vpp.git] / vnet / test / lisp-cp / test_cp_serdes.c
1 /*
2  * Copyright (c) 2016 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     goto done;
28
29 static void print_chunk(u8 * b, int * offset, int c, char * des)
30 {
31   int i, n = offset[0] + c;;
32   for (i = offset[0]; i < n; i++)
33   {
34     printf("0x%02x, ", b[i]);
35   }
36   printf(" // %s\n", des);
37   *offset += c;
38 }
39
40 void print_map_request(map_request_hdr_t * h)
41 {
42 #define pchunk(_count, _desc) \
43   print_chunk((u8 *)h, &offset, _count, _desc)
44
45   int offset = 0;
46
47   pchunk(4, "data");
48   pchunk(8, "Nonce");
49   pchunk(2, "Source-EID-AFI");
50   pchunk(4, "Source EID Address");
51   pchunk(2, "ITR-RLOC-AFI 1");
52   pchunk(4, "ITR-RLOC Address 1");
53   pchunk(2, "ITR-RLOC-AFI 2");
54   pchunk(16, "ITR-RLOC Address 2");
55   pchunk(1, "REC: reserved");
56   pchunk(1, "REC: EID mask-len");
57   pchunk(2, "REC: EID-prefix-AFI");
58   pchunk(4, "REC: EID-prefix");
59   printf("\n");
60 }
61
62 static clib_error_t * test_lisp_msg_push_ecm ()
63 {
64   vlib_main_t * vm = vlib_get_main ();
65   clib_error_t * error = 0;
66   gid_address_t la, ra;
67   vlib_buffer_t * b = 0;
68   u32 buff_len = 900;
69   int lp = 0x15, rp = 0x14;
70
71   b = clib_mem_alloc (buff_len);
72   memset((u8 *)b, 0, buff_len);
73   b->current_length = buff_len;
74   b->current_data = sizeof(udp_header_t) + sizeof(ip4_header_t) +
75     sizeof(ecm_hdr_t) + 1;
76
77   la.type = GID_ADDR_IP_PREFIX;
78   la.ippref.addr.ip.v4.as_u32 = 0xa1b2c3d4;
79   la.ippref.addr.version = IP4;
80
81   ra.type = GID_ADDR_IP_PREFIX;
82   ra.ippref.addr.ip.v4.as_u32 = 0x90817263;
83   ra.ippref.addr.version = IP4;
84
85   ecm_hdr_t * lh = lisp_msg_push_ecm (vm, b, lp, rp, &la, &ra);
86
87   u8 expected_ecm_hdr[] = {
88     0x80, 0x00, 0x00, 0x00
89   };
90   _assert(0 == memcmp(expected_ecm_hdr, lh, sizeof(expected_ecm_hdr)));
91
92   ip4_header_t * ih = (ip4_header_t *) (lh + 1);
93   /* clear ip checksum */
94   memset((u8 *)ih + 10, 0, 2);
95
96   u8 expected_ip4_hdr[] = {
97     0x45,                   /* version; IHL */
98     0x00,                   /* services */
99     0x03, 0xa0,             /* total length */
100     0x00, 0x00,             /* identification */
101     0x40, 0x00,             /* flags; fragment offset*/
102     0xff,                   /* TTL */
103     0x11,                   /* protocol */
104     0x00, 0x00,             /* header checksum */
105     0xd4, 0xc3, 0xb2, 0xa1, /* src IP */
106     0x63, 0x72, 0x81, 0x90, /* dst IP */
107   };
108   _assert(0 == memcmp(ih, expected_ip4_hdr, sizeof(expected_ip4_hdr)));
109
110   udp_header_t * uh = (udp_header_t *) (ih + 1);
111   /* clear udp checksum */
112   memset((u8 *)uh + 6, 0, 2);
113
114   u8 expected_udp_hdr[] = {
115     0x00, 0x15, /* src port */
116     0x00, 0x14, /* dst port */
117     0x03, 0x8c, /* length */
118     0x00, 0x00, /* checksum */
119   };
120   _assert(0 == memcmp(uh, expected_udp_hdr, sizeof(expected_udp_hdr)));
121
122 done:
123   clib_mem_free (b);
124   return error;
125 }
126
127 static clib_error_t * test_lisp_msg_parse_mapping_record ()
128 {
129   clib_error_t * error = 0;
130   locator_t probed;
131   locator_t * locs = 0;
132   vlib_buffer_t * b = 0;
133   gid_address_t eid;
134   u32 buff_len = 500;
135
136   b = clib_mem_alloc (buff_len);
137   memset((u8 *)b, 0, buff_len);
138
139   u8 map_reply_records[] = {
140     /* 1. record */
141     0x01, 0x02, 0x03, 0x04, /* record TTL */
142     0x01,                   /* locator count */
143     0x00, 0x00, 0x00,       /* eid-mask-len; ... */
144     0x00, 0x00,             /* reserved; map-version num */
145     0x00, 0x01,             /* EID-Prefix-AFI */
146     0x33, 0x44, 0x55, 0x66, /* eid-prefix */
147     /* loc */
148     0x0a,                   /* prority */
149     0x0b,                   /* weight */
150     0x0c,                   /* m-prority */
151     0x0d,                   /* m-weight */
152     0x00, 0x00,             /* unused flags */
153     0x00, 0x01,             /* Loc-AFI */
154     0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
155   };
156   b->current_length = buff_len;
157   clib_memcpy(b->data, map_reply_records, sizeof(map_reply_records));
158
159   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
160   _assert(vec_len (locs) == 1);
161   _assert(eid.ippref.addr.ip.v4.as_u32 == 0x66554433);
162   _assert(locs[0].local == 0);
163   _assert(locs[0].address.ippref.addr.ip.v4.as_u32 == 0xddccbbaa);
164   _assert(locs[0].address.type == GID_ADDR_IP_PREFIX);
165   _assert(locs[0].priority == 0xa);
166   _assert(locs[0].weight == 0xb);
167   _assert(locs[0].mpriority == 0xc);
168   _assert(locs[0].mweight == 0xd);
169
170 done:
171   clib_mem_free (b);
172   if (locs)
173     vec_free (locs);
174   return error;
175 }
176
177 static map_request_hdr_t *
178 build_map_request (lisp_cp_main_t * lcm, vlib_buffer_t * b,
179                    gid_address_t * rlocs)
180 {
181   gid_address_t _seid, * seid = &_seid;
182   gid_address_t _deid, * deid = &_deid;
183   u8 is_smr_invoked = 1;
184   u64 nonce = 0;
185   map_request_hdr_t * h = 0;
186
187   gid_address_type (seid) = GID_ADDR_IP_PREFIX;
188   ip_address_t * ip_addr = &gid_address_ip (seid);
189   ip_addr_v4 (ip_addr).as_u32 = 0x12345678;
190   seid->ippref.addr.version = IP4;
191
192   gid_address_type (deid) = GID_ADDR_IP_PREFIX;
193   ip_address_t * ip_addr2 = &gid_address_ip (deid);
194   ip_addr_v4 (ip_addr2).as_u32 = 0x9abcdef0;
195   deid->ippref.addr.version = IP4;
196   gid_address_ippref_len (deid) = 24;
197
198   h = lisp_msg_put_mreq (lcm, b, seid, deid, rlocs,
199                      is_smr_invoked, &nonce);
200   vec_free(rlocs);
201   return h;
202 }
203
204 static void
205 generate_rlocs (gid_address_t **rlocs, u32 * count)
206 {
207   gid_address_t gid_addr_data, * gid_addr = &gid_addr_data;
208   ip_address_t * addr = &gid_address_ip (gid_addr);
209
210   gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX;
211
212   ip_addr_version (addr) = IP4;
213   ip_addr_v4 (addr).data_u32 = 0x10203040;
214   vec_add1 (rlocs[0], gid_addr[0]);
215
216   ip_addr_v6 (addr).as_u32[0] = 0xffeeddcc;
217   ip_addr_v6 (addr).as_u32[1] = 0xbbaa9988;
218   ip_addr_v6 (addr).as_u32[2] = 0x77665544;
219   ip_addr_v6 (addr).as_u32[3] = 0x33221100;
220   ip_addr_version (addr) = IP6;
221   vec_add1 (rlocs[0], gid_addr[0]);
222 }
223
224 static clib_error_t * test_lisp_msg_parse ()
225 {
226   gid_address_t eid;
227   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
228   map_request_hdr_t *h;
229   gid_address_t gid;
230   clib_error_t * error = 0;
231   vlib_buffer_t * b;
232   gid_address_t * rlocs_decode = 0, * rlocs = 0;
233   u32 rloc_count_parse = 0;
234
235   u8 * data = clib_mem_alloc(500);
236   memset(data, 0, 500);
237   b = (vlib_buffer_t *) data;
238
239   generate_rlocs (&rlocs_decode, &rloc_count_parse);
240   h = build_map_request (lcm, b, rlocs_decode);
241
242   vlib_buffer_pull(b, sizeof(*h));
243   u32 len = lisp_msg_parse_addr(b, &gid);
244   _assert (len == 2 + 4
245       /* Source-EID-AFI field lenght + IPv4 address length */);
246   _assert (gid.ippref.addr.ip.v4.as_u32 == 0x12345678);
247   _assert (gid.ippref.addr.version == IP4);
248
249   u8 rloc_count = MREQ_ITR_RLOC_COUNT(h) + 1;
250   lisp_msg_parse_itr_rlocs (b, &rlocs, rloc_count);
251
252   _assert (vec_len (rlocs) == 2);
253   _assert (rlocs[0].ippref.addr.ip.v4.as_u32 == 0x10203040);
254   _assert (rlocs[0].ippref.addr.version == IP4);
255
256   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[0] == 0xffeeddcc);
257   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[1] == 0xbbaa9988);
258   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[2] == 0x77665544);
259   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[3] == 0x33221100);
260   _assert (rlocs[1].ippref.addr.version == IP6);
261
262   lisp_msg_parse_eid_rec (b, &eid);
263   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x9abcdef0);
264   _assert (eid.ippref.addr.version == IP4);
265   _assert (eid.ippref.len == 24);
266
267 done:
268   clib_mem_free (data);
269   if (rlocs)
270     vec_free (rlocs);
271   return error;
272 }
273
274 static clib_error_t * test_lisp_msg_put_mreq_with_lcaf ()
275 {
276   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
277   clib_error_t * error = 0;
278   map_request_hdr_t *h = 0;
279   gid_address_t * rlocs = 0;
280   gid_address_t rloc;
281
282   ip_prefix_t ippref;
283   ip_prefix_version (&ippref) = IP4;
284   ip4_address_t * ip = &ip_prefix_v4 (&ippref);
285   ip->as_u32 = 0x11223344;
286
287   gid_address_t gid1 =
288     {
289       .type = GID_ADDR_IP_PREFIX,
290       .ippref = ippref
291     };
292
293   lcaf_t lcaf1 =
294     {
295       .type = LCAF_INSTANCE_ID,
296       .uni =
297         {
298           .vni_mask_len = 0x17,
299           .vni = 0x90919293,
300           .gid_addr = &gid1
301         }
302     };
303
304   gid_address_type (&rloc) = GID_ADDR_LCAF;
305   gid_address_lcaf (&rloc) = lcaf1;
306
307   vec_add1 (rlocs, rloc);
308
309   u8 * data = clib_mem_alloc (500);
310   memset (data, 0, 500);
311
312   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
313
314   /* clear Nonce to simplify comparison */
315   memset ((u8 *)h + 4, 0, 8);
316
317   u8 expected_data[] =
318     {
319       0x10, 0x40, 0x00, 0x01, /* type; flags; IRC; REC count */
320       0x00, 0x00, 0x00, 0x00,
321       0x00, 0x00, 0x00, 0x00, /* nonce */
322       0x00, 0x01,             /* Source-EID-AFI */
323       0x78, 0x56, 0x34, 0x12, /* Source EID Address */
324
325       /* RLOCs */
326       0x40, 0x03,             /* AFI = LCAF*/
327       /* LCAF header*/
328       0x00, 0x00,             /* reserved1, flags */
329       0x02,                   /* type = Instance ID */
330       0x17,                   /* IID mask-len */
331       0x00, 0x0a,             /* iid length + next AFI lenght */
332       0x90, 0x91, 0x92, 0x93, /* IID / VNI */
333
334       0x00, 0x01,             /* AFI = ipv4 */
335       0x44, 0x33, 0x22, 0x11, /* ITR-RLOC Address 1 */
336
337       /* record */
338       0x00,                   /* reserved */
339       0x18,                   /* EID mask-len */
340       0x00, 0x01,             /* EID-prefix-AFI */
341       0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
342     };
343
344   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
345 done:
346   clib_mem_free (data);
347   return error;
348 }
349
350 static clib_error_t * test_lisp_msg_put_mreq ()
351 {
352   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
353   clib_error_t * error = 0;
354   map_request_hdr_t *h;
355   gid_address_t * rlocs = 0;
356   u32 rloc_count = 0;
357
358   u8 * data = clib_mem_alloc(500);
359   memset(data, 0, 500);
360
361   generate_rlocs (&rlocs, &rloc_count);
362   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
363
364   /* clear Nonce to simplify comparison */
365   memset((u8 *)h + 4, 0, 8);
366
367   print_map_request(h);
368
369   u8 expected_data[50] = {
370     0x10, 0x40, 0x01, 0x01, /* type; flags; IRC; REC count */
371     0x00, 0x00, 0x00, 0x00,
372     0x00, 0x00, 0x00, 0x00, /* nonce */
373     0x00, 0x01,             /* Source-EID-AFI */
374     0x78, 0x56, 0x34, 0x12, /* Source EID Address */
375
376     /* RLOCs */
377     0x00, 0x01,             /* ITR-RLOC-AFI 1 */
378     0x40, 0x30, 0x20, 0x10, /* ITR-RLOC Address 1 */
379     0x00, 0x02,             /* ITR-RLOC-AFI 2 */
380     0xcc, 0xdd, 0xee, 0xff,
381     0x88, 0x99, 0xaa, 0xbb,
382     0x44, 0x55, 0x66, 0x77,
383     0x00, 0x11, 0x22, 0x33, /* ITR-RLOC Address 2 */
384
385     /* record */
386     0x00,                   /* reserved */
387     0x18,                   /* EID mask-len */
388     0x00, 0x01,             /* EID-prefix-AFI */
389     0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
390   };
391   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
392
393 done:
394   clib_mem_free (data);
395   return error;
396 }
397
398 static clib_error_t *
399 test_lisp_parse_lcaf ()
400 {
401   int i;
402   clib_error_t * error = 0;
403   gid_address_t eid;
404   locator_t * locs = 0;
405   locator_t probed;
406   vlib_buffer_t * b = 0;
407   u32 buff_len = 500;
408
409   b = clib_mem_alloc (buff_len);
410   memset ((u8 *)b, 0, buff_len);
411
412   u8 map_reply_records[] =
413     {
414       /* 1. record */
415       0x01, 0x02, 0x03, 0x04, /* record TTL */
416       0x03,                   /* locator count */
417       0x00, 0x00, 0x00,       /* eid-mask-len; ... */
418       0x00, 0x00,             /* reserved; map-version num */
419       0x00, 0x01,             /* EID-Prefix-AFI */
420       0x33, 0x44, 0x55, 0x66, /* eid-prefix */
421
422       /* 1st locator */
423       0x0a,                   /* prority */
424       0x0b,                   /* weight */
425       0x0c,                   /* m-prority */
426       0x0d,                   /* m-weight */
427       0x00, 0x00,             /* unused flags */
428       0x40, 0x03,             /* Loc-AFI = LCAF*/
429
430       /* LCAF header*/
431       0x00, 0x00,             /* reserved1, flags */
432       0x02,                   /* type = Instance ID */
433       0x18,                   /* IID mask-len */
434       0x0a, 0x00,             /* iid length + next AFI lenght */
435       /* LCAF Instance ID */
436       0x00, 0x00, 0x00, 0x09, /* iid */
437       0x00, 0x01,             /* AFI = ipv4 */
438       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 loator address */
439
440       /* 2nd locator */
441       0x07,                   /* prority */
442       0x06,                   /* weight */
443       0x05,                   /* m-prority */
444       0x04,                   /* m-weight */
445       0x00, 0x00,             /* unused flags */
446       0x40, 0x03,             /* Loc-AFI = LCAF*/
447
448       /* LCAF header*/
449       0x00, 0x00,             /* reserved1, flags */
450       0x02,                   /* type = Instance ID */
451       0x18,                   /* IID mask-len */
452       0x00, 0x16,             /* iid length + next AFI lenght */
453       /* LCAF Instance ID */
454       0x22, 0x44, 0x66, 0x88, /* iid */
455       0x00, 0x02,             /* AFI = ipv6 */
456       0xcc, 0xdd, 0xee, 0xff,
457       0x88, 0x99, 0xaa, 0xbb,
458       0x44, 0x55, 0x66, 0x77,
459       0x00, 0x11, 0x22, 0x33, /* ipv6 locator address */
460
461       /* 3rd locator */
462       0x0a,                   /* prority */
463       0x0b,                   /* weight */
464       0x0c,                   /* m-prority */
465       0x0d,                   /* m-weight */
466       0x00, 0x00,             /* unused flags */
467       0x00, 0x01,             /* Loc-AFI */
468       0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
469     };
470
471   b->current_length = buff_len;
472   memcpy (b->data, map_reply_records, sizeof (map_reply_records));
473
474   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
475   _assert (vec_len (locs) == 3);
476   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x66554433);
477
478   /* check 1st locator - an LCAF with ipv4 */
479   _assert (locs[0].local == 0);
480   _assert (locs[0].priority == 0xa);
481   _assert (locs[0].weight == 0xb);
482   _assert (locs[0].mpriority == 0xc);
483   _assert (locs[0].mweight == 0xd);
484
485   /* check LCAF header data */
486   lcaf_t * lcaf = &gid_address_lcaf (&locs[0].address);
487   _assert (gid_address_type (&locs[0].address) == GID_ADDR_LCAF);
488   _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID);
489   vni_t * v = (vni_t *) lcaf;
490   _assert (vni_vni (v) == 0x09);
491
492   gid_address_t * nested_gid = vni_gid (v);
493   _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid));
494   ip_prefix_t * ip_pref = &gid_address_ippref (nested_gid);
495   _assert (IP4 == ip_prefix_version (ip_pref));
496
497   /* 2nd locator - LCAF entry with ipv6 address */
498   _assert (locs[1].local == 0);
499   _assert (locs[1].priority == 0x7);
500   _assert (locs[1].weight == 0x6);
501   _assert (locs[1].mpriority == 0x5);
502   _assert (locs[1].mweight == 0x4);
503
504   /* LCAF header */
505   _assert (gid_address_type (&locs[1].address) == GID_ADDR_LCAF);
506   lcaf = &gid_address_lcaf (&locs[1].address);
507   _assert (lcaf_type (lcaf) == LCAF_INSTANCE_ID);
508   v = (vni_t *) lcaf;
509   _assert (vni_vni (v) == 0x22446688);
510
511   nested_gid = vni_gid (v);
512   _assert (GID_ADDR_IP_PREFIX == gid_address_type (nested_gid));
513   ip_pref = &gid_address_ippref (nested_gid);
514   _assert (IP6 == ip_prefix_version (ip_pref));
515
516   /* 3rd locator - simple ipv4 address */
517   _assert (gid_address_type (&locs[2].address) == GID_ADDR_IP_PREFIX);
518 done:
519   clib_mem_free (b);
520
521   for (i = 0; i < 3; i++)
522     locator_free (&locs[i]);
523   vec_free (locs);
524   return error;
525 }
526
527 #define foreach_test_case                 \
528   _(lisp_msg_put_mreq)                    \
529   _(lisp_msg_put_mreq_with_lcaf)          \
530   _(lisp_msg_push_ecm)                    \
531   _(lisp_msg_parse)                       \
532   _(lisp_msg_parse_mapping_record)        \
533   _(lisp_parse_lcaf)
534
535 int run_tests (void)
536 {
537   clib_error_t * error;
538
539 #define _(_test_name)                   \
540   error = test_ ## _test_name ();       \
541   if (error)                            \
542     {                                   \
543       clib_error_report (error);        \
544       return 0;                         \
545     }
546
547   foreach_test_case
548 #undef _
549
550   return 0;
551 }
552
553 int main()
554 {
555   return run_tests ();
556 }
557 #undef _assert