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