991d877f7af36b3bbae632905e7323e06a6a8ad4
[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 static void vl_api_acl_interface_etype_whitelist_details_t_handler
159     (vl_api_acl_interface_etype_whitelist_details_t * mp)
160     {
161         int i;
162         vat_main_t * vam = acl_test_main.vat_main;
163         u8 *out = 0;
164         vl_api_acl_interface_etype_whitelist_details_t_endian(mp);
165         out = format(out, "sw_if_index: %d, count: %d, n_input: %d\n", mp->sw_if_index, mp->count, mp->n_input);
166         out = format(out, "   input ");
167         for(i=0; i<mp->count; i++) {
168           if (i == mp->n_input)
169             out = format(out, "\n  output ");
170           out = format(out, "%04x ", ntohs(mp->whitelist[i]));
171         }
172         out = format(out, "\n");
173         clib_warning("%s", out);
174         vec_free(out);
175         vam->result_ready = 1;
176     }
177
178
179
180 static inline u8 *
181 vl_api_acl_rule_t_pretty_format (u8 *out, vl_api_acl_rule_t * a)
182 {
183   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
184   u8 src[INET6_ADDRSTRLEN];
185   u8 dst[INET6_ADDRSTRLEN];
186   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
187   inet_ntop(af, a->dst_ip_addr, (void *)dst, sizeof(dst));
188
189   out = format(out, "%s action %d src %s/%d dst %s/%d proto %d sport %d-%d dport %d-%d tcpflags %d mask %d",
190                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
191                      src, a->src_ip_prefix_len,
192                      dst, a->dst_ip_prefix_len,
193                      a->proto,
194                      a->srcport_or_icmptype_first, a->srcport_or_icmptype_last,
195                      a->dstport_or_icmpcode_first, a->dstport_or_icmpcode_last,
196                      a->tcp_flags_value, a->tcp_flags_mask);
197   return(out);
198 }
199
200
201
202 static void vl_api_acl_details_t_handler
203     (vl_api_acl_details_t * mp)
204     {
205         int i;
206         vat_main_t * vam = acl_test_main.vat_main;
207         vl_api_acl_details_t_endian(mp);
208         u8 *out = 0;
209         out = format(0, "acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
210         for(i=0; i<mp->count; i++) {
211           out = format(out, "   ");
212           out = vl_api_acl_rule_t_pretty_format(out, &mp->r[i]);
213           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
214         }
215         clib_warning("%s", out);
216         vec_free(out);
217         vam->result_ready = 1;
218     }
219
220 static inline u8 *
221 vl_api_macip_acl_rule_t_pretty_format (u8 *out, vl_api_macip_acl_rule_t * a)
222 {
223   int af = a->is_ipv6 ? AF_INET6 : AF_INET;
224   u8 src[INET6_ADDRSTRLEN];
225   inet_ntop(af, a->src_ip_addr, (void *)src, sizeof(src));
226
227   out = format(out, "%s action %d ip %s/%d mac %U mask %U",
228                      a->is_ipv6 ? "ipv6" : "ipv4", a->is_permit,
229                      src, a->src_ip_prefix_len,
230                      my_format_mac_address, a->src_mac,
231                      my_format_mac_address, a->src_mac_mask);
232   return(out);
233 }
234
235
236 static void vl_api_macip_acl_details_t_handler
237     (vl_api_macip_acl_details_t * mp)
238     {
239         int i;
240         vat_main_t * vam = acl_test_main.vat_main;
241         vl_api_macip_acl_details_t_endian(mp);
242         u8 *out = format(0,"MACIP acl_index: %d, count: %d\n   tag {%s}\n", mp->acl_index, mp->count, mp->tag);
243         for(i=0; i<mp->count; i++) {
244           out = format(out, "   ");
245           out = vl_api_macip_acl_rule_t_pretty_format(out, &mp->r[i]);
246           out = format(out, "%s\n", i<mp->count-1 ? "," : "");
247         }
248         clib_warning("%s", out);
249         vec_free(out);
250         vam->result_ready = 1;
251     }
252
253 static void vl_api_macip_acl_interface_get_reply_t_handler
254     (vl_api_macip_acl_interface_get_reply_t * mp)
255     {
256         int i;
257         vat_main_t * vam = acl_test_main.vat_main;
258         u8 *out = format(0, "sw_if_index with MACIP ACL count: %d\n", ntohl(mp->count));
259         for(i=0; i<ntohl(mp->count); i++) {
260           out = format(out, "  macip_acl_interface_add_del sw_if_index %d add acl %d\n", i, ntohl(mp->acls[i]));
261         }
262         out = format(out, "\n");
263         clib_warning("%s", out);
264         vec_free(out);
265         vam->result_ready = 1;
266     }
267
268 static void vl_api_acl_plugin_control_ping_reply_t_handler
269   (vl_api_acl_plugin_control_ping_reply_t * mp)
270 {
271   vat_main_t *vam = &vat_main;
272   i32 retval = ntohl (mp->retval);
273   if (vam->async_mode)
274     {
275       vam->async_errors += (retval < 0);
276     }
277   else
278     {
279       vam->retval = retval;
280       vam->result_ready = 1;
281     }
282 }
283
284
285 /*
286  * Table of message reply handlers, must include boilerplate handlers
287  * we just generated
288  */
289 #define foreach_vpe_api_reply_msg                                       \
290 _(ACL_ADD_REPLACE_REPLY, acl_add_replace_reply) \
291 _(ACL_DEL_REPLY, acl_del_reply) \
292 _(ACL_INTERFACE_ADD_DEL_REPLY, acl_interface_add_del_reply)  \
293 _(ACL_INTERFACE_SET_ACL_LIST_REPLY, acl_interface_set_acl_list_reply) \
294 _(ACL_INTERFACE_SET_ETYPE_WHITELIST_REPLY, acl_interface_set_etype_whitelist_reply) \
295 _(ACL_INTERFACE_ETYPE_WHITELIST_DETAILS, acl_interface_etype_whitelist_details)  \
296 _(ACL_INTERFACE_LIST_DETAILS, acl_interface_list_details)  \
297 _(ACL_DETAILS, acl_details)  \
298 _(MACIP_ACL_ADD_REPLY, macip_acl_add_reply) \
299 _(MACIP_ACL_ADD_REPLACE_REPLY, macip_acl_add_replace_reply) \
300 _(MACIP_ACL_DEL_REPLY, macip_acl_del_reply) \
301 _(MACIP_ACL_DETAILS, macip_acl_details)  \
302 _(MACIP_ACL_INTERFACE_ADD_DEL_REPLY, macip_acl_interface_add_del_reply)  \
303 _(MACIP_ACL_INTERFACE_GET_REPLY, macip_acl_interface_get_reply)  \
304 _(ACL_PLUGIN_CONTROL_PING_REPLY, acl_plugin_control_ping_reply) \
305 _(ACL_PLUGIN_GET_VERSION_REPLY, acl_plugin_get_version_reply)
306
307 static int api_acl_plugin_get_version (vat_main_t * vam)
308 {
309     acl_test_main_t * sm = &acl_test_main;
310     vl_api_acl_plugin_get_version_t * mp;
311     u32 msg_size = sizeof(*mp);
312     int ret;
313
314     vam->result_ready = 0;
315     mp = vl_msg_api_alloc_as_if_client(msg_size);
316     memset (mp, 0, msg_size);
317     mp->_vl_msg_id = ntohs (VL_API_ACL_PLUGIN_GET_VERSION + sm->msg_id_base);
318     mp->client_index = vam->my_client_index;
319
320     /* send it... */
321     S(mp);
322
323     /* Wait for a reply... */
324     W (ret);
325     return ret;
326 }
327
328 static int api_macip_acl_interface_get (vat_main_t * vam)
329 {
330     acl_test_main_t * sm = &acl_test_main;
331     vl_api_acl_plugin_get_version_t * mp;
332     u32 msg_size = sizeof(*mp);
333     int ret;
334
335     vam->result_ready = 0;
336     mp = vl_msg_api_alloc_as_if_client(msg_size);
337     memset (mp, 0, msg_size);
338     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_INTERFACE_GET + sm->msg_id_base);
339     mp->client_index = vam->my_client_index;
340
341     /* send it... */
342     S(mp);
343
344     /* Wait for a reply... */
345     W (ret);
346     return ret;
347 }
348
349 #define vec_validate_acl_rules(v, idx) \
350   do {                                 \
351     if (vec_len(v) < idx+1) {  \
352       vec_validate(v, idx); \
353       v[idx].is_permit = 0x1; \
354       v[idx].srcport_or_icmptype_last = 0xffff; \
355       v[idx].dstport_or_icmpcode_last = 0xffff; \
356     } \
357   } while (0)
358
359
360 static int api_acl_add_replace (vat_main_t * vam)
361 {
362     acl_test_main_t * sm = &acl_test_main;
363     unformat_input_t * i = vam->input;
364     vl_api_acl_add_replace_t * mp;
365     u32 acl_index = ~0;
366     u32 msg_size = sizeof (*mp); /* without the rules */
367
368     vl_api_acl_rule_t *rules = 0;
369     int rule_idx = 0;
370     int n_rules = 0;
371     int n_rules_override = -1;
372     u32 proto = 0;
373     u32 port1 = 0;
374     u32 port2 = 0;
375     u32 action = 0;
376     u32 tcpflags, tcpmask;
377     u32 src_prefix_length = 0, dst_prefix_length = 0;
378     ip4_address_t src_v4address, dst_v4address;
379     ip6_address_t src_v6address, dst_v6address;
380     u8 *tag = 0;
381     int ret;
382
383     if (!unformat (i, "%d", &acl_index)) {
384         /* Just assume -1 */
385     }
386
387     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
388     {
389         if (unformat (i, "ipv6"))
390           {
391             vec_validate_acl_rules(rules, rule_idx);
392             rules[rule_idx].is_ipv6 = 1;
393           }
394         else if (unformat (i, "ipv4"))
395           {
396             vec_validate_acl_rules(rules, rule_idx);
397             rules[rule_idx].is_ipv6 = 0;
398           }
399         else if (unformat (i, "permit+reflect"))
400           {
401             vec_validate_acl_rules(rules, rule_idx);
402             rules[rule_idx].is_permit = 2;
403           }
404         else if (unformat (i, "permit"))
405           {
406             vec_validate_acl_rules(rules, rule_idx);
407             rules[rule_idx].is_permit = 1;
408           }
409         else if (unformat (i, "deny"))
410           {
411             vec_validate_acl_rules(rules, rule_idx);
412             rules[rule_idx].is_permit = 0;
413           }
414         else if (unformat (i, "count %d", &n_rules_override))
415           {
416             /* we will use this later */
417           }
418         else if (unformat (i, "action %d", &action))
419           {
420             vec_validate_acl_rules(rules, rule_idx);
421             rules[rule_idx].is_permit = action;
422           }
423         else if (unformat (i, "src %U/%d",
424          unformat_ip4_address, &src_v4address, &src_prefix_length))
425           {
426             vec_validate_acl_rules(rules, rule_idx);
427             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
428             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
429             rules[rule_idx].is_ipv6 = 0;
430           }
431         else if (unformat (i, "src %U/%d",
432          unformat_ip6_address, &src_v6address, &src_prefix_length))
433           {
434             vec_validate_acl_rules(rules, rule_idx);
435             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
436             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
437             rules[rule_idx].is_ipv6 = 1;
438           }
439         else if (unformat (i, "dst %U/%d",
440          unformat_ip4_address, &dst_v4address, &dst_prefix_length))
441           {
442             vec_validate_acl_rules(rules, rule_idx);
443             memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
444             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
445             rules[rule_idx].is_ipv6 = 0;
446           }
447         else if (unformat (i, "dst %U/%d",
448          unformat_ip6_address, &dst_v6address, &dst_prefix_length))
449           {
450             vec_validate_acl_rules(rules, rule_idx);
451             memcpy (rules[rule_idx].dst_ip_addr, &dst_v6address, 16);
452             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
453             rules[rule_idx].is_ipv6 = 1;
454           }
455         else if (unformat (i, "sport %d-%d", &port1, &port2))
456           {
457             vec_validate_acl_rules(rules, rule_idx);
458             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
459             rules[rule_idx].srcport_or_icmptype_last = htons(port2);
460           }
461         else if (unformat (i, "sport %d", &port1))
462           {
463             vec_validate_acl_rules(rules, rule_idx);
464             rules[rule_idx].srcport_or_icmptype_first = htons(port1);
465             rules[rule_idx].srcport_or_icmptype_last = htons(port1);
466           }
467         else if (unformat (i, "dport %d-%d", &port1, &port2))
468           {
469             vec_validate_acl_rules(rules, rule_idx);
470             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
471             rules[rule_idx].dstport_or_icmpcode_last = htons(port2);
472           }
473         else if (unformat (i, "dport %d", &port1))
474           {
475             vec_validate_acl_rules(rules, rule_idx);
476             rules[rule_idx].dstport_or_icmpcode_first = htons(port1);
477             rules[rule_idx].dstport_or_icmpcode_last = htons(port1);
478           }
479         else if (unformat (i, "tcpflags %d %d", &tcpflags, &tcpmask))
480           {
481             vec_validate_acl_rules(rules, rule_idx);
482             rules[rule_idx].tcp_flags_value = tcpflags;
483             rules[rule_idx].tcp_flags_mask = tcpmask;
484           }
485         else if (unformat (i, "tcpflags %d mask %d", &tcpflags, &tcpmask))
486           {
487             vec_validate_acl_rules(rules, rule_idx);
488             rules[rule_idx].tcp_flags_value = tcpflags;
489             rules[rule_idx].tcp_flags_mask = tcpmask;
490           }
491         else if (unformat (i, "proto %d", &proto))
492           {
493             vec_validate_acl_rules(rules, rule_idx);
494             rules[rule_idx].proto = proto;
495           }
496         else if (unformat (i, "tag %s", &tag))
497           {
498           }
499         else if (unformat (i, ","))
500           {
501             rule_idx++;
502             vec_validate_acl_rules(rules, rule_idx);
503           }
504         else
505     break;
506     }
507
508     /* Construct the API message */
509     vam->result_ready = 0;
510
511     if(rules)
512       n_rules = vec_len(rules);
513     else
514       n_rules = 0;
515
516     if (n_rules_override >= 0)
517       n_rules = n_rules_override;
518
519     msg_size += n_rules*sizeof(rules[0]);
520
521     mp = vl_msg_api_alloc_as_if_client(msg_size);
522     memset (mp, 0, msg_size);
523     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
524     mp->client_index = vam->my_client_index;
525     if ((n_rules > 0) && rules)
526       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
527     if (tag)
528       {
529         if (vec_len(tag) >= sizeof(mp->tag))
530           {
531             tag[sizeof(mp->tag)-1] = 0;
532             _vec_len(tag) = sizeof(mp->tag);
533           }
534         clib_memcpy(mp->tag, tag, vec_len(tag));
535         vec_free(tag);
536       }
537     mp->acl_index = ntohl(acl_index);
538     mp->count = htonl(n_rules);
539
540     /* send it... */
541     S(mp);
542
543     /* Wait for a reply... */
544     W (ret);
545     return ret;
546 }
547
548
549 /*
550  * Read the series of ACL entries from file in the following format:
551  *
552
553 @0.0.0.0/1      131.179.121.0/24        0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
554 @128.0.0.0/1    85.54.226.0/23  0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
555 @128.0.0.0/1    85.54.48.0/23   0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
556 @128.0.0.0/1    31.237.44.0/23  0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
557 @0.0.0.0/1      255.84.184.0/23 0 : 65535       0 : 65535       0x00/0x00       0x0000/0x0000
558 @132.92.0.0/16  0.0.0.0/0       0 : 65535       0 : 65535       0x01/0xFF       0x0000/0x0000
559
560  *
561  */
562
563 static int
564 api_acl_add_replace_from_file (vat_main_t * vam)
565 {
566     int ret = -1;
567     unformat_input_t * input = vam->input;
568     acl_test_main_t * sm = &acl_test_main;
569     vl_api_acl_add_replace_t * mp;
570     u32 acl_index = ~0;
571     u32 msg_size = sizeof (*mp); /* without the rules */
572
573     vl_api_acl_rule_t *rules = 0;
574     int rule_idx = -1;
575     int n_rules = 0;
576     int is_permit = 0;
577     int append_default_permit = 0;
578     u32 tcpflags = 0, tcpmask = 0;
579     ip4_address_t src_v4address, dst_v4address;
580     int fd = -1;
581
582     char *file_name = NULL;
583     unformat_input_t file_input;
584
585     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
586       {
587         if (unformat (input, "filename %s", &file_name))
588           {
589             /* we will use this later */
590           }
591         else if (unformat (input, "acl-index %d", &acl_index))
592           {
593             /* we will try to replace an existing ACL */
594           }
595         else if (unformat (input, "permit+reflect"))
596           {
597             is_permit = 2;
598           }
599         else if (unformat (input, "permit"))
600           {
601             is_permit = 1;
602           }
603         else if (unformat (input, "append-default-permit"))
604           {
605             append_default_permit = 1;
606           }
607         else
608           break;
609       }
610
611     fd = open(file_name, O_RDONLY);
612     if (fd < 0)
613       {
614         clib_warning("Could not open file '%s'");
615         goto done;
616       }
617
618     /* input from file */
619     input =  &file_input;
620     unformat_init_clib_file(input, fd);
621
622     unsigned sport_low, sport_high, dport_low, dport_high;
623     unsigned proto, protomask;
624     u32 src_prefix_length, dst_prefix_length;
625     u32 unused1, unused2;
626
627     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
628       {
629             if (!unformat(input, "@%U/%d\t%U/%d\t%d : %d\t%d : %d\t0x%x/0x%x\t0x%x/0x%x",
630                                  unformat_ip4_address, &src_v4address, &src_prefix_length,
631                                  unformat_ip4_address, &dst_v4address, &dst_prefix_length,
632                                  &sport_low, &sport_high, &dport_low, &dport_high, &proto, &protomask, &unused1, &unused2)) {
633               clib_warning("Error parsing");
634               break;
635             }
636
637             rule_idx++;
638             vec_validate_acl_rules(rules, rule_idx);
639
640             rules[rule_idx].is_ipv6 = 0;
641             rules[rule_idx].is_permit = is_permit;
642             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
643             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
644             memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
645             rules[rule_idx].dst_ip_prefix_len = dst_prefix_length;
646             rules[rule_idx].srcport_or_icmptype_first = htons(sport_low);
647             rules[rule_idx].srcport_or_icmptype_last = htons(sport_high);
648             rules[rule_idx].dstport_or_icmpcode_first = htons(dport_low);
649             rules[rule_idx].dstport_or_icmpcode_last = htons(dport_high);
650             rules[rule_idx].tcp_flags_value = tcpflags;
651             rules[rule_idx].tcp_flags_mask = tcpmask;
652             rules[rule_idx].proto = proto;
653
654       }
655     rules[rule_idx].is_permit = is_permit;
656
657     if (append_default_permit) {
658         rule_idx++;
659         vec_validate_acl_rules(rules, rule_idx);
660
661         rules[rule_idx].is_ipv6 = 0;
662         rules[rule_idx].is_permit = is_permit == 2 ? 2 : 1;
663
664         src_v4address.data[0]=0;
665         src_v4address.data[1]=0;
666         src_v4address.data[2]=0;
667         src_v4address.data[3]=0;
668         memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
669         rules[rule_idx].src_ip_prefix_len = 0;
670
671         dst_v4address.data[0]=0;
672         dst_v4address.data[1]=0;
673         dst_v4address.data[2]=0;
674         dst_v4address.data[3]=0;
675         memcpy (rules[rule_idx].dst_ip_addr, &dst_v4address, 4);
676         rules[rule_idx].dst_ip_prefix_len = 0;
677
678         rules[rule_idx].srcport_or_icmptype_first = htons(0);
679         rules[rule_idx].srcport_or_icmptype_last = htons(65535);
680         rules[rule_idx].dstport_or_icmpcode_first = htons(0);
681         rules[rule_idx].dstport_or_icmpcode_last = htons(65535);
682         rules[rule_idx].tcp_flags_value = 0;
683         rules[rule_idx].tcp_flags_mask = 0;
684         rules[rule_idx].proto = 0;
685     }
686
687     /* Construct the API message */
688
689     vam->result_ready = 0;
690
691     n_rules = vec_len(rules);
692
693     msg_size += n_rules*sizeof(rules[0]);
694
695     mp = vl_msg_api_alloc_as_if_client(msg_size);
696     memset (mp, 0, msg_size);
697     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
698     mp->client_index = vam->my_client_index;
699     if (n_rules > 0)
700       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
701     mp->acl_index = ntohl(acl_index);
702     mp->count = htonl(n_rules);
703
704     /* send it... */
705     S(mp);
706
707     /* Wait for a reply... */
708     W (ret);
709 done:
710     if (fd > 0)
711       close (fd);
712     vec_free(file_name);
713
714     return ret;
715 }
716
717
718 static int api_acl_del (vat_main_t * vam)
719 {
720     unformat_input_t * i = vam->input;
721     vl_api_acl_del_t * mp;
722     u32 acl_index = ~0;
723     int ret;
724
725     if (!unformat (i, "%d", &acl_index)) {
726       errmsg ("missing acl index\n");
727       return -99;
728     }
729
730     /* Construct the API message */
731     M(ACL_DEL, mp);
732     mp->acl_index = ntohl(acl_index);
733
734     /* send it... */
735     S(mp);
736
737     /* Wait for a reply... */
738     W (ret);
739     return ret;
740 }
741
742 static int api_macip_acl_del (vat_main_t * vam)
743 {
744     unformat_input_t * i = vam->input;
745     vl_api_acl_del_t * mp;
746     u32 acl_index = ~0;
747     int ret;
748
749     if (!unformat (i, "%d", &acl_index)) {
750       errmsg ("missing acl index\n");
751       return -99;
752     }
753
754     /* Construct the API message */
755     M(MACIP_ACL_DEL, mp);
756     mp->acl_index = ntohl(acl_index);
757
758     /* send it... */
759     S(mp);
760
761     /* Wait for a reply... */
762     W (ret);
763     return ret;
764 }
765
766 static int api_acl_interface_add_del (vat_main_t * vam)
767 {
768     unformat_input_t * i = vam->input;
769     vl_api_acl_interface_add_del_t * mp;
770     u32 sw_if_index = ~0;
771     u32 acl_index = ~0;
772     u8 is_input = 0;
773     u8 is_add = 0;
774     int ret;
775
776 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
777
778     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
779     {
780         if (unformat (i, "%d", &acl_index))
781     ;
782         else
783     break;
784     }
785
786
787     /* Parse args required to build the message */
788     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
789         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
790             ;
791         else if (unformat (i, "sw_if_index %d", &sw_if_index))
792             ;
793         else if (unformat (i, "add"))
794             is_add = 1;
795         else if (unformat (i, "del"))
796             is_add = 0;
797         else if (unformat (i, "acl %d", &acl_index))
798             ;
799         else if (unformat (i, "input"))
800             is_input = 1;
801         else if (unformat (i, "output"))
802             is_input = 0;
803         else
804             break;
805     }
806
807     if (sw_if_index == ~0) {
808         errmsg ("missing interface name / explicit sw_if_index number \n");
809         return -99;
810     }
811
812     if (acl_index == ~0) {
813         errmsg ("missing ACL index\n");
814         return -99;
815     }
816
817
818
819     /* Construct the API message */
820     M(ACL_INTERFACE_ADD_DEL, mp);
821     mp->acl_index = ntohl(acl_index);
822     mp->sw_if_index = ntohl(sw_if_index);
823     mp->is_add = is_add;
824     mp->is_input = is_input;
825
826     /* send it... */
827     S(mp);
828
829     /* Wait for a reply... */
830     W (ret);
831     return ret;
832 }
833
834 static int api_macip_acl_interface_add_del (vat_main_t * vam)
835 {
836     unformat_input_t * i = vam->input;
837     vl_api_macip_acl_interface_add_del_t * mp;
838     u32 sw_if_index = ~0;
839     u32 acl_index = ~0;
840     u8 is_add = 0;
841     int ret;
842
843     /* Parse args required to build the message */
844     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
845         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
846             ;
847         else if (unformat (i, "sw_if_index %d", &sw_if_index))
848             ;
849         else if (unformat (i, "add"))
850             is_add = 1;
851         else if (unformat (i, "del"))
852             is_add = 0;
853         else if (unformat (i, "acl %d", &acl_index))
854             ;
855         else
856             break;
857     }
858
859     if (sw_if_index == ~0) {
860         errmsg ("missing interface name / explicit sw_if_index number \n");
861         return -99;
862     }
863
864     if (acl_index == ~0) {
865         errmsg ("missing ACL index\n");
866         return -99;
867     }
868
869
870
871     /* Construct the API message */
872     M(MACIP_ACL_INTERFACE_ADD_DEL, mp);
873     mp->acl_index = ntohl(acl_index);
874     mp->sw_if_index = ntohl(sw_if_index);
875     mp->is_add = is_add;
876
877     /* send it... */
878     S(mp);
879
880     /* Wait for a reply... */
881     W (ret);
882     return ret;
883 }
884
885 static int api_acl_interface_set_acl_list (vat_main_t * vam)
886 {
887     unformat_input_t * i = vam->input;
888     vl_api_acl_interface_set_acl_list_t * mp;
889     u32 sw_if_index = ~0;
890     u32 acl_index = ~0;
891     u32 *inacls = 0;
892     u32 *outacls = 0;
893     u8 is_input = 0;
894     int ret;
895
896 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
897
898     /* Parse args required to build the message */
899     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
900         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
901             ;
902         else if (unformat (i, "sw_if_index %d", &sw_if_index))
903             ;
904         else if (unformat (i, "%d", &acl_index))
905           {
906             if(is_input)
907               vec_add1(inacls, htonl(acl_index));
908             else
909               vec_add1(outacls, htonl(acl_index));
910           }
911         else if (unformat (i, "acl %d", &acl_index))
912             ;
913         else if (unformat (i, "input"))
914             is_input = 1;
915         else if (unformat (i, "output"))
916             is_input = 0;
917         else
918             break;
919     }
920
921     if (sw_if_index == ~0) {
922         errmsg ("missing interface name / explicit sw_if_index number \n");
923         return -99;
924     }
925
926     /* Construct the API message */
927     M2(ACL_INTERFACE_SET_ACL_LIST, mp, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
928     mp->sw_if_index = ntohl(sw_if_index);
929     mp->n_input = vec_len(inacls);
930     mp->count = vec_len(inacls) + vec_len(outacls);
931     vec_append(inacls, outacls);
932     if (vec_len(inacls) > 0)
933       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
934
935     /* send it... */
936     S(mp);
937
938     /* Wait for a reply... */
939     W (ret);
940     return ret;
941 }
942
943 static int api_acl_interface_set_etype_whitelist (vat_main_t * vam)
944 {
945     unformat_input_t * i = vam->input;
946     vl_api_acl_interface_set_etype_whitelist_t * mp;
947     u32 sw_if_index = ~0;
948     u32 ethertype = ~0;
949     u16 *etypes_in = 0;
950     u16 *etypes_out = 0;
951     u8 is_input = 1;
952     int ret;
953
954 //  acl_interface_set_etype_whitelist <intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]
955
956     /* Parse args required to build the message */
957     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
958         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
959             ;
960         else if (unformat (i, "sw_if_index %d", &sw_if_index))
961             ;
962         else if (unformat (i, "%x", &ethertype))
963           {
964             ethertype = ethertype & 0xffff;
965             if(is_input)
966               vec_add1(etypes_in, htons(ethertype));
967             else
968               vec_add1(etypes_out, htons(ethertype));
969           }
970         else if (unformat (i, "input"))
971             is_input = 1;
972         else if (unformat (i, "output"))
973             is_input = 0;
974         else
975             break;
976     }
977
978     if (sw_if_index == ~0) {
979         errmsg ("missing interface name / explicit sw_if_index number \n");
980         return -99;
981     }
982
983     /* Construct the API message */
984     M2(ACL_INTERFACE_SET_ETYPE_WHITELIST, mp, sizeof(u32) * (vec_len(etypes_in) + vec_len(etypes_out)));
985     mp->sw_if_index = ntohl(sw_if_index);
986     mp->n_input = vec_len(etypes_in);
987     mp->count = vec_len(etypes_in) + vec_len(etypes_out);
988     vec_append(etypes_in, etypes_out);
989     if (vec_len(etypes_in) > 0)
990       clib_memcpy(mp->whitelist, etypes_in, vec_len(etypes_in)*sizeof(etypes_in[0]));
991
992     /* send it... */
993     S(mp);
994
995     /* Wait for a reply... */
996     W (ret);
997     return ret;
998 }
999
1000 static void
1001 api_acl_send_control_ping(vat_main_t *vam)
1002 {
1003   vl_api_acl_plugin_control_ping_t *mp_ping;
1004
1005   M(ACL_PLUGIN_CONTROL_PING, mp_ping);
1006   S(mp_ping);
1007 }
1008
1009
1010 static int api_acl_interface_list_dump (vat_main_t * vam)
1011 {
1012     unformat_input_t * i = vam->input;
1013     u32 sw_if_index = ~0;
1014     vl_api_acl_interface_list_dump_t * mp;
1015     int ret;
1016
1017     /* Parse args required to build the message */
1018     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1019         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1020             ;
1021         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1022             ;
1023         else
1024             break;
1025     }
1026
1027     /* Construct the API message */
1028     M(ACL_INTERFACE_LIST_DUMP, mp);
1029     mp->sw_if_index = ntohl (sw_if_index);
1030
1031     /* send it... */
1032     S(mp);
1033
1034     /* Use control ping for synchronization */
1035     api_acl_send_control_ping(vam);
1036
1037     /* Wait for a reply... */
1038     W (ret);
1039     return ret;
1040 }
1041
1042 static int api_acl_dump (vat_main_t * vam)
1043 {
1044     unformat_input_t * i = vam->input;
1045     u32 acl_index = ~0;
1046     vl_api_acl_dump_t * mp;
1047     int ret;
1048
1049     /* Parse args required to build the message */
1050     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1051         if (unformat (i, "%d", &acl_index))
1052             ;
1053         else
1054             break;
1055     }
1056
1057     /* Construct the API message */
1058     M(ACL_DUMP, mp);
1059     mp->acl_index = ntohl (acl_index);
1060
1061     /* send it... */
1062     S(mp);
1063
1064     /* Use control ping for synchronization */
1065     api_acl_send_control_ping(vam);
1066
1067     /* Wait for a reply... */
1068     W (ret);
1069     return ret;
1070 }
1071
1072 static int api_macip_acl_dump (vat_main_t * vam)
1073 {
1074     unformat_input_t * i = vam->input;
1075     u32 acl_index = ~0;
1076     vl_api_acl_dump_t * mp;
1077     int ret;
1078
1079     /* Parse args required to build the message */
1080     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1081         if (unformat (i, "%d", &acl_index))
1082             ;
1083         else
1084             break;
1085     }
1086
1087     /* Construct the API message */
1088     M(MACIP_ACL_DUMP, mp);
1089     mp->acl_index = ntohl (acl_index);
1090
1091     /* send it... */
1092     S(mp);
1093
1094     /* Use control ping for synchronization */
1095     api_acl_send_control_ping(vam);
1096
1097     /* Wait for a reply... */
1098     W (ret);
1099     return ret;
1100 }
1101
1102 static int api_acl_interface_etype_whitelist_dump (vat_main_t * vam)
1103 {
1104     unformat_input_t * i = vam->input;
1105     u32 sw_if_index = ~0;
1106     vl_api_acl_interface_etype_whitelist_dump_t * mp;
1107     int ret;
1108
1109     /* Parse args required to build the message */
1110     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1111         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1112             ;
1113         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1114             ;
1115         else
1116             break;
1117     }
1118
1119     /* Construct the API message */
1120     M(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, mp);
1121     mp->sw_if_index = ntohl (sw_if_index);
1122
1123     /* send it... */
1124     S(mp);
1125
1126     /* Use control ping for synchronization */
1127     api_acl_send_control_ping(vam);
1128
1129     /* Wait for a reply... */
1130     W (ret);
1131     return ret;
1132 }
1133
1134
1135 #define vec_validate_macip_acl_rules(v, idx) \
1136   do {                                 \
1137     if (vec_len(v) < idx+1) {  \
1138       vec_validate(v, idx); \
1139       v[idx].is_permit = 0x1; \
1140     } \
1141   } while (0)
1142
1143
1144 static int api_macip_acl_add (vat_main_t * vam)
1145 {
1146     acl_test_main_t * sm = &acl_test_main;
1147     unformat_input_t * i = vam->input;
1148     vl_api_macip_acl_add_t * mp;
1149     u32 msg_size = sizeof (*mp); /* without the rules */
1150
1151     vl_api_macip_acl_rule_t *rules = 0;
1152     int rule_idx = 0;
1153     int n_rules = 0;
1154     int n_rules_override = -1;
1155     u32 src_prefix_length = 0;
1156     u32 action = 0;
1157     ip4_address_t src_v4address;
1158     ip6_address_t src_v6address;
1159     u8 src_mac[6];
1160     u8 *tag = 0;
1161     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1162     int ret;
1163
1164     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1165     {
1166         if (unformat (i, "ipv6"))
1167           {
1168             vec_validate_macip_acl_rules(rules, rule_idx);
1169             rules[rule_idx].is_ipv6 = 1;
1170           }
1171         else if (unformat (i, "ipv4"))
1172           {
1173             vec_validate_macip_acl_rules(rules, rule_idx);
1174             rules[rule_idx].is_ipv6 = 0;
1175           }
1176         else if (unformat (i, "permit"))
1177           {
1178             vec_validate_macip_acl_rules(rules, rule_idx);
1179             rules[rule_idx].is_permit = 1;
1180           }
1181         else if (unformat (i, "deny"))
1182           {
1183             vec_validate_macip_acl_rules(rules, rule_idx);
1184             rules[rule_idx].is_permit = 0;
1185           }
1186         else if (unformat (i, "count %d", &n_rules_override))
1187           {
1188             /* we will use this later */
1189           }
1190         else if (unformat (i, "action %d", &action))
1191           {
1192             vec_validate_macip_acl_rules(rules, rule_idx);
1193             rules[rule_idx].is_permit = action;
1194           }
1195         else if (unformat (i, "ip %U/%d",
1196          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1197                  unformat (i, "ip %U",
1198          unformat_ip4_address, &src_v4address))
1199           {
1200             if (src_prefix_length == 0)
1201               src_prefix_length = 32;
1202             vec_validate_macip_acl_rules(rules, rule_idx);
1203             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
1204             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1205             rules[rule_idx].is_ipv6 = 0;
1206           }
1207         else if (unformat (i, "src"))
1208           {
1209             /* Everything in MACIP is "source" but allow this verbosity */
1210           }
1211         else if (unformat (i, "ip %U/%d",
1212          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1213                  unformat (i, "ip %U",
1214          unformat_ip6_address, &src_v6address))
1215           {
1216             if (src_prefix_length == 0)
1217               src_prefix_length = 128;
1218             vec_validate_macip_acl_rules(rules, rule_idx);
1219             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
1220             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1221             rules[rule_idx].is_ipv6 = 1;
1222           }
1223         else if (unformat (i, "mac %U",
1224          my_unformat_mac_address, &src_mac))
1225           {
1226             vec_validate_macip_acl_rules(rules, rule_idx);
1227             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1228             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1229           }
1230         else if (unformat (i, "mask %U",
1231          my_unformat_mac_address, &src_mac))
1232           {
1233             vec_validate_macip_acl_rules(rules, rule_idx);
1234             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1235           }
1236         else if (unformat (i, "tag %s", &tag))
1237           {
1238           }
1239         else if (unformat (i, ","))
1240           {
1241             rule_idx++;
1242             vec_validate_macip_acl_rules(rules, rule_idx);
1243           }
1244         else
1245     break;
1246     }
1247
1248     /* Construct the API message */
1249     vam->result_ready = 0;
1250
1251     if(rules)
1252       n_rules = vec_len(rules);
1253
1254     if (n_rules_override >= 0)
1255       n_rules = n_rules_override;
1256
1257     msg_size += n_rules*sizeof(rules[0]);
1258
1259     mp = vl_msg_api_alloc_as_if_client(msg_size);
1260     memset (mp, 0, msg_size);
1261     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
1262     mp->client_index = vam->my_client_index;
1263     if ((n_rules > 0) && rules)
1264       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1265     if (tag)
1266       {
1267         if (vec_len(tag) >= sizeof(mp->tag))
1268           {
1269             tag[sizeof(mp->tag)-1] = 0;
1270             _vec_len(tag) = sizeof(mp->tag);
1271           }
1272         clib_memcpy(mp->tag, tag, vec_len(tag));
1273         vec_free(tag);
1274       }
1275
1276     mp->count = htonl(n_rules);
1277
1278     /* send it... */
1279     S(mp);
1280
1281     /* Wait for a reply... */
1282     W (ret);
1283     return ret;
1284 }
1285
1286 static int api_macip_acl_add_replace (vat_main_t * vam)
1287 {
1288     acl_test_main_t * sm = &acl_test_main;
1289     unformat_input_t * i = vam->input;
1290     vl_api_macip_acl_add_replace_t * mp;
1291     u32 acl_index = ~0;
1292     u32 msg_size = sizeof (*mp); /* without the rules */
1293
1294     vl_api_macip_acl_rule_t *rules = 0;
1295     int rule_idx = 0;
1296     int n_rules = 0;
1297     int n_rules_override = -1;
1298     u32 src_prefix_length = 0;
1299     u32 action = 0;
1300     ip4_address_t src_v4address;
1301     ip6_address_t src_v6address;
1302     u8 src_mac[6];
1303     u8 *tag = 0;
1304     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1305     int ret;
1306
1307     if (!unformat (i, "%d", &acl_index)) {
1308         /* Just assume -1 */
1309     }
1310
1311     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1312     {
1313         if (unformat (i, "ipv6"))
1314           {
1315             vec_validate_macip_acl_rules(rules, rule_idx);
1316             rules[rule_idx].is_ipv6 = 1;
1317           }
1318         else if (unformat (i, "ipv4"))
1319           {
1320             vec_validate_macip_acl_rules(rules, rule_idx);
1321             rules[rule_idx].is_ipv6 = 0;
1322           }
1323         else if (unformat (i, "permit"))
1324           {
1325             vec_validate_macip_acl_rules(rules, rule_idx);
1326             rules[rule_idx].is_permit = 1;
1327           }
1328         else if (unformat (i, "deny"))
1329           {
1330             vec_validate_macip_acl_rules(rules, rule_idx);
1331             rules[rule_idx].is_permit = 0;
1332           }
1333         else if (unformat (i, "count %d", &n_rules_override))
1334           {
1335             /* we will use this later */
1336           }
1337         else if (unformat (i, "action %d", &action))
1338           {
1339             vec_validate_macip_acl_rules(rules, rule_idx);
1340             rules[rule_idx].is_permit = action;
1341           }
1342         else if (unformat (i, "ip %U/%d",
1343          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1344                  unformat (i, "ip %U",
1345          unformat_ip4_address, &src_v4address))
1346           {
1347             if (src_prefix_length == 0)
1348               src_prefix_length = 32;
1349             vec_validate_macip_acl_rules(rules, rule_idx);
1350             memcpy (rules[rule_idx].src_ip_addr, &src_v4address, 4);
1351             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1352             rules[rule_idx].is_ipv6 = 0;
1353           }
1354         else if (unformat (i, "src"))
1355           {
1356             /* Everything in MACIP is "source" but allow this verbosity */
1357           }
1358         else if (unformat (i, "ip %U/%d",
1359          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1360                  unformat (i, "ip %U",
1361          unformat_ip6_address, &src_v6address))
1362           {
1363             if (src_prefix_length == 0)
1364               src_prefix_length = 128;
1365             vec_validate_macip_acl_rules(rules, rule_idx);
1366             memcpy (rules[rule_idx].src_ip_addr, &src_v6address, 16);
1367             rules[rule_idx].src_ip_prefix_len = src_prefix_length;
1368             rules[rule_idx].is_ipv6 = 1;
1369           }
1370         else if (unformat (i, "mac %U",
1371          my_unformat_mac_address, &src_mac))
1372           {
1373             vec_validate_macip_acl_rules(rules, rule_idx);
1374             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1375             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1376           }
1377         else if (unformat (i, "mask %U",
1378          my_unformat_mac_address, &src_mac))
1379           {
1380             vec_validate_macip_acl_rules(rules, rule_idx);
1381             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1382           }
1383         else if (unformat (i, "tag %s", &tag))
1384           {
1385           }
1386         else if (unformat (i, ","))
1387           {
1388             rule_idx++;
1389             vec_validate_macip_acl_rules(rules, rule_idx);
1390           }
1391         else
1392     break;
1393     }
1394
1395     if (!rules)
1396       {
1397       errmsg ("rule/s required\n");
1398       return -99;
1399       }
1400     /* Construct the API message */
1401     vam->result_ready = 0;
1402
1403     if(rules)
1404       n_rules = vec_len(rules);
1405
1406     if (n_rules_override >= 0)
1407       n_rules = n_rules_override;
1408
1409     msg_size += n_rules*sizeof(rules[0]);
1410
1411     mp = vl_msg_api_alloc_as_if_client(msg_size);
1412     memset (mp, 0, msg_size);
1413     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD_REPLACE + sm->msg_id_base);
1414     mp->client_index = vam->my_client_index;
1415     if ((n_rules > 0) && rules)
1416       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1417     if (tag)
1418       {
1419         if (vec_len(tag) >= sizeof(mp->tag))
1420           {
1421             tag[sizeof(mp->tag)-1] = 0;
1422             _vec_len(tag) = sizeof(mp->tag);
1423           }
1424         clib_memcpy(mp->tag, tag, vec_len(tag));
1425         vec_free(tag);
1426       }
1427
1428     mp->acl_index = ntohl(acl_index);
1429     mp->count = htonl(n_rules);
1430
1431     /* send it... */
1432     S(mp);
1433
1434     /* Wait for a reply... */
1435     W (ret);
1436     return ret;
1437 }
1438
1439 /*
1440  * List of messages that the api test plugin sends,
1441  * and that the data plane plugin processes
1442  */
1443 #define foreach_vpe_api_msg \
1444 _(acl_plugin_get_version, "") \
1445 _(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], ... , ...") \
1446 _(acl_add_replace_from_file, "filename <file> [permit] [append-default-permit]") \
1447 _(acl_del, "<acl-idx>") \
1448 _(acl_dump, "[<acl-idx>]") \
1449 _(acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] [input|output] acl <acl-idx>") \
1450 _(acl_interface_set_acl_list, "<intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]") \
1451 _(acl_interface_set_etype_whitelist, "<intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]") \
1452 _(acl_interface_etype_whitelist_dump, "[<intfc> | sw_if_index <if-idx>]") \
1453 _(acl_interface_list_dump, "[<intfc> | sw_if_index <if-idx>]") \
1454 _(macip_acl_add, "...") \
1455 _(macip_acl_add_replace, "<acl-idx> [<ipv4|ipv6> <permit|deny|action N> [count <count>] [src] ip <ipaddress/[plen]> mac <mac> mask <mac_mask>, ... , ...") \
1456 _(macip_acl_del, "<acl-idx>")\
1457 _(macip_acl_dump, "[<acl-idx>]") \
1458 _(macip_acl_interface_add_del, "<intfc> | sw_if_index <if-idx> [add|del] acl <acl-idx>") \
1459 _(macip_acl_interface_get, "")
1460
1461
1462 static
1463 void acl_vat_api_hookup (vat_main_t *vam)
1464 {
1465     acl_test_main_t * sm = &acl_test_main;
1466     /* Hook up handlers for replies from the data plane plug-in */
1467 #define _(N,n)                                                  \
1468     vl_msg_api_set_handlers((VL_API_##N + sm->msg_id_base),     \
1469                            #n,                                  \
1470                            vl_api_##n##_t_handler,              \
1471                            vl_noop_handler,                     \
1472                            vl_api_##n##_t_endian,               \
1473                            vl_api_##n##_t_print,                \
1474                            sizeof(vl_api_##n##_t), 1);
1475     foreach_vpe_api_reply_msg;
1476 #undef _
1477
1478     /* API messages we can send */
1479 #define _(n,h) hash_set_mem (vam->function_by_name, #n, api_##n);
1480     foreach_vpe_api_msg;
1481 #undef _
1482
1483     /* Help strings */
1484 #define _(n,h) hash_set_mem (vam->help_by_name, #n, h);
1485     foreach_vpe_api_msg;
1486 #undef _
1487 }
1488
1489 clib_error_t * vat_plugin_register (vat_main_t *vam)
1490 {
1491   acl_test_main_t * sm = &acl_test_main;
1492   u8 * name;
1493
1494   sm->vat_main = vam;
1495
1496   name = format (0, "acl_%08x%c", api_version, 0);
1497   sm->msg_id_base = vl_client_get_first_plugin_msg_id ((char *) name);
1498
1499   if (sm->msg_id_base != (u16) ~0)
1500     acl_vat_api_hookup (vam);
1501
1502   vec_free(name);
1503
1504   return 0;
1505 }