Merge "Initial support for DPDK 18.05"
[samplevnf.git] / VNFs / DPPD-PROX / prox_lua_types.c
1 /*
2 // Copyright (c) 2010-2017 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include <lua.h>
18 #include <lauxlib.h>
19 #include <lualib.h>
20
21 #include <string.h>
22 #include <rte_ether.h>
23 #include <rte_lpm.h>
24 #include <rte_lpm6.h>
25 #include <rte_acl.h>
26 #include <rte_version.h>
27 #include <rte_hash_crc.h>
28
29 #include "prox_malloc.h"
30 #include "etypes.h"
31 #include "prox_lua.h"
32 #include "log.h"
33 #include "quit.h"
34 #include "defines.h"
35 #include "prox_globals.h"
36 #include "prox_lua_types.h"
37 #include "ip_subnet.h"
38 #include "hash_entry_types.h"
39 #include "handle_qinq_encap4.h"
40 #include "toeplitz.h"
41 #include "handle_lb_5tuple.h"
42
43 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
44 #define RTE_CACHE_LINE_SIZE CACHE_LINE_SIZE
45 #endif
46
47 static char error_str[1024];
48 static char *cur_pos;
49
50 const char *get_lua_to_errors(void)
51 {
52         return error_str;
53 }
54
55 static void null_terminate_error(void)
56 {
57         size_t diff = cur_pos - error_str;
58
59         if (diff >= sizeof(error_str) &&
60             error_str[sizeof(error_str) - 1] != 0)
61                 error_str[sizeof(error_str) - 1] = 0;
62 }
63
64 __attribute__((format(printf, 1, 2))) static void set_err(const char *fmt, ...)
65 {
66         va_list ap;
67         va_start(ap, fmt);
68
69         cur_pos = error_str;
70         cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
71         null_terminate_error();
72
73         va_end(ap);
74 }
75
76 __attribute__((format(printf, 1, 2))) static void concat_err(const char *fmt, ...)
77 {
78         va_list ap;
79         va_start(ap, fmt);
80
81         cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
82         null_terminate_error();
83
84         va_end(ap);
85 }
86
87 /* Make sure that an element is on the top of the stack (zero on success) */
88 int lua_getfrom(struct lua_State *L, enum lua_place from, const char *name)
89 {
90         switch (from) {
91         case STACK:
92                 return lua_gettop(L) > 0? 0 : -1;
93         case TABLE:
94                 if (!lua_istable(L, -1)) {
95                         set_err("Failed to get field '%s' from table (no table)\n", name);
96                         return -1;
97                 }
98
99                 lua_pushstring(L, name);
100                 lua_gettable(L, -2);
101                 if (lua_isnil(L, -1)) {
102                         set_err("Field '%s' is missing from table\n", name);
103                         lua_pop(L, 1);
104                         return -1;
105                 }
106                 return 1;
107         case GLOBAL:
108                 lua_getglobal(L, name);
109                 if (lua_isnil(L, -1)) {
110                         set_err("Couldn't find global data '%s'\n", name);
111                         lua_pop(L, 1);
112                         return -1;
113                 }
114                 return 1;
115         }
116         return -1;
117 }
118
119 int lua_to_ip(struct lua_State *L, enum lua_place from, const char *name, uint32_t *ip)
120 {
121         uint32_t n_entries;
122         uint32_t ip_array[4];
123         ptrdiff_t v;
124         int pop;
125
126         if ((pop = lua_getfrom(L, from, name)) < 0)
127                 return -1;
128
129         lua_len(L, -1);
130         n_entries = lua_tointeger(L, -1);
131         lua_pop(L, 1);
132
133         if (n_entries != 4) {
134                 set_err("Invalid IPv4 format\n");
135                 return -1;
136         }
137
138         *ip = 0;
139         for (int i = 0; i < 4; ++i) {
140                 lua_pushinteger(L, i + 1);
141                 lua_gettable(L, -2);
142                 v = lua_tointeger(L, -1);
143                 lua_pop(L, 1);
144                 if (!(v >= 0 && v <= 255)) {
145                         set_err("Invalid IPv4 format\n");
146                         return -1;
147                 }
148                 *ip |= v << (24 - i*8);
149         }
150
151         lua_pop(L, pop);
152         return 0;
153 }
154
155 int lua_to_ip6(struct lua_State *L, enum lua_place from, const char *name, uint8_t *ip)
156 {
157         uint32_t n_entries;
158         ptrdiff_t v;
159         int pop;
160
161         if ((pop = lua_getfrom(L, from, name)) < 0)
162                 return -1;
163
164         lua_len(L, -1);
165         n_entries = lua_tointeger(L, -1);
166         lua_pop(L, 1);
167
168         if (n_entries != 16) {
169                 set_err("Invalid IPv6 format\n");
170                 return -1;
171         }
172
173         for (int i = 0; i < 16; ++i) {
174                 lua_pushinteger(L, i + 1);
175                 lua_gettable(L, -2);
176                 v = lua_tointeger(L, -1);
177                 lua_pop(L, 1);
178                 ip[i] = v;
179         }
180
181         lua_pop(L, pop);
182         return 0;
183 }
184
185 int lua_to_mac(struct lua_State *L, enum lua_place from, const char *name, struct ether_addr *mac)
186 {
187         uint32_t n_entries;
188         uint32_t mac_array[4];
189         ptrdiff_t v;
190         int pop;
191
192         if ((pop = lua_getfrom(L, from, name)) < 0)
193                 return -1;
194
195         lua_len(L, -1);
196         n_entries = lua_tointeger(L, -1);
197         lua_pop(L, 1);
198
199         if (n_entries != 6) {
200                 set_err("Invalid MAC format\n");
201                 return -1;
202         }
203
204         for (int i = 0; i < 6; ++i) {
205                 lua_pushinteger(L, i + 1);
206                 lua_gettable(L, -2);
207                 v = lua_tointeger(L, -1);
208                 lua_pop(L, 1);
209                 if (!(v >= 0 && v <= 255)) {
210                         set_err("Invalid MAC format\n");
211                         return -1;
212                 }
213                 mac->addr_bytes[i] = v;
214         }
215
216         lua_pop(L, pop);
217         return 0;
218 }
219
220 int lua_to_cidr(struct lua_State *L, enum lua_place from, const char *name, struct ip4_subnet *cidr)
221 {
222         uint32_t depth, ip;
223         int pop;
224
225         if ((pop = lua_getfrom(L, from, name)) < 0)
226                 return -1;
227
228         if (!lua_istable(L, -1)) {
229                 set_err("CIDR is not a table\n");
230                 return -1;
231         }
232
233         if (lua_to_ip(L, TABLE, "ip", &ip) ||
234             lua_to_int(L, TABLE, "depth", &depth)) {
235                 return -1;
236         }
237         cidr->ip = ip;
238         cidr->prefix = depth;
239
240         lua_pop(L, pop);
241         return 0;
242 }
243
244 int lua_to_cidr6(struct lua_State *L, enum lua_place from, const char *name, struct ip6_subnet *cidr)
245 {
246         uint32_t depth;
247         int pop;
248
249         if ((pop = lua_getfrom(L, from, name)) < 0)
250                 return -1;
251
252         if (!lua_istable(L, -1)) {
253                 set_err("CIDR6 is not a table\n");
254                 return -1;
255         }
256
257         if (lua_to_ip6(L, TABLE, "ip6", cidr->ip) ||
258             lua_to_int(L, TABLE, "depth", &depth)) {
259                 return -1;
260         }
261         cidr->prefix = depth;
262
263         lua_pop(L, pop);
264         return 0;
265 }
266
267 int lua_to_val_mask(struct lua_State *L, enum lua_place from, const char *name, struct val_mask *val_mask)
268 {
269         int pop;
270
271         if ((pop = lua_getfrom(L, from, name)) < 0)
272                 return -1;
273
274         if (!lua_istable(L, -1)) {
275                 set_err("data entry is not a table\n");
276                 return -1;
277         }
278
279         if (lua_to_int(L, TABLE, "val", &val_mask->val) ||
280             lua_to_int(L, TABLE, "mask", &val_mask->mask))
281                 return -1;
282
283         lua_pop(L, pop);
284         return 0;
285 }
286
287 int lua_to_val_range(struct lua_State *L, enum lua_place from, const char *name, struct val_range *val_range)
288 {
289         int pop;
290
291         if ((pop = lua_getfrom(L, from, name)) < 0)
292                 return -1;
293
294         if (!lua_istable(L, -1)) {
295                 set_err("data entry is not a table\n");
296                 return -1;
297         }
298
299         if (lua_to_int(L, TABLE, "beg", &val_range->beg) ||
300             lua_to_int(L, TABLE, "end", &val_range->end))
301                 return -1;
302
303         lua_pop(L, pop);
304         return 0;
305 }
306
307 int lua_to_action(struct lua_State *L, enum lua_place from, const char *name, enum acl_action *action)
308 {
309         int pop;
310
311         if ((pop = lua_getfrom(L, from, name)) < 0)
312                 return -1;
313
314         if (!lua_isstring(L, -1)) {
315                 set_err("data entry is not a table\n");
316                 return -1;
317         }
318
319         const char *s = lua_tostring(L, -1);
320
321         if (!strcmp(s, "drop"))
322                 *action = ACL_DROP;
323         else if (!strcmp(s, "allow"))
324                 *action = ACL_ALLOW;
325         else if (!strcmp(s, "rate_limit"))
326                 *action = ACL_RATE_LIMIT;
327         else
328                 return -1;
329
330         lua_pop(L, pop);
331         return 0;
332 }
333
334 int lua_to_string(struct lua_State *L, enum lua_place from, const char *name, char *dst, size_t size)
335 {
336         const char *str;
337         int pop;
338
339         if ((pop = lua_getfrom(L, from, name)) < 0)
340                 return -1;
341
342         if (!lua_isstring(L, -1)) {
343                 plog_err("data is not an integer\n");
344                 return -1;
345         }
346         str = lua_tostring(L, -1);
347
348         strncpy(dst, str, size);
349
350         lua_pop(L, pop);
351         return 0;
352 }
353
354 int lua_to_port(struct lua_State *L, enum lua_place from, const char *name, uint16_t *port)
355 {
356         double tmp = 0;
357         int ret;
358
359         ret = lua_to_double(L, from, name, &tmp);
360         if (ret == 0)
361                 *port = tmp;
362         return ret;
363 }
364
365 int lua_to_int(struct lua_State *L, enum lua_place from, const char *name, uint32_t *val)
366 {
367         double tmp = 0;
368         int ret;
369
370         ret = lua_to_double(L, from, name, &tmp);
371         if (ret == 0)
372                 *val = tmp;
373         return ret;
374 }
375
376 int lua_to_double(struct lua_State *L, enum lua_place from, const char *name, double *val)
377 {
378         int pop;
379
380         if ((pop = lua_getfrom(L, from, name)) < 0)
381                 return -1;
382
383         if (!lua_isnumber(L, -1)) {
384                 set_err("data is not a number\n");
385                 return -1;
386         }
387         *val = lua_tonumber(L, -1);
388
389         lua_pop(L, pop);
390         return 0;
391 }
392
393 int lua_to_routes4_entry(struct lua_State *L, enum lua_place from, const char *name, struct ip4_subnet *cidr, uint32_t *nh_idx)
394 {
395         int pop;
396
397         if ((pop = lua_getfrom(L, from, name)) < 0)
398                 return -1;
399
400         if (!lua_istable(L, -1)) {
401                 set_err("Can't read routes4 entry since data is not a table\n");
402                 return -1;
403         }
404
405         if (lua_to_cidr(L, TABLE, "cidr", cidr) ||
406             lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
407                 return -1;
408         }
409
410         lua_pop(L, pop);
411         return 0;
412 }
413
414 int lua_to_next_hop(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop **nh)
415 {
416         struct next_hop *ret;
417         uint32_t next_hop_index;
418         uint32_t port_id;
419         uint32_t ip;
420         uint32_t mpls;
421         struct ether_addr mac;
422         int pop;
423
424         if ((pop = lua_getfrom(L, from, name)) < 0)
425                 return -1;
426
427         if (!lua_istable(L, -1)) {
428                 set_err("Can't read next hop since data is not a table\n");
429                 return -1;
430         }
431
432         ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
433         PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
434
435         lua_pushnil(L);
436         while (lua_next(L, -2)) {
437                 if (lua_to_int(L, TABLE, "id", &next_hop_index) ||
438                     lua_to_int(L, TABLE, "port_id", &port_id) ||
439                     lua_to_ip(L, TABLE, "ip", &ip) ||
440                     lua_to_mac(L, TABLE, "mac", &mac) ||
441                     lua_to_int(L, TABLE, "mpls", &mpls))
442                         return -1;
443
444                 PROX_PANIC(port_id >= PROX_MAX_PORTS, "Port id too high (only supporting %d ports)\n", PROX_MAX_PORTS);
445                 PROX_PANIC(next_hop_index >= MAX_HOP_INDEX, "Next-hop to high (only supporting %d next hops)\n", MAX_HOP_INDEX);
446
447                 ret[next_hop_index].mac_port.out_idx = port_id;
448                 ret[next_hop_index].ip_dst = ip;
449
450                 ret[next_hop_index].mac_port.mac = mac;
451                 ret[next_hop_index].mpls = mpls;
452
453                 lua_pop(L, 1);
454         }
455
456         *nh = ret;
457         lua_pop(L, pop);
458         return 0;
459 }
460
461 int lua_to_next_hop6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop6 **nh)
462 {
463         struct next_hop6 *ret;
464         uint32_t next_hop_index, port_id, mpls;
465         struct ether_addr mac;
466         uint8_t ip[16];
467         int pop;
468
469         if ((pop = lua_getfrom(L, from, name)) < 0)
470                 return -1;
471
472         if (!lua_istable(L, -1)) {
473                 set_err("Data is not a table\n");
474                 return -1;
475         }
476
477         ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
478         PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
479
480         lua_pushnil(L);
481         while (lua_next(L, -2)) {
482                 if (lua_to_int(L, TABLE, "id", &next_hop_index) ||
483                     lua_to_int(L, TABLE, "port_id", &port_id) ||
484                     lua_to_ip6(L, TABLE, "ip6", ip) ||
485                     lua_to_mac(L, TABLE, "mac", &mac) ||
486                     lua_to_int(L, TABLE, "mpls", &mpls))
487                         return -1;
488
489                 PROX_PANIC(port_id >= PROX_MAX_PORTS, "Port id too high (only supporting %d ports)\n", PROX_MAX_PORTS);
490                 PROX_PANIC(next_hop_index >= MAX_HOP_INDEX, "Next-hop to high (only supporting %d next hops)\n", MAX_HOP_INDEX);
491
492                 ret[next_hop_index].mac_port.out_idx = port_id;
493                 memcpy(ret[next_hop_index].ip_dst,ip, 16);
494
495                 ret[next_hop_index].mac_port.mac = mac;
496                 ret[next_hop_index].mpls = mpls;
497
498                 lua_pop(L, 1);
499         }
500
501         *nh = ret;
502         lua_pop(L, pop);
503         return 0;
504 }
505
506 int lua_to_routes4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 *lpm)
507 {
508         struct ip4_subnet dst;
509         uint32_t next_hop_index;
510         uint32_t n_loaded_rules;
511         uint32_t n_tot_rules;
512         struct rte_lpm *new_lpm;
513         char lpm_name[64];
514         int ret;
515         int pop;
516
517         if ((pop = lua_getfrom(L, from, name)) < 0)
518                 return -1;
519
520         snprintf(lpm_name, sizeof(lpm_name), "IPv4_lpm_s%u", socket);
521
522         if (!lua_istable(L, -1)) {
523                 set_err("Data is not a table\n");
524                 return -1;
525         }
526
527         lua_len(L, -1);
528         n_tot_rules = lua_tointeger(L, -1);
529         n_loaded_rules = 0;
530         lua_pop(L, 1);
531 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,1)
532         struct rte_lpm_config conf;
533         conf.max_rules = 2 * n_tot_rules;
534         conf.number_tbl8s = 256;
535         conf.flags = 0;
536         new_lpm = rte_lpm_create(lpm_name, socket, &conf);
537 #else
538         new_lpm = rte_lpm_create(lpm_name, socket, 2 * n_tot_rules, 0);
539 #endif
540         PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
541
542         lua_pushnil(L);
543         while (lua_next(L, -2)) {
544                 if (lua_to_routes4_entry(L, STACK, NULL, &dst, &next_hop_index)) {
545                         set_err("Failed to read entry while setting up lpm\n");
546                         return -1;
547                 }
548                 ret = rte_lpm_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
549
550                 if (ret != 0) {
551                         set_err("Failed to add (%d) index %u ip %x/%u to lpm\n",
552                                  ret, next_hop_index, dst.ip, dst.prefix);
553                 }
554                 else if (++n_loaded_rules % 10000 == 0) {
555                         plog_info("Route %d added\n", n_loaded_rules);
556                 }
557
558                 lua_pop(L, 1);
559         }
560
561         lpm->rte_lpm = new_lpm;
562         lpm->n_used_rules = n_loaded_rules;
563         lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
564
565         lua_pop(L, pop);
566         return 0;
567 }
568
569 int lua_to_lpm4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 **lpm)
570 {
571         struct lpm4 *ret;
572         int pop;
573
574         if ((pop = lua_getfrom(L, from, name)) < 0)
575                 return -1;
576
577         ret = prox_zmalloc(sizeof(struct lpm4), socket);
578
579         if (!lua_istable(L, -1)) {
580                 set_err("Can't read lpm4 since data is not a table\n");
581                 return -1;
582         }
583
584         if (lua_to_routes4(L, TABLE, "routes", socket, ret) ||
585             lua_to_next_hop(L, TABLE, "next_hops", socket, &ret->next_hops)) {
586                 return -1;
587         }
588
589         if (ret->rte_lpm)
590                 plog_info("Loaded %d routes\n", ret->n_used_rules);
591
592         *lpm = ret;
593         lua_pop(L, pop);
594         return 0;
595 }
596
597 int lua_to_lpm6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 **lpm)
598 {
599         struct lpm6 *ret;
600         int pop;
601
602         if ((pop = lua_getfrom(L, from, name)) < 0)
603                 return -1;
604
605         if (!lua_istable(L, -1)) {
606                 set_err("Lpm6 is not a table\n");
607                 return -1;
608         }
609
610         ret = prox_zmalloc(sizeof(struct lpm6), socket);
611
612         if (lua_to_routes6(L, TABLE, "routes6", socket, ret) ||
613             lua_to_next_hop6(L, TABLE, "next_hops6", socket, &ret->next_hops))
614                 return -1;
615
616         if (ret->rte_lpm6)
617                 plog_info("Loaded %d routes\n", ret->n_used_rules);
618
619         *lpm = ret;
620
621         lua_pop(L, pop);
622         return 0;
623 }
624
625 static int lua_to_lpm6_entry(struct lua_State *L, enum lua_place from, const char *name, struct ip6_subnet *cidr, uint32_t *nh_idx)
626 {
627         int pop;
628
629         if ((pop = lua_getfrom(L, from, name)) < 0)
630                 return -1;
631
632         if (!lua_istable(L, -1)) {
633                 set_err("lpm6 entry is not a table\n");
634                 return -1;
635         }
636         if (lua_to_cidr6(L, TABLE, "cidr6", cidr) ||
637             lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
638                 return -1;
639         }
640
641         lua_pop(L, pop);
642         return 0;
643 }
644
645 int lua_to_routes6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 *lpm)
646 {
647         struct ip6_subnet dst;
648         uint32_t next_hop_index;
649         uint32_t n_loaded_rules;
650         struct rte_lpm6 *new_lpm;
651         struct rte_lpm6_config config;
652         uint32_t n_tot_rules;
653         char lpm_name[64];
654         int ret;
655         int pop;
656
657         if ((pop = lua_getfrom(L, from, name)) < 0)
658                 return -1;
659
660         snprintf(lpm_name, sizeof(lpm_name), "IPv6_lpm_s%u", socket);
661
662         if (!lua_istable(L, -1)) {
663                 set_err("Data is not a table\n");
664                 return -1;
665         }
666
667         lua_len(L, -1);
668         n_tot_rules = lua_tointeger(L, -1);
669         n_loaded_rules = 0;
670         lua_pop(L, 1);
671
672         config.max_rules = n_tot_rules;
673         config.number_tbl8s = (1 << 16);
674         config.flags = 0;
675
676         new_lpm = rte_lpm6_create(lpm_name, socket, &config);
677         PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
678
679         lua_pushnil(L);
680         while (lua_next(L, -2)) {
681
682                 if (lua_to_lpm6_entry(L, STACK, NULL, &dst, &next_hop_index)) {
683                         concat_err("Failed to read entry while setting up lpm\n");
684                         return -1;
685                 }
686
687                 ret = rte_lpm6_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
688
689                 if (ret != 0) {
690                         plog_warn("Failed to add (%d) index %u, %d\n",
691                                   ret, next_hop_index, dst.prefix);
692                 }
693                 else if (++n_loaded_rules % 10000 == 0) {
694                         plog_info("Route %d added\n", n_loaded_rules);
695                 }
696
697                 lua_pop(L, 1);
698         }
699
700         lpm->rte_lpm6 = new_lpm;
701         lpm->n_used_rules = n_loaded_rules;
702         lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
703
704         lua_pop(L, pop);
705         return 0;
706 }
707
708 int lua_to_dscp(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint8_t **dscp)
709 {
710         int pop;
711
712         if ((pop = lua_getfrom(L, from, name)) < 0)
713                 return -1;
714
715         if (!lua_istable(L, -1)) {
716                 set_err("DSCP is not a table\n");
717                 return -1;
718         }
719
720         uint32_t dscp_bits, tc, queue;
721         int status;
722         *dscp = prox_zmalloc(64, socket);
723         PROX_PANIC(dscp == NULL, "Error creating dscp table");
724
725         lua_pushnil(L);
726         while (lua_next(L, -2)) {
727                 if (lua_to_int(L, TABLE, "dscp", &dscp_bits) ||
728                     lua_to_int(L, TABLE, "tc", &tc) ||
729                     lua_to_int(L, TABLE, "queue", &queue)) {
730                         concat_err("Failed to read dscp config\n");
731                         return -1;
732                 }
733
734                 lua_pop(L, 1);
735
736                 (*dscp)[dscp_bits] = tc << 2 | queue;
737         }
738
739         lua_pop(L, pop);
740         return 0;
741 }
742
743 int lua_to_qinq_gre_map(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct qinq_gre_map **qinq_gre_map)
744 {
745         int pop;
746
747         if ((pop = lua_getfrom(L, from, name)) < 0)
748                 return -1;
749
750         if (!lua_istable(L, -1)) {
751                 if (from != STACK)
752                         set_err("QinQ to gre map is not a table\n");
753                 else
754                         set_err("QinQ to gre map %s is not a table\n", name);
755                 return -1;
756         }
757
758         struct qinq_gre_map *ret;
759         uint32_t svlan, cvlan;
760         uint16_t be_svlan, be_cvlan;
761         uint32_t user;
762         uint32_t gre_id;
763
764         uint32_t n_entries;
765         uint32_t idx = 0;
766
767         lua_len(L, -1);
768         n_entries = lua_tointeger(L, -1);
769         lua_pop(L, 1);
770
771         size_t mem_size = 0;
772         mem_size += sizeof(struct qinq_gre_map);
773         mem_size += n_entries * sizeof(struct qinq_gre_entry);
774
775         ret = prox_zmalloc(mem_size, socket);
776         PROX_PANIC(ret == NULL, "Error creating gre_qinq map");
777
778         ret->count = n_entries;
779
780         lua_pushnil(L);
781         while (lua_next(L, -2)) {
782
783                 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
784                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
785                     lua_to_int(L, TABLE, "gre_id", &gre_id) ||
786                     lua_to_int(L, TABLE, "user_id", &user)) {
787                         concat_err("Failed to read user table config\n");
788                         return -1;
789                 }
790
791                 be_svlan = rte_bswap16((uint16_t)svlan);
792                 be_cvlan = rte_bswap16((uint16_t)cvlan);
793
794                 ret->entries[idx].user = user;
795                 ret->entries[idx].svlan = be_svlan;
796                 ret->entries[idx].cvlan = be_cvlan;
797                 ret->entries[idx].gre_id = gre_id;
798                 ret->entries[idx].rss = toeplitz_hash((uint8_t *)&be_cvlan, 4);
799
800                 plog_dbg("elem %u: be_svlan=%x, be_cvlan=%x, rss_input=%x, rss=%x, gre_id=%x\n",
801                          idx, be_svlan, be_cvlan, be_cvlan, ret->entries[idx].rss, gre_id);
802
803                 idx++;
804                 lua_pop(L, 1);
805         }
806
807         *qinq_gre_map = ret;
808
809         lua_pop(L, pop);
810         return 0;
811 }
812
813 int lua_to_user_table(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint16_t **user_table)
814 {
815         int pop;
816
817         if ((pop = lua_getfrom(L, from, name)) < 0)
818                 return -1;
819
820         if (!lua_istable(L, -1)) {
821                 set_err("Data is not a table\n");
822                 return -1;
823         }
824
825         uint32_t svlan, cvlan;
826         uint16_t be_svlan, be_cvlan;
827         uint32_t user;
828
829         *user_table = prox_zmalloc(0x1000000 * sizeof(uint16_t), socket);
830         PROX_PANIC(*user_table == NULL, "Error creating user table");
831
832         lua_pushnil(L);
833         while (lua_next(L, -2)) {
834                 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
835                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
836                     lua_to_int(L, TABLE, "user_id", &user)) {
837                         concat_err("Failed to read user table config\n");
838                         return -1;
839                 }
840
841                 be_svlan = rte_bswap16((uint16_t)svlan);
842                 be_cvlan = rte_bswap16((uint16_t)cvlan);
843
844                 (*user_table)[PKT_TO_LUTQINQ(be_svlan, be_cvlan)] = user;
845
846                 lua_pop(L, 1);
847         }
848
849         lua_pop(L, pop);
850         return 0;
851 }
852
853 int lua_to_ip6_tun_binding(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct ipv6_tun_binding_table **data)
854 {
855         struct ipv6_tun_binding_table *ret;
856         uint32_t n_entries;
857         uint32_t idx = 0;
858         uint32_t port = 0;
859         size_t memsize = 0;
860         int pop;
861
862         if ((pop = lua_getfrom(L, from, name)) < 0)
863                 return -1;
864
865         if (!lua_istable(L, -1)) {
866                 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
867                 return -1;
868         }
869
870         lua_len(L, -1);
871         n_entries = lua_tointeger(L, -1);
872         lua_pop(L, 1);
873
874         memsize = sizeof(struct ipv6_tun_binding_table);
875         memsize += n_entries * sizeof(struct ipv6_tun_binding_entry);
876
877         ret = prox_zmalloc(memsize, socket);
878
879         lua_pushnil(L);
880         while (lua_next(L, -2)) {
881                 if (lua_to_ip6(L, TABLE, "ip6", ret->entry[idx].endpoint_addr.bytes) ||
882                     lua_to_mac(L, TABLE, "mac", &ret->entry[idx].next_hop_mac) ||
883                     lua_to_ip(L, TABLE, "ip", &ret->entry[idx].public_ipv4) ||
884                     lua_to_int(L, TABLE, "port", &port))
885                         return -1;
886
887                 ret->entry[idx].public_port = port;
888                 idx++;
889                 lua_pop(L, 1);
890         }
891         ret->num_binding_entries = idx;
892
893         plog_info("\tRead %d IPv6 Tunnel Binding entries\n", idx);
894
895         *data = ret;
896
897         lua_pop(L, pop);
898         return 0;
899 }
900
901 int lua_to_cpe_table_data(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct cpe_table_data **data)
902 {
903         struct cpe_table_data *ret;
904         int pop;
905
906         if ((pop = lua_getfrom(L, from, name)) < 0)
907                 return -1;
908
909         if (!lua_istable(L, -1)) {
910                 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
911                 return -1;
912         }
913
914         /* Each entry in the input table expands to multiple entries
915            depending on the number of hosts within the subnet. For
916            this reason, go through the whole table and find out how
917            many entries will be added in total. */
918         struct ip4_subnet cidr;
919         uint32_t n_entries = 0;
920         uint32_t port_idx, gre_id, svlan, cvlan, user;
921         struct ether_addr mac;
922         uint32_t idx = 0;
923
924         lua_pushnil(L);
925         while (lua_next(L, -2)) {
926                 if (lua_to_cidr(L, TABLE, "cidr", &cidr))
927                         return -1;
928                 n_entries += ip4_subet_get_n_hosts(&cidr);
929                 lua_pop(L, 1);
930         }
931
932         ret = prox_zmalloc(sizeof(*ret) + n_entries * sizeof(struct cpe_table_entry), 0);
933
934         lua_pushnil(L);
935         while (lua_next(L, -2)) {
936                 if (lua_to_int(L, TABLE, "dest_id", &port_idx) ||
937                     lua_to_int(L, TABLE, "gre_id", &gre_id) ||
938                     lua_to_int(L, TABLE, "svlan_id", &svlan) ||
939                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
940                     lua_to_cidr(L, TABLE, "cidr", &cidr) ||
941                     lua_to_mac(L, TABLE, "mac", &mac) ||
942                     lua_to_int(L, TABLE, "user_id", &user))
943                         return -1;
944
945                 uint32_t n_hosts = ip4_subet_get_n_hosts(&cidr);
946
947                 for (uint32_t i = 0; i < n_hosts; ++i) {
948                         ret->entries[idx].port_idx = port_idx;
949                         ret->entries[idx].gre_id = gre_id;
950                         ret->entries[idx].svlan = rte_bswap16(svlan);
951                         ret->entries[idx].cvlan = rte_bswap16(cvlan);
952                         ret->entries[idx].eth_addr = mac;
953                         ret->entries[idx].user = user;
954
955                         PROX_PANIC(ip4_subnet_to_host(&cidr, i, &ret->entries[idx].ip), "Invalid host in address\n");
956                         ret->entries[idx].ip = rte_bswap32(ret->entries[idx].ip);
957                         idx++;
958                 }
959
960                 lua_pop(L, 1);
961         }
962
963         ret->n_entries = n_entries;
964         *data = ret;
965
966         lua_pop(L, pop);
967         return 0;
968 }
969
970 struct acl4_rule {
971         struct rte_acl_rule_data data;
972         struct rte_acl_field fields[9];
973 };
974
975 int lua_to_rules(struct lua_State *L, enum lua_place from, const char *name, struct rte_acl_ctx *ctx, uint32_t* n_max_rules, int use_qinq, uint16_t qinq_tag)
976 {
977         int pop;
978
979         if ((pop = lua_getfrom(L, from, name)) < 0)
980                 return -1;
981
982         if (!lua_istable(L, -1)) {
983                 set_err("Can't read rules since data is not a table\n");
984                 return -1;
985         }
986
987         struct val_mask svlan, cvlan, ip_proto;
988         struct ip4_subnet src_cidr, dst_cidr;
989         struct val_range sport, dport;
990         enum acl_action action;
991         uint32_t n_rules = 0;
992         lua_pushnil(L);
993         while (lua_next(L, -2)) {
994                 if (n_rules == *n_max_rules) {
995                         set_err("Too many rules");
996                         return -1;
997                 }
998                 if (use_qinq) {
999                         if (lua_to_val_mask(L, TABLE, "svlan_id", &svlan) ||
1000                             lua_to_val_mask(L, TABLE, "cvlan_id", &cvlan))
1001                                 return -1;
1002                 }
1003
1004                 if (lua_to_val_mask(L, TABLE, "ip_proto", &ip_proto) ||
1005                     lua_to_cidr(L, TABLE, "src_cidr", &src_cidr) ||
1006                     lua_to_cidr(L, TABLE, "dst_cidr", &dst_cidr) ||
1007                     lua_to_val_range(L, TABLE, "sport", &sport) ||
1008                     lua_to_val_range(L, TABLE, "dport", &dport) ||
1009                     lua_to_action(L, TABLE, "action", &action))
1010                         return -1;
1011
1012                 struct acl4_rule rule;
1013
1014                 rule.data.userdata = action; /* allow, drop or rate_limit */
1015                 rule.data.category_mask = 1;
1016                 rule.data.priority = n_rules++;
1017
1018                 /* Configuration for rules is done in little-endian so no bswap is needed here.. */
1019
1020                 rule.fields[0].value.u8 = ip_proto.val;
1021                 rule.fields[0].mask_range.u8 = ip_proto.mask;
1022                 rule.fields[1].value.u32 = src_cidr.ip;
1023                 rule.fields[1].mask_range.u32 = src_cidr.prefix;
1024
1025                 rule.fields[2].value.u32 = dst_cidr.ip;
1026                 rule.fields[2].mask_range.u32 = dst_cidr.prefix;
1027
1028                 rule.fields[3].value.u16 = sport.beg;
1029                 rule.fields[3].mask_range.u16 = sport.end;
1030
1031                 rule.fields[4].value.u16 = dport.beg;
1032                 rule.fields[4].mask_range.u16 = dport.end;
1033
1034                 if (use_qinq) {
1035                         rule.fields[5].value.u16 = rte_bswap16(qinq_tag);
1036                         rule.fields[5].mask_range.u16 = 0xffff;
1037
1038                         /* To mask out the TCI and only keep the VID, the mask should be 0x0fff */
1039                         rule.fields[6].value.u16 = svlan.val;
1040                         rule.fields[6].mask_range.u16 = svlan.mask;
1041
1042                         rule.fields[7].value.u16 = rte_bswap16(ETYPE_VLAN);
1043                         rule.fields[7].mask_range.u16 = 0xffff;
1044
1045                         rule.fields[8].value.u16 = cvlan.val;
1046                         rule.fields[8].mask_range.u16 = cvlan.mask;
1047                 }
1048                 else {
1049                         /* Reuse first ethertype from vlan to check if packet is IPv4 packet */
1050                         rule.fields[5].value.u16 =  rte_bswap16(ETYPE_IPv4);
1051                         rule.fields[5].mask_range.u16 = 0xffff;
1052
1053                         /* Other fields are ignored */
1054                         rule.fields[6].value.u16 = 0;
1055                         rule.fields[6].mask_range.u16 = 0;
1056                         rule.fields[7].value.u16 = 0;
1057                         rule.fields[7].mask_range.u16 = 0;
1058                         rule.fields[8].value.u16 = 0;
1059                         rule.fields[8].mask_range.u16 = 0;
1060                 }
1061
1062                 rte_acl_add_rules(ctx, (struct rte_acl_rule*) &rule, 1);
1063                 lua_pop(L, 1);
1064         }
1065
1066         *n_max_rules -= n_rules;
1067         lua_pop(L, pop);
1068         return 0;
1069 }
1070
1071 static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val)
1072 {
1073         const union ipv4_5tuple_host *k;
1074         uint32_t t;
1075         const uint32_t *p;
1076
1077         k = data;
1078         t = k->proto;
1079         p = (const uint32_t *)&k->port_src;
1080
1081         init_val = rte_hash_crc_4byte(t, init_val);
1082         init_val = rte_hash_crc_4byte(k->ip_src, init_val);
1083         init_val = rte_hash_crc_4byte(k->ip_dst, init_val);
1084         init_val = rte_hash_crc_4byte(*p, init_val);
1085         return (init_val);
1086 }
1087
1088 int lua_to_tuples(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct rte_hash **lookup_hash, uint8_t **out_if)
1089 {
1090         int pop;
1091         char s[64];
1092
1093         if ((pop = lua_getfrom(L, from, name)) < 0)
1094                 return -1;
1095
1096         if (!lua_istable(L, -1)) {
1097                 plog_err("Can't read rules since data is not a table\n");
1098                 return -1;
1099         }
1100
1101         lua_len(L, -1);
1102         uint32_t n_tot_tuples = lua_tointeger(L, -1);
1103         lua_pop(L, 1);
1104
1105         struct rte_hash_parameters ipv4_l3fwd_hash_params = {
1106                 .name = NULL,
1107                 .entries = n_tot_tuples * 4,
1108                 .key_len = sizeof(union ipv4_5tuple_host),
1109 #if RTE_VERSION < RTE_VERSION_NUM(2, 1, 0, 0)
1110                 .bucket_entries = 4,
1111 #endif
1112                 .hash_func = ipv4_hash_crc,
1113                 .hash_func_init_val = 0,
1114         };
1115
1116         /* create lb_5tuple hash - same hash is shared between cores on same socket */
1117         snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socket);
1118         if ((*lookup_hash = rte_hash_find_existing(s)) == NULL) {
1119                 ipv4_l3fwd_hash_params.name = s;
1120                 ipv4_l3fwd_hash_params.socket_id = socket;
1121                 *lookup_hash = rte_hash_create(&ipv4_l3fwd_hash_params);
1122                 PROX_PANIC(*lookup_hash == NULL, "Unable to create the lb_5tuple hash\n");
1123         }
1124
1125         lua_pushnil(L);
1126         while (lua_next(L, -2)) {
1127                 uint32_t if_out, ip_src, ip_dst, port_src, port_dst, proto;
1128                 union ipv4_5tuple_host newkey;
1129
1130                 if (lua_to_int(L, TABLE, "if_out", &if_out) ||
1131                     lua_to_int(L, TABLE, "ip_src", &ip_src) ||
1132                     lua_to_int(L, TABLE, "ip_dst", &ip_dst) ||
1133                     lua_to_int(L, TABLE, "port_src", &port_src) ||
1134                     lua_to_int(L, TABLE, "port_dst", &port_dst) ||
1135                     lua_to_int(L, TABLE, "proto", &proto)) {
1136                         plog_err("Failed to read user table config\n");
1137                         return -1;
1138                 }
1139
1140                 newkey.ip_dst = rte_cpu_to_be_32(ip_dst);
1141                 newkey.ip_src = rte_cpu_to_be_32(ip_src);
1142                 newkey.port_dst = rte_cpu_to_be_16((uint16_t)port_dst);
1143                 newkey.port_src = rte_cpu_to_be_16((uint16_t)port_src);
1144                 newkey.proto = (uint8_t)proto;
1145                 newkey.pad0 = 0;
1146                 newkey.pad1 = 0;
1147
1148                 int32_t ret = rte_hash_add_key(*lookup_hash, (void *) &newkey);
1149                 PROX_PANIC(ret < 0, "Unable to add entry (err code %d)\n", ret);
1150                 (*out_if)[ret] = (uint8_t) if_out;
1151
1152                 lua_pop(L, 1);
1153         }
1154         lua_pop(L, pop);
1155         return 0;
1156 }