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