a0e413e16da77a30cc42d0093469fb462ea7d4d7
[vpp.git] / plugins / acl-plugin / acl / acl_test.c
1 /*
2  * Copyright (c) 2015 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  *------------------------------------------------------------------
17  * acl_test.c - test harness plugin
18  *------------------------------------------------------------------
19  */
20
21 #include <vat/vat.h>
22 #include <vlibapi/api.h>
23 #include <vlibmemory/api.h>
24 #include <vlibsocket/api.h>
25 #include <vppinfra/error.h>
26 #include <vnet/ip/ip.h>
27 #include <arpa/inet.h>
28
29 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
30
31 /* Declare message IDs */
32 #include <acl/acl_msg_enum.h>
33
34 /* define message structures */
35 #define vl_typedefs
36 #include <acl/acl_all_api_h.h>
37 #undef vl_typedefs
38
39 /* define message structures */
40 #define vl_endianfun
41 #include <acl/acl_all_api_h.h>
42 #undef vl_endianfun
43
44 /* instantiate all the print functions we know about */
45 #define vl_print(handle, ...)
46 #define vl_printfun
47 #include <acl/acl_all_api_h.h>
48 #undef vl_printfun
49
50 /* Get the API version number. */
51 #define vl_api_version(n,v) static u32 api_version=(v);
52 #include <acl/acl_all_api_h.h>
53 #undef vl_api_version
54
55 typedef struct {
56     /* API message ID base */
57     u16 msg_id_base;
58     vat_main_t *vat_main;
59 } acl_test_main_t;
60
61 acl_test_main_t acl_test_main;
62
63 #define foreach_standard_reply_retval_handler   \
64 _(acl_del_reply) \
65 _(acl_interface_add_del_reply) \
66 _(macip_acl_interface_add_del_reply) \
67 _(acl_interface_set_acl_list_reply) \
68 _(macip_acl_del_reply)
69
70 #define foreach_reply_retval_aclindex_handler  \
71 _(acl_add_replace_reply) \
72 _(macip_acl_add_reply)
73
74 #define _(n)                                            \
75     static void vl_api_##n##_t_handler                  \
76     (vl_api_##n##_t * mp)                               \
77     {                                                   \
78         vat_main_t * vam = acl_test_main.vat_main;   \
79         i32 retval = ntohl(mp->retval);                 \
80         if (vam->async_mode) {                          \
81             vam->async_errors += (retval < 0);          \
82         } else {                                        \
83             vam->retval = retval;                       \
84             vam->result_ready = 1;                      \
85         }                                               \
86     }
87 foreach_standard_reply_retval_handler;
88 #undef _
89
90 #define _(n)                                            \
91     static void vl_api_##n##_t_handler                  \
92     (vl_api_##n##_t * mp)                               \
93     {                                                   \
94         vat_main_t * vam = acl_test_main.vat_main;   \
95         i32 retval = ntohl(mp->retval);                 \
96         if (vam->async_mode) {                          \
97             vam->async_errors += (retval < 0);          \
98         } else {                                        \
99             clib_warning("ACL index: %d", ntohl(mp->acl_index)); \
100             vam->retval = retval;                       \
101             vam->result_ready = 1;                      \
102         }                                               \
103     }
104 foreach_reply_retval_aclindex_handler;
105 #undef _
106
107 /* These two ought to be in a library somewhere but they aren't */
108 static uword
109 my_unformat_mac_address (unformat_input_t * input, va_list * args)
110 {
111   u8 *a = va_arg (*args, u8 *);
112   return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
113                    &a[4], &a[5]);
114 }
115
116 static u8 *
117 my_format_mac_address (u8 * s, va_list * args)
118 {
119   u8 *a = va_arg (*args, u8 *);
120   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
121                  a[0], a[1], a[2], a[3], a[4], a[5]);
122 }
123
124
125
126 static void vl_api_acl_plugin_get_version_reply_t_handler
127     (vl_api_acl_plugin_get_version_reply_t * mp)
128     {
129         vat_main_t * vam = acl_test_main.vat_main;
130         clib_warning("ACL plugin version: %d.%d", ntohl(mp->major), ntohl(mp->minor));
131         vam->result_ready = 1;
132     }
133
134 static void vl_api_acl_interface_list_details_t_handler
135     (vl_api_acl_interface_list_details_t * mp)
136     {
137         int i;
138         vat_main_t * vam = acl_test_main.vat_main;
139         u8 *out = 0;
140         vl_api_acl_interface_list_details_t_endian(mp);
141         out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
142         out = format(out, "   input ");
143         for(i=0; i<mp->count; i++) {
144           out = format(out, "%d ", mp->acls[i]);
145           if (i == mp->n_input-1)
146             out = format(out, "\n  output ");
147         }
148         out = format(out, "\n");
149         clib_warning("%s", out);
150         vec_free(out);
151         vam->result_ready = 1;
152     }
153
154
155 static inline u8 *
156 vl_api_acl_rule_t_pretty_format (u8 *out, vl_api_acl_rule_t * a)
157 {
158   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
159   u8 src[INET6_ADDRSTRLEN];
160   u8 dst[INET6_ADDRSTRLEN];
161   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
162   inet_ntop(af, a->dst_ip_addr, (void *)dst, sizeof(dst));
163
164   out = format(out, "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport %d-%d tcpflags %d %d",
165                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
166                      src, a->src_ip_prefix_len,
167                      dst, a->dst_ip_prefix_len,
168                      a->proto,
169                      a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
170                      a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
171                      a->tcp_flags_mask, a->tcp_flags_value);
172   return(out);
173 }
174
175
176
177 static void vl_api_acl_details_t_handler
178     (vl_api_acl_details_t * mp)
179     {
180         int i;
181         vat_main_t * vam = acl_test_main.vat_main;
182         vl_api_acl_details_t_endian(mp);
183         u8 *out = 0;
184         out = format(0, "acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
185         for(i=0; i<mp->count; i++) {
186           out = format(out, "   ");
187           out = vl_api_acl_rule_t_pretty_format(out, &mp->r[i]);
188           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
189         }
190         clib_warning("%s", out);
191         vec_free(out);
192         vam->result_ready = 1;
193     }
194
195 static inline u8 *
196 vl_api_macip_acl_rule_t_pretty_format (u8 *out, vl_api_macip_acl_rule_t * a)
197 {
198   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
199   u8 src[INET6_ADDRSTRLEN];
200   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
201
202   out = format(out, "%s action %d ip %s/%d mac %U mask %U",
203                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
204                      src, a->src_ip_prefix_len,
205                      my_format_mac_address, a->src_mac,
206                      my_format_mac_address, a->src_mac_mask);
207   return(out);
208 }
209
210
211 static void vl_api_macip_acl_details_t_handler
212     (vl_api_macip_acl_details_t * mp)
213     {
214         int i;
215         vat_main_t * vam = acl_test_main.vat_main;
216         vl_api_macip_acl_details_t_endian(mp);
217         u8 *out = format(0,"MACIP acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
218         for(i=0; i<mp->count; i++) {
219           out = format(out, "   ");
220           out = vl_api_macip_acl_rule_t_pretty_format(out, &mp->r[i]);
221           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
222         }
223         clib_warning("%s", out);
224         vec_free(out);
225         vam->result_ready = 1;
226     }
227
228 static void vl_api_macip_acl_interface_get_reply_t_handler
229     (vl_api_macip_acl_interface_get_reply_t * mp)
230     {
231         int i;
232         vat_main_t * vam = acl_test_main.vat_main;
233         u8 *out = format(0, "sw_if_index with MACIP ACL count: %d\n", ntohl(mp->count));
234         for(i=0; i<ntohl(mp->count); i++) {
235           out = format(out, "  macip_acl_interface_add_del sw_if_index %d add acl %d\n", i, ntohl(mp->acls[i]));
236         }
237         out = format(out, "\n");
238         clib_warning("%s", out);
239         vec_free(out);
240         vam->result_ready = 1;
241     }
242
243
244 /*
245  * Table of message reply handlers, must include boilerplate handlers
246  * we just generated
247  */
248 #define foreach_vpe_api_reply_msg                                       \
249 _(ACL_ADD_REPLACE_REPLY, acl_add_replace_reply) \
250 _(ACL_DEL_REPLY, acl_del_reply) \
251 _(ACL_INTERFACE_ADD_DEL_REPLY, acl_interface_add_del_reply)  \
252 _(ACL_INTERFACE_SET_ACL_LIST_REPLY, acl_interface_set_acl_list_reply) \
253 _(ACL_INTERFACE_LIST_DETAILS, acl_interface_list_details)  \
254 _(ACL_DETAILS, acl_details)  \
255 _(MACIP_ACL_ADD_REPLY, macip_acl_add_reply) \
256 _(MACIP_ACL_DEL_REPLY, macip_acl_del_reply) \
257 _(MACIP_ACL_DETAILS, macip_acl_details)  \
258 _(MACIP_ACL_INTERFACE_ADD_DEL_REPLY, macip_acl_interface_add_del_reply)  \
259 _(MACIP_ACL_INTERFACE_GET_REPLY, macip_acl_interface_get_reply)  \
260 _(ACL_PLUGIN_GET_VERSION_REPLY, acl_plugin_get_version_reply)
261
262 /* M: construct, but don't yet send a message */
263
264 #define M(T,t)                                                  \
265 do {                                                            \
266     vam->result_ready = 0;                                      \
267     mp = vl_msg_api_alloc(sizeof(*mp));                         \
268     memset (mp, 0, sizeof (*mp));                               \
269     mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base);      \
270     mp->client_index = vam->my_client_index;                    \
271 } while(0);
272
273 #define M2(T,t,n)                                               \
274 do {                                                            \
275     vam->result_ready = 0;                                      \
276     mp = vl_msg_api_alloc(sizeof(*mp)+(n));                     \
277     memset (mp, 0, sizeof (*mp));                               \
278     mp->_vl_msg_id = ntohs (VL_API_##T + sm->msg_id_base);      \
279     mp->client_index = vam->my_client_index;                    \
280 } while(0);
281
282 /* S: send a message */
283 #define S (vl_msg_api_send_shmem (vam->vl_input_queue, (u8 *)&mp))
284
285 /* W: wait for results, with timeout */
286 #define W                                       \
287 do {                                            \
288     timeout = vat_time_now (vam) + 1.0;         \
289                                                 \
290     while (vat_time_now (vam) < timeout) {      \
291         if (vam->result_ready == 1) {           \
292             return (vam->retval);               \
293         }                                       \
294     }                                           \
295     return -99;                                 \
296 } while(0);
297
298 static int api_acl_plugin_get_version (vat_main_t * vam)
299 {
300     acl_test_main_t * sm = &acl_test_main;
301     vl_api_acl_plugin_get_version_t * mp;
302     u32 msg_size = sizeof(*mp);
303     f64 timeout;
304
305     vam->result_ready = 0;
306     mp = vl_msg_api_alloc_as_if_client(msg_size);
307     memset (mp, 0, msg_size);
308     mp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_VERSION + sm->msg_id_base);
309     mp->client_index = vam->my_client_index;
310
311     /* send it... */
312     S;
313
314     /* Wait for a reply... */
315     W;
316
317     return 0;
318 }
319
320 static int api_macip_acl_interface_get (vat_main_t * vam)
321 {
322     acl_test_main_t * sm = &acl_test_main;
323     vl_api_acl_plugin_get_version_t * mp;
324     u32 msg_size = sizeof(*mp);
325     f64 timeout;
326
327     vam->result_ready = 0;
328     mp = vl_msg_api_alloc_as_if_client(msg_size);
329     memset (mp, 0, msg_size);
330     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET + sm->msg_id_base);
331     mp->client_index = vam->my_client_index;
332
333     /* send it... */
334     S;
335
336     /* Wait for a reply... */
337     W;
338
339     return 0;
340 }
341
342 #define vec_validate_acl_rules(v, idx) \
343   do {                                 \
344     if (vec_len(v) < idx+1) {  \
345       vec_validate(v, idx); \
346       v[idx].is_permit = 0x1; \
347       v[idx].srcport_or_icmptype_last = 0xffff; \
348       v[idx].dstport_or_icmpcode_last = 0xffff; \
349     } \
350   } while (0)
351
352
353 static int api_acl_add_replace (vat_main_t * vam)
354 {
355     acl_test_main_t * sm = &acl_test_main;
356     unformat_input_t * i = vam->input;
357     f64 timeout;
358     vl_api_acl_add_replace_t * mp;
359     u32 acl_index = ~0;
360     u32 msg_size = sizeof (*mp); /* without the rules */
361
362     vl_api_acl_rule_t *rules = 0;
363     int rule_idx = 0;
364     int n_rules = 0;
365     u32 proto = 0;
366     u32 port1 = 0;
367     u32 port2 = 0;
368     u32 action = 0;
369     u32 tcpflags, tcpmask;
370     u32 src_prefix_length = 0, dst_prefix_length = 0;
371     ip4_address_t src_v4address, dst_v4address;
372     ip6_address_t src_v6address, dst_v6address;
373     u8 *tag = 0;
374
375     if (!unformat (i, "%d", &acl_index)) {
376         /* Just assume -1 */
377     }
378
379     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
380     {
381         if (unformat (i, "ipv6"))
382           {
383             vec_validate_acl_rules(rules, rule_idx);
384             rules[rule_idx].is_ipv6 = 1;
385           }
386         else if (unformat (i, "ipv4"))
387           {
388             vec_validate_acl_rules(rules, rule_idx);
389             rules[rule_idx].is_ipv6 = 0;
390           }
391         else if (unformat (i, "permit+reflect"))
392           {
393             vec_validate_acl_rules(rules, rule_idx);
394             rules[rule_idx].is_permit = 2;
395           }
396         else if (unformat (i, "permit"))
397           {
398             vec_validate_acl_rules(rules, rule_idx);
399             rules[rule_idx].is_permit = 1;
400           }
401         else if (unformat (i, "action %d", &action))
402           {
403             vec_validate_acl_rules(rules, rule_idx);
404             rules[rule_idx].is_permit = action;
405           }
406         else if (unformat (i, "src %U/%d",
407          unformat_ip4_address, &src_v4address, &src_prefix_length))
408           {
409             vec_validate_acl_rules(rules, rule_idx);
410             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
411             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
412             rules[rule_idx].is_ipv6 = 0;
413           }
414         else if (unformat (i, "src %U/%d",
415          unformat_ip6_address, &src_v6address, &src_prefix_length))
416           {
417             vec_validate_acl_rules(rules, rule_idx);
418             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
419             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
420             rules[rule_idx].is_ipv6 = 1;
421           }
422         else if (unformat (i, "dst %U/%d",
423          unformat_ip4_address, &dst_v4address, &dst_prefix_length))
424           {
425             vec_validate_acl_rules(rules, rule_idx);
426             memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
427             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
428             rules[rule_idx].is_ipv6 = 0;
429           }
430         else if (unformat (i, "dst %U/%d",
431          unformat_ip6_address, &dst_v6address, &dst_prefix_length))
432           {
433             vec_validate_acl_rules(rules, rule_idx);
434             memcpy (rules[rule_idx].dst_ip_addr, &dst_v6address, 16);
435             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
436             rules[rule_idx].is_ipv6 = 1;
437           }
438         else if (unformat (i, "sport %d-%d", &port1, &port2))
439           {
440             vec_validate_acl_rules(rules, rule_idx);
441             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
442             rules[rule_idx].srcport_or_icmptype_last = htons(port2);
443           }
444         else if (unformat (i, "sport %d", &port1))
445           {
446             vec_validate_acl_rules(rules, rule_idx);
447             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
448             rules[rule_idx].srcport_or_icmptype_last = htons(port1);
449           }
450         else if (unformat (i, "dport %d-%d", &port1, &port2))
451           {
452             vec_validate_acl_rules(rules, rule_idx);
453             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
454             rules[rule_idx].dstport_or_icmpcode_last = htons(port2);
455           }
456         else if (unformat (i, "dport %d", &port1))
457           {
458             vec_validate_acl_rules(rules, rule_idx);
459             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
460             rules[rule_idx].dstport_or_icmpcode_last = htons(port1);
461           }
462         else if (unformat (i, "tcpflags %d %d", &tcpflags, &tcpmask))
463           {
464             vec_validate_acl_rules(rules, rule_idx);
465             rules[rule_idx].tcp_flags_value = tcpflags;
466             rules[rule_idx].tcp_flags_mask = tcpmask;
467           }
468         else if (unformat (i, "proto %d", &proto))
469           {
470             vec_validate_acl_rules(rules, rule_idx);
471             rules[rule_idx].proto = proto;
472           }
473         else if (unformat (i, "tag %s", &tag))
474           {
475           }
476         else if (unformat (i, ","))
477           {
478             rule_idx++;
479             vec_validate_acl_rules(rules, rule_idx);
480           }
481         else
482     break;
483     }
484
485     /* Construct the API message */
486     vam->result_ready = 0;
487
488     if(rules)
489       n_rules = vec_len(rules);
490     else
491       n_rules = 0;
492
493     msg_size += n_rules*sizeof(rules[0]);
494
495     mp = vl_msg_api_alloc_as_if_client(msg_size);
496     memset (mp, 0, msg_size);
497     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
498     mp->client_index = vam->my_client_index;
499     if (n_rules > 0)
500       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
501     if (tag)
502       {
503         if (vec_len(tag) >= sizeof(mp->tag))
504           {
505             tag[sizeof(mp->tag)-1] = 0;
506             _vec_len(tag) = sizeof(mp->tag);
507           }
508         clib_memcpy(mp->tag, tag, vec_len(tag));
509         vec_free(tag);
510       }
511     mp->acl_index = ntohl(acl_index);
512     mp->count = htonl(n_rules);
513
514     /* send it... */
515     S;
516
517     /* Wait for a reply... */
518     W;
519 }
520
521 static int api_acl_del (vat_main_t * vam)
522 {
523     acl_test_main_t * sm = &acl_test_main;
524     unformat_input_t * i = vam->input;
525     f64 timeout;
526     vl_api_acl_del_t * mp;
527     u32 acl_index = ~0;
528
529     if (!unformat (i, "%d", &acl_index)) {
530       errmsg ("missing acl index\n");
531       return -99;
532     }
533
534     /* Construct the API message */
535     M(ACL_DEL, acl_del);
536     mp->acl_index = ntohl(acl_index);
537
538     /* send it... */
539     S;
540
541     /* Wait for a reply... */
542     W;
543 }
544
545 static int api_macip_acl_del (vat_main_t * vam)
546 {
547     acl_test_main_t * sm = &acl_test_main;
548     unformat_input_t * i = vam->input;
549     f64 timeout;
550     vl_api_acl_del_t * mp;
551     u32 acl_index = ~0;
552
553     if (!unformat (i, "%d", &acl_index)) {
554       errmsg ("missing acl index\n");
555       return -99;
556     }
557
558     /* Construct the API message */
559     M(MACIP_ACL_DEL, acl_del);
560     mp->acl_index = ntohl(acl_index);
561
562     /* send it... */
563     S;
564
565     /* Wait for a reply... */
566     W;
567 }
568
569 static int api_acl_interface_add_del (vat_main_t * vam)
570 {
571     acl_test_main_t * sm = &acl_test_main;
572     unformat_input_t * i = vam->input;
573     f64 timeout;
574     vl_api_acl_interface_add_del_t * mp;
575     u32 sw_if_index = ~0;
576     u32 acl_index = ~0;
577     u8 is_input = 0;
578     u8 is_add = 0;
579
580 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
581
582     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
583     {
584         if (unformat (i, "%d", &acl_index))
585     ;
586         else
587     break;
588     }
589
590
591     /* Parse args required to build the message */
592     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
593         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
594             ;
595         else if (unformat (i, "sw_if_index %d", &sw_if_index))
596             ;
597         else if (unformat (i, "add"))
598             is_add = 1;
599         else if (unformat (i, "del"))
600             is_add = 0;
601         else if (unformat (i, "acl %d", &acl_index))
602             ;
603         else if (unformat (i, "input"))
604             is_input = 1;
605         else if (unformat (i, "output"))
606             is_input = 0;
607         else
608             break;
609     }
610
611     if (sw_if_index == ~0) {
612         errmsg ("missing interface name / explicit sw_if_index number \n");
613         return -99;
614     }
615
616     if (acl_index == ~0) {
617         errmsg ("missing ACL index\n");
618         return -99;
619     }
620
621
622
623     /* Construct the API message */
624     M(ACL_INTERFACE_ADD_DEL, acl_interface_add_del);
625     mp->acl_index = ntohl(acl_index);
626     mp->sw_if_index = ntohl(sw_if_index);
627     mp->is_add = is_add;
628     mp->is_input = is_input;
629
630     /* send it... */
631     S;
632
633     /* Wait for a reply... */
634     W;
635 }
636
637 static int api_macip_acl_interface_add_del (vat_main_t * vam)
638 {
639     acl_test_main_t * sm = &acl_test_main;
640     unformat_input_t * i = vam->input;
641     f64 timeout;
642     vl_api_macip_acl_interface_add_del_t * mp;
643     u32 sw_if_index = ~0;
644     u32 acl_index = ~0;
645     u8 is_add = 0;
646
647     /* Parse args required to build the message */
648     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
649         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
650             ;
651         else if (unformat (i, "sw_if_index %d", &sw_if_index))
652             ;
653         else if (unformat (i, "add"))
654             is_add = 1;
655         else if (unformat (i, "del"))
656             is_add = 0;
657         else if (unformat (i, "acl %d", &acl_index))
658             ;
659         else
660             break;
661     }
662
663     if (sw_if_index == ~0) {
664         errmsg ("missing interface name / explicit sw_if_index number \n");
665         return -99;
666     }
667
668     if (acl_index == ~0) {
669         errmsg ("missing ACL index\n");
670         return -99;
671     }
672
673
674
675     /* Construct the API message */
676     M(MACIP_ACL_INTERFACE_ADD_DEL, macip_acl_interface_add_del);
677     mp->acl_index = ntohl(acl_index);
678     mp->sw_if_index = ntohl(sw_if_index);
679     mp->is_add = is_add;
680
681     /* send it... */
682     S;
683
684     /* Wait for a reply... */
685     W;
686 }
687
688 static int api_acl_interface_set_acl_list (vat_main_t * vam)
689 {
690     acl_test_main_t * sm = &acl_test_main;
691     unformat_input_t * i = vam->input;
692     f64 timeout;
693     vl_api_acl_interface_set_acl_list_t * mp;
694     u32 sw_if_index = ~0;
695     u32 acl_index = ~0;
696     u32 *inacls = 0;
697     u32 *outacls = 0;
698     u8 is_input = 0;
699
700 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
701
702     /* Parse args required to build the message */
703     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
704         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
705             ;
706         else if (unformat (i, "sw_if_index %d", &sw_if_index))
707             ;
708         else if (unformat (i, "%d", &acl_index))
709           {
710             if(is_input)
711               vec_add1(inacls, htonl(acl_index));
712             else
713               vec_add1(outacls, htonl(acl_index));
714           }
715         else if (unformat (i, "acl %d", &acl_index))
716             ;
717         else if (unformat (i, "input"))
718             is_input = 1;
719         else if (unformat (i, "output"))
720             is_input = 0;
721         else
722             break;
723     }
724
725     if (sw_if_index == ~0) {
726         errmsg ("missing interface name / explicit sw_if_index number \n");
727         return -99;
728     }
729
730     /* Construct the API message */
731     M2(ACL_INTERFACE_SET_ACL_LIST, acl_interface_set_acl_list, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
732     mp->sw_if_index = ntohl(sw_if_index);
733     mp->n_input = vec_len(inacls);
734     mp->count = vec_len(inacls) + vec_len(outacls);
735     vec_append(inacls, outacls);
736     if (vec_len(inacls) > 0)
737       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
738
739     /* send it... */
740     S;
741
742     /* Wait for a reply... */
743     W;
744 }
745
746
747 static int api_acl_interface_list_dump (vat_main_t * vam)
748 {
749     acl_test_main_t * sm = &acl_test_main;
750     unformat_input_t * i = vam->input;
751     f64 timeout;
752     u32 sw_if_index = ~0;
753     vl_api_acl_interface_list_dump_t * mp;
754
755     /* Parse args required to build the message */
756     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
757         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
758             ;
759         else if (unformat (i, "sw_if_index %d", &sw_if_index))
760             ;
761         else
762             break;
763     }
764
765     /* Construct the API message */
766     M(ACL_INTERFACE_LIST_DUMP, acl_interface_list_dump);
767     mp->sw_if_index = ntohl (sw_if_index);
768
769     /* send it... */
770     S;
771
772     /* Wait for a reply... */
773     W;
774 }
775
776 static int api_acl_dump (vat_main_t * vam)
777 {
778     acl_test_main_t * sm = &acl_test_main;
779     unformat_input_t * i = vam->input;
780     f64 timeout;
781     u32 acl_index = ~0;
782     vl_api_acl_dump_t * mp;
783
784     /* Parse args required to build the message */
785     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
786         if (unformat (i, "%d", &acl_index))
787             ;
788         else
789             break;
790     }
791
792     /* Construct the API message */
793     M(ACL_DUMP, acl_dump);
794     mp->acl_index = ntohl (acl_index);
795
796     /* send it... */
797     S;
798
799     /* Wait for a reply... */
800     W;
801 }
802
803 static int api_macip_acl_dump (vat_main_t * vam)
804 {
805     acl_test_main_t * sm = &acl_test_main;
806     unformat_input_t * i = vam->input;
807     f64 timeout;
808     u32 acl_index = ~0;
809     vl_api_acl_dump_t * mp;
810
811     /* Parse args required to build the message */
812     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
813         if (unformat (i, "%d", &acl_index))
814             ;
815         else
816             break;
817     }
818
819     /* Construct the API message */
820     M(MACIP_ACL_DUMP, macip_acl_dump);
821     mp->acl_index = ntohl (acl_index);
822
823     /* send it... */
824     S;
825
826     /* Wait for a reply... */
827     W;
828 }
829
830 #define vec_validate_macip_acl_rules(v, idx) \
831   do {                                 \
832     if (vec_len(v) < idx+1) {  \
833       vec_validate(v, idx); \
834       v[idx].is_permit = 0x1; \
835     } \
836   } while (0)
837
838
839 static int api_macip_acl_add (vat_main_t * vam)
840 {
841     acl_test_main_t * sm = &acl_test_main;
842     unformat_input_t * i = vam->input;
843     f64 timeout;
844     vl_api_macip_acl_add_t * mp;
845     u32 msg_size = sizeof (*mp); /* without the rules */
846
847     vl_api_macip_acl_rule_t *rules = 0;
848     int rule_idx = 0;
849     int n_rules = 0;
850     u32 src_prefix_length = 0;
851     u32 action = 0;
852     ip4_address_t src_v4address;
853     ip6_address_t src_v6address;
854     u8 src_mac[6];
855     u8 *tag = 0;
856     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
857
858     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
859     {
860         if (unformat (i, "ipv6"))
861           {
862             vec_validate_macip_acl_rules(rules, rule_idx);
863             rules[rule_idx].is_ipv6 = 1;
864           }
865         else if (unformat (i, "ipv4"))
866           {
867             vec_validate_macip_acl_rules(rules, rule_idx);
868             rules[rule_idx].is_ipv6 = 1;
869           }
870         else if (unformat (i, "permit"))
871           {
872             vec_validate_macip_acl_rules(rules, rule_idx);
873             rules[rule_idx].is_permit = 1;
874           }
875         else if (unformat (i, "deny"))
876           {
877             vec_validate_macip_acl_rules(rules, rule_idx);
878             rules[rule_idx].is_permit = 0;
879           }
880         else if (unformat (i, "action %d", &action))
881           {
882             vec_validate_macip_acl_rules(rules, rule_idx);
883             rules[rule_idx].is_permit = action;
884           }
885         else if (unformat (i, "ip %U/%d",
886          unformat_ip4_address, &src_v4address, &src_prefix_length))
887           {
888             vec_validate_macip_acl_rules(rules, rule_idx);
889             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
890             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
891             rules[rule_idx].is_ipv6 = 0;
892           }
893         else if (unformat (i, "ip %U/%d",
894          unformat_ip6_address, &src_v6address, &src_prefix_length))
895           {
896             vec_validate_macip_acl_rules(rules, rule_idx);
897             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
898             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
899             rules[rule_idx].is_ipv6 = 1;
900           }
901         else if (unformat (i, "mac %U",
902          my_unformat_mac_address, &src_mac))
903           {
904             vec_validate_macip_acl_rules(rules, rule_idx);
905             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
906             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
907           }
908         else if (unformat (i, "mask %U",
909          my_unformat_mac_address, &src_mac))
910           {
911             vec_validate_macip_acl_rules(rules, rule_idx);
912             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
913           }
914         else if (unformat (i, "tag %s", &tag))
915           {
916           }
917         else if (unformat (i, ","))
918           {
919             rule_idx++;
920             vec_validate_macip_acl_rules(rules, rule_idx);
921           }
922         else
923     break;
924     }
925
926     /* Construct the API message */
927     vam->result_ready = 0;
928
929     if(rules)
930       n_rules = vec_len(rules);
931     else
932       n_rules = 0;
933
934     msg_size += n_rules*sizeof(rules[0]);
935
936     mp = vl_msg_api_alloc_as_if_client(msg_size);
937     memset (mp, 0, msg_size);
938     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
939     mp->client_index = vam->my_client_index;
940     if (n_rules > 0)
941       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
942     if (tag)
943       {
944         if (vec_len(tag) >= sizeof(mp->tag))
945           {
946             tag[sizeof(mp->tag)-1] = 0;
947             _vec_len(tag) = sizeof(mp->tag);
948           }
949         clib_memcpy(mp->tag, tag, vec_len(tag));
950         vec_free(tag);
951       }
952
953     mp->count = htonl(n_rules);
954
955     /* send it... */
956     S;
957
958     /* Wait for a reply... */
959     W;
960 }
961
962 /*
963  * List of messages that the api test plugin sends,
964  * and that the data plane plugin processes
965  */
966 #define foreach_vpe_api_msg \
967 _(acl_plugin_get_version, "") \
968 _(acl_add_replace, "<acl-idx> [<ipv4|ipv6> <permit|permit+reflect|deny|action N> [src IP/plen] [dst IP/plen] [sport X-Y] [dport X-Y] [proto P] [tcpflags FL MASK], ... , ...") \
969 _(acl_del, "<acl-idx>") \
970 _(acl_dump, "[<acl-idx>]") \
971 _(acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] [input|output] acl <acl-idx>") \
972 _(acl_interface_set_acl_list, "<intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]") \
973 _(acl_interface_list_dump, "[<intfc> | sw_if_index <if-idx>]") \
974 _(macip_acl_add, "...") \
975 _(macip_acl_del, "<acl-idx>")\
976 _(macip_acl_dump, "[<acl-idx>]") \
977 _(macip_acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] acl <acl-idx>") \
978 _(macip_acl_interface_get, "")
979
980
981
982 void vat_api_hookup (vat_main_t *vam)
983 {
984     acl_test_main_t * sm = &acl_test_main;
985     /* Hook up handlers for replies from the data plane plug-in */
986 #define _(N,n)                                                  \
987     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
988                            #n,                                  \
989                            vl_api_##n##_t_handler,              \
990                            vl_noop_handler,                     \
991                            vl_api_##n##_t_endian,               \
992                            vl_api_##n##_t_print,                \
993                            sizeof(vl_api_##n##_t), 1);
994     foreach_vpe_api_reply_msg;
995 #undef _
996
997     /* API messages we can send */
998 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
999     foreach_vpe_api_msg;
1000 #undef _
1001
1002     /* Help strings */
1003 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
1004     foreach_vpe_api_msg;
1005 #undef _
1006 }
1007
1008 clib_error_t * vat_plugin_register (vat_main_t *vam)
1009 {
1010   acl_test_main_t * sm = &acl_test_main;
1011   u8 * name;
1012
1013   sm->vat_main = vam;
1014
1015   name = format (0, "acl_%08x%c", api_version, 0);
1016   sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
1017
1018   if (sm->msg_id_base != (u16) ~0)
1019     vat_api_hookup (vam);
1020
1021   vec_free(name);
1022
1023   return 0;
1024 }