acl: API cleanup
[vpp.git] / src / plugins / acl / acl_test.c
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16  *------------------------------------------------------------------
17  * acl_test.c - test harness plugin
18  *------------------------------------------------------------------
19  */
20
21 #include <vat/vat.h>
22 #include <vlibapi/api.h>
23 #include <vlibmemory/api.h>
24 #include <vppinfra/error.h>
25 #include <vnet/ip/ip.h>
26 #include <arpa/inet.h>
27
28 #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     fd = open(file_name, O_RDONLY);
619     if (fd < 0)
620       {
621         clib_warning("Could not open file '%s'");
622         goto done;
623       }
624
625     /* input from file */
626     input =  &file_input;
627     unformat_init_clib_file(input, fd);
628
629     unsigned sport_low, sport_high, dport_low, dport_high;
630     unsigned proto, protomask;
631     u32 src_prefix_length, dst_prefix_length;
632     u32 unused1, unused2;
633
634     while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
635       {
636             if (!unformat(input, "@%U/%d\t%U/%d\t%d : %d\t%d : %d\t0x%x/0x%x\t0x%x/0x%x",
637                                  unformat_ip4_address, &src_v4address, &src_prefix_length,
638                                  unformat_ip4_address, &dst_v4address, &dst_prefix_length,
639                                  &sport_low, &sport_high, &dport_low, &dport_high, &proto, &protomask, &unused1, &unused2)) {
640               clib_warning("Error parsing");
641               break;
642             }
643
644             rule_idx++;
645             vec_validate_acl_rules(rules, rule_idx);
646
647             rules[rule_idx].is_permit = is_permit;
648             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
649             rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
650             rules[rule_idx].src_prefix.len = src_prefix_length;
651             memcpy (rules[rule_idx].dst_prefix.address.un.ip4, &dst_v4address, 4);
652             rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
653             rules[rule_idx].dst_prefix.len = dst_prefix_length;
654             rules[rule_idx].srcport_or_icmptype_first = htons(sport_low);
655             rules[rule_idx].srcport_or_icmptype_last = htons(sport_high);
656             rules[rule_idx].dstport_or_icmpcode_first = htons(dport_low);
657             rules[rule_idx].dstport_or_icmpcode_last = htons(dport_high);
658             rules[rule_idx].tcp_flags_value = tcpflags;
659             rules[rule_idx].tcp_flags_mask = tcpmask;
660             rules[rule_idx].proto = proto;
661
662       }
663
664     if (append_default_permit) {
665         rule_idx++;
666         vec_validate_acl_rules(rules, rule_idx);
667
668         rules[rule_idx].is_permit = is_permit == 2 ? 2 : 1;
669
670         src_v4address.data[0]=0;
671         src_v4address.data[1]=0;
672         src_v4address.data[2]=0;
673         src_v4address.data[3]=0;
674         memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
675         rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
676         rules[rule_idx].src_prefix.len = 0;
677
678         dst_v4address.data[0]=0;
679         dst_v4address.data[1]=0;
680         dst_v4address.data[2]=0;
681         dst_v4address.data[3]=0;
682         memcpy (rules[rule_idx].dst_prefix.address.un.ip4, &dst_v4address, 4);
683         rules[rule_idx].dst_prefix.address.af = ADDRESS_IP4;
684         rules[rule_idx].dst_prefix.len = 0;
685
686         rules[rule_idx].srcport_or_icmptype_first = htons(0);
687         rules[rule_idx].srcport_or_icmptype_last = htons(65535);
688         rules[rule_idx].dstport_or_icmpcode_first = htons(0);
689         rules[rule_idx].dstport_or_icmpcode_last = htons(65535);
690         rules[rule_idx].tcp_flags_value = 0;
691         rules[rule_idx].tcp_flags_mask = 0;
692         rules[rule_idx].proto = 0;
693     }
694
695     /* Construct the API message */
696
697     vam->result_ready = 0;
698
699     n_rules = vec_len(rules);
700
701     msg_size += n_rules*sizeof(rules[0]);
702
703     mp = vl_msg_api_alloc_as_if_client(msg_size);
704     clib_memset (mp, 0, msg_size);
705     mp->_vl_msg_id = ntohs (VL_API_ACL_ADD_REPLACE + sm->msg_id_base);
706     mp->client_index = vam->my_client_index;
707     if (n_rules > 0)
708       clib_memcpy(mp->r, rules, n_rules*sizeof (vl_api_acl_rule_t));
709     mp->acl_index = ntohl(acl_index);
710     mp->count = htonl(n_rules);
711
712     /* send it... */
713     S(mp);
714
715     /* Wait for a reply... */
716     W (ret);
717 done:
718     if (fd > 0)
719       close (fd);
720     vec_free(file_name);
721
722     return ret;
723 }
724
725
726 static int api_acl_del (vat_main_t * vam)
727 {
728     unformat_input_t * i = vam->input;
729     vl_api_acl_del_t * mp;
730     u32 acl_index = ~0;
731     int ret;
732
733     if (!unformat (i, "%d", &acl_index)) {
734       errmsg ("missing acl index\n");
735       return -99;
736     }
737
738     /* Construct the API message */
739     M(ACL_DEL, mp);
740     mp->acl_index = ntohl(acl_index);
741
742     /* send it... */
743     S(mp);
744
745     /* Wait for a reply... */
746     W (ret);
747     return ret;
748 }
749
750 static int api_macip_acl_del (vat_main_t * vam)
751 {
752     unformat_input_t * i = vam->input;
753     vl_api_acl_del_t * mp;
754     u32 acl_index = ~0;
755     int ret;
756
757     if (!unformat (i, "%d", &acl_index)) {
758       errmsg ("missing acl index\n");
759       return -99;
760     }
761
762     /* Construct the API message */
763     M(MACIP_ACL_DEL, mp);
764     mp->acl_index = ntohl(acl_index);
765
766     /* send it... */
767     S(mp);
768
769     /* Wait for a reply... */
770     W (ret);
771     return ret;
772 }
773
774 static int api_acl_interface_add_del (vat_main_t * vam)
775 {
776     unformat_input_t * i = vam->input;
777     vl_api_acl_interface_add_del_t * mp;
778     u32 sw_if_index = ~0;
779     u32 acl_index = ~0;
780     u8 is_input = 0;
781     u8 is_add = 0;
782     int ret;
783
784 //    acl_interface_add_del <intfc> | sw_if_index <if-idx> acl_index <acl-idx> [out] [del]
785
786     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
787     {
788         if (unformat (i, "%d", &acl_index))
789     ;
790         else
791     break;
792     }
793
794
795     /* Parse args required to build the message */
796     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
797         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
798             ;
799         else if (unformat (i, "sw_if_index %d", &sw_if_index))
800             ;
801         else if (unformat (i, "add"))
802             is_add = 1;
803         else if (unformat (i, "del"))
804             is_add = 0;
805         else if (unformat (i, "acl %d", &acl_index))
806             ;
807         else if (unformat (i, "input"))
808             is_input = 1;
809         else if (unformat (i, "output"))
810             is_input = 0;
811         else
812             break;
813     }
814
815     if (sw_if_index == ~0) {
816         errmsg ("missing interface name / explicit sw_if_index number \n");
817         return -99;
818     }
819
820     if (acl_index == ~0) {
821         errmsg ("missing ACL index\n");
822         return -99;
823     }
824
825
826
827     /* Construct the API message */
828     M(ACL_INTERFACE_ADD_DEL, mp);
829     mp->acl_index = ntohl(acl_index);
830     mp->sw_if_index = ntohl(sw_if_index);
831     mp->is_add = is_add;
832     mp->is_input = is_input;
833
834     /* send it... */
835     S(mp);
836
837     /* Wait for a reply... */
838     W (ret);
839     return ret;
840 }
841
842 static int api_macip_acl_interface_add_del (vat_main_t * vam)
843 {
844     unformat_input_t * i = vam->input;
845     vl_api_macip_acl_interface_add_del_t * mp;
846     u32 sw_if_index = ~0;
847     u32 acl_index = ~0;
848     u8 is_add = 0;
849     int ret;
850
851     /* Parse args required to build the message */
852     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
853         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
854             ;
855         else if (unformat (i, "sw_if_index %d", &sw_if_index))
856             ;
857         else if (unformat (i, "add"))
858             is_add = 1;
859         else if (unformat (i, "del"))
860             is_add = 0;
861         else if (unformat (i, "acl %d", &acl_index))
862             ;
863         else
864             break;
865     }
866
867     if (sw_if_index == ~0) {
868         errmsg ("missing interface name / explicit sw_if_index number \n");
869         return -99;
870     }
871
872     if (acl_index == ~0) {
873         errmsg ("missing ACL index\n");
874         return -99;
875     }
876
877
878
879     /* Construct the API message */
880     M(MACIP_ACL_INTERFACE_ADD_DEL, mp);
881     mp->acl_index = ntohl(acl_index);
882     mp->sw_if_index = ntohl(sw_if_index);
883     mp->is_add = is_add;
884
885     /* send it... */
886     S(mp);
887
888     /* Wait for a reply... */
889     W (ret);
890     return ret;
891 }
892
893 static int api_acl_interface_set_acl_list (vat_main_t * vam)
894 {
895     unformat_input_t * i = vam->input;
896     vl_api_acl_interface_set_acl_list_t * mp;
897     u32 sw_if_index = ~0;
898     u32 acl_index = ~0;
899     u32 *inacls = 0;
900     u32 *outacls = 0;
901     u8 is_input = 0;
902     int ret;
903
904 //  acl_interface_set_acl_list <intfc> | sw_if_index <if-idx> input [acl-idx list] output [acl-idx list]
905
906     /* Parse args required to build the message */
907     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
908         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
909             ;
910         else if (unformat (i, "sw_if_index %d", &sw_if_index))
911             ;
912         else if (unformat (i, "%d", &acl_index))
913           {
914             if(is_input)
915               vec_add1(inacls, htonl(acl_index));
916             else
917               vec_add1(outacls, htonl(acl_index));
918           }
919         else if (unformat (i, "acl %d", &acl_index))
920             ;
921         else if (unformat (i, "input"))
922             is_input = 1;
923         else if (unformat (i, "output"))
924             is_input = 0;
925         else
926             break;
927     }
928
929     if (sw_if_index == ~0) {
930         errmsg ("missing interface name / explicit sw_if_index number \n");
931         return -99;
932     }
933
934     /* Construct the API message */
935     M2(ACL_INTERFACE_SET_ACL_LIST, mp, sizeof(u32) * (vec_len(inacls) + vec_len(outacls)));
936     mp->sw_if_index = ntohl(sw_if_index);
937     mp->n_input = vec_len(inacls);
938     mp->count = vec_len(inacls) + vec_len(outacls);
939     vec_append(inacls, outacls);
940     if (vec_len(inacls) > 0)
941       clib_memcpy(mp->acls, inacls, vec_len(inacls)*sizeof(u32));
942
943     /* send it... */
944     S(mp);
945
946     /* Wait for a reply... */
947     W (ret);
948     return ret;
949 }
950
951 static int api_acl_interface_set_etype_whitelist (vat_main_t * vam)
952 {
953     unformat_input_t * i = vam->input;
954     vl_api_acl_interface_set_etype_whitelist_t * mp;
955     u32 sw_if_index = ~0;
956     u32 ethertype = ~0;
957     u16 *etypes_in = 0;
958     u16 *etypes_out = 0;
959     u8 is_input = 1;
960     int ret;
961
962 //  acl_interface_set_etype_whitelist <intfc> | sw_if_index <if-idx> input [ethertype list] output [ethertype list]
963
964     /* Parse args required to build the message */
965     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
966         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
967             ;
968         else if (unformat (i, "sw_if_index %d", &sw_if_index))
969             ;
970         else if (unformat (i, "%x", &ethertype))
971           {
972             ethertype = ethertype & 0xffff;
973             if(is_input)
974               vec_add1(etypes_in, htons(ethertype));
975             else
976               vec_add1(etypes_out, htons(ethertype));
977           }
978         else if (unformat (i, "input"))
979             is_input = 1;
980         else if (unformat (i, "output"))
981             is_input = 0;
982         else
983             break;
984     }
985
986     if (sw_if_index == ~0) {
987         errmsg ("missing interface name / explicit sw_if_index number \n");
988         return -99;
989     }
990
991     /* Construct the API message */
992     M2(ACL_INTERFACE_SET_ETYPE_WHITELIST, mp, sizeof(u32) * (vec_len(etypes_in) + vec_len(etypes_out)));
993     mp->sw_if_index = ntohl(sw_if_index);
994     mp->n_input = vec_len(etypes_in);
995     mp->count = vec_len(etypes_in) + vec_len(etypes_out);
996     vec_append(etypes_in, etypes_out);
997     if (vec_len(etypes_in) > 0)
998       clib_memcpy(mp->whitelist, etypes_in, vec_len(etypes_in)*sizeof(etypes_in[0]));
999
1000     /* send it... */
1001     S(mp);
1002
1003     /* Wait for a reply... */
1004     W (ret);
1005     return ret;
1006 }
1007
1008 static void
1009 api_acl_send_control_ping(vat_main_t *vam)
1010 {
1011   vl_api_acl_plugin_control_ping_t *mp_ping;
1012
1013   M(ACL_PLUGIN_CONTROL_PING, mp_ping);
1014   S(mp_ping);
1015 }
1016
1017
1018 static int api_acl_interface_list_dump (vat_main_t * vam)
1019 {
1020     unformat_input_t * i = vam->input;
1021     u32 sw_if_index = ~0;
1022     vl_api_acl_interface_list_dump_t * mp;
1023     int ret;
1024
1025     /* Parse args required to build the message */
1026     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1027         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1028             ;
1029         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1030             ;
1031         else
1032             break;
1033     }
1034
1035     /* Construct the API message */
1036     M(ACL_INTERFACE_LIST_DUMP, mp);
1037     mp->sw_if_index = ntohl (sw_if_index);
1038
1039     /* send it... */
1040     S(mp);
1041
1042     /* Use control ping for synchronization */
1043     api_acl_send_control_ping(vam);
1044
1045     /* Wait for a reply... */
1046     W (ret);
1047     return ret;
1048 }
1049
1050 static int api_acl_dump (vat_main_t * vam)
1051 {
1052     unformat_input_t * i = vam->input;
1053     u32 acl_index = ~0;
1054     vl_api_acl_dump_t * mp;
1055     int ret;
1056
1057     /* Parse args required to build the message */
1058     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1059         if (unformat (i, "%d", &acl_index))
1060             ;
1061         else
1062             break;
1063     }
1064
1065     /* Construct the API message */
1066     M(ACL_DUMP, mp);
1067     mp->acl_index = ntohl (acl_index);
1068
1069     /* send it... */
1070     S(mp);
1071
1072     /* Use control ping for synchronization */
1073     api_acl_send_control_ping(vam);
1074
1075     /* Wait for a reply... */
1076     W (ret);
1077     return ret;
1078 }
1079
1080 static int api_macip_acl_dump (vat_main_t * vam)
1081 {
1082     unformat_input_t * i = vam->input;
1083     u32 acl_index = ~0;
1084     vl_api_acl_dump_t * mp;
1085     int ret;
1086
1087     /* Parse args required to build the message */
1088     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1089         if (unformat (i, "%d", &acl_index))
1090             ;
1091         else
1092             break;
1093     }
1094
1095     /* Construct the API message */
1096     M(MACIP_ACL_DUMP, mp);
1097     mp->acl_index = ntohl (acl_index);
1098
1099     /* send it... */
1100     S(mp);
1101
1102     /* Use control ping for synchronization */
1103     api_acl_send_control_ping(vam);
1104
1105     /* Wait for a reply... */
1106     W (ret);
1107     return ret;
1108 }
1109
1110 static int api_acl_interface_etype_whitelist_dump (vat_main_t * vam)
1111 {
1112     unformat_input_t * i = vam->input;
1113     u32 sw_if_index = ~0;
1114     vl_api_acl_interface_etype_whitelist_dump_t * mp;
1115     int ret;
1116
1117     /* Parse args required to build the message */
1118     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT) {
1119         if (unformat (i, "%U", unformat_sw_if_index, vam, &sw_if_index))
1120             ;
1121         else if (unformat (i, "sw_if_index %d", &sw_if_index))
1122             ;
1123         else
1124             break;
1125     }
1126
1127     /* Construct the API message */
1128     M(ACL_INTERFACE_ETYPE_WHITELIST_DUMP, mp);
1129     mp->sw_if_index = ntohl (sw_if_index);
1130
1131     /* send it... */
1132     S(mp);
1133
1134     /* Use control ping for synchronization */
1135     api_acl_send_control_ping(vam);
1136
1137     /* Wait for a reply... */
1138     W (ret);
1139     return ret;
1140 }
1141
1142
1143 #define vec_validate_macip_acl_rules(v, idx) \
1144   do {                                 \
1145     if (vec_len(v) < idx+1) {  \
1146       vec_validate(v, idx); \
1147       v[idx].is_permit = 0x1; \
1148     } \
1149   } while (0)
1150
1151
1152 static int api_macip_acl_add (vat_main_t * vam)
1153 {
1154     acl_test_main_t * sm = &acl_test_main;
1155     unformat_input_t * i = vam->input;
1156     vl_api_macip_acl_add_t * mp;
1157     u32 msg_size = sizeof (*mp); /* without the rules */
1158
1159     vl_api_macip_acl_rule_t *rules = 0;
1160     int rule_idx = 0;
1161     int n_rules = 0;
1162     int n_rules_override = -1;
1163     u32 src_prefix_length = 0;
1164     u32 action = 0;
1165     ip4_address_t src_v4address;
1166     ip6_address_t src_v6address;
1167     u8 src_mac[6];
1168     u8 *tag = 0;
1169     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1170     int ret;
1171
1172     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1173     {
1174         if (unformat (i, "permit"))
1175           {
1176             vec_validate_macip_acl_rules(rules, rule_idx);
1177             rules[rule_idx].is_permit = 1;
1178           }
1179         else if (unformat (i, "deny"))
1180           {
1181             vec_validate_macip_acl_rules(rules, rule_idx);
1182             rules[rule_idx].is_permit = 0;
1183           }
1184         else if (unformat (i, "count %d", &n_rules_override))
1185           {
1186             /* we will use this later */
1187           }
1188         else if (unformat (i, "action %d", &action))
1189           {
1190             vec_validate_macip_acl_rules(rules, rule_idx);
1191             rules[rule_idx].is_permit = action;
1192           }
1193         else if (unformat (i, "ip %U/%d",
1194          unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1195                  unformat (i, "ip %U",
1196          unformat_ip4_address, &src_v4address))
1197           {
1198             if (src_prefix_length == 0)
1199               src_prefix_length = 32;
1200             vec_validate_macip_acl_rules(rules, rule_idx);
1201             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
1202             rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
1203             rules[rule_idx].src_prefix.len = src_prefix_length;
1204           }
1205         else if (unformat (i, "src"))
1206           {
1207             /* Everything in MACIP is "source" but allow this verbosity */
1208           }
1209         else if (unformat (i, "ip %U/%d",
1210          unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1211                  unformat (i, "ip %U",
1212          unformat_ip6_address, &src_v6address))
1213           {
1214             if (src_prefix_length == 0)
1215               src_prefix_length = 128;
1216             vec_validate_macip_acl_rules(rules, rule_idx);
1217             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v6address, 4);
1218             rules[rule_idx].src_prefix.address.af = ADDRESS_IP6;
1219             rules[rule_idx].src_prefix.len = src_prefix_length;
1220           }
1221         else if (unformat (i, "mac %U",
1222          my_unformat_mac_address, &src_mac))
1223           {
1224             vec_validate_macip_acl_rules(rules, rule_idx);
1225             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1226             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1227           }
1228         else if (unformat (i, "mask %U",
1229          my_unformat_mac_address, &src_mac))
1230           {
1231             vec_validate_macip_acl_rules(rules, rule_idx);
1232             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1233           }
1234         else if (unformat (i, "tag %s", &tag))
1235           {
1236           }
1237         else if (unformat (i, ","))
1238           {
1239             rule_idx++;
1240             vec_validate_macip_acl_rules(rules, rule_idx);
1241           }
1242         else
1243     break;
1244     }
1245
1246     /* Construct the API message */
1247     vam->result_ready = 0;
1248
1249     if(rules)
1250       n_rules = vec_len(rules);
1251
1252     if (n_rules_override >= 0)
1253       n_rules = n_rules_override;
1254
1255     msg_size += n_rules*sizeof(rules[0]);
1256
1257     mp = vl_msg_api_alloc_as_if_client(msg_size);
1258     clib_memset (mp, 0, msg_size);
1259     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD + sm->msg_id_base);
1260     mp->client_index = vam->my_client_index;
1261     if ((n_rules > 0) && rules)
1262       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1263     if (tag)
1264       {
1265         if (vec_len(tag) >= sizeof(mp->tag))
1266           {
1267             tag[sizeof(mp->tag)-1] = 0;
1268             _vec_len(tag) = sizeof(mp->tag);
1269           }
1270         clib_memcpy(mp->tag, tag, vec_len(tag));
1271         vec_free(tag);
1272       }
1273
1274     mp->count = htonl(n_rules);
1275
1276     /* send it... */
1277     S(mp);
1278
1279     /* Wait for a reply... */
1280     W (ret);
1281     return ret;
1282 }
1283
1284 static int api_macip_acl_add_replace (vat_main_t * vam)
1285 {
1286     acl_test_main_t * sm = &acl_test_main;
1287     unformat_input_t * i = vam->input;
1288     vl_api_macip_acl_add_replace_t * mp;
1289     u32 acl_index = ~0;
1290     u32 msg_size = sizeof (*mp); /* without the rules */
1291
1292     vl_api_macip_acl_rule_t *rules = 0;
1293     int rule_idx = 0;
1294     int n_rules = 0;
1295     int n_rules_override = -1;
1296     u32 src_prefix_length = 0;
1297     u32 action = 0;
1298     ip4_address_t src_v4address;
1299     ip6_address_t src_v6address;
1300     u8 src_mac[6];
1301     u8 *tag = 0;
1302     u8 mac_mask_all_1[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1303     int ret;
1304
1305     if (!unformat (i, "%d", &acl_index)) {
1306         /* Just assume -1 */
1307     }
1308
1309     while (unformat_check_input (i) != UNFORMAT_END_OF_INPUT)
1310     {
1311         if (unformat (i, "permit"))
1312           {
1313             vec_validate_macip_acl_rules(rules, rule_idx);
1314             rules[rule_idx].is_permit = 1;
1315           }
1316         else if (unformat (i, "deny"))
1317           {
1318             vec_validate_macip_acl_rules(rules, rule_idx);
1319             rules[rule_idx].is_permit = 0;
1320           }
1321         else if (unformat (i, "count %d", &n_rules_override))
1322           {
1323             /* we will use this later */
1324           }
1325         else if (unformat (i, "action %d", &action))
1326           {
1327             vec_validate_macip_acl_rules(rules, rule_idx);
1328             rules[rule_idx].is_permit = action;
1329           }
1330         else if (unformat (i, "ip %U/%d",
1331             unformat_ip4_address, &src_v4address, &src_prefix_length) ||
1332                    unformat (i, "ip %U",
1333             unformat_ip4_address, &src_v4address))
1334           {
1335               if (src_prefix_length == 0)
1336                 src_prefix_length = 32;
1337               vec_validate_macip_acl_rules(rules, rule_idx);
1338               memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v4address, 4);
1339               rules[rule_idx].src_prefix.address.af = ADDRESS_IP4;
1340               rules[rule_idx].src_prefix.len = src_prefix_length;
1341           }
1342         else if (unformat (i, "src"))
1343           {
1344               /* Everything in MACIP is "source" but allow this verbosity */
1345           }
1346         else if (unformat (i, "ip %U/%d",
1347            unformat_ip6_address, &src_v6address, &src_prefix_length) ||
1348                    unformat (i, "ip %U",
1349            unformat_ip6_address, &src_v6address))
1350           {
1351             if (src_prefix_length == 0)
1352              src_prefix_length = 128;
1353             vec_validate_macip_acl_rules(rules, rule_idx);
1354             memcpy (rules[rule_idx].src_prefix.address.un.ip4, &src_v6address, 4);
1355             rules[rule_idx].src_prefix.address.af = ADDRESS_IP6;
1356             rules[rule_idx].src_prefix.len = src_prefix_length;
1357           }
1358         else if (unformat (i, "mac %U",
1359          my_unformat_mac_address, &src_mac))
1360           {
1361             vec_validate_macip_acl_rules(rules, rule_idx);
1362             memcpy (rules[rule_idx].src_mac, &src_mac, 6);
1363             memcpy (rules[rule_idx].src_mac_mask, &mac_mask_all_1, 6);
1364           }
1365         else if (unformat (i, "mask %U",
1366          my_unformat_mac_address, &src_mac))
1367           {
1368             vec_validate_macip_acl_rules(rules, rule_idx);
1369             memcpy (rules[rule_idx].src_mac_mask, &src_mac, 6);
1370           }
1371         else if (unformat (i, "tag %s", &tag))
1372           {
1373           }
1374         else if (unformat (i, ","))
1375           {
1376             rule_idx++;
1377             vec_validate_macip_acl_rules(rules, rule_idx);
1378           }
1379         else
1380     break;
1381     }
1382
1383     if (!rules)
1384       {
1385       errmsg ("rule/s required\n");
1386       return -99;
1387       }
1388     /* Construct the API message */
1389     vam->result_ready = 0;
1390
1391     if(rules)
1392       n_rules = vec_len(rules);
1393
1394     if (n_rules_override >= 0)
1395       n_rules = n_rules_override;
1396
1397     msg_size += n_rules*sizeof(rules[0]);
1398
1399     mp = vl_msg_api_alloc_as_if_client(msg_size);
1400     clib_memset (mp, 0, msg_size);
1401     mp->_vl_msg_id = ntohs (VL_API_MACIP_ACL_ADD_REPLACE + sm->msg_id_base);
1402     mp->client_index = vam->my_client_index;
1403     if ((n_rules > 0) && rules)
1404       clib_memcpy(mp->r, rules, n_rules*sizeof (mp->r[0]));
1405     if (tag)
1406       {
1407         if (vec_len(tag) >= sizeof(mp->tag))
1408           {
1409             tag[sizeof(mp->tag)-1] = 0;
1410             _vec_len(tag) = sizeof(mp->tag);
1411           }
1412         clib_memcpy(mp->tag, tag, vec_len(tag));
1413         vec_free(tag);
1414       }
1415
1416     mp->acl_index = ntohl(acl_index);
1417     mp->count = htonl(n_rules);
1418
1419     /* send it... */
1420     S(mp);
1421
1422     /* Wait for a reply... */
1423     W (ret);
1424     return ret;
1425 }
1426
1427 #define VL_API_LOCAL_SETUP_MESSAGE_ID_TABLE local_setup_message_id_table
1428 static void local_setup_message_id_table (vat_main_t * vam)
1429 {
1430   hash_set_mem (vam->function_by_name, "acl_add_replace_from_file", api_acl_add_replace_from_file);
1431   hash_set_mem (vam->help_by_name, "acl_add_replace_from_file",
1432                 "filename <file> [permit] [append-default-permit]");
1433 }
1434
1435 #include <acl/acl.api_test.c>