abb9643ef1c76def3b495b081013f0282021c8be
[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
29 #define __plugin_msg_base acl_test_main.msg_id_base
30 #include <vlibapi/vat_helper_macros.h>
31
32 uword unformat_sw_if_index (unformat_input_t * input, va_list * args);
33
34 /* Declare message IDs */
35 #include <acl/acl_msg_enum.h>
36
37 /* define message structures */
38 #define vl_typedefs
39 #include <acl/acl_all_api_h.h>
40 #undef vl_typedefs
41
42 /* define message structures */
43 #define vl_endianfun
44 #include <acl/acl_all_api_h.h>
45 #undef vl_endianfun
46
47 /* instantiate all the print functions we know about */
48 #define vl_print(handle, ...)
49 #define vl_printfun
50 #include <acl/acl_all_api_h.h>
51 #undef vl_printfun
52
53 /* Get the API version number. */
54 #define vl_api_version(n,v) static u32 api_version=(v);
55 #include <acl/acl_all_api_h.h>
56 #undef vl_api_version
57
58 typedef struct {
59     /* API message ID base */
60     u16 msg_id_base;
61     vat_main_t *vat_main;
62 } acl_test_main_t;
63
64 acl_test_main_t acl_test_main;
65
66 #define foreach_standard_reply_retval_handler   \
67 _(acl_del_reply) \
68 _(acl_interface_add_del_reply) \
69 _(macip_acl_interface_add_del_reply) \
70 _(acl_interface_set_acl_list_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_LIST_DETAILS, acl_interface_list_details)  \
274 _(ACL_DETAILS, acl_details)  \
275 _(MACIP_ACL_ADD_REPLY, macip_acl_add_reply) \
276 _(MACIP_ACL_ADD_REPLACE_REPLY, macip_acl_add_replace_reply) \
277 _(MACIP_ACL_DEL_REPLY, macip_acl_del_reply) \
278 _(MACIP_ACL_DETAILS, macip_acl_details)  \
279 _(MACIP_ACL_INTERFACE_ADD_DEL_REPLY, macip_acl_interface_add_del_reply)  \
280 _(MACIP_ACL_INTERFACE_GET_REPLY, macip_acl_interface_get_reply)  \
281 _(ACL_PLUGIN_CONTROL_PING_REPLY, acl_plugin_control_ping_reply) \
282 _(ACL_PLUGIN_GET_VERSION_REPLY, acl_plugin_get_version_reply)
283
284 static int api_acl_plugin_get_version (vat_main_t * vam)
285 {
286     acl_test_main_t * sm = &acl_test_main;
287     vl_api_acl_plugin_get_version_t * mp;
288     u32 msg_size = sizeof(*mp);
289     int ret;
290
291     vam->result_ready = 0;
292     mp = vl_msg_api_alloc_as_if_client(msg_size);
293     memset (mp, 0, msg_size);
294     mp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_VERSION + sm->msg_id_base);
295     mp->client_index = vam->my_client_index;
296
297     /* send it... */
298     S(mp);
299
300     /* Wait for a reply... */
301     W (ret);
302     return ret;
303 }
304
305 static int api_macip_acl_interface_get (vat_main_t * vam)
306 {
307     acl_test_main_t * sm = &acl_test_main;
308     vl_api_acl_plugin_get_version_t * mp;
309     u32 msg_size = sizeof(*mp);
310     int ret;
311
312     vam->result_ready = 0;
313     mp = vl_msg_api_alloc_as_if_client(msg_size);
314     memset (mp, 0, msg_size);
315     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET + sm->msg_id_base);
316     mp->client_index = vam->my_client_index;
317
318     /* send it... */
319     S(mp);
320
321     /* Wait for a reply... */
322     W (ret);
323     return ret;
324 }
325
326 #define vec_validate_acl_rules(v, idx) \
327   do {                                 \
328     if (vec_len(v) < idx+1) {  \
329       vec_validate(v, idx); \
330       v[idx].is_permit = 0x1; \
331       v[idx].srcport_or_icmptype_last = 0xffff; \
332       v[idx].dstport_or_icmpcode_last = 0xffff; \
333     } \
334   } while (0)
335
336
337 static int api_acl_add_replace (vat_main_t * vam)
338 {
339     acl_test_main_t * sm = &acl_test_main;
340     unformat_input_t * i = vam->input;
341     vl_api_acl_add_replace_t * mp;
342     u32 acl_index = ~0;
343     u32 msg_size = sizeof (*mp); /* without the rules */
344
345     vl_api_acl_rule_t *rules = 0;
346     int rule_idx = 0;
347     int n_rules = 0;
348     int n_rules_override = -1;
349     u32 proto = 0;
350     u32 port1 = 0;
351     u32 port2 = 0;
352     u32 action = 0;
353     u32 tcpflags, tcpmask;
354     u32 src_prefix_length = 0, dst_prefix_length = 0;
355     ip4_address_t src_v4address, dst_v4address;
356     ip6_address_t src_v6address, dst_v6address;
357     u8 *tag = 0;
358     int ret;
359
360     if (!unformat (i, "%d", &acl_index)) {
361         /* Just assume -1 */
362     }
363
364     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
365     {
366         if (unformat (i, "ipv6"))
367           {
368             vec_validate_acl_rules(rules, rule_idx);
369             rules[rule_idx].is_ipv6 = 1;
370           }
371         else if (unformat (i, "ipv4"))
372           {
373             vec_validate_acl_rules(rules, rule_idx);
374             rules[rule_idx].is_ipv6 = 0;
375           }
376         else if (unformat (i, "permit+reflect"))
377           {
378             vec_validate_acl_rules(rules, rule_idx);
379             rules[rule_idx].is_permit = 2;
380           }
381         else if (unformat (i, "permit"))
382           {
383             vec_validate_acl_rules(rules, rule_idx);
384             rules[rule_idx].is_permit = 1;
385           }
386         else if (unformat (i, "deny"))
387           {
388             vec_validate_acl_rules(rules, rule_idx);
389             rules[rule_idx].is_permit = 0;
390           }
391         else if (unformat (i, "count %d", &n_rules_override))
392           {
393             /* we will use this later */
394           }
395         else if (unformat (i, "action %d", &action))
396           {
397             vec_validate_acl_rules(rules, rule_idx);
398             rules[rule_idx].is_permit = action;
399           }
400         else if (unformat (i, "src %U/%d",
401          unformat_ip4_address, &src_v4address, &src_prefix_length))
402           {
403             vec_validate_acl_rules(rules, rule_idx);
404             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
405             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
406             rules[rule_idx].is_ipv6 = 0;
407           }
408         else if (unformat (i, "src %U/%d",
409          unformat_ip6_address, &src_v6address, &src_prefix_length))
410           {
411             vec_validate_acl_rules(rules, rule_idx);
412             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
413             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
414             rules[rule_idx].is_ipv6 = 1;
415           }
416         else if (unformat (i, "dst %U/%d",
417          unformat_ip4_address, &dst_v4address, &dst_prefix_length))
418           {
419             vec_validate_acl_rules(rules, rule_idx);
420             memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
421             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
422             rules[rule_idx].is_ipv6 = 0;
423           }
424         else if (unformat (i, "dst %U/%d",
425          unformat_ip6_address, &dst_v6address, &dst_prefix_length))
426           {
427             vec_validate_acl_rules(rules, rule_idx);
428             memcpy (rules[rule_idx].dst_ip_addr, &dst_v6address, 16);
429             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
430             rules[rule_idx].is_ipv6 = 1;
431           }
432         else if (unformat (i, "sport %d-%d", &port1, &port2))
433           {
434             vec_validate_acl_rules(rules, rule_idx);
435             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
436             rules[rule_idx].srcport_or_icmptype_last = htons(port2);
437           }
438         else if (unformat (i, "sport %d", &port1))
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(port1);
443           }
444         else if (unformat (i, "dport %d-%d", &port1, &port2))
445           {
446             vec_validate_acl_rules(rules, rule_idx);
447             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
448             rules[rule_idx].dstport_or_icmpcode_last = htons(port2);
449           }
450         else if (unformat (i, "dport %d", &port1))
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(port1);
455           }
456         else if (unformat (i, "tcpflags %d %d", &tcpflags, &tcpmask))
457           {
458             vec_validate_acl_rules(rules, rule_idx);
459             rules[rule_idx].tcp_flags_value = tcpflags;
460             rules[rule_idx].tcp_flags_mask = tcpmask;
461           }
462         else if (unformat (i, "tcpflags %d mask %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     if (n_rules_override >= 0)
494       n_rules = n_rules_override;
495
496     msg_size += n_rules*sizeof(rules[0]);
497
498     mp = vl_msg_api_alloc_as_if_client(msg_size);
499     memset (mp, 0, msg_size);
500     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
501     mp->client_index = vam->my_client_index;
502     if ((n_rules > 0) && rules)
503       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
504     if (tag)
505       {
506         if (vec_len(tag) >= sizeof(mp->tag))
507           {
508             tag[sizeof(mp->tag)-1] = 0;
509             _vec_len(tag) = sizeof(mp->tag);
510           }
511         clib_memcpy(mp->tag, tag, vec_len(tag));
512         vec_free(tag);
513       }
514     mp->acl_index = ntohl(acl_index);
515     mp->count = htonl(n_rules);
516
517     /* send it... */
518     S(mp);
519
520     /* Wait for a reply... */
521     W (ret);
522     return ret;
523 }
524
525 static int api_acl_del (vat_main_t * vam)
526 {
527     unformat_input_t * i = vam->input;
528     vl_api_acl_del_t * mp;
529     u32 acl_index = ~0;
530     int ret;
531
532     if (!unformat (i, "%d", &acl_index)) {
533       errmsg ("missing acl index\n");
534       return -99;
535     }
536
537     /* Construct the API message */
538     M(ACL_DEL, mp);
539     mp->acl_index = ntohl(acl_index);
540
541     /* send it... */
542     S(mp);
543
544     /* Wait for a reply... */
545     W (ret);
546     return ret;
547 }
548
549 static int api_macip_acl_del (vat_main_t * vam)
550 {
551     unformat_input_t * i = vam->input;
552     vl_api_acl_del_t * mp;
553     u32 acl_index = ~0;
554     int ret;
555
556     if (!unformat (i, "%d", &acl_index)) {
557       errmsg ("missing acl index\n");
558       return -99;
559     }
560
561     /* Construct the API message */
562     M(MACIP_ACL_DEL, mp);
563     mp->acl_index = ntohl(acl_index);
564
565     /* send it... */
566     S(mp);
567
568     /* Wait for a reply... */
569     W (ret);
570     return ret;
571 }
572
573 static int api_acl_interface_add_del (vat_main_t * vam)
574 {
575     unformat_input_t * i = vam->input;
576     vl_api_acl_interface_add_del_t * mp;
577     u32 sw_if_index = ~0;
578     u32 acl_index = ~0;
579     u8 is_input = 0;
580     u8 is_add = 0;
581     int ret;
582
583 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
584
585     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
586     {
587         if (unformat (i, "%d", &acl_index))
588     ;
589         else
590     break;
591     }
592
593
594     /* Parse args required to build the message */
595     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
596         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
597             ;
598         else if (unformat (i, "sw_if_index %d", &sw_if_index))
599             ;
600         else if (unformat (i, "add"))
601             is_add = 1;
602         else if (unformat (i, "del"))
603             is_add = 0;
604         else if (unformat (i, "acl %d", &acl_index))
605             ;
606         else if (unformat (i, "input"))
607             is_input = 1;
608         else if (unformat (i, "output"))
609             is_input = 0;
610         else
611             break;
612     }
613
614     if (sw_if_index == ~0) {
615         errmsg ("missing interface name / explicit sw_if_index number \n");
616         return -99;
617     }
618
619     if (acl_index == ~0) {
620         errmsg ("missing ACL index\n");
621         return -99;
622     }
623
624
625
626     /* Construct the API message */
627     M(ACL_INTERFACE_ADD_DEL, mp);
628     mp->acl_index = ntohl(acl_index);
629     mp->sw_if_index = ntohl(sw_if_index);
630     mp->is_add = is_add;
631     mp->is_input = is_input;
632
633     /* send it... */
634     S(mp);
635
636     /* Wait for a reply... */
637     W (ret);
638     return ret;
639 }
640
641 static int api_macip_acl_interface_add_del (vat_main_t * vam)
642 {
643     unformat_input_t * i = vam->input;
644     vl_api_macip_acl_interface_add_del_t * mp;
645     u32 sw_if_index = ~0;
646     u32 acl_index = ~0;
647     u8 is_add = 0;
648     int ret;
649
650     /* Parse args required to build the message */
651     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
652         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
653             ;
654         else if (unformat (i, "sw_if_index %d", &sw_if_index))
655             ;
656         else if (unformat (i, "add"))
657             is_add = 1;
658         else if (unformat (i, "del"))
659             is_add = 0;
660         else if (unformat (i, "acl %d", &acl_index))
661             ;
662         else
663             break;
664     }
665
666     if (sw_if_index == ~0) {
667         errmsg ("missing interface name / explicit sw_if_index number \n");
668         return -99;
669     }
670
671     if (acl_index == ~0) {
672         errmsg ("missing ACL index\n");
673         return -99;
674     }
675
676
677
678     /* Construct the API message */
679     M(MACIP_ACL_INTERFACE_ADD_DEL, mp);
680     mp->acl_index = ntohl(acl_index);
681     mp->sw_if_index = ntohl(sw_if_index);
682     mp->is_add = is_add;
683
684     /* send it... */
685     S(mp);
686
687     /* Wait for a reply... */
688     W (ret);
689     return ret;
690 }
691
692 static int api_acl_interface_set_acl_list (vat_main_t * vam)
693 {
694     unformat_input_t * i = vam->input;
695     vl_api_acl_interface_set_acl_list_t * mp;
696     u32 sw_if_index = ~0;
697     u32 acl_index = ~0;
698     u32 *inacls = 0;
699     u32 *outacls = 0;
700     u8 is_input = 0;
701     int ret;
702
703 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
704
705     /* Parse args required to build the message */
706     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
707         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
708             ;
709         else if (unformat (i, "sw_if_index %d", &sw_if_index))
710             ;
711         else if (unformat (i, "%d", &acl_index))
712           {
713             if(is_input)
714               vec_add1(inacls, htonl(acl_index));
715             else
716               vec_add1(outacls, htonl(acl_index));
717           }
718         else if (unformat (i, "acl %d", &acl_index))
719             ;
720         else if (unformat (i, "input"))
721             is_input = 1;
722         else if (unformat (i, "output"))
723             is_input = 0;
724         else
725             break;
726     }
727
728     if (sw_if_index == ~0) {
729         errmsg ("missing interface name / explicit sw_if_index number \n");
730         return -99;
731     }
732
733     /* Construct the API message */
734     M2(ACL_INTERFACE_SET_ACL_LIST, mp, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
735     mp->sw_if_index = ntohl(sw_if_index);
736     mp->n_input = vec_len(inacls);
737     mp->count = vec_len(inacls) + vec_len(outacls);
738     vec_append(inacls, outacls);
739     if (vec_len(inacls) > 0)
740       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
741
742     /* send it... */
743     S(mp);
744
745     /* Wait for a reply... */
746     W (ret);
747     return ret;
748 }
749
750 static void
751 api_acl_send_control_ping(vat_main_t *vam)
752 {
753   vl_api_acl_plugin_control_ping_t *mp_ping;
754
755   M(ACL_PLUGIN_CONTROL_PING, mp_ping);
756   S(mp_ping);
757 }
758
759
760 static int api_acl_interface_list_dump (vat_main_t * vam)
761 {
762     unformat_input_t * i = vam->input;
763     u32 sw_if_index = ~0;
764     vl_api_acl_interface_list_dump_t * mp;
765     int ret;
766
767     /* Parse args required to build the message */
768     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
769         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
770             ;
771         else if (unformat (i, "sw_if_index %d", &sw_if_index))
772             ;
773         else
774             break;
775     }
776
777     /* Construct the API message */
778     M(ACL_INTERFACE_LIST_DUMP, mp);
779     mp->sw_if_index = ntohl (sw_if_index);
780
781     /* send it... */
782     S(mp);
783
784     /* Use control ping for synchronization */
785     api_acl_send_control_ping(vam);
786
787     /* Wait for a reply... */
788     W (ret);
789     return ret;
790 }
791
792 static int api_acl_dump (vat_main_t * vam)
793 {
794     unformat_input_t * i = vam->input;
795     u32 acl_index = ~0;
796     vl_api_acl_dump_t * mp;
797     int ret;
798
799     /* Parse args required to build the message */
800     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
801         if (unformat (i, "%d", &acl_index))
802             ;
803         else
804             break;
805     }
806
807     /* Construct the API message */
808     M(ACL_DUMP, mp);
809     mp->acl_index = ntohl (acl_index);
810
811     /* send it... */
812     S(mp);
813
814     /* Use control ping for synchronization */
815     api_acl_send_control_ping(vam);
816
817     /* Wait for a reply... */
818     W (ret);
819     return ret;
820 }
821
822 static int api_macip_acl_dump (vat_main_t * vam)
823 {
824     unformat_input_t * i = vam->input;
825     u32 acl_index = ~0;
826     vl_api_acl_dump_t * mp;
827     int ret;
828
829     /* Parse args required to build the message */
830     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
831         if (unformat (i, "%d", &acl_index))
832             ;
833         else
834             break;
835     }
836
837     /* Construct the API message */
838     M(MACIP_ACL_DUMP, mp);
839     mp->acl_index = ntohl (acl_index);
840
841     /* send it... */
842     S(mp);
843
844     /* Use control ping for synchronization */
845     api_acl_send_control_ping(vam);
846
847     /* Wait for a reply... */
848     W (ret);
849     return ret;
850 }
851
852 #define vec_validate_macip_acl_rules(v, idx) \
853   do {                                 \
854     if (vec_len(v) < idx+1) {  \
855       vec_validate(v, idx); \
856       v[idx].is_permit = 0x1; \
857     } \
858   } while (0)
859
860
861 static int api_macip_acl_add (vat_main_t * vam)
862 {
863     acl_test_main_t * sm = &acl_test_main;
864     unformat_input_t * i = vam->input;
865     vl_api_macip_acl_add_t * mp;
866     u32 msg_size = sizeof (*mp); /* without the rules */
867
868     vl_api_macip_acl_rule_t *rules = 0;
869     int rule_idx = 0;
870     int n_rules = 0;
871     int n_rules_override = -1;
872     u32 src_prefix_length = 0;
873     u32 action = 0;
874     ip4_address_t src_v4address;
875     ip6_address_t src_v6address;
876     u8 src_mac[6];
877     u8 *tag = 0;
878     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
879     int ret;
880
881     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
882     {
883         if (unformat (i, "ipv6"))
884           {
885             vec_validate_macip_acl_rules(rules, rule_idx);
886             rules[rule_idx].is_ipv6 = 1;
887           }
888         else if (unformat (i, "ipv4"))
889           {
890             vec_validate_macip_acl_rules(rules, rule_idx);
891             rules[rule_idx].is_ipv6 = 0;
892           }
893         else if (unformat (i, "permit"))
894           {
895             vec_validate_macip_acl_rules(rules, rule_idx);
896             rules[rule_idx].is_permit = 1;
897           }
898         else if (unformat (i, "deny"))
899           {
900             vec_validate_macip_acl_rules(rules, rule_idx);
901             rules[rule_idx].is_permit = 0;
902           }
903         else if (unformat (i, "count %d", &n_rules_override))
904           {
905             /* we will use this later */
906           }
907         else if (unformat (i, "action %d", &action))
908           {
909             vec_validate_macip_acl_rules(rules, rule_idx);
910             rules[rule_idx].is_permit = action;
911           }
912         else if (unformat (i, "ip %U/%d",
913          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
914                  unformat (i, "ip %U",
915          unformat_ip4_address, &src_v4address))
916           {
917             if (src_prefix_length == 0)
918               src_prefix_length = 32;
919             vec_validate_macip_acl_rules(rules, rule_idx);
920             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
921             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
922             rules[rule_idx].is_ipv6 = 0;
923           }
924         else if (unformat (i, "src"))
925           {
926             /* Everything in MACIP is "source" but allow this verbosity */
927           }
928         else if (unformat (i, "ip %U/%d",
929          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
930                  unformat (i, "ip %U",
931          unformat_ip6_address, &src_v6address))
932           {
933             if (src_prefix_length == 0)
934               src_prefix_length = 128;
935             vec_validate_macip_acl_rules(rules, rule_idx);
936             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
937             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
938             rules[rule_idx].is_ipv6 = 1;
939           }
940         else if (unformat (i, "mac %U",
941          my_unformat_mac_address, &src_mac))
942           {
943             vec_validate_macip_acl_rules(rules, rule_idx);
944             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
945             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
946           }
947         else if (unformat (i, "mask %U",
948          my_unformat_mac_address, &src_mac))
949           {
950             vec_validate_macip_acl_rules(rules, rule_idx);
951             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
952           }
953         else if (unformat (i, "tag %s", &tag))
954           {
955           }
956         else if (unformat (i, ","))
957           {
958             rule_idx++;
959             vec_validate_macip_acl_rules(rules, rule_idx);
960           }
961         else
962     break;
963     }
964
965     /* Construct the API message */
966     vam->result_ready = 0;
967
968     if(rules)
969       n_rules = vec_len(rules);
970
971     if (n_rules_override >= 0)
972       n_rules = n_rules_override;
973
974     msg_size += n_rules*sizeof(rules[0]);
975
976     mp = vl_msg_api_alloc_as_if_client(msg_size);
977     memset (mp, 0, msg_size);
978     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
979     mp->client_index = vam->my_client_index;
980     if ((n_rules > 0) && rules)
981       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
982     if (tag)
983       {
984         if (vec_len(tag) >= sizeof(mp->tag))
985           {
986             tag[sizeof(mp->tag)-1] = 0;
987             _vec_len(tag) = sizeof(mp->tag);
988           }
989         clib_memcpy(mp->tag, tag, vec_len(tag));
990         vec_free(tag);
991       }
992
993     mp->count = htonl(n_rules);
994
995     /* send it... */
996     S(mp);
997
998     /* Wait for a reply... */
999     W (ret);
1000     return ret;
1001 }
1002
1003 static int api_macip_acl_add_replace (vat_main_t * vam)
1004 {
1005     acl_test_main_t * sm = &acl_test_main;
1006     unformat_input_t * i = vam->input;
1007     vl_api_macip_acl_add_replace_t * mp;
1008     u32 acl_index = ~0;
1009     u32 msg_size = sizeof (*mp); /* without the rules */
1010
1011     vl_api_macip_acl_rule_t *rules = 0;
1012     int rule_idx = 0;
1013     int n_rules = 0;
1014     int n_rules_override = -1;
1015     u32 src_prefix_length = 0;
1016     u32 action = 0;
1017     ip4_address_t src_v4address;
1018     ip6_address_t src_v6address;
1019     u8 src_mac[6];
1020     u8 *tag = 0;
1021     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1022     int ret;
1023
1024     if (!unformat (i, "%d", &acl_index)) {
1025         /* Just assume -1 */
1026     }
1027
1028     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1029     {
1030         if (unformat (i, "ipv6"))
1031           {
1032             vec_validate_macip_acl_rules(rules, rule_idx);
1033             rules[rule_idx].is_ipv6 = 1;
1034           }
1035         else if (unformat (i, "ipv4"))
1036           {
1037             vec_validate_macip_acl_rules(rules, rule_idx);
1038             rules[rule_idx].is_ipv6 = 0;
1039           }
1040         else if (unformat (i, "permit"))
1041           {
1042             vec_validate_macip_acl_rules(rules, rule_idx);
1043             rules[rule_idx].is_permit = 1;
1044           }
1045         else if (unformat (i, "deny"))
1046           {
1047             vec_validate_macip_acl_rules(rules, rule_idx);
1048             rules[rule_idx].is_permit = 0;
1049           }
1050         else if (unformat (i, "count %d", &n_rules_override))
1051           {
1052             /* we will use this later */
1053           }
1054         else if (unformat (i, "action %d", &action))
1055           {
1056             vec_validate_macip_acl_rules(rules, rule_idx);
1057             rules[rule_idx].is_permit = action;
1058           }
1059         else if (unformat (i, "ip %U/%d",
1060          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1061                  unformat (i, "ip %U",
1062          unformat_ip4_address, &src_v4address))
1063           {
1064             if (src_prefix_length == 0)
1065               src_prefix_length = 32;
1066             vec_validate_macip_acl_rules(rules, rule_idx);
1067             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
1068             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1069             rules[rule_idx].is_ipv6 = 0;
1070           }
1071         else if (unformat (i, "src"))
1072           {
1073             /* Everything in MACIP is "source" but allow this verbosity */
1074           }
1075         else if (unformat (i, "ip %U/%d",
1076          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1077                  unformat (i, "ip %U",
1078          unformat_ip6_address, &src_v6address))
1079           {
1080             if (src_prefix_length == 0)
1081               src_prefix_length = 128;
1082             vec_validate_macip_acl_rules(rules, rule_idx);
1083             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
1084             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1085             rules[rule_idx].is_ipv6 = 1;
1086           }
1087         else if (unformat (i, "mac %U",
1088          my_unformat_mac_address, &src_mac))
1089           {
1090             vec_validate_macip_acl_rules(rules, rule_idx);
1091             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1092             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1093           }
1094         else if (unformat (i, "mask %U",
1095          my_unformat_mac_address, &src_mac))
1096           {
1097             vec_validate_macip_acl_rules(rules, rule_idx);
1098             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1099           }
1100         else if (unformat (i, "tag %s", &tag))
1101           {
1102           }
1103         else if (unformat (i, ","))
1104           {
1105             rule_idx++;
1106             vec_validate_macip_acl_rules(rules, rule_idx);
1107           }
1108         else
1109     break;
1110     }
1111
1112     if (!rules)
1113       {
1114       errmsg ("rule/s required\n");
1115       return -99;
1116       }
1117     /* Construct the API message */
1118     vam->result_ready = 0;
1119
1120     if(rules)
1121       n_rules = vec_len(rules);
1122
1123     if (n_rules_override >= 0)
1124       n_rules = n_rules_override;
1125
1126     msg_size += n_rules*sizeof(rules[0]);
1127
1128     mp = vl_msg_api_alloc_as_if_client(msg_size);
1129     memset (mp, 0, msg_size);
1130     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD_REPLACE + sm->msg_id_base);
1131     mp->client_index = vam->my_client_index;
1132     if ((n_rules > 0) && rules)
1133       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1134     if (tag)
1135       {
1136         if (vec_len(tag) >= sizeof(mp->tag))
1137           {
1138             tag[sizeof(mp->tag)-1] = 0;
1139             _vec_len(tag) = sizeof(mp->tag);
1140           }
1141         clib_memcpy(mp->tag, tag, vec_len(tag));
1142         vec_free(tag);
1143       }
1144
1145     mp->acl_index = ntohl(acl_index);
1146     mp->count = htonl(n_rules);
1147
1148     /* send it... */
1149     S(mp);
1150
1151     /* Wait for a reply... */
1152     W (ret);
1153     return ret;
1154 }
1155
1156 /*
1157  * List of messages that the api test plugin sends,
1158  * and that the data plane plugin processes
1159  */
1160 #define foreach_vpe_api_msg \
1161 _(acl_plugin_get_version, "") \
1162 _(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], ... , ...") \
1163 _(acl_del, "<acl-idx>") \
1164 _(acl_dump, "[<acl-idx>]") \
1165 _(acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] [input|output] acl <acl-idx>") \
1166 _(acl_interface_set_acl_list, "<intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]") \
1167 _(acl_interface_list_dump, "[<intfc> | sw_if_index <if-idx>]") \
1168 _(macip_acl_add, "...") \
1169 _(macip_acl_add_replace, "<acl-idx> [<ipv4|ipv6> <permit|deny|action N> [count <count>] [src] ip <ipaddress/[plen]> mac <mac> mask <mac_mask>, ... , ...") \
1170 _(macip_acl_del, "<acl-idx>")\
1171 _(macip_acl_dump, "[<acl-idx>]") \
1172 _(macip_acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] acl <acl-idx>") \
1173 _(macip_acl_interface_get, "")
1174
1175
1176 static
1177 void acl_vat_api_hookup (vat_main_t *vam)
1178 {
1179     acl_test_main_t * sm = &acl_test_main;
1180     /* Hook up handlers for replies from the data plane plug-in */
1181 #define _(N,n)                                                  \
1182     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1183                            #n,                                  \
1184                            vl_api_##n##_t_handler,              \
1185                            vl_noop_handler,                     \
1186                            vl_api_##n##_t_endian,               \
1187                            vl_api_##n##_t_print,                \
1188                            sizeof(vl_api_##n##_t), 1);
1189     foreach_vpe_api_reply_msg;
1190 #undef _
1191
1192     /* API messages we can send */
1193 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
1194     foreach_vpe_api_msg;
1195 #undef _
1196
1197     /* Help strings */
1198 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
1199     foreach_vpe_api_msg;
1200 #undef _
1201 }
1202
1203 clib_error_t * vat_plugin_register (vat_main_t *vam)
1204 {
1205   acl_test_main_t * sm = &acl_test_main;
1206   u8 * name;
1207
1208   sm->vat_main = vam;
1209
1210   name = format (0, "acl_%08x%c", api_version, 0);
1211   sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
1212
1213   if (sm->msg_id_base != (u16) ~0)
1214     acl_vat_api_hookup (vam);
1215
1216   vec_free(name);
1217
1218   return 0;
1219 }