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) ||
441 lua_to_mac(L, TABLE, "mac", &mac) ||
442 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 int lua_to_routes4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 *lpm)
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;
518 if ((pop = lua_getfrom(L, from, name)) < 0)
521 snprintf(lpm_name, sizeof(lpm_name), "IPv4_lpm_s%u", socket);
523 if (!lua_istable(L, -1)) {
524 set_err("Data is not a table\n");
529 n_tot_rules = lua_tointeger(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;
537 new_lpm = rte_lpm_create(lpm_name, socket, &conf);
539 new_lpm = rte_lpm_create(lpm_name, socket, 2 * n_tot_rules, 0);
541 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
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");
549 ret = rte_lpm_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
552 set_err("Failed to add (%d) index %u ip %x/%u to lpm\n",
553 ret, next_hop_index, dst.ip, dst.prefix);
555 else if (++n_loaded_rules % 10000 == 0) {
556 plog_info("Route %d added\n", n_loaded_rules);
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;
570 int lua_to_lpm4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 **lpm)
575 if ((pop = lua_getfrom(L, from, name)) < 0)
578 ret = prox_zmalloc(sizeof(struct lpm4), socket);
580 if (!lua_istable(L, -1)) {
581 set_err("Can't read lpm4 since data is not a table\n");
585 if (lua_to_routes4(L, TABLE, "routes", socket, ret) ||
586 lua_to_next_hop(L, TABLE, "next_hops", socket, &ret->next_hops)) {
591 plog_info("Loaded %d routes\n", ret->n_used_rules);
598 int lua_to_lpm6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 **lpm)
603 if ((pop = lua_getfrom(L, from, name)) < 0)
606 if (!lua_istable(L, -1)) {
607 set_err("Lpm6 is not a table\n");
611 ret = prox_zmalloc(sizeof(struct lpm6), socket);
613 if (lua_to_routes6(L, TABLE, "routes6", socket, ret) ||
614 lua_to_next_hop6(L, TABLE, "next_hops6", socket, &ret->next_hops))
618 plog_info("Loaded %d routes\n", ret->n_used_rules);
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)
630 if ((pop = lua_getfrom(L, from, name)) < 0)
633 if (!lua_istable(L, -1)) {
634 set_err("lpm6 entry is not a table\n");
637 if (lua_to_cidr6(L, TABLE, "cidr6", cidr) ||
638 lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
646 int lua_to_routes6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 *lpm)
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;
658 if ((pop = lua_getfrom(L, from, name)) < 0)
661 snprintf(lpm_name, sizeof(lpm_name), "IPv6_lpm_s%u", socket);
663 if (!lua_istable(L, -1)) {
664 set_err("Data is not a table\n");
669 n_tot_rules = lua_tointeger(L, -1);
673 config.max_rules = n_tot_rules;
674 config.number_tbl8s = (1 << 16);
677 new_lpm = rte_lpm6_create(lpm_name, socket, &config);
678 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
681 while (lua_next(L, -2)) {
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");
688 ret = rte_lpm6_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
691 plog_warn("Failed to add (%d) index %u, %d\n",
692 ret, next_hop_index, dst.prefix);
694 else if (++n_loaded_rules % 10000 == 0) {
695 plog_info("Route %d added\n", n_loaded_rules);
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;
709 int lua_to_dscp(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint8_t **dscp)
713 if ((pop = lua_getfrom(L, from, name)) < 0)
716 if (!lua_istable(L, -1)) {
717 set_err("DSCP is not a table\n");
721 uint32_t dscp_bits, tc, queue;
723 *dscp = prox_zmalloc(64, socket);
724 PROX_PANIC(dscp == NULL, "Error creating dscp table");
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");
737 (*dscp)[dscp_bits] = tc << 2 | queue;
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)
748 if ((pop = lua_getfrom(L, from, name)) < 0)
751 if (!lua_istable(L, -1)) {
753 set_err("QinQ to gre map is not a table\n");
755 set_err("QinQ to gre map %s is not a table\n", name);
759 struct qinq_gre_map *ret;
760 uint32_t svlan, cvlan;
761 uint16_t be_svlan, be_cvlan;
769 n_entries = lua_tointeger(L, -1);
773 mem_size += sizeof(struct qinq_gre_map);
774 mem_size += n_entries * sizeof(struct qinq_gre_entry);
776 ret = prox_zmalloc(mem_size, socket);
777 PROX_PANIC(ret == NULL, "Error creating gre_qinq map");
779 ret->count = n_entries;
782 while (lua_next(L, -2)) {
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");
792 be_svlan = rte_bswap16((uint16_t)svlan);
793 be_cvlan = rte_bswap16((uint16_t)cvlan);
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);
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);
814 int lua_to_user_table(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint16_t **user_table)
818 if ((pop = lua_getfrom(L, from, name)) < 0)
821 if (!lua_istable(L, -1)) {
822 set_err("Data is not a table\n");
826 uint32_t svlan, cvlan;
827 uint16_t be_svlan, be_cvlan;
830 *user_table = prox_zmalloc(0x1000000 * sizeof(uint16_t), socket);
831 PROX_PANIC(*user_table == NULL, "Error creating user table");
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");
842 be_svlan = rte_bswap16((uint16_t)svlan);
843 be_cvlan = rte_bswap16((uint16_t)cvlan);
845 (*user_table)[PKT_TO_LUTQINQ(be_svlan, be_cvlan)] = user;
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)
856 struct ipv6_tun_binding_table *ret;
863 if ((pop = lua_getfrom(L, from, name)) < 0)
866 if (!lua_istable(L, -1)) {
867 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
872 n_entries = lua_tointeger(L, -1);
875 memsize = sizeof(struct ipv6_tun_binding_table);
876 memsize += n_entries * sizeof(struct ipv6_tun_binding_entry);
878 ret = prox_zmalloc(memsize, socket);
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))
888 ret->entry[idx].public_port = port;
892 ret->num_binding_entries = idx;
894 plog_info("\tRead %d IPv6 Tunnel Binding entries\n", idx);
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)
904 struct cpe_table_data *ret;
907 if ((pop = lua_getfrom(L, from, name)) < 0)
910 if (!lua_istable(L, -1)) {
911 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
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 prox_rte_ether_addr mac;
926 while (lua_next(L, -2)) {
927 if (lua_to_cidr(L, TABLE, "cidr", &cidr))
929 n_entries += ip4_subet_get_n_hosts(&cidr);
933 ret = prox_zmalloc(sizeof(*ret) + n_entries * sizeof(struct cpe_table_entry), 0);
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))
946 uint32_t n_hosts = ip4_subet_get_n_hosts(&cidr);
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;
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);
964 ret->n_entries = n_entries;
972 struct rte_acl_rule_data data;
973 struct rte_acl_field fields[9];
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)
980 if ((pop = lua_getfrom(L, from, name)) < 0)
983 if (!lua_istable(L, -1)) {
984 set_err("Can't read rules since data is not a table\n");
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;
994 while (lua_next(L, -2)) {
995 if (n_rules == *n_max_rules) {
996 set_err("Too many rules");
1000 if (lua_to_val_mask(L, TABLE, "svlan_id", &svlan) ||
1001 lua_to_val_mask(L, TABLE, "cvlan_id", &cvlan))
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))
1013 struct acl4_rule rule;
1015 rule.data.userdata = action; /* allow, drop or rate_limit */
1016 rule.data.category_mask = 1;
1017 rule.data.priority = n_rules++;
1019 /* Configuration for rules is done in little-endian so no bswap is needed here.. */
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;
1026 rule.fields[2].value.u32 = dst_cidr.ip;
1027 rule.fields[2].mask_range.u32 = dst_cidr.prefix;
1029 rule.fields[3].value.u16 = sport.beg;
1030 rule.fields[3].mask_range.u16 = sport.end;
1032 rule.fields[4].value.u16 = dport.beg;
1033 rule.fields[4].mask_range.u16 = dport.end;
1036 rule.fields[5].value.u16 = rte_bswap16(qinq_tag);
1037 rule.fields[5].mask_range.u16 = 0xffff;
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;
1043 rule.fields[7].value.u16 = rte_bswap16(ETYPE_VLAN);
1044 rule.fields[7].mask_range.u16 = 0xffff;
1046 rule.fields[8].value.u16 = cvlan.val;
1047 rule.fields[8].mask_range.u16 = cvlan.mask;
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;
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;
1063 rte_acl_add_rules(ctx, (struct rte_acl_rule*) &rule, 1);
1067 *n_max_rules -= n_rules;
1072 static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val)
1074 const union ipv4_5tuple_host *k;
1080 p = (const uint32_t *)&k->port_src;
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);
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)
1094 if ((pop = lua_getfrom(L, from, name)) < 0)
1097 if (!lua_istable(L, -1)) {
1098 plog_err("Can't read rules since data is not a table\n");
1103 uint32_t n_tot_tuples = lua_tointeger(L, -1);
1106 struct rte_hash_parameters ipv4_l3fwd_hash_params = {
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,
1113 .hash_func = ipv4_hash_crc,
1114 .hash_func_init_val = 0,
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");
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;
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");
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;
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;