2 // Copyright (c) 2010-2017 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
22 #include <rte_ether.h>
26 #include <rte_version.h>
27 #include <rte_hash_crc.h>
29 #include "prox_malloc.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"
41 #include "handle_lb_5tuple.h"
42 #include "prox_compat.h"
44 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
45 #define RTE_CACHE_LINE_SIZE CACHE_LINE_SIZE
48 static char error_str[1024];
51 const char *get_lua_to_errors(void)
56 static void null_terminate_error(void)
58 size_t diff = cur_pos - error_str;
60 if (diff >= sizeof(error_str) &&
61 error_str[sizeof(error_str) - 1] != 0)
62 error_str[sizeof(error_str) - 1] = 0;
65 __attribute__((format(printf, 1, 2))) static void set_err(const char *fmt, ...)
71 cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
72 null_terminate_error();
77 __attribute__((format(printf, 1, 2))) static void concat_err(const char *fmt, ...)
82 cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
83 null_terminate_error();
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)
93 return lua_gettop(L) > 0? 0 : -1;
95 if (!lua_istable(L, -1)) {
96 set_err("Failed to get field '%s' from table (no table)\n", name);
100 lua_pushstring(L, name);
102 if (lua_isnil(L, -1)) {
103 set_err("Field '%s' is missing from table\n", name);
109 lua_getglobal(L, name);
110 if (lua_isnil(L, -1)) {
111 set_err("Couldn't find global data '%s'\n", name);
120 int lua_to_ip(struct lua_State *L, enum lua_place from, const char *name, uint32_t *ip)
123 uint32_t ip_array[4];
127 if ((pop = lua_getfrom(L, from, name)) < 0)
131 n_entries = lua_tointeger(L, -1);
134 if (n_entries != 4) {
135 set_err("Invalid IPv4 format\n");
140 for (int i = 0; i < 4; ++i) {
141 lua_pushinteger(L, i + 1);
143 v = lua_tointeger(L, -1);
145 if (!(v >= 0 && v <= 255)) {
146 set_err("Invalid IPv4 format\n");
149 *ip |= v << (24 - i*8);
156 int lua_to_ip6(struct lua_State *L, enum lua_place from, const char *name, uint8_t *ip)
162 if ((pop = lua_getfrom(L, from, name)) < 0)
166 n_entries = lua_tointeger(L, -1);
169 if (n_entries != 16) {
170 set_err("Invalid IPv6 format\n");
174 for (int i = 0; i < 16; ++i) {
175 lua_pushinteger(L, i + 1);
177 v = lua_tointeger(L, -1);
186 int lua_to_mac(struct lua_State *L, enum lua_place from, const char *name, prox_rte_ether_addr *mac)
189 uint32_t mac_array[4];
193 if ((pop = lua_getfrom(L, from, name)) < 0)
197 n_entries = lua_tointeger(L, -1);
200 if (n_entries != 6) {
201 set_err("Invalid MAC format\n");
205 for (int i = 0; i < 6; ++i) {
206 lua_pushinteger(L, i + 1);
208 v = lua_tointeger(L, -1);
210 if (!(v >= 0 && v <= 255)) {
211 set_err("Invalid MAC format\n");
214 mac->addr_bytes[i] = v;
221 int lua_to_cidr(struct lua_State *L, enum lua_place from, const char *name, struct ip4_subnet *cidr)
226 if ((pop = lua_getfrom(L, from, name)) < 0)
229 if (!lua_istable(L, -1)) {
230 set_err("CIDR is not a table\n");
234 if (lua_to_ip(L, TABLE, "ip", &ip) ||
235 lua_to_int(L, TABLE, "depth", &depth)) {
239 cidr->prefix = depth;
245 int lua_to_cidr6(struct lua_State *L, enum lua_place from, const char *name, struct ip6_subnet *cidr)
250 if ((pop = lua_getfrom(L, from, name)) < 0)
253 if (!lua_istable(L, -1)) {
254 set_err("CIDR6 is not a table\n");
258 if (lua_to_ip6(L, TABLE, "ip6", cidr->ip) ||
259 lua_to_int(L, TABLE, "depth", &depth)) {
262 cidr->prefix = depth;
268 int lua_to_val_mask(struct lua_State *L, enum lua_place from, const char *name, struct val_mask *val_mask)
272 if ((pop = lua_getfrom(L, from, name)) < 0)
275 if (!lua_istable(L, -1)) {
276 set_err("data entry is not a table\n");
280 if (lua_to_int(L, TABLE, "val", &val_mask->val) ||
281 lua_to_int(L, TABLE, "mask", &val_mask->mask))
288 int lua_to_val_range(struct lua_State *L, enum lua_place from, const char *name, struct val_range *val_range)
292 if ((pop = lua_getfrom(L, from, name)) < 0)
295 if (!lua_istable(L, -1)) {
296 set_err("data entry is not a table\n");
300 if (lua_to_int(L, TABLE, "beg", &val_range->beg) ||
301 lua_to_int(L, TABLE, "end", &val_range->end))
308 int lua_to_action(struct lua_State *L, enum lua_place from, const char *name, enum acl_action *action)
312 if ((pop = lua_getfrom(L, from, name)) < 0)
315 if (!lua_isstring(L, -1)) {
316 set_err("data entry is not a table\n");
320 const char *s = lua_tostring(L, -1);
322 if (!strcmp(s, "drop"))
324 else if (!strcmp(s, "allow"))
326 else if (!strcmp(s, "rate_limit"))
327 *action = ACL_RATE_LIMIT;
335 int lua_to_string(struct lua_State *L, enum lua_place from, const char *name, char *dst, size_t size)
340 if ((pop = lua_getfrom(L, from, name)) < 0)
343 if (!lua_isstring(L, -1)) {
344 plog_err("data is not an integer\n");
347 str = lua_tostring(L, -1);
349 prox_strncpy(dst, str, size);
355 int lua_to_port(struct lua_State *L, enum lua_place from, const char *name, uint16_t *port)
360 ret = lua_to_double(L, from, name, &tmp);
366 int lua_to_int(struct lua_State *L, enum lua_place from, const char *name, uint32_t *val)
371 ret = lua_to_double(L, from, name, &tmp);
377 int lua_to_double(struct lua_State *L, enum lua_place from, const char *name, double *val)
381 if ((pop = lua_getfrom(L, from, name)) < 0)
384 if (!lua_isnumber(L, -1)) {
385 set_err("data is not a number\n");
388 *val = lua_tonumber(L, -1);
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)
398 if ((pop = lua_getfrom(L, from, name)) < 0)
401 if (!lua_istable(L, -1)) {
402 set_err("Can't read routes4 entry since data is not a table\n");
406 if (lua_to_cidr(L, TABLE, "cidr", cidr) ||
407 lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
415 int lua_to_next_hop(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop **nh)
417 struct next_hop *ret;
418 uint32_t next_hop_index;
422 prox_rte_ether_addr mac;
425 if ((pop = lua_getfrom(L, from, name)) < 0)
428 if (!lua_istable(L, -1)) {
429 set_err("Can't read next hop since data is not a table\n");
433 ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
434 PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
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))
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);
448 ret[next_hop_index].mac_port.out_idx = port_id;
449 ret[next_hop_index].ip_dst = ip;
451 ret[next_hop_index].mac_port.mac = mac;
452 ret[next_hop_index].mpls = mpls;
462 int lua_to_next_hop6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop6 **nh)
464 struct next_hop6 *ret;
465 uint32_t next_hop_index, port_id, mpls;
466 prox_rte_ether_addr mac;
470 if ((pop = lua_getfrom(L, from, name)) < 0)
473 if (!lua_istable(L, -1)) {
474 set_err("Data is not a table\n");
478 ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
479 PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
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))
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);
493 ret[next_hop_index].mac_port.out_idx = port_id;
494 memcpy(ret[next_hop_index].ip_dst,ip, 16);
496 ret[next_hop_index].mac_port.mac = mac;
497 ret[next_hop_index].mpls = mpls;
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)
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;
518 static int count = 1;
520 if ((pop = lua_getfrom(L, from, name)) < 0)
523 snprintf(lpm_name, sizeof(lpm_name), "IPv4_lpm_s%u_%d", socket, count++);
525 if (!lua_istable(L, -1)) {
526 set_err("Data is not a table\n");
531 n_tot_rules = lua_tointeger(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;
539 new_lpm = rte_lpm_create(lpm_name, socket, &conf);
541 new_lpm = rte_lpm_create(lpm_name, socket, 2 * n_tot_rules + MAX_NEW_RULES, 0);
543 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
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");
551 ret = rte_lpm_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
554 set_err("Failed to add (%d) index %u ip %x/%u to lpm\n",
555 ret, next_hop_index, dst.ip, dst.prefix);
557 else if (++n_loaded_rules % 10000 == 0) {
558 plog_info("Route %d added\n", n_loaded_rules);
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;
572 int lua_to_lpm4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 **lpm)
577 if ((pop = lua_getfrom(L, from, name)) < 0)
580 ret = prox_zmalloc(sizeof(struct lpm4), socket);
582 if (!lua_istable(L, -1)) {
583 set_err("Can't read lpm4 since data is not a table\n");
587 if (lua_to_routes4(L, TABLE, "routes", socket, ret) ||
588 lua_to_next_hop(L, TABLE, "next_hops", socket, &ret->next_hops)) {
593 plog_info("Loaded %d routes\n", ret->n_used_rules);
600 int lua_to_lpm6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 **lpm)
605 if ((pop = lua_getfrom(L, from, name)) < 0)
608 if (!lua_istable(L, -1)) {
609 set_err("Lpm6 is not a table\n");
613 ret = prox_zmalloc(sizeof(struct lpm6), socket);
615 if (lua_to_routes6(L, TABLE, "routes6", socket, ret) ||
616 lua_to_next_hop6(L, TABLE, "next_hops6", socket, &ret->next_hops))
620 plog_info("Loaded %d routes\n", ret->n_used_rules);
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)
632 if ((pop = lua_getfrom(L, from, name)) < 0)
635 if (!lua_istable(L, -1)) {
636 set_err("lpm6 entry is not a table\n");
639 if (lua_to_cidr6(L, TABLE, "cidr6", cidr) ||
640 lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
648 int lua_to_routes6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 *lpm)
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;
660 if ((pop = lua_getfrom(L, from, name)) < 0)
663 snprintf(lpm_name, sizeof(lpm_name), "IPv6_lpm_s%u", socket);
665 if (!lua_istable(L, -1)) {
666 set_err("Data is not a table\n");
671 n_tot_rules = lua_tointeger(L, -1);
675 config.max_rules = n_tot_rules;
676 config.number_tbl8s = (1 << 16);
679 new_lpm = rte_lpm6_create(lpm_name, socket, &config);
680 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
683 while (lua_next(L, -2)) {
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");
690 ret = rte_lpm6_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
693 plog_warn("Failed to add (%d) index %u, %d\n",
694 ret, next_hop_index, dst.prefix);
696 else if (++n_loaded_rules % 10000 == 0) {
697 plog_info("Route %d added\n", n_loaded_rules);
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;
711 int lua_to_dscp(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint8_t **dscp)
715 if ((pop = lua_getfrom(L, from, name)) < 0)
718 if (!lua_istable(L, -1)) {
719 set_err("DSCP is not a table\n");
723 uint32_t dscp_bits, tc, queue;
725 *dscp = prox_zmalloc(64, socket);
726 PROX_PANIC(dscp == NULL, "Error creating dscp table");
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");
739 (*dscp)[dscp_bits] = tc << 2 | queue;
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)
750 if ((pop = lua_getfrom(L, from, name)) < 0)
753 if (!lua_istable(L, -1)) {
755 set_err("QinQ to gre map is not a table\n");
757 set_err("QinQ to gre map %s is not a table\n", name);
761 struct qinq_gre_map *ret;
762 uint32_t svlan, cvlan;
763 uint16_t be_svlan, be_cvlan;
771 n_entries = lua_tointeger(L, -1);
775 mem_size += sizeof(struct qinq_gre_map);
776 mem_size += n_entries * sizeof(struct qinq_gre_entry);
778 ret = prox_zmalloc(mem_size, socket);
779 PROX_PANIC(ret == NULL, "Error creating gre_qinq map");
781 ret->count = n_entries;
784 while (lua_next(L, -2)) {
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");
794 be_svlan = rte_bswap16((uint16_t)svlan);
795 be_cvlan = rte_bswap16((uint16_t)cvlan);
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);
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);
816 int lua_to_user_table(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint16_t **user_table)
820 if ((pop = lua_getfrom(L, from, name)) < 0)
823 if (!lua_istable(L, -1)) {
824 set_err("Data is not a table\n");
828 uint32_t svlan, cvlan;
829 uint16_t be_svlan, be_cvlan;
832 *user_table = prox_zmalloc(0x1000000 * sizeof(uint16_t), socket);
833 PROX_PANIC(*user_table == NULL, "Error creating user table");
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");
844 be_svlan = rte_bswap16((uint16_t)svlan);
845 be_cvlan = rte_bswap16((uint16_t)cvlan);
847 (*user_table)[PKT_TO_LUTQINQ(be_svlan, be_cvlan)] = user;
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)
858 struct ipv6_tun_binding_table *ret;
865 if ((pop = lua_getfrom(L, from, name)) < 0)
868 if (!lua_istable(L, -1)) {
869 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
874 n_entries = lua_tointeger(L, -1);
877 memsize = sizeof(struct ipv6_tun_binding_table);
878 memsize += n_entries * sizeof(struct ipv6_tun_binding_entry);
880 ret = prox_zmalloc(memsize, socket);
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))
890 ret->entry[idx].public_port = port;
894 ret->num_binding_entries = idx;
896 plog_info("\tRead %d IPv6 Tunnel Binding entries\n", idx);
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)
906 struct cpe_table_data *ret;
909 if ((pop = lua_getfrom(L, from, name)) < 0)
912 if (!lua_istable(L, -1)) {
913 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
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;
928 while (lua_next(L, -2)) {
929 if (lua_to_cidr(L, TABLE, "cidr", &cidr))
931 n_entries += ip4_subet_get_n_hosts(&cidr);
935 ret = prox_zmalloc(sizeof(*ret) + n_entries * sizeof(struct cpe_table_entry), 0);
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))
948 uint32_t n_hosts = ip4_subet_get_n_hosts(&cidr);
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;
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);
966 ret->n_entries = n_entries;
974 struct rte_acl_rule_data data;
975 struct rte_acl_field fields[9];
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)
982 if ((pop = lua_getfrom(L, from, name)) < 0)
985 if (!lua_istable(L, -1)) {
986 set_err("Can't read rules since data is not a table\n");
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;
996 while (lua_next(L, -2)) {
997 if (n_rules == *n_max_rules) {
998 set_err("Too many rules");
1002 if (lua_to_val_mask(L, TABLE, "svlan_id", &svlan) ||
1003 lua_to_val_mask(L, TABLE, "cvlan_id", &cvlan))
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))
1015 struct acl4_rule rule;
1017 rule.data.userdata = action; /* allow, drop or rate_limit */
1018 rule.data.category_mask = 1;
1019 rule.data.priority = n_rules++;
1021 /* Configuration for rules is done in little-endian so no bswap is needed here.. */
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;
1028 rule.fields[2].value.u32 = dst_cidr.ip;
1029 rule.fields[2].mask_range.u32 = dst_cidr.prefix;
1031 rule.fields[3].value.u16 = sport.beg;
1032 rule.fields[3].mask_range.u16 = sport.end;
1034 rule.fields[4].value.u16 = dport.beg;
1035 rule.fields[4].mask_range.u16 = dport.end;
1038 rule.fields[5].value.u16 = rte_bswap16(qinq_tag);
1039 rule.fields[5].mask_range.u16 = 0xffff;
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;
1045 rule.fields[7].value.u16 = rte_bswap16(ETYPE_VLAN);
1046 rule.fields[7].mask_range.u16 = 0xffff;
1048 rule.fields[8].value.u16 = cvlan.val;
1049 rule.fields[8].mask_range.u16 = cvlan.mask;
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;
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;
1065 rte_acl_add_rules(ctx, (struct rte_acl_rule*) &rule, 1);
1069 *n_max_rules -= n_rules;
1074 static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val)
1076 const union ipv4_5tuple_host *k;
1082 p = (const uint32_t *)&k->port_src;
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);
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)
1096 if ((pop = lua_getfrom(L, from, name)) < 0)
1099 if (!lua_istable(L, -1)) {
1100 plog_err("Can't read rules since data is not a table\n");
1105 uint32_t n_tot_tuples = lua_tointeger(L, -1);
1108 struct rte_hash_parameters ipv4_l3fwd_hash_params = {
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,
1115 .hash_func = ipv4_hash_crc,
1116 .hash_func_init_val = 0,
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");
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;
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");
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;
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;