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