vppapigen: require reply/details messages for requests/dumps
[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 <vppinfra/error.h>
25 #include <vnet/ip/ip.h>
26 #include <arpa/inet.h>
27
28 #define __plugin_msg_base acl_test_main.msg_id_base
29 #include <vlibapi/vat_helper_macros.h>
30
31 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
32
33 /* Declare message IDs */
34 #include <acl/acl_msg_enum.h>
35
36 /* define message structures */
37 #define vl_typedefs
38 #include <acl/acl_all_api_h.h>
39 #undef vl_typedefs
40
41 /* define message structures */
42 #define vl_endianfun
43 #include <acl/acl_all_api_h.h>
44 #undef vl_endianfun
45
46 /* instantiate all the print functions we know about */
47 #define vl_print(handle, ...)
48 #define vl_printfun
49 #include <acl/acl_all_api_h.h>
50 #undef vl_printfun
51
52 /* Get the API version number. */
53 #define vl_api_version(n,v) static u32 api_version=(v);
54 #include <acl/acl_all_api_h.h>
55 #undef vl_api_version
56
57 typedef struct {
58     /* API message ID base */
59     u16 msg_id_base;
60     vat_main_t *vat_main;
61 } acl_test_main_t;
62
63 acl_test_main_t acl_test_main;
64
65 #define foreach_standard_reply_retval_handler   \
66 _(acl_del_reply) \
67 _(acl_interface_add_del_reply) \
68 _(macip_acl_interface_add_del_reply) \
69 _(acl_interface_set_acl_list_reply) \
70 _(acl_interface_set_etype_whitelist_reply) \
71 _(macip_acl_del_reply)
72
73 #define foreach_reply_retval_aclindex_handler  \
74 _(acl_add_replace_reply) \
75 _(macip_acl_add_reply) \
76 _(macip_acl_add_replace_reply)
77
78 #define _(n)                                            \
79     static void vl_api_##n##_t_handler                  \
80     (vl_api_##n##_t * mp)                               \
81     {                                                   \
82         vat_main_t * vam = acl_test_main.vat_main;   \
83         i32 retval = ntohl(mp->retval);                 \
84         if (vam->async_mode) {                          \
85             vam->async_errors += (retval < 0);          \
86         } else {                                        \
87             vam->retval = retval;                       \
88             vam->result_ready = 1;                      \
89         }                                               \
90     }
91 foreach_standard_reply_retval_handler;
92 #undef _
93
94 #define _(n)                                            \
95     static void vl_api_##n##_t_handler                  \
96     (vl_api_##n##_t * mp)                               \
97     {                                                   \
98         vat_main_t * vam = acl_test_main.vat_main;   \
99         i32 retval = ntohl(mp->retval);                 \
100         if (vam->async_mode) {                          \
101             vam->async_errors += (retval < 0);          \
102         } else {                                        \
103             clib_warning("ACL index: %d", ntohl(mp->acl_index)); \
104             vam->retval = retval;                       \
105             vam->result_ready = 1;                      \
106         }                                               \
107     }
108 foreach_reply_retval_aclindex_handler;
109 #undef _
110
111 /* These two ought to be in a library somewhere but they aren't */
112 static uword
113 my_unformat_mac_address (unformat_input_t * input, va_list * args)
114 {
115   u8 *a = va_arg (*args, u8 *);
116   return unformat (input, "%x:%x:%x:%x:%x:%x", &a[0], &a[1], &a[2], &a[3],
117                    &a[4], &a[5]);
118 }
119
120 static u8 *
121 my_format_mac_address (u8 * s, va_list * args)
122 {
123   u8 *a = va_arg (*args, u8 *);
124   return format (s, "%02x:%02x:%02x:%02x:%02x:%02x",
125                  a[0], a[1], a[2], a[3], a[4], a[5]);
126 }
127
128
129
130 static void vl_api_acl_plugin_get_version_reply_t_handler
131     (vl_api_acl_plugin_get_version_reply_t * mp)
132     {
133         vat_main_t * vam = acl_test_main.vat_main;
134         clib_warning("ACL plugin version: %d.%d", ntohl(mp->major), ntohl(mp->minor));
135         vam->result_ready = 1;
136     }
137
138 static void vl_api_acl_interface_list_details_t_handler
139     (vl_api_acl_interface_list_details_t * mp)
140     {
141         int i;
142         vat_main_t * vam = acl_test_main.vat_main;
143         u8 *out = 0;
144         vl_api_acl_interface_list_details_t_endian(mp);
145         out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
146         out = format(out, "   input ");
147         for(i=0; i<mp->count; i++) {
148           if (i == mp->n_input)
149             out = format(out, "\n  output ");
150           out = format(out, "%d ", ntohl (mp->acls[i]));
151         }
152         out = format(out, "\n");
153         clib_warning("%s", out);
154         vec_free(out);
155         vam->result_ready = 1;
156     }
157
158
159 static inline u8 *
160 vl_api_acl_rule_t_pretty_format (u8 *out, vl_api_acl_rule_t * a)
161 {
162   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
163   u8 src[INET6_ADDRSTRLEN];
164   u8 dst[INET6_ADDRSTRLEN];
165   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
166   inet_ntop(af, a->dst_ip_addr, (void *)dst, sizeof(dst));
167
168   out = format(out, "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport %d-%d tcpflags %d mask %d",
169                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
170                      src, a->src_ip_prefix_len,
171                      dst, a->dst_ip_prefix_len,
172                      a->proto,
173                      a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
174                      a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
175                      a->tcp_flags_value, a->tcp_flags_mask);
176   return(out);
177 }
178
179
180
181 static void vl_api_acl_details_t_handler
182     (vl_api_acl_details_t * mp)
183     {
184         int i;
185         vat_main_t * vam = acl_test_main.vat_main;
186         vl_api_acl_details_t_endian(mp);
187         u8 *out = 0;
188         out = format(0, "acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
189         for(i=0; i<mp->count; i++) {
190           out = format(out, "   ");
191           out = vl_api_acl_rule_t_pretty_format(out, &mp->r[i]);
192           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
193         }
194         clib_warning("%s", out);
195         vec_free(out);
196         vam->result_ready = 1;
197     }
198
199 static inline u8 *
200 vl_api_macip_acl_rule_t_pretty_format (u8 *out, vl_api_macip_acl_rule_t * a)
201 {
202   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
203   u8 src[INET6_ADDRSTRLEN];
204   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
205
206   out = format(out, "%s action %d ip %s/%d mac %U mask %U",
207                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
208                      src, a->src_ip_prefix_len,
209                      my_format_mac_address, a->src_mac,
210                      my_format_mac_address, a->src_mac_mask);
211   return(out);
212 }
213
214
215 static void vl_api_macip_acl_details_t_handler
216     (vl_api_macip_acl_details_t * mp)
217     {
218         int i;
219         vat_main_t * vam = acl_test_main.vat_main;
220         vl_api_macip_acl_details_t_endian(mp);
221         u8 *out = format(0,"MACIP acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
222         for(i=0; i<mp->count; i++) {
223           out = format(out, "   ");
224           out = vl_api_macip_acl_rule_t_pretty_format(out, &mp->r[i]);
225           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
226         }
227         clib_warning("%s", out);
228         vec_free(out);
229         vam->result_ready = 1;
230     }
231
232 static void vl_api_macip_acl_interface_get_reply_t_handler
233     (vl_api_macip_acl_interface_get_reply_t * mp)
234     {
235         int i;
236         vat_main_t * vam = acl_test_main.vat_main;
237         u8 *out = format(0, "sw_if_index with MACIP ACL count: %d\n", ntohl(mp->count));
238         for(i=0; i<ntohl(mp->count); i++) {
239           out = format(out, "  macip_acl_interface_add_del sw_if_index %d add acl %d\n", i, ntohl(mp->acls[i]));
240         }
241         out = format(out, "\n");
242         clib_warning("%s", out);
243         vec_free(out);
244         vam->result_ready = 1;
245     }
246
247 static void vl_api_acl_plugin_control_ping_reply_t_handler
248   (vl_api_acl_plugin_control_ping_reply_t * mp)
249 {
250   vat_main_t *vam = &vat_main;
251   i32 retval = ntohl (mp->retval);
252   if (vam->async_mode)
253     {
254       vam->async_errors += (retval < 0);
255     }
256   else
257     {
258       vam->retval = retval;
259       vam->result_ready = 1;
260     }
261 }
262
263
264 /*
265  * Table of message reply handlers, must include boilerplate handlers
266  * we just generated
267  */
268 #define foreach_vpe_api_reply_msg                                       \
269 _(ACL_ADD_REPLACE_REPLY, acl_add_replace_reply) \
270 _(ACL_DEL_REPLY, acl_del_reply) \
271 _(ACL_INTERFACE_ADD_DEL_REPLY, acl_interface_add_del_reply)  \
272 _(ACL_INTERFACE_SET_ACL_LIST_REPLY, acl_interface_set_acl_list_reply) \
273 _(ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY, acl_interface_set_etype_whitelist_reply) \
274 _(ACL_INTERFACE_LIST_DETAILS, acl_interface_list_details)  \
275 _(ACL_DETAILS, acl_details)  \
276 _(MACIP_ACL_ADD_REPLY, macip_acl_add_reply) \
277 _(MACIP_ACL_ADD_REPLACE_REPLY, macip_acl_add_replace_reply) \
278 _(MACIP_ACL_DEL_REPLY, macip_acl_del_reply) \
279 _(MACIP_ACL_DETAILS, macip_acl_details)  \
280 _(MACIP_ACL_INTERFACE_ADD_DEL_REPLY, macip_acl_interface_add_del_reply)  \
281 _(MACIP_ACL_INTERFACE_GET_REPLY, macip_acl_interface_get_reply)  \
282 _(ACL_PLUGIN_CONTROL_PING_REPLY, acl_plugin_control_ping_reply) \
283 _(ACL_PLUGIN_GET_VERSION_REPLY, acl_plugin_get_version_reply)
284
285 static int api_acl_plugin_get_version (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     int ret;
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_ACL_PLUGIN_GET_VERSION + sm->msg_id_base);
296     mp->client_index = vam->my_client_index;
297
298     /* send it... */
299     S(mp);
300
301     /* Wait for a reply... */
302     W (ret);
303     return ret;
304 }
305
306 static int api_macip_acl_interface_get (vat_main_t * vam)
307 {
308     acl_test_main_t * sm = &acl_test_main;
309     vl_api_acl_plugin_get_version_t * mp;
310     u32 msg_size = sizeof(*mp);
311     int ret;
312
313     vam->result_ready = 0;
314     mp = vl_msg_api_alloc_as_if_client(msg_size);
315     memset (mp, 0, msg_size);
316     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET + sm->msg_id_base);
317     mp->client_index = vam->my_client_index;
318
319     /* send it... */
320     S(mp);
321
322     /* Wait for a reply... */
323     W (ret);
324     return ret;
325 }
326
327 #define vec_validate_acl_rules(v, idx) \
328   do {                                 \
329     if (vec_len(v) < idx+1) {  \
330       vec_validate(v, idx); \
331       v[idx].is_permit = 0x1; \
332       v[idx].srcport_or_icmptype_last = 0xffff; \
333       v[idx].dstport_or_icmpcode_last = 0xffff; \
334     } \
335   } while (0)
336
337
338 static int api_acl_add_replace (vat_main_t * vam)
339 {
340     acl_test_main_t * sm = &acl_test_main;
341     unformat_input_t * i = vam->input;
342     vl_api_acl_add_replace_t * mp;
343     u32 acl_index = ~0;
344     u32 msg_size = sizeof (*mp); /* without the rules */
345
346     vl_api_acl_rule_t *rules = 0;
347     int rule_idx = 0;
348     int n_rules = 0;
349     int n_rules_override = -1;
350     u32 proto = 0;
351     u32 port1 = 0;
352     u32 port2 = 0;
353     u32 action = 0;
354     u32 tcpflags, tcpmask;
355     u32 src_prefix_length = 0, dst_prefix_length = 0;
356     ip4_address_t src_v4address, dst_v4address;
357     ip6_address_t src_v6address, dst_v6address;
358     u8 *tag = 0;
359     int ret;
360
361     if (!unformat (i, "%d", &acl_index)) {
362         /* Just assume -1 */
363     }
364
365     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
366     {
367         if (unformat (i, "ipv6"))
368           {
369             vec_validate_acl_rules(rules, rule_idx);
370             rules[rule_idx].is_ipv6 = 1;
371           }
372         else if (unformat (i, "ipv4"))
373           {
374             vec_validate_acl_rules(rules, rule_idx);
375             rules[rule_idx].is_ipv6 = 0;
376           }
377         else if (unformat (i, "permit+reflect"))
378           {
379             vec_validate_acl_rules(rules, rule_idx);
380             rules[rule_idx].is_permit = 2;
381           }
382         else if (unformat (i, "permit"))
383           {
384             vec_validate_acl_rules(rules, rule_idx);
385             rules[rule_idx].is_permit = 1;
386           }
387         else if (unformat (i, "deny"))
388           {
389             vec_validate_acl_rules(rules, rule_idx);
390             rules[rule_idx].is_permit = 0;
391           }
392         else if (unformat (i, "count %d", &n_rules_override))
393           {
394             /* we will use this later */
395           }
396         else if (unformat (i, "action %d", &action))
397           {
398             vec_validate_acl_rules(rules, rule_idx);
399             rules[rule_idx].is_permit = action;
400           }
401         else if (unformat (i, "src %U/%d",
402          unformat_ip4_address, &src_v4address, &src_prefix_length))
403           {
404             vec_validate_acl_rules(rules, rule_idx);
405             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
406             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
407             rules[rule_idx].is_ipv6 = 0;
408           }
409         else if (unformat (i, "src %U/%d",
410          unformat_ip6_address, &src_v6address, &src_prefix_length))
411           {
412             vec_validate_acl_rules(rules, rule_idx);
413             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
414             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
415             rules[rule_idx].is_ipv6 = 1;
416           }
417         else if (unformat (i, "dst %U/%d",
418          unformat_ip4_address, &dst_v4address, &dst_prefix_length))
419           {
420             vec_validate_acl_rules(rules, rule_idx);
421             memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
422             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
423             rules[rule_idx].is_ipv6 = 0;
424           }
425         else if (unformat (i, "dst %U/%d",
426          unformat_ip6_address, &dst_v6address, &dst_prefix_length))
427           {
428             vec_validate_acl_rules(rules, rule_idx);
429             memcpy (rules[rule_idx].dst_ip_addr, &dst_v6address, 16);
430             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
431             rules[rule_idx].is_ipv6 = 1;
432           }
433         else if (unformat (i, "sport %d-%d", &port1, &port2))
434           {
435             vec_validate_acl_rules(rules, rule_idx);
436             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
437             rules[rule_idx].srcport_or_icmptype_last = htons(port2);
438           }
439         else if (unformat (i, "sport %d", &port1))
440           {
441             vec_validate_acl_rules(rules, rule_idx);
442             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
443             rules[rule_idx].srcport_or_icmptype_last = htons(port1);
444           }
445         else if (unformat (i, "dport %d-%d", &port1, &port2))
446           {
447             vec_validate_acl_rules(rules, rule_idx);
448             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
449             rules[rule_idx].dstport_or_icmpcode_last = htons(port2);
450           }
451         else if (unformat (i, "dport %d", &port1))
452           {
453             vec_validate_acl_rules(rules, rule_idx);
454             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
455             rules[rule_idx].dstport_or_icmpcode_last = htons(port1);
456           }
457         else if (unformat (i, "tcpflags %d %d", &tcpflags, &tcpmask))
458           {
459             vec_validate_acl_rules(rules, rule_idx);
460             rules[rule_idx].tcp_flags_value = tcpflags;
461             rules[rule_idx].tcp_flags_mask = tcpmask;
462           }
463         else if (unformat (i, "tcpflags %d mask %d", &tcpflags, &tcpmask))
464           {
465             vec_validate_acl_rules(rules, rule_idx);
466             rules[rule_idx].tcp_flags_value = tcpflags;
467             rules[rule_idx].tcp_flags_mask = tcpmask;
468           }
469         else if (unformat (i, "proto %d", &proto))
470           {
471             vec_validate_acl_rules(rules, rule_idx);
472             rules[rule_idx].proto = proto;
473           }
474         else if (unformat (i, "tag %s", &tag))
475           {
476           }
477         else if (unformat (i, ","))
478           {
479             rule_idx++;
480             vec_validate_acl_rules(rules, rule_idx);
481           }
482         else
483     break;
484     }
485
486     /* Construct the API message */
487     vam->result_ready = 0;
488
489     if(rules)
490       n_rules = vec_len(rules);
491     else
492       n_rules = 0;
493
494     if (n_rules_override >= 0)
495       n_rules = n_rules_override;
496
497     msg_size += n_rules*sizeof(rules[0]);
498
499     mp = vl_msg_api_alloc_as_if_client(msg_size);
500     memset (mp, 0, msg_size);
501     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
502     mp->client_index = vam->my_client_index;
503     if ((n_rules > 0) && rules)
504       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
505     if (tag)
506       {
507         if (vec_len(tag) >= sizeof(mp->tag))
508           {
509             tag[sizeof(mp->tag)-1] = 0;
510             _vec_len(tag) = sizeof(mp->tag);
511           }
512         clib_memcpy(mp->tag, tag, vec_len(tag));
513         vec_free(tag);
514       }
515     mp->acl_index = ntohl(acl_index);
516     mp->count = htonl(n_rules);
517
518     /* send it... */
519     S(mp);
520
521     /* Wait for a reply... */
522     W (ret);
523     return ret;
524 }
525
526 static int api_acl_del (vat_main_t * vam)
527 {
528     unformat_input_t * i = vam->input;
529     vl_api_acl_del_t * mp;
530     u32 acl_index = ~0;
531     int ret;
532
533     if (!unformat (i, "%d", &acl_index)) {
534       errmsg ("missing acl index\n");
535       return -99;
536     }
537
538     /* Construct the API message */
539     M(ACL_DEL, mp);
540     mp->acl_index = ntohl(acl_index);
541
542     /* send it... */
543     S(mp);
544
545     /* Wait for a reply... */
546     W (ret);
547     return ret;
548 }
549
550 static int api_macip_acl_del (vat_main_t * vam)
551 {
552     unformat_input_t * i = vam->input;
553     vl_api_acl_del_t * mp;
554     u32 acl_index = ~0;
555     int ret;
556
557     if (!unformat (i, "%d", &acl_index)) {
558       errmsg ("missing acl index\n");
559       return -99;
560     }
561
562     /* Construct the API message */
563     M(MACIP_ACL_DEL, mp);
564     mp->acl_index = ntohl(acl_index);
565
566     /* send it... */
567     S(mp);
568
569     /* Wait for a reply... */
570     W (ret);
571     return ret;
572 }
573
574 static int api_acl_interface_add_del (vat_main_t * vam)
575 {
576     unformat_input_t * i = vam->input;
577     vl_api_acl_interface_add_del_t * mp;
578     u32 sw_if_index = ~0;
579     u32 acl_index = ~0;
580     u8 is_input = 0;
581     u8 is_add = 0;
582     int ret;
583
584 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
585
586     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
587     {
588         if (unformat (i, "%d", &acl_index))
589     ;
590         else
591     break;
592     }
593
594
595     /* Parse args required to build the message */
596     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
597         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
598             ;
599         else if (unformat (i, "sw_if_index %d", &sw_if_index))
600             ;
601         else if (unformat (i, "add"))
602             is_add = 1;
603         else if (unformat (i, "del"))
604             is_add = 0;
605         else if (unformat (i, "acl %d", &acl_index))
606             ;
607         else if (unformat (i, "input"))
608             is_input = 1;
609         else if (unformat (i, "output"))
610             is_input = 0;
611         else
612             break;
613     }
614
615     if (sw_if_index == ~0) {
616         errmsg ("missing interface name / explicit sw_if_index number \n");
617         return -99;
618     }
619
620     if (acl_index == ~0) {
621         errmsg ("missing ACL index\n");
622         return -99;
623     }
624
625
626
627     /* Construct the API message */
628     M(ACL_INTERFACE_ADD_DEL, mp);
629     mp->acl_index = ntohl(acl_index);
630     mp->sw_if_index = ntohl(sw_if_index);
631     mp->is_add = is_add;
632     mp->is_input = is_input;
633
634     /* send it... */
635     S(mp);
636
637     /* Wait for a reply... */
638     W (ret);
639     return ret;
640 }
641
642 static int api_macip_acl_interface_add_del (vat_main_t * vam)
643 {
644     unformat_input_t * i = vam->input;
645     vl_api_macip_acl_interface_add_del_t * mp;
646     u32 sw_if_index = ~0;
647     u32 acl_index = ~0;
648     u8 is_add = 0;
649     int ret;
650
651     /* Parse args required to build the message */
652     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
653         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
654             ;
655         else if (unformat (i, "sw_if_index %d", &sw_if_index))
656             ;
657         else if (unformat (i, "add"))
658             is_add = 1;
659         else if (unformat (i, "del"))
660             is_add = 0;
661         else if (unformat (i, "acl %d", &acl_index))
662             ;
663         else
664             break;
665     }
666
667     if (sw_if_index == ~0) {
668         errmsg ("missing interface name / explicit sw_if_index number \n");
669         return -99;
670     }
671
672     if (acl_index == ~0) {
673         errmsg ("missing ACL index\n");
674         return -99;
675     }
676
677
678
679     /* Construct the API message */
680     M(MACIP_ACL_INTERFACE_ADD_DEL, mp);
681     mp->acl_index = ntohl(acl_index);
682     mp->sw_if_index = ntohl(sw_if_index);
683     mp->is_add = is_add;
684
685     /* send it... */
686     S(mp);
687
688     /* Wait for a reply... */
689     W (ret);
690     return ret;
691 }
692
693 static int api_acl_interface_set_acl_list (vat_main_t * vam)
694 {
695     unformat_input_t * i = vam->input;
696     vl_api_acl_interface_set_acl_list_t * mp;
697     u32 sw_if_index = ~0;
698     u32 acl_index = ~0;
699     u32 *inacls = 0;
700     u32 *outacls = 0;
701     u8 is_input = 0;
702     int ret;
703
704 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
705
706     /* Parse args required to build the message */
707     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
708         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
709             ;
710         else if (unformat (i, "sw_if_index %d", &sw_if_index))
711             ;
712         else if (unformat (i, "%d", &acl_index))
713           {
714             if(is_input)
715               vec_add1(inacls, htonl(acl_index));
716             else
717               vec_add1(outacls, htonl(acl_index));
718           }
719         else if (unformat (i, "acl %d", &acl_index))
720             ;
721         else if (unformat (i, "input"))
722             is_input = 1;
723         else if (unformat (i, "output"))
724             is_input = 0;
725         else
726             break;
727     }
728
729     if (sw_if_index == ~0) {
730         errmsg ("missing interface name / explicit sw_if_index number \n");
731         return -99;
732     }
733
734     /* Construct the API message */
735     M2(ACL_INTERFACE_SET_ACL_LIST, mp, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
736     mp->sw_if_index = ntohl(sw_if_index);
737     mp->n_input = vec_len(inacls);
738     mp->count = vec_len(inacls) + vec_len(outacls);
739     vec_append(inacls, outacls);
740     if (vec_len(inacls) > 0)
741       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
742
743     /* send it... */
744     S(mp);
745
746     /* Wait for a reply... */
747     W (ret);
748     return ret;
749 }
750
751 static int api_acl_interface_set_etype_whitelist (vat_main_t * vam)
752 {
753     unformat_input_t * i = vam->input;
754     vl_api_acl_interface_set_etype_whitelist_t * mp;
755     u32 sw_if_index = ~0;
756     u32 ethertype = ~0;
757     u16 *etypes_in = 0;
758     u16 *etypes_out = 0;
759     u8 is_input = 1;
760     int ret;
761
762 //  acl_interface_set_etype_whitelist <intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]
763
764     /* Parse args required to build the message */
765     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
766         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
767             ;
768         else if (unformat (i, "sw_if_index %d", &sw_if_index))
769             ;
770         else if (unformat (i, "%x", &ethertype))
771           {
772             ethertype = ethertype & 0xffff;
773             if(is_input)
774               vec_add1(etypes_in, htons(ethertype));
775             else
776               vec_add1(etypes_out, htons(ethertype));
777           }
778         else if (unformat (i, "input"))
779             is_input = 1;
780         else if (unformat (i, "output"))
781             is_input = 0;
782         else
783             break;
784     }
785
786     if (sw_if_index == ~0) {
787         errmsg ("missing interface name / explicit sw_if_index number \n");
788         return -99;
789     }
790
791     /* Construct the API message */
792     M2(ACL_INTERFACE_SET_ETYPE_WHITELIST, mp, sizeof(u32) * (vec_len(etypes_in) + vec_len(etypes_out)));
793     mp->sw_if_index = ntohl(sw_if_index);
794     mp->n_input = vec_len(etypes_in);
795     mp->count = vec_len(etypes_in) + vec_len(etypes_out);
796     vec_append(etypes_in, etypes_out);
797     if (vec_len(etypes_in) > 0)
798       clib_memcpy(mp->whitelist, etypes_in, vec_len(etypes_in)*sizeof(etypes_in[0]));
799
800     /* send it... */
801     S(mp);
802
803     /* Wait for a reply... */
804     W (ret);
805     return ret;
806 }
807
808 static void
809 api_acl_send_control_ping(vat_main_t *vam)
810 {
811   vl_api_acl_plugin_control_ping_t *mp_ping;
812
813   M(ACL_PLUGIN_CONTROL_PING, mp_ping);
814   S(mp_ping);
815 }
816
817
818 static int api_acl_interface_list_dump (vat_main_t * vam)
819 {
820     unformat_input_t * i = vam->input;
821     u32 sw_if_index = ~0;
822     vl_api_acl_interface_list_dump_t * mp;
823     int ret;
824
825     /* Parse args required to build the message */
826     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
827         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
828             ;
829         else if (unformat (i, "sw_if_index %d", &sw_if_index))
830             ;
831         else
832             break;
833     }
834
835     /* Construct the API message */
836     M(ACL_INTERFACE_LIST_DUMP, mp);
837     mp->sw_if_index = ntohl (sw_if_index);
838
839     /* send it... */
840     S(mp);
841
842     /* Use control ping for synchronization */
843     api_acl_send_control_ping(vam);
844
845     /* Wait for a reply... */
846     W (ret);
847     return ret;
848 }
849
850 static int api_acl_dump (vat_main_t * vam)
851 {
852     unformat_input_t * i = vam->input;
853     u32 acl_index = ~0;
854     vl_api_acl_dump_t * mp;
855     int ret;
856
857     /* Parse args required to build the message */
858     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
859         if (unformat (i, "%d", &acl_index))
860             ;
861         else
862             break;
863     }
864
865     /* Construct the API message */
866     M(ACL_DUMP, mp);
867     mp->acl_index = ntohl (acl_index);
868
869     /* send it... */
870     S(mp);
871
872     /* Use control ping for synchronization */
873     api_acl_send_control_ping(vam);
874
875     /* Wait for a reply... */
876     W (ret);
877     return ret;
878 }
879
880 static int api_macip_acl_dump (vat_main_t * vam)
881 {
882     unformat_input_t * i = vam->input;
883     u32 acl_index = ~0;
884     vl_api_acl_dump_t * mp;
885     int ret;
886
887     /* Parse args required to build the message */
888     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
889         if (unformat (i, "%d", &acl_index))
890             ;
891         else
892             break;
893     }
894
895     /* Construct the API message */
896     M(MACIP_ACL_DUMP, mp);
897     mp->acl_index = ntohl (acl_index);
898
899     /* send it... */
900     S(mp);
901
902     /* Use control ping for synchronization */
903     api_acl_send_control_ping(vam);
904
905     /* Wait for a reply... */
906     W (ret);
907     return ret;
908 }
909
910 #define vec_validate_macip_acl_rules(v, idx) \
911   do {                                 \
912     if (vec_len(v) < idx+1) {  \
913       vec_validate(v, idx); \
914       v[idx].is_permit = 0x1; \
915     } \
916   } while (0)
917
918
919 static int api_macip_acl_add (vat_main_t * vam)
920 {
921     acl_test_main_t * sm = &acl_test_main;
922     unformat_input_t * i = vam->input;
923     vl_api_macip_acl_add_t * mp;
924     u32 msg_size = sizeof (*mp); /* without the rules */
925
926     vl_api_macip_acl_rule_t *rules = 0;
927     int rule_idx = 0;
928     int n_rules = 0;
929     int n_rules_override = -1;
930     u32 src_prefix_length = 0;
931     u32 action = 0;
932     ip4_address_t src_v4address;
933     ip6_address_t src_v6address;
934     u8 src_mac[6];
935     u8 *tag = 0;
936     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
937     int ret;
938
939     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
940     {
941         if (unformat (i, "ipv6"))
942           {
943             vec_validate_macip_acl_rules(rules, rule_idx);
944             rules[rule_idx].is_ipv6 = 1;
945           }
946         else if (unformat (i, "ipv4"))
947           {
948             vec_validate_macip_acl_rules(rules, rule_idx);
949             rules[rule_idx].is_ipv6 = 0;
950           }
951         else if (unformat (i, "permit"))
952           {
953             vec_validate_macip_acl_rules(rules, rule_idx);
954             rules[rule_idx].is_permit = 1;
955           }
956         else if (unformat (i, "deny"))
957           {
958             vec_validate_macip_acl_rules(rules, rule_idx);
959             rules[rule_idx].is_permit = 0;
960           }
961         else if (unformat (i, "count %d", &n_rules_override))
962           {
963             /* we will use this later */
964           }
965         else if (unformat (i, "action %d", &action))
966           {
967             vec_validate_macip_acl_rules(rules, rule_idx);
968             rules[rule_idx].is_permit = action;
969           }
970         else if (unformat (i, "ip %U/%d",
971          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
972                  unformat (i, "ip %U",
973          unformat_ip4_address, &src_v4address))
974           {
975             if (src_prefix_length == 0)
976               src_prefix_length = 32;
977             vec_validate_macip_acl_rules(rules, rule_idx);
978             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
979             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
980             rules[rule_idx].is_ipv6 = 0;
981           }
982         else if (unformat (i, "src"))
983           {
984             /* Everything in MACIP is "source" but allow this verbosity */
985           }
986         else if (unformat (i, "ip %U/%d",
987          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
988                  unformat (i, "ip %U",
989          unformat_ip6_address, &src_v6address))
990           {
991             if (src_prefix_length == 0)
992               src_prefix_length = 128;
993             vec_validate_macip_acl_rules(rules, rule_idx);
994             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
995             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
996             rules[rule_idx].is_ipv6 = 1;
997           }
998         else if (unformat (i, "mac %U",
999          my_unformat_mac_address, &src_mac))
1000           {
1001             vec_validate_macip_acl_rules(rules, rule_idx);
1002             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1003             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1004           }
1005         else if (unformat (i, "mask %U",
1006          my_unformat_mac_address, &src_mac))
1007           {
1008             vec_validate_macip_acl_rules(rules, rule_idx);
1009             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1010           }
1011         else if (unformat (i, "tag %s", &tag))
1012           {
1013           }
1014         else if (unformat (i, ","))
1015           {
1016             rule_idx++;
1017             vec_validate_macip_acl_rules(rules, rule_idx);
1018           }
1019         else
1020     break;
1021     }
1022
1023     /* Construct the API message */
1024     vam->result_ready = 0;
1025
1026     if(rules)
1027       n_rules = vec_len(rules);
1028
1029     if (n_rules_override >= 0)
1030       n_rules = n_rules_override;
1031
1032     msg_size += n_rules*sizeof(rules[0]);
1033
1034     mp = vl_msg_api_alloc_as_if_client(msg_size);
1035     memset (mp, 0, msg_size);
1036     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
1037     mp->client_index = vam->my_client_index;
1038     if ((n_rules > 0) && rules)
1039       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1040     if (tag)
1041       {
1042         if (vec_len(tag) >= sizeof(mp->tag))
1043           {
1044             tag[sizeof(mp->tag)-1] = 0;
1045             _vec_len(tag) = sizeof(mp->tag);
1046           }
1047         clib_memcpy(mp->tag, tag, vec_len(tag));
1048         vec_free(tag);
1049       }
1050
1051     mp->count = htonl(n_rules);
1052
1053     /* send it... */
1054     S(mp);
1055
1056     /* Wait for a reply... */
1057     W (ret);
1058     return ret;
1059 }
1060
1061 static int api_macip_acl_add_replace (vat_main_t * vam)
1062 {
1063     acl_test_main_t * sm = &acl_test_main;
1064     unformat_input_t * i = vam->input;
1065     vl_api_macip_acl_add_replace_t * mp;
1066     u32 acl_index = ~0;
1067     u32 msg_size = sizeof (*mp); /* without the rules */
1068
1069     vl_api_macip_acl_rule_t *rules = 0;
1070     int rule_idx = 0;
1071     int n_rules = 0;
1072     int n_rules_override = -1;
1073     u32 src_prefix_length = 0;
1074     u32 action = 0;
1075     ip4_address_t src_v4address;
1076     ip6_address_t src_v6address;
1077     u8 src_mac[6];
1078     u8 *tag = 0;
1079     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1080     int ret;
1081
1082     if (!unformat (i, "%d", &acl_index)) {
1083         /* Just assume -1 */
1084     }
1085
1086     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1087     {
1088         if (unformat (i, "ipv6"))
1089           {
1090             vec_validate_macip_acl_rules(rules, rule_idx);
1091             rules[rule_idx].is_ipv6 = 1;
1092           }
1093         else if (unformat (i, "ipv4"))
1094           {
1095             vec_validate_macip_acl_rules(rules, rule_idx);
1096             rules[rule_idx].is_ipv6 = 0;
1097           }
1098         else if (unformat (i, "permit"))
1099           {
1100             vec_validate_macip_acl_rules(rules, rule_idx);
1101             rules[rule_idx].is_permit = 1;
1102           }
1103         else if (unformat (i, "deny"))
1104           {
1105             vec_validate_macip_acl_rules(rules, rule_idx);
1106             rules[rule_idx].is_permit = 0;
1107           }
1108         else if (unformat (i, "count %d", &n_rules_override))
1109           {
1110             /* we will use this later */
1111           }
1112         else if (unformat (i, "action %d", &action))
1113           {
1114             vec_validate_macip_acl_rules(rules, rule_idx);
1115             rules[rule_idx].is_permit = action;
1116           }
1117         else if (unformat (i, "ip %U/%d",
1118          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1119                  unformat (i, "ip %U",
1120          unformat_ip4_address, &src_v4address))
1121           {
1122             if (src_prefix_length == 0)
1123               src_prefix_length = 32;
1124             vec_validate_macip_acl_rules(rules, rule_idx);
1125             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
1126             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1127             rules[rule_idx].is_ipv6 = 0;
1128           }
1129         else if (unformat (i, "src"))
1130           {
1131             /* Everything in MACIP is "source" but allow this verbosity */
1132           }
1133         else if (unformat (i, "ip %U/%d",
1134          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1135                  unformat (i, "ip %U",
1136          unformat_ip6_address, &src_v6address))
1137           {
1138             if (src_prefix_length == 0)
1139               src_prefix_length = 128;
1140             vec_validate_macip_acl_rules(rules, rule_idx);
1141             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
1142             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1143             rules[rule_idx].is_ipv6 = 1;
1144           }
1145         else if (unformat (i, "mac %U",
1146          my_unformat_mac_address, &src_mac))
1147           {
1148             vec_validate_macip_acl_rules(rules, rule_idx);
1149             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1150             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1151           }
1152         else if (unformat (i, "mask %U",
1153          my_unformat_mac_address, &src_mac))
1154           {
1155             vec_validate_macip_acl_rules(rules, rule_idx);
1156             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1157           }
1158         else if (unformat (i, "tag %s", &tag))
1159           {
1160           }
1161         else if (unformat (i, ","))
1162           {
1163             rule_idx++;
1164             vec_validate_macip_acl_rules(rules, rule_idx);
1165           }
1166         else
1167     break;
1168     }
1169
1170     if (!rules)
1171       {
1172       errmsg ("rule/s required\n");
1173       return -99;
1174       }
1175     /* Construct the API message */
1176     vam->result_ready = 0;
1177
1178     if(rules)
1179       n_rules = vec_len(rules);
1180
1181     if (n_rules_override >= 0)
1182       n_rules = n_rules_override;
1183
1184     msg_size += n_rules*sizeof(rules[0]);
1185
1186     mp = vl_msg_api_alloc_as_if_client(msg_size);
1187     memset (mp, 0, msg_size);
1188     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD_REPLACE + sm->msg_id_base);
1189     mp->client_index = vam->my_client_index;
1190     if ((n_rules > 0) && rules)
1191       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1192     if (tag)
1193       {
1194         if (vec_len(tag) >= sizeof(mp->tag))
1195           {
1196             tag[sizeof(mp->tag)-1] = 0;
1197             _vec_len(tag) = sizeof(mp->tag);
1198           }
1199         clib_memcpy(mp->tag, tag, vec_len(tag));
1200         vec_free(tag);
1201       }
1202
1203     mp->acl_index = ntohl(acl_index);
1204     mp->count = htonl(n_rules);
1205
1206     /* send it... */
1207     S(mp);
1208
1209     /* Wait for a reply... */
1210     W (ret);
1211     return ret;
1212 }
1213
1214 /*
1215  * List of messages that the api test plugin sends,
1216  * and that the data plane plugin processes
1217  */
1218 #define foreach_vpe_api_msg \
1219 _(acl_plugin_get_version, "") \
1220 _(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], ... , ...") \
1221 _(acl_del, "<acl-idx>") \
1222 _(acl_dump, "[<acl-idx>]") \
1223 _(acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] [input|output] acl <acl-idx>") \
1224 _(acl_interface_set_acl_list, "<intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]") \
1225 _(acl_interface_set_etype_whitelist, "<intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]") \
1226 _(acl_interface_list_dump, "[<intfc> | sw_if_index <if-idx>]") \
1227 _(macip_acl_add, "...") \
1228 _(macip_acl_add_replace, "<acl-idx> [<ipv4|ipv6> <permit|deny|action N> [count <count>] [src] ip <ipaddress/[plen]> mac <mac> mask <mac_mask>, ... , ...") \
1229 _(macip_acl_del, "<acl-idx>")\
1230 _(macip_acl_dump, "[<acl-idx>]") \
1231 _(macip_acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] acl <acl-idx>") \
1232 _(macip_acl_interface_get, "")
1233
1234
1235 static
1236 void acl_vat_api_hookup (vat_main_t *vam)
1237 {
1238     acl_test_main_t * sm = &acl_test_main;
1239     /* Hook up handlers for replies from the data plane plug-in */
1240 #define _(N,n)                                                  \
1241     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1242                            #n,                                  \
1243                            vl_api_##n##_t_handler,              \
1244                            vl_noop_handler,                     \
1245                            vl_api_##n##_t_endian,               \
1246                            vl_api_##n##_t_print,                \
1247                            sizeof(vl_api_##n##_t), 1);
1248     foreach_vpe_api_reply_msg;
1249 #undef _
1250
1251     /* API messages we can send */
1252 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
1253     foreach_vpe_api_msg;
1254 #undef _
1255
1256     /* Help strings */
1257 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
1258     foreach_vpe_api_msg;
1259 #undef _
1260 }
1261
1262 clib_error_t * vat_plugin_register (vat_main_t *vam)
1263 {
1264   acl_test_main_t * sm = &acl_test_main;
1265   u8 * name;
1266
1267   sm->vat_main = vam;
1268
1269   name = format (0, "acl_%08x%c", api_version, 0);
1270   sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
1271
1272   if (sm->msg_id_base != (u16) ~0)
1273     acl_vat_api_hookup (vam);
1274
1275   vec_free(name);
1276
1277   return 0;
1278 }