Specify latency bucket size & correct calculation
[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, struct 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;
422         struct 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                     lua_to_mac(L, TABLE, "mac", &mac) ||
442                     lua_to_int(L, TABLE, "mpls", &mpls))
443                         return -1;
444
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         struct 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 int lua_to_routes4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 *lpm)
508 {
509         struct ip4_subnet dst;
510         uint32_t next_hop_index;
511         uint32_t n_loaded_rules;
512         uint32_t n_tot_rules;
513         struct rte_lpm *new_lpm;
514         char lpm_name[64];
515         int ret;
516         int pop;
517
518         if ((pop = lua_getfrom(L, from, name)) < 0)
519                 return -1;
520
521         snprintf(lpm_name, sizeof(lpm_name), "IPv4_lpm_s%u", socket);
522
523         if (!lua_istable(L, -1)) {
524                 set_err("Data is not a table\n");
525                 return -1;
526         }
527
528         lua_len(L, -1);
529         n_tot_rules = lua_tointeger(L, -1);
530         n_loaded_rules = 0;
531         lua_pop(L, 1);
532 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,1)
533         struct rte_lpm_config conf;
534         conf.max_rules = 2 * n_tot_rules;
535         conf.number_tbl8s = 256;
536         conf.flags = 0;
537         new_lpm = rte_lpm_create(lpm_name, socket, &conf);
538 #else
539         new_lpm = rte_lpm_create(lpm_name, socket, 2 * n_tot_rules, 0);
540 #endif
541         PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
542
543         lua_pushnil(L);
544         while (lua_next(L, -2)) {
545                 if (lua_to_routes4_entry(L, STACK, NULL, &dst, &next_hop_index)) {
546                         set_err("Failed to read entry while setting up lpm\n");
547                         return -1;
548                 }
549                 ret = rte_lpm_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
550
551                 if (ret != 0) {
552                         set_err("Failed to add (%d) index %u ip %x/%u to lpm\n",
553                                  ret, next_hop_index, dst.ip, dst.prefix);
554                 }
555                 else if (++n_loaded_rules % 10000 == 0) {
556                         plog_info("Route %d added\n", n_loaded_rules);
557                 }
558
559                 lua_pop(L, 1);
560         }
561
562         lpm->rte_lpm = new_lpm;
563         lpm->n_used_rules = n_loaded_rules;
564         lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
565
566         lua_pop(L, pop);
567         return 0;
568 }
569
570 int lua_to_lpm4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 **lpm)
571 {
572         struct lpm4 *ret;
573         int pop;
574
575         if ((pop = lua_getfrom(L, from, name)) < 0)
576                 return -1;
577
578         ret = prox_zmalloc(sizeof(struct lpm4), socket);
579
580         if (!lua_istable(L, -1)) {
581                 set_err("Can't read lpm4 since data is not a table\n");
582                 return -1;
583         }
584
585         if (lua_to_routes4(L, TABLE, "routes", socket, ret) ||
586             lua_to_next_hop(L, TABLE, "next_hops", socket, &ret->next_hops)) {
587                 return -1;
588         }
589
590         if (ret->rte_lpm)
591                 plog_info("Loaded %d routes\n", ret->n_used_rules);
592
593         *lpm = ret;
594         lua_pop(L, pop);
595         return 0;
596 }
597
598 int lua_to_lpm6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 **lpm)
599 {
600         struct lpm6 *ret;
601         int pop;
602
603         if ((pop = lua_getfrom(L, from, name)) < 0)
604                 return -1;
605
606         if (!lua_istable(L, -1)) {
607                 set_err("Lpm6 is not a table\n");
608                 return -1;
609         }
610
611         ret = prox_zmalloc(sizeof(struct lpm6), socket);
612
613         if (lua_to_routes6(L, TABLE, "routes6", socket, ret) ||
614             lua_to_next_hop6(L, TABLE, "next_hops6", socket, &ret->next_hops))
615                 return -1;
616
617         if (ret->rte_lpm6)
618                 plog_info("Loaded %d routes\n", ret->n_used_rules);
619
620         *lpm = ret;
621
622         lua_pop(L, pop);
623         return 0;
624 }
625
626 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)
627 {
628         int pop;
629
630         if ((pop = lua_getfrom(L, from, name)) < 0)
631                 return -1;
632
633         if (!lua_istable(L, -1)) {
634                 set_err("lpm6 entry is not a table\n");
635                 return -1;
636         }
637         if (lua_to_cidr6(L, TABLE, "cidr6", cidr) ||
638             lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
639                 return -1;
640         }
641
642         lua_pop(L, pop);
643         return 0;
644 }
645
646 int lua_to_routes6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 *lpm)
647 {
648         struct ip6_subnet dst;
649         uint32_t next_hop_index;
650         uint32_t n_loaded_rules;
651         struct rte_lpm6 *new_lpm;
652         struct rte_lpm6_config config;
653         uint32_t n_tot_rules;
654         char lpm_name[64];
655         int ret;
656         int pop;
657
658         if ((pop = lua_getfrom(L, from, name)) < 0)
659                 return -1;
660
661         snprintf(lpm_name, sizeof(lpm_name), "IPv6_lpm_s%u", socket);
662
663         if (!lua_istable(L, -1)) {
664                 set_err("Data is not a table\n");
665                 return -1;
666         }
667
668         lua_len(L, -1);
669         n_tot_rules = lua_tointeger(L, -1);
670         n_loaded_rules = 0;
671         lua_pop(L, 1);
672
673         config.max_rules = n_tot_rules;
674         config.number_tbl8s = (1 << 16);
675         config.flags = 0;
676
677         new_lpm = rte_lpm6_create(lpm_name, socket, &config);
678         PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
679
680         lua_pushnil(L);
681         while (lua_next(L, -2)) {
682
683                 if (lua_to_lpm6_entry(L, STACK, NULL, &dst, &next_hop_index)) {
684                         concat_err("Failed to read entry while setting up lpm\n");
685                         return -1;
686                 }
687
688                 ret = rte_lpm6_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
689
690                 if (ret != 0) {
691                         plog_warn("Failed to add (%d) index %u, %d\n",
692                                   ret, next_hop_index, dst.prefix);
693                 }
694                 else if (++n_loaded_rules % 10000 == 0) {
695                         plog_info("Route %d added\n", n_loaded_rules);
696                 }
697
698                 lua_pop(L, 1);
699         }
700
701         lpm->rte_lpm6 = new_lpm;
702         lpm->n_used_rules = n_loaded_rules;
703         lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
704
705         lua_pop(L, pop);
706         return 0;
707 }
708
709 int lua_to_dscp(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint8_t **dscp)
710 {
711         int pop;
712
713         if ((pop = lua_getfrom(L, from, name)) < 0)
714                 return -1;
715
716         if (!lua_istable(L, -1)) {
717                 set_err("DSCP is not a table\n");
718                 return -1;
719         }
720
721         uint32_t dscp_bits, tc, queue;
722         int status;
723         *dscp = prox_zmalloc(64, socket);
724         PROX_PANIC(dscp == NULL, "Error creating dscp table");
725
726         lua_pushnil(L);
727         while (lua_next(L, -2)) {
728                 if (lua_to_int(L, TABLE, "dscp", &dscp_bits) ||
729                     lua_to_int(L, TABLE, "tc", &tc) ||
730                     lua_to_int(L, TABLE, "queue", &queue)) {
731                         concat_err("Failed to read dscp config\n");
732                         return -1;
733                 }
734
735                 lua_pop(L, 1);
736
737                 (*dscp)[dscp_bits] = tc << 2 | queue;
738         }
739
740         lua_pop(L, pop);
741         return 0;
742 }
743
744 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)
745 {
746         int pop;
747
748         if ((pop = lua_getfrom(L, from, name)) < 0)
749                 return -1;
750
751         if (!lua_istable(L, -1)) {
752                 if (from != STACK)
753                         set_err("QinQ to gre map is not a table\n");
754                 else
755                         set_err("QinQ to gre map %s is not a table\n", name);
756                 return -1;
757         }
758
759         struct qinq_gre_map *ret;
760         uint32_t svlan, cvlan;
761         uint16_t be_svlan, be_cvlan;
762         uint32_t user;
763         uint32_t gre_id;
764
765         uint32_t n_entries;
766         uint32_t idx = 0;
767
768         lua_len(L, -1);
769         n_entries = lua_tointeger(L, -1);
770         lua_pop(L, 1);
771
772         size_t mem_size = 0;
773         mem_size += sizeof(struct qinq_gre_map);
774         mem_size += n_entries * sizeof(struct qinq_gre_entry);
775
776         ret = prox_zmalloc(mem_size, socket);
777         PROX_PANIC(ret == NULL, "Error creating gre_qinq map");
778
779         ret->count = n_entries;
780
781         lua_pushnil(L);
782         while (lua_next(L, -2)) {
783
784                 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
785                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
786                     lua_to_int(L, TABLE, "gre_id", &gre_id) ||
787                     lua_to_int(L, TABLE, "user_id", &user)) {
788                         concat_err("Failed to read user table config\n");
789                         return -1;
790                 }
791
792                 be_svlan = rte_bswap16((uint16_t)svlan);
793                 be_cvlan = rte_bswap16((uint16_t)cvlan);
794
795                 ret->entries[idx].user = user;
796                 ret->entries[idx].svlan = be_svlan;
797                 ret->entries[idx].cvlan = be_cvlan;
798                 ret->entries[idx].gre_id = gre_id;
799                 ret->entries[idx].rss = toeplitz_hash((uint8_t *)&be_cvlan, 4);
800
801                 plog_dbg("elem %u: be_svlan=%x, be_cvlan=%x, rss_input=%x, rss=%x, gre_id=%x\n",
802                          idx, be_svlan, be_cvlan, be_cvlan, ret->entries[idx].rss, gre_id);
803
804                 idx++;
805                 lua_pop(L, 1);
806         }
807
808         *qinq_gre_map = ret;
809
810         lua_pop(L, pop);
811         return 0;
812 }
813
814 int lua_to_user_table(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint16_t **user_table)
815 {
816         int pop;
817
818         if ((pop = lua_getfrom(L, from, name)) < 0)
819                 return -1;
820
821         if (!lua_istable(L, -1)) {
822                 set_err("Data is not a table\n");
823                 return -1;
824         }
825
826         uint32_t svlan, cvlan;
827         uint16_t be_svlan, be_cvlan;
828         uint32_t user;
829
830         *user_table = prox_zmalloc(0x1000000 * sizeof(uint16_t), socket);
831         PROX_PANIC(*user_table == NULL, "Error creating user table");
832
833         lua_pushnil(L);
834         while (lua_next(L, -2)) {
835                 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
836                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
837                     lua_to_int(L, TABLE, "user_id", &user)) {
838                         concat_err("Failed to read user table config\n");
839                         return -1;
840                 }
841
842                 be_svlan = rte_bswap16((uint16_t)svlan);
843                 be_cvlan = rte_bswap16((uint16_t)cvlan);
844
845                 (*user_table)[PKT_TO_LUTQINQ(be_svlan, be_cvlan)] = user;
846
847                 lua_pop(L, 1);
848         }
849
850         lua_pop(L, pop);
851         return 0;
852 }
853
854 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)
855 {
856         struct ipv6_tun_binding_table *ret;
857         uint32_t n_entries;
858         uint32_t idx = 0;
859         uint32_t port = 0;
860         size_t memsize = 0;
861         int pop;
862
863         if ((pop = lua_getfrom(L, from, name)) < 0)
864                 return -1;
865
866         if (!lua_istable(L, -1)) {
867                 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
868                 return -1;
869         }
870
871         lua_len(L, -1);
872         n_entries = lua_tointeger(L, -1);
873         lua_pop(L, 1);
874
875         memsize = sizeof(struct ipv6_tun_binding_table);
876         memsize += n_entries * sizeof(struct ipv6_tun_binding_entry);
877
878         ret = prox_zmalloc(memsize, socket);
879
880         lua_pushnil(L);
881         while (lua_next(L, -2)) {
882                 if (lua_to_ip6(L, TABLE, "ip6", ret->entry[idx].endpoint_addr.bytes) ||
883                     lua_to_mac(L, TABLE, "mac", &ret->entry[idx].next_hop_mac) ||
884                     lua_to_ip(L, TABLE, "ip", &ret->entry[idx].public_ipv4) ||
885                     lua_to_int(L, TABLE, "port", &port))
886                         return -1;
887
888                 ret->entry[idx].public_port = port;
889                 idx++;
890                 lua_pop(L, 1);
891         }
892         ret->num_binding_entries = idx;
893
894         plog_info("\tRead %d IPv6 Tunnel Binding entries\n", idx);
895
896         *data = ret;
897
898         lua_pop(L, pop);
899         return 0;
900 }
901
902 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)
903 {
904         struct cpe_table_data *ret;
905         int pop;
906
907         if ((pop = lua_getfrom(L, from, name)) < 0)
908                 return -1;
909
910         if (!lua_istable(L, -1)) {
911                 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
912                 return -1;
913         }
914
915         /* Each entry in the input table expands to multiple entries
916            depending on the number of hosts within the subnet. For
917            this reason, go through the whole table and find out how
918            many entries will be added in total. */
919         struct ip4_subnet cidr;
920         uint32_t n_entries = 0;
921         uint32_t port_idx, gre_id, svlan, cvlan, user;
922         struct ether_addr mac;
923         uint32_t idx = 0;
924
925         lua_pushnil(L);
926         while (lua_next(L, -2)) {
927                 if (lua_to_cidr(L, TABLE, "cidr", &cidr))
928                         return -1;
929                 n_entries += ip4_subet_get_n_hosts(&cidr);
930                 lua_pop(L, 1);
931         }
932
933         ret = prox_zmalloc(sizeof(*ret) + n_entries * sizeof(struct cpe_table_entry), 0);
934
935         lua_pushnil(L);
936         while (lua_next(L, -2)) {
937                 if (lua_to_int(L, TABLE, "dest_id", &port_idx) ||
938                     lua_to_int(L, TABLE, "gre_id", &gre_id) ||
939                     lua_to_int(L, TABLE, "svlan_id", &svlan) ||
940                     lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
941                     lua_to_cidr(L, TABLE, "cidr", &cidr) ||
942                     lua_to_mac(L, TABLE, "mac", &mac) ||
943                     lua_to_int(L, TABLE, "user_id", &user))
944                         return -1;
945
946                 uint32_t n_hosts = ip4_subet_get_n_hosts(&cidr);
947
948                 for (uint32_t i = 0; i < n_hosts; ++i) {
949                         ret->entries[idx].port_idx = port_idx;
950                         ret->entries[idx].gre_id = gre_id;
951                         ret->entries[idx].svlan = rte_bswap16(svlan);
952                         ret->entries[idx].cvlan = rte_bswap16(cvlan);
953                         ret->entries[idx].eth_addr = mac;
954                         ret->entries[idx].user = user;
955
956                         PROX_PANIC(ip4_subnet_to_host(&cidr, i, &ret->entries[idx].ip), "Invalid host in address\n");
957                         ret->entries[idx].ip = rte_bswap32(ret->entries[idx].ip);
958                         idx++;
959                 }
960
961                 lua_pop(L, 1);
962         }
963
964         ret->n_entries = n_entries;
965         *data = ret;
966
967         lua_pop(L, pop);
968         return 0;
969 }
970
971 struct acl4_rule {
972         struct rte_acl_rule_data data;
973         struct rte_acl_field fields[9];
974 };
975
976 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)
977 {
978         int pop;
979
980         if ((pop = lua_getfrom(L, from, name)) < 0)
981                 return -1;
982
983         if (!lua_istable(L, -1)) {
984                 set_err("Can't read rules since data is not a table\n");
985                 return -1;
986         }
987
988         struct val_mask svlan, cvlan, ip_proto;
989         struct ip4_subnet src_cidr, dst_cidr;
990         struct val_range sport, dport;
991         enum acl_action action;
992         uint32_t n_rules = 0;
993         lua_pushnil(L);
994         while (lua_next(L, -2)) {
995                 if (n_rules == *n_max_rules) {
996                         set_err("Too many rules");
997                         return -1;
998                 }
999                 if (use_qinq) {
1000                         if (lua_to_val_mask(L, TABLE, "svlan_id", &svlan) ||
1001                             lua_to_val_mask(L, TABLE, "cvlan_id", &cvlan))
1002                                 return -1;
1003                 }
1004
1005                 if (lua_to_val_mask(L, TABLE, "ip_proto", &ip_proto) ||
1006                     lua_to_cidr(L, TABLE, "src_cidr", &src_cidr) ||
1007                     lua_to_cidr(L, TABLE, "dst_cidr", &dst_cidr) ||
1008                     lua_to_val_range(L, TABLE, "sport", &sport) ||
1009                     lua_to_val_range(L, TABLE, "dport", &dport) ||
1010                     lua_to_action(L, TABLE, "action", &action))
1011                         return -1;
1012
1013                 struct acl4_rule rule;
1014
1015                 rule.data.userdata = action; /* allow, drop or rate_limit */
1016                 rule.data.category_mask = 1;
1017                 rule.data.priority = n_rules++;
1018
1019                 /* Configuration for rules is done in little-endian so no bswap is needed here.. */
1020
1021                 rule.fields[0].value.u8 = ip_proto.val;
1022                 rule.fields[0].mask_range.u8 = ip_proto.mask;
1023                 rule.fields[1].value.u32 = src_cidr.ip;
1024                 rule.fields[1].mask_range.u32 = src_cidr.prefix;
1025
1026                 rule.fields[2].value.u32 = dst_cidr.ip;
1027                 rule.fields[2].mask_range.u32 = dst_cidr.prefix;
1028
1029                 rule.fields[3].value.u16 = sport.beg;
1030                 rule.fields[3].mask_range.u16 = sport.end;
1031
1032                 rule.fields[4].value.u16 = dport.beg;
1033                 rule.fields[4].mask_range.u16 = dport.end;
1034
1035                 if (use_qinq) {
1036                         rule.fields[5].value.u16 = rte_bswap16(qinq_tag);
1037                         rule.fields[5].mask_range.u16 = 0xffff;
1038
1039                         /* To mask out the TCI and only keep the VID, the mask should be 0x0fff */
1040                         rule.fields[6].value.u16 = svlan.val;
1041                         rule.fields[6].mask_range.u16 = svlan.mask;
1042
1043                         rule.fields[7].value.u16 = rte_bswap16(ETYPE_VLAN);
1044                         rule.fields[7].mask_range.u16 = 0xffff;
1045
1046                         rule.fields[8].value.u16 = cvlan.val;
1047                         rule.fields[8].mask_range.u16 = cvlan.mask;
1048                 }
1049                 else {
1050                         /* Reuse first ethertype from vlan to check if packet is IPv4 packet */
1051                         rule.fields[5].value.u16 =  rte_bswap16(ETYPE_IPv4);
1052                         rule.fields[5].mask_range.u16 = 0xffff;
1053
1054                         /* Other fields are ignored */
1055                         rule.fields[6].value.u16 = 0;
1056                         rule.fields[6].mask_range.u16 = 0;
1057                         rule.fields[7].value.u16 = 0;
1058                         rule.fields[7].mask_range.u16 = 0;
1059                         rule.fields[8].value.u16 = 0;
1060                         rule.fields[8].mask_range.u16 = 0;
1061                 }
1062
1063                 rte_acl_add_rules(ctx, (struct rte_acl_rule*) &rule, 1);
1064                 lua_pop(L, 1);
1065         }
1066
1067         *n_max_rules -= n_rules;
1068         lua_pop(L, pop);
1069         return 0;
1070 }
1071
1072 static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val)
1073 {
1074         const union ipv4_5tuple_host *k;
1075         uint32_t t;
1076         const uint32_t *p;
1077
1078         k = data;
1079         t = k->proto;
1080         p = (const uint32_t *)&k->port_src;
1081
1082         init_val = rte_hash_crc_4byte(t, init_val);
1083         init_val = rte_hash_crc_4byte(k->ip_src, init_val);
1084         init_val = rte_hash_crc_4byte(k->ip_dst, init_val);
1085         init_val = rte_hash_crc_4byte(*p, init_val);
1086         return (init_val);
1087 }
1088
1089 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)
1090 {
1091         int pop;
1092         char s[64];
1093
1094         if ((pop = lua_getfrom(L, from, name)) < 0)
1095                 return -1;
1096
1097         if (!lua_istable(L, -1)) {
1098                 plog_err("Can't read rules since data is not a table\n");
1099                 return -1;
1100         }
1101
1102         lua_len(L, -1);
1103         uint32_t n_tot_tuples = lua_tointeger(L, -1);
1104         lua_pop(L, 1);
1105
1106         struct rte_hash_parameters ipv4_l3fwd_hash_params = {
1107                 .name = NULL,
1108                 .entries = n_tot_tuples * 4,
1109                 .key_len = sizeof(union ipv4_5tuple_host),
1110 #if RTE_VERSION < RTE_VERSION_NUM(2, 1, 0, 0)
1111                 .bucket_entries = 4,
1112 #endif
1113                 .hash_func = ipv4_hash_crc,
1114                 .hash_func_init_val = 0,
1115         };
1116
1117         /* create lb_5tuple hash - same hash is shared between cores on same socket */
1118         snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socket);
1119         if ((*lookup_hash = rte_hash_find_existing(s)) == NULL) {
1120                 ipv4_l3fwd_hash_params.name = s;
1121                 ipv4_l3fwd_hash_params.socket_id = socket;
1122                 *lookup_hash = rte_hash_create(&ipv4_l3fwd_hash_params);
1123                 PROX_PANIC(*lookup_hash == NULL, "Unable to create the lb_5tuple hash\n");
1124         }
1125
1126         lua_pushnil(L);
1127         while (lua_next(L, -2)) {
1128                 uint32_t if_out, ip_src, ip_dst, port_src, port_dst, proto;
1129                 union ipv4_5tuple_host newkey;
1130
1131                 if (lua_to_int(L, TABLE, "if_out", &if_out) ||
1132                     lua_to_int(L, TABLE, "ip_src", &ip_src) ||
1133                     lua_to_int(L, TABLE, "ip_dst", &ip_dst) ||
1134                     lua_to_int(L, TABLE, "port_src", &port_src) ||
1135                     lua_to_int(L, TABLE, "port_dst", &port_dst) ||
1136                     lua_to_int(L, TABLE, "proto", &proto)) {
1137                         plog_err("Failed to read user table config\n");
1138                         return -1;
1139                 }
1140
1141                 newkey.ip_dst = rte_cpu_to_be_32(ip_dst);
1142                 newkey.ip_src = rte_cpu_to_be_32(ip_src);
1143                 newkey.port_dst = rte_cpu_to_be_16((uint16_t)port_dst);
1144                 newkey.port_src = rte_cpu_to_be_16((uint16_t)port_src);
1145                 newkey.proto = (uint8_t)proto;
1146                 newkey.pad0 = 0;
1147                 newkey.pad1 = 0;
1148
1149                 int32_t ret = rte_hash_add_key(*lookup_hash, (void *) &newkey);
1150                 PROX_PANIC(ret < 0, "Unable to add entry (err code %d)\n", ret);
1151                 (*out_if)[ret] = (uint8_t) if_out;
1152
1153                 lua_pop(L, 1);
1154         }
1155         lua_pop(L, pop);
1156         return 0;
1157 }