Add unit test infrastructure for LISP protocol
[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 = 500;
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 = IP_PREFIX;
78   la.ippref.addr.ip.v4.as_u32 = 0xa1b2c3d4;
79   la.ippref.addr.version = IP4;
80
81   ra.type = 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     0x02, 0x10,             /* 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     0x01, 0xfc, /* 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   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 == 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 {
180   gid_address_t _seid, * seid = &_seid;
181   gid_address_t _deid, * deid = &_deid;
182   u8 is_smr_invoked = 1;
183   u64 nonce = 0;
184   map_request_hdr_t *h;
185   ip_address_t * rlocs = 0;
186   ip_address_t _addr, * addr = &_addr;
187
188   gid_address_type(seid) = IP_PREFIX;
189   gid_address_ip(seid).ip.v4.as_u32 = 0x12345678;
190   seid->ippref.addr.version = IP4;
191
192   gid_address_type(deid) = IP_PREFIX;
193   gid_address_ip(deid).ip.v4.as_u32 = 0x9abcdef0;
194   deid->ippref.addr.version = IP4;
195   gid_address_ippref_len(deid) = 24;
196
197   ip_addr_version(addr) = IP4;
198   ip_addr_v4(addr).data_u32 = 0x10203040;
199   vec_add1(rlocs, addr[0]);
200
201   ip_addr_v6(addr).as_u32[0] = 0xffeeddcc;
202   ip_addr_v6(addr).as_u32[1] = 0xbbaa9988;
203   ip_addr_v6(addr).as_u32[2] = 0x77665544;
204   ip_addr_v6(addr).as_u32[3] = 0x33221100;
205   ip_addr_version(addr) = IP6;
206   vec_add1(rlocs, addr[0]);
207
208   h = lisp_msg_put_mreq (lcm, b, seid, deid, rlocs,
209                      is_smr_invoked, &nonce);
210   vec_free(rlocs);
211   return h;
212 }
213
214 static clib_error_t * test_lisp_msg_parse ()
215 {
216   gid_address_t eid;
217   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
218   map_request_hdr_t *h;
219   gid_address_t gid;
220   clib_error_t * error = 0;
221   vlib_buffer_t * b;
222   gid_address_t * rlocs = 0;
223
224   u8 * data = clib_mem_alloc(500);
225   memset(data, 0, 500);
226   b = (vlib_buffer_t *) data;
227
228   h = build_map_request (lcm, b);
229
230   vlib_buffer_pull(b, sizeof(*h));
231   u32 len = lisp_msg_parse_addr(b, &gid);
232   _assert (len == 2 + 4
233       /* Source-EID-AFI field lenght + IPv4 address length */);
234   _assert (gid.ippref.addr.ip.v4.as_u32 == 0x12345678);
235   _assert (gid.ippref.addr.version == IP4);
236
237   u8 rloc_count = MREQ_ITR_RLOC_COUNT(h) + 1;
238   lisp_msg_parse_itr_rlocs (b, &rlocs, rloc_count);
239
240   _assert (vec_len (rlocs) == 2);
241   _assert (rlocs[0].ippref.addr.ip.v4.as_u32 == 0x10203040);
242   _assert (rlocs[0].ippref.addr.version == IP4);
243
244   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[0] == 0xffeeddcc);
245   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[1] == 0xbbaa9988);
246   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[2] == 0x77665544);
247   _assert (rlocs[1].ippref.addr.ip.v6.as_u32[3] == 0x33221100);
248   _assert (rlocs[1].ippref.addr.version == IP6);
249
250   lisp_msg_parse_eid_rec (b, &eid);
251   _assert (eid.ippref.addr.ip.v4.as_u32 == 0x9abcdef0);
252   _assert (eid.ippref.addr.version == IP4);
253   _assert (eid.ippref.len == 24);
254
255 done:
256   clib_mem_free (data);
257   if (rlocs)
258     vec_free (rlocs);
259   return error;
260 }
261
262 static clib_error_t * test_lisp_msg_put_mreq ()
263 {
264   lisp_cp_main_t * lcm = vnet_lisp_cp_get_main();
265   clib_error_t * error = 0;
266   map_request_hdr_t *h;
267
268   u8 * data = clib_mem_alloc(500);
269   memset(data, 0, 500);
270
271   h = build_map_request (lcm, (vlib_buffer_t *)data);
272
273   /* clear Nonce to simplify comparison */
274   memset((u8 *)h + 4, 0, 8);
275
276   print_map_request(h);
277
278   u8 expected_data[50] = {
279     0x10, 0x40, 0x01, 0x01, /* type; flags; IRC; REC count */
280     0x00, 0x00, 0x00, 0x00,
281     0x00, 0x00, 0x00, 0x00, /* nonce */
282     0x00, 0x01,             /* Source-EID-AFI */
283     0x78, 0x56, 0x34, 0x12, /* Source EID Address */
284
285     /* RLOCs */
286     0x00, 0x01,             /* ITR-RLOC-AFI 1 */
287     0x40, 0x30, 0x20, 0x10, /* ITR-RLOC Address 1 */
288     0x00, 0x02,             /* ITR-RLOC-AFI 2 */
289     0xcc, 0xdd, 0xee, 0xff,
290     0x88, 0x99, 0xaa, 0xbb,
291     0x44, 0x55, 0x66, 0x77,
292     0x00, 0x11, 0x22, 0x33, /* ITR-RLOC Address 2 */
293
294     /* record */
295     0x00,                   /* reserved */
296     0x18,                   /* EID mask-len */
297     0x00, 0x01,             /* EID-prefix-AFI */
298     0xf0, 0xde, 0xbc, 0x9a, /* EID-prefix */
299   };
300
301   int r = memcmp(expected_data, (u8 *)h, sizeof(expected_data));
302   error = CLIB_ERROR_ASSERT (r == 0);
303
304   clib_mem_free(data);
305   return error;
306 }
307
308 #define foreach_test_case                 \
309   _(lisp_msg_put_mreq)                    \
310   _(lisp_msg_push_ecm)                    \
311   _(lisp_msg_parse)                       \
312   _(lisp_msg_parse_mapping_record)
313
314 int run_tests (void)
315 {
316   clib_error_t * error;
317
318 #define _(_test_name)                   \
319   error = test_ ## _test_name ();       \
320   if (error)                            \
321     {                                   \
322       clib_error_report (error);        \
323       return 0;                         \
324     }
325
326   foreach_test_case
327 #undef _
328
329   return 0;
330 }
331
332 int main()
333 {
334   return run_tests ();
335 }
336 #undef _assert