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