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