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