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