LISP EID virtualization support
[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   memset (deid, 0, sizeof (deid[0]));
187   memset (seid, 0, sizeof (seid[0]));
188
189   gid_address_type (seid) = GID_ADDR_IP_PREFIX;
190   ip_address_t * ip_addr = &gid_address_ip (seid);
191   ip_addr_v4 (ip_addr).as_u32 = 0x12345678;
192   seid->ippref.addr.version = IP4;
193
194   gid_address_type (deid) = GID_ADDR_IP_PREFIX;
195   ip_address_t * ip_addr2 = &gid_address_ip (deid);
196   ip_addr_v4 (ip_addr2).as_u32 = 0x9abcdef0;
197   deid->ippref.addr.version = IP4;
198   gid_address_ippref_len (deid) = 24;
199
200   h = lisp_msg_put_mreq (lcm, b, seid, deid, rlocs,
201                      is_smr_invoked, &nonce);
202   vec_free(rlocs);
203   return h;
204 }
205
206 static void
207 generate_rlocs (gid_address_t **rlocs, u32 * count)
208 {
209   gid_address_t gid_addr_data, * gid_addr = &gid_addr_data;
210   memset (gid_addr, 0, sizeof (gid_addr[0]));
211   ip_address_t * addr = &gid_address_ip (gid_addr);
212
213   gid_address_type (gid_addr) = GID_ADDR_IP_PREFIX;
214
215   ip_addr_version (addr) = IP4;
216   ip_addr_v4 (addr).data_u32 = 0x10203040;
217   vec_add1 (rlocs[0], gid_addr[0]);
218
219   ip_addr_v6 (addr).as_u32[0] = 0xffeeddcc;
220   ip_addr_v6 (addr).as_u32[1] = 0xbbaa9988;
221   ip_addr_v6 (addr).as_u32[2] = 0x77665544;
222   ip_addr_v6 (addr).as_u32[3] = 0x33221100;
223   ip_addr_version (addr) = IP6;
224   vec_add1 (rlocs[0], gid_addr[0]);
225 }
226
227 static clib_error_t * test_lisp_msg_parse ()
228 {
229   gid_address_t eid;
230   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
231   map_request_hdr_t *h;
232   gid_address_t gid;
233   clib_error_t * error = 0;
234   vlib_buffer_t * b;
235   gid_address_t * rlocs_decode = 0, * rlocs = 0;
236   u32 rloc_count_parse = 0;
237
238   u8 * data = clib_mem_alloc(500);
239   memset(data, 0, 500);
240   b = (vlib_buffer_t *) data;
241
242   generate_rlocs (&rlocs_decode, &rloc_count_parse);
243   h = build_map_request (lcm, b, rlocs_decode);
244
245   vlib_buffer_pull(b, sizeof(*h));
246   u32 len = lisp_msg_parse_addr(b, &gid);
247   _assert (len == 2 + 4
248       /* Source-EID-AFI field lenght + IPv4 address length */);
249   _assert (gid.ippref.addr.ip.v4.as_u32 == 0x12345678);
250   _assert (gid.ippref.addr.version == IP4);
251
252   u8 rloc_count = MREQ_ITR_RLOC_COUNT(h) + 1;
253   lisp_msg_parse_itr_rlocs (b, &rlocs, rloc_count);
254
255   _assert (vec_len (rlocs) == 2);
256   _assert (rlocs[0].ippref.addr.ip.v4.as_u32 == 0x10203040);
257   _assert (rlocs[0].ippref.addr.version == IP4);
258
259   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[0] == 0xffeeddcc);
260   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[1] == 0xbbaa9988);
261   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[2] == 0x77665544);
262   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[3] == 0x33221100);
263   _assert (rlocs[1].ippref.addr.version == IP6);
264
265   lisp_msg_parse_eid_rec (b, &eid);
266   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x9abcdef0);
267   _assert (eid.ippref.addr.version == IP4);
268   _assert (eid.ippref.len == 24);
269
270 done:
271   clib_mem_free (data);
272   if (rlocs)
273     vec_free (rlocs);
274   return error;
275 }
276
277 static clib_error_t * test_lisp_msg_put_mreq_with_lcaf ()
278 {
279   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main ();
280   clib_error_t * error = 0;
281   map_request_hdr_t *h = 0;
282   gid_address_t * rlocs = 0;
283
284   ip_prefix_t ippref;
285   ip_prefix_version (&ippref) = IP4;
286   ip4_address_t * ip = &ip_prefix_v4 (&ippref);
287   ip->as_u32 = 0x11223344;
288
289   gid_address_t g =
290     {
291       .type = GID_ADDR_IP_PREFIX,
292       .ippref = ippref,
293       .vni = 0x90919293,
294       .vni_mask = 0x17
295     };
296   vec_add1 (rlocs, g);
297
298   u8 * data = clib_mem_alloc (500);
299   memset (data, 0, 500);
300
301   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
302
303   /* clear Nonce to simplify comparison */
304   memset ((u8 *)h + 4, 0, 8);
305
306   u8 expected_data[] =
307     {
308       0x10, 0x40, 0x00, 0x01, /* type; flags; IRC; REC count */
309       0x00, 0x00, 0x00, 0x00,
310       0x00, 0x00, 0x00, 0x00, /* nonce */
311       0x00, 0x01,             /* Source-EID-AFI */
312       0x78, 0x56, 0x34, 0x12, /* Source EID Address */
313
314       /* RLOCs */
315       0x40, 0x03,             /* AFI = LCAF*/
316       /* LCAF header*/
317       0x00, 0x00,             /* reserved1, flags */
318       0x02,                   /* type = Instance ID */
319       0x17,                   /* IID mask-len */
320       0x00, 0x0a,             /* iid length + next AFI lenght */
321       0x90, 0x91, 0x92, 0x93, /* IID / VNI */
322
323       0x00, 0x01,             /* AFI = ipv4 */
324       0x44, 0x33, 0x22, 0x11, /* ITR-RLOC Address 1 */
325
326       /* record */
327       0x00,                   /* reserved */
328       0x18,                   /* EID mask-len */
329       0x00, 0x01,             /* EID-prefix-AFI */
330       0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
331     };
332
333   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
334 done:
335   clib_mem_free (data);
336   return error;
337 }
338
339 static clib_error_t * test_lisp_msg_put_mreq ()
340 {
341   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
342   clib_error_t * error = 0;
343   map_request_hdr_t *h;
344   gid_address_t * rlocs = 0;
345   u32 rloc_count = 0;
346
347   u8 * data = clib_mem_alloc(500);
348   memset(data, 0, 500);
349
350   generate_rlocs (&rlocs, &rloc_count);
351   h = build_map_request (lcm, (vlib_buffer_t *) data, rlocs);
352
353   /* clear Nonce to simplify comparison */
354   memset((u8 *)h + 4, 0, 8);
355
356   print_map_request(h);
357
358   u8 expected_data[50] = {
359     0x10, 0x40, 0x01, 0x01, /* type; flags; IRC; REC count */
360     0x00, 0x00, 0x00, 0x00,
361     0x00, 0x00, 0x00, 0x00, /* nonce */
362     0x00, 0x01,             /* Source-EID-AFI */
363     0x78, 0x56, 0x34, 0x12, /* Source EID Address */
364
365     /* RLOCs */
366     0x00, 0x01,             /* ITR-RLOC-AFI 1 */
367     0x40, 0x30, 0x20, 0x10, /* ITR-RLOC Address 1 */
368     0x00, 0x02,             /* ITR-RLOC-AFI 2 */
369     0xcc, 0xdd, 0xee, 0xff,
370     0x88, 0x99, 0xaa, 0xbb,
371     0x44, 0x55, 0x66, 0x77,
372     0x00, 0x11, 0x22, 0x33, /* ITR-RLOC Address 2 */
373
374     /* record */
375     0x00,                   /* reserved */
376     0x18,                   /* EID mask-len */
377     0x00, 0x01,             /* EID-prefix-AFI */
378     0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
379   };
380   _assert (0 == memcmp (expected_data, (u8 *) h, sizeof (expected_data)));
381
382 done:
383   clib_mem_free (data);
384   return error;
385 }
386
387 static clib_error_t *
388 test_lisp_parse_lcaf ()
389 {
390   int i;
391   clib_error_t * error = 0;
392   gid_address_t eid;
393   locator_t * locs = 0;
394   locator_t probed;
395   vlib_buffer_t * b = 0;
396   u32 buff_len = 500;
397
398   b = clib_mem_alloc (buff_len);
399   memset ((u8 *)b, 0, buff_len);
400
401   u8 map_reply_records[] =
402     {
403       /* 1. record */
404       0x01, 0x02, 0x03, 0x04, /* record TTL */
405       0x03,                   /* locator count */
406       0x00, 0x00, 0x00,       /* eid-mask-len; ... */
407       0x00, 0x00,             /* reserved; map-version num */
408       0x00, 0x01,             /* EID-Prefix-AFI */
409       0x33, 0x44, 0x55, 0x66, /* eid-prefix */
410
411       /* 1st locator */
412       0x0a,                   /* prority */
413       0x0b,                   /* weight */
414       0x0c,                   /* m-prority */
415       0x0d,                   /* m-weight */
416       0x00, 0x00,             /* unused flags */
417       0x40, 0x03,             /* Loc-AFI = LCAF*/
418
419       /* LCAF header*/
420       0x00, 0x00,             /* reserved1, flags */
421       0x02,                   /* type = Instance ID */
422       0x18,                   /* IID mask-len */
423       0x0a, 0x00,             /* iid length + next AFI lenght */
424       /* LCAF Instance ID */
425       0x00, 0x00, 0x00, 0x09, /* iid */
426       0x00, 0x01,             /* AFI = ipv4 */
427       0x10, 0xbb, 0xcc, 0xdd, /* ipv4 loator address */
428
429       /* 2nd locator */
430       0x07,                   /* prority */
431       0x06,                   /* weight */
432       0x05,                   /* m-prority */
433       0x04,                   /* m-weight */
434       0x00, 0x00,             /* unused flags */
435       0x40, 0x03,             /* Loc-AFI = LCAF*/
436
437       /* LCAF header*/
438       0x00, 0x00,             /* reserved1, flags */
439       0x02,                   /* type = Instance ID */
440       0x18,                   /* IID mask-len */
441       0x00, 0x16,             /* iid length + next AFI lenght */
442       /* LCAF Instance ID */
443       0x22, 0x44, 0x66, 0x88, /* iid */
444       0x00, 0x02,             /* AFI = ipv6 */
445       0xcc, 0xdd, 0xee, 0xff,
446       0x88, 0x99, 0xaa, 0xbb,
447       0x44, 0x55, 0x66, 0x77,
448       0x00, 0x11, 0x22, 0x33, /* ipv6 locator address */
449
450       /* 3rd locator */
451       0x0a,                   /* prority */
452       0x0b,                   /* weight */
453       0x0c,                   /* m-prority */
454       0x0d,                   /* m-weight */
455       0x00, 0x00,             /* unused flags */
456       0x00, 0x01,             /* Loc-AFI */
457       0xaa, 0xbb, 0xcc, 0xdd, /* Loator */
458     };
459
460   b->current_length = buff_len;
461   memcpy (b->data, map_reply_records, sizeof (map_reply_records));
462
463   lisp_msg_parse_mapping_record (b, &eid, &locs, &probed);
464   _assert (vec_len (locs) == 3);
465   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x66554433);
466
467   /* check 1st locator - an LCAF with ipv4 */
468   _assert (locs[0].local == 0);
469   _assert (locs[0].priority == 0xa);
470   _assert (locs[0].weight == 0xb);
471   _assert (locs[0].mpriority == 0xc);
472   _assert (locs[0].mweight == 0xd);
473
474   _assert (gid_address_type (&locs[0].address) == GID_ADDR_IP_PREFIX);
475   _assert (gid_address_vni (&locs[0].address) == 0x09);
476   ip_prefix_t * ip_pref = &gid_address_ippref (&locs[0].address);
477   _assert (IP4 == ip_prefix_version (ip_pref));
478
479   /* 2nd locator - LCAF entry with ipv6 address */
480   _assert (locs[1].local == 0);
481   _assert (locs[1].priority == 0x7);
482   _assert (locs[1].weight == 0x6);
483   _assert (locs[1].mpriority == 0x5);
484   _assert (locs[1].mweight == 0x4);
485
486   _assert (gid_address_type (&locs[1].address) == GID_ADDR_IP_PREFIX);
487   _assert (0x22446688 == gid_address_vni (&locs[1].address));
488   ip_pref = &gid_address_ippref (&locs[1].address);
489   _assert (IP6 == ip_prefix_version (ip_pref));
490
491   /* 3rd locator - simple ipv4 address */
492   _assert (gid_address_type (&locs[2].address) == GID_ADDR_IP_PREFIX);
493 done:
494   clib_mem_free (b);
495
496   for (i = 0; i < 3; i++)
497     locator_free (&locs[i]);
498   vec_free (locs);
499   return error;
500 }
501
502 #define foreach_test_case                 \
503   _(lisp_msg_put_mreq)                    \
504   _(lisp_msg_put_mreq_with_lcaf)          \
505   _(lisp_msg_push_ecm)                    \
506   _(lisp_msg_parse)                       \
507   _(lisp_msg_parse_mapping_record)        \
508   _(lisp_parse_lcaf)
509
510 int run_tests (void)
511 {
512   clib_error_t * error;
513
514 #define _(_test_name)                   \
515   error = test_ ## _test_name ();       \
516   if (error)                            \
517     {                                   \
518       clib_error_report (error);        \
519       return 0;                         \
520     }
521
522   foreach_test_case
523 #undef _
524
525   return 0;
526 }
527
528 int main()
529 {
530   return run_tests ();
531 }
532 #undef _assert