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"
43 #if RTE_VERSION < RTE_VERSION_NUM(1,8,0,0)
44 #define RTE_CACHE_LINE_SIZE CACHE_LINE_SIZE
47 static char error_str[1024];
50 const char *get_lua_to_errors(void)
55 static void null_terminate_error(void)
57 size_t diff = cur_pos - error_str;
59 if (diff >= sizeof(error_str) &&
60 error_str[sizeof(error_str) - 1] != 0)
61 error_str[sizeof(error_str) - 1] = 0;
64 __attribute__((format(printf, 1, 2))) static void set_err(const char *fmt, ...)
70 cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
71 null_terminate_error();
76 __attribute__((format(printf, 1, 2))) static void concat_err(const char *fmt, ...)
81 cur_pos += vsnprintf(cur_pos, sizeof(error_str) - (cur_pos - error_str), fmt, ap);
82 null_terminate_error();
87 /* Make sure that an element is on the top of the stack (zero on success) */
88 int lua_getfrom(struct lua_State *L, enum lua_place from, const char *name)
92 return lua_gettop(L) > 0? 0 : -1;
94 if (!lua_istable(L, -1)) {
95 set_err("Failed to get field '%s' from table (no table)\n", name);
99 lua_pushstring(L, name);
101 if (lua_isnil(L, -1)) {
102 set_err("Field '%s' is missing from table\n", name);
108 lua_getglobal(L, name);
109 if (lua_isnil(L, -1)) {
110 set_err("Couldn't find global data '%s'\n", name);
119 int lua_to_ip(struct lua_State *L, enum lua_place from, const char *name, uint32_t *ip)
122 uint32_t ip_array[4];
126 if ((pop = lua_getfrom(L, from, name)) < 0)
130 n_entries = lua_tointeger(L, -1);
133 if (n_entries != 4) {
134 set_err("Invalid IPv4 format\n");
139 for (int i = 0; i < 4; ++i) {
140 lua_pushinteger(L, i + 1);
142 v = lua_tointeger(L, -1);
144 if (!(v >= 0 && v <= 255)) {
145 set_err("Invalid IPv4 format\n");
148 *ip |= v << (24 - i*8);
155 int lua_to_ip6(struct lua_State *L, enum lua_place from, const char *name, uint8_t *ip)
161 if ((pop = lua_getfrom(L, from, name)) < 0)
165 n_entries = lua_tointeger(L, -1);
168 if (n_entries != 16) {
169 set_err("Invalid IPv6 format\n");
173 for (int i = 0; i < 16; ++i) {
174 lua_pushinteger(L, i + 1);
176 v = lua_tointeger(L, -1);
185 int lua_to_mac(struct lua_State *L, enum lua_place from, const char *name, struct ether_addr *mac)
188 uint32_t mac_array[4];
192 if ((pop = lua_getfrom(L, from, name)) < 0)
196 n_entries = lua_tointeger(L, -1);
199 if (n_entries != 6) {
200 set_err("Invalid MAC format\n");
204 for (int i = 0; i < 6; ++i) {
205 lua_pushinteger(L, i + 1);
207 v = lua_tointeger(L, -1);
209 if (!(v >= 0 && v <= 255)) {
210 set_err("Invalid MAC format\n");
213 mac->addr_bytes[i] = v;
220 int lua_to_cidr(struct lua_State *L, enum lua_place from, const char *name, struct ip4_subnet *cidr)
225 if ((pop = lua_getfrom(L, from, name)) < 0)
228 if (!lua_istable(L, -1)) {
229 set_err("CIDR is not a table\n");
233 if (lua_to_ip(L, TABLE, "ip", &ip) ||
234 lua_to_int(L, TABLE, "depth", &depth)) {
238 cidr->prefix = depth;
244 int lua_to_cidr6(struct lua_State *L, enum lua_place from, const char *name, struct ip6_subnet *cidr)
249 if ((pop = lua_getfrom(L, from, name)) < 0)
252 if (!lua_istable(L, -1)) {
253 set_err("CIDR6 is not a table\n");
257 if (lua_to_ip6(L, TABLE, "ip6", cidr->ip) ||
258 lua_to_int(L, TABLE, "depth", &depth)) {
261 cidr->prefix = depth;
267 int lua_to_val_mask(struct lua_State *L, enum lua_place from, const char *name, struct val_mask *val_mask)
271 if ((pop = lua_getfrom(L, from, name)) < 0)
274 if (!lua_istable(L, -1)) {
275 set_err("data entry is not a table\n");
279 if (lua_to_int(L, TABLE, "val", &val_mask->val) ||
280 lua_to_int(L, TABLE, "mask", &val_mask->mask))
287 int lua_to_val_range(struct lua_State *L, enum lua_place from, const char *name, struct val_range *val_range)
291 if ((pop = lua_getfrom(L, from, name)) < 0)
294 if (!lua_istable(L, -1)) {
295 set_err("data entry is not a table\n");
299 if (lua_to_int(L, TABLE, "beg", &val_range->beg) ||
300 lua_to_int(L, TABLE, "end", &val_range->end))
307 int lua_to_action(struct lua_State *L, enum lua_place from, const char *name, enum acl_action *action)
311 if ((pop = lua_getfrom(L, from, name)) < 0)
314 if (!lua_isstring(L, -1)) {
315 set_err("data entry is not a table\n");
319 const char *s = lua_tostring(L, -1);
321 if (!strcmp(s, "drop"))
323 else if (!strcmp(s, "allow"))
325 else if (!strcmp(s, "rate_limit"))
326 *action = ACL_RATE_LIMIT;
334 int lua_to_string(struct lua_State *L, enum lua_place from, const char *name, char *dst, size_t size)
339 if ((pop = lua_getfrom(L, from, name)) < 0)
342 if (!lua_isstring(L, -1)) {
343 plog_err("data is not an integer\n");
346 str = lua_tostring(L, -1);
348 strncpy(dst, str, size);
354 int lua_to_port(struct lua_State *L, enum lua_place from, const char *name, uint16_t *port)
359 ret = lua_to_double(L, from, name, &tmp);
365 int lua_to_int(struct lua_State *L, enum lua_place from, const char *name, uint32_t *val)
370 ret = lua_to_double(L, from, name, &tmp);
376 int lua_to_double(struct lua_State *L, enum lua_place from, const char *name, double *val)
380 if ((pop = lua_getfrom(L, from, name)) < 0)
383 if (!lua_isnumber(L, -1)) {
384 set_err("data is not a number\n");
387 *val = lua_tonumber(L, -1);
393 int lua_to_routes4_entry(struct lua_State *L, enum lua_place from, const char *name, struct ip4_subnet *cidr, uint32_t *nh_idx)
397 if ((pop = lua_getfrom(L, from, name)) < 0)
400 if (!lua_istable(L, -1)) {
401 set_err("Can't read routes4 entry since data is not a table\n");
405 if (lua_to_cidr(L, TABLE, "cidr", cidr) ||
406 lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
414 int lua_to_next_hop(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop **nh)
416 struct next_hop *ret;
417 uint32_t next_hop_index;
421 struct ether_addr mac;
424 if ((pop = lua_getfrom(L, from, name)) < 0)
427 if (!lua_istable(L, -1)) {
428 set_err("Can't read next hop since data is not a table\n");
432 ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
433 PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
436 while (lua_next(L, -2)) {
437 if (lua_to_int(L, TABLE, "id", &next_hop_index) ||
438 lua_to_int(L, TABLE, "port_id", &port_id) ||
439 lua_to_ip(L, TABLE, "ip", &ip) ||
440 lua_to_mac(L, TABLE, "mac", &mac) ||
441 lua_to_int(L, TABLE, "mpls", &mpls))
444 PROX_PANIC(port_id >= PROX_MAX_PORTS, "Port id too high (only supporting %d ports)\n", PROX_MAX_PORTS);
445 PROX_PANIC(next_hop_index >= MAX_HOP_INDEX, "Next-hop to high (only supporting %d next hops)\n", MAX_HOP_INDEX);
447 ret[next_hop_index].mac_port.out_idx = port_id;
448 ret[next_hop_index].ip_dst = ip;
450 ret[next_hop_index].mac_port.mac = mac;
451 ret[next_hop_index].mpls = mpls;
461 int lua_to_next_hop6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct next_hop6 **nh)
463 struct next_hop6 *ret;
464 uint32_t next_hop_index, port_id, mpls;
465 struct ether_addr mac;
469 if ((pop = lua_getfrom(L, from, name)) < 0)
472 if (!lua_istable(L, -1)) {
473 set_err("Data is not a table\n");
477 ret = prox_zmalloc(sizeof(*ret) * MAX_HOP_INDEX, socket);
478 PROX_PANIC(ret == NULL, "Could not allocate memory for next hop\n");
481 while (lua_next(L, -2)) {
482 if (lua_to_int(L, TABLE, "id", &next_hop_index) ||
483 lua_to_int(L, TABLE, "port_id", &port_id) ||
484 lua_to_ip6(L, TABLE, "ip6", ip) ||
485 lua_to_mac(L, TABLE, "mac", &mac) ||
486 lua_to_int(L, TABLE, "mpls", &mpls))
489 PROX_PANIC(port_id >= PROX_MAX_PORTS, "Port id too high (only supporting %d ports)\n", PROX_MAX_PORTS);
490 PROX_PANIC(next_hop_index >= MAX_HOP_INDEX, "Next-hop to high (only supporting %d next hops)\n", MAX_HOP_INDEX);
492 ret[next_hop_index].mac_port.out_idx = port_id;
493 memcpy(ret[next_hop_index].ip_dst,ip, 16);
495 ret[next_hop_index].mac_port.mac = mac;
496 ret[next_hop_index].mpls = mpls;
506 int lua_to_routes4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 *lpm)
508 struct ip4_subnet dst;
509 uint32_t next_hop_index;
510 uint32_t n_loaded_rules;
511 uint32_t n_tot_rules;
512 struct rte_lpm *new_lpm;
517 if ((pop = lua_getfrom(L, from, name)) < 0)
520 snprintf(lpm_name, sizeof(lpm_name), "IPv4_lpm_s%u", socket);
522 if (!lua_istable(L, -1)) {
523 set_err("Data is not a table\n");
528 n_tot_rules = lua_tointeger(L, -1);
531 #if RTE_VERSION >= RTE_VERSION_NUM(16,4,0,1)
532 struct rte_lpm_config conf;
533 conf.max_rules = 2 * n_tot_rules;
534 conf.number_tbl8s = 256;
536 new_lpm = rte_lpm_create(lpm_name, socket, &conf);
538 new_lpm = rte_lpm_create(lpm_name, socket, 2 * n_tot_rules, 0);
540 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
543 while (lua_next(L, -2)) {
544 if (lua_to_routes4_entry(L, STACK, NULL, &dst, &next_hop_index)) {
545 set_err("Failed to read entry while setting up lpm\n");
548 ret = rte_lpm_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
551 set_err("Failed to add (%d) index %u ip %x/%u to lpm\n",
552 ret, next_hop_index, dst.ip, dst.prefix);
554 else if (++n_loaded_rules % 10000 == 0) {
555 plog_info("Route %d added\n", n_loaded_rules);
561 lpm->rte_lpm = new_lpm;
562 lpm->n_used_rules = n_loaded_rules;
563 lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
569 int lua_to_lpm4(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm4 **lpm)
574 if ((pop = lua_getfrom(L, from, name)) < 0)
577 ret = prox_zmalloc(sizeof(struct lpm4), socket);
579 if (!lua_istable(L, -1)) {
580 set_err("Can't read lpm4 since data is not a table\n");
584 if (lua_to_routes4(L, TABLE, "routes", socket, ret) ||
585 lua_to_next_hop(L, TABLE, "next_hops", socket, &ret->next_hops)) {
590 plog_info("Loaded %d routes\n", ret->n_used_rules);
597 int lua_to_lpm6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 **lpm)
602 if ((pop = lua_getfrom(L, from, name)) < 0)
605 if (!lua_istable(L, -1)) {
606 set_err("Lpm6 is not a table\n");
610 ret = prox_zmalloc(sizeof(struct lpm6), socket);
612 if (lua_to_routes6(L, TABLE, "routes6", socket, ret) ||
613 lua_to_next_hop6(L, TABLE, "next_hops6", socket, &ret->next_hops))
617 plog_info("Loaded %d routes\n", ret->n_used_rules);
625 static int lua_to_lpm6_entry(struct lua_State *L, enum lua_place from, const char *name, struct ip6_subnet *cidr, uint32_t *nh_idx)
629 if ((pop = lua_getfrom(L, from, name)) < 0)
632 if (!lua_istable(L, -1)) {
633 set_err("lpm6 entry is not a table\n");
636 if (lua_to_cidr6(L, TABLE, "cidr6", cidr) ||
637 lua_to_int(L, TABLE, "next_hop_id", nh_idx)) {
645 int lua_to_routes6(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct lpm6 *lpm)
647 struct ip6_subnet dst;
648 uint32_t next_hop_index;
649 uint32_t n_loaded_rules;
650 struct rte_lpm6 *new_lpm;
651 struct rte_lpm6_config config;
652 uint32_t n_tot_rules;
657 if ((pop = lua_getfrom(L, from, name)) < 0)
660 snprintf(lpm_name, sizeof(lpm_name), "IPv6_lpm_s%u", socket);
662 if (!lua_istable(L, -1)) {
663 set_err("Data is not a table\n");
668 n_tot_rules = lua_tointeger(L, -1);
672 config.max_rules = n_tot_rules;
673 config.number_tbl8s = (1 << 16);
676 new_lpm = rte_lpm6_create(lpm_name, socket, &config);
677 PROX_PANIC(NULL == new_lpm, "Failed to allocate lpm\n");
680 while (lua_next(L, -2)) {
682 if (lua_to_lpm6_entry(L, STACK, NULL, &dst, &next_hop_index)) {
683 concat_err("Failed to read entry while setting up lpm\n");
687 ret = rte_lpm6_add(new_lpm, dst.ip, dst.prefix, next_hop_index);
690 plog_warn("Failed to add (%d) index %u, %d\n",
691 ret, next_hop_index, dst.prefix);
693 else if (++n_loaded_rules % 10000 == 0) {
694 plog_info("Route %d added\n", n_loaded_rules);
700 lpm->rte_lpm6 = new_lpm;
701 lpm->n_used_rules = n_loaded_rules;
702 lpm->n_free_rules = 2 * n_tot_rules - n_loaded_rules;
708 int lua_to_dscp(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint8_t **dscp)
712 if ((pop = lua_getfrom(L, from, name)) < 0)
715 if (!lua_istable(L, -1)) {
716 set_err("DSCP is not a table\n");
720 uint32_t dscp_bits, tc, queue;
722 *dscp = prox_zmalloc(64, socket);
723 PROX_PANIC(dscp == NULL, "Error creating dscp table");
726 while (lua_next(L, -2)) {
727 if (lua_to_int(L, TABLE, "dscp", &dscp_bits) ||
728 lua_to_int(L, TABLE, "tc", &tc) ||
729 lua_to_int(L, TABLE, "queue", &queue)) {
730 concat_err("Failed to read dscp config\n");
736 (*dscp)[dscp_bits] = tc << 2 | queue;
743 int lua_to_qinq_gre_map(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct qinq_gre_map **qinq_gre_map)
747 if ((pop = lua_getfrom(L, from, name)) < 0)
750 if (!lua_istable(L, -1)) {
752 set_err("QinQ to gre map is not a table\n");
754 set_err("QinQ to gre map %s is not a table\n", name);
758 struct qinq_gre_map *ret;
759 uint32_t svlan, cvlan;
760 uint16_t be_svlan, be_cvlan;
768 n_entries = lua_tointeger(L, -1);
772 mem_size += sizeof(struct qinq_gre_map);
773 mem_size += n_entries * sizeof(struct qinq_gre_entry);
775 ret = prox_zmalloc(mem_size, socket);
776 PROX_PANIC(ret == NULL, "Error creating gre_qinq map");
778 ret->count = n_entries;
781 while (lua_next(L, -2)) {
783 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
784 lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
785 lua_to_int(L, TABLE, "gre_id", &gre_id) ||
786 lua_to_int(L, TABLE, "user_id", &user)) {
787 concat_err("Failed to read user table config\n");
791 be_svlan = rte_bswap16((uint16_t)svlan);
792 be_cvlan = rte_bswap16((uint16_t)cvlan);
794 ret->entries[idx].user = user;
795 ret->entries[idx].svlan = be_svlan;
796 ret->entries[idx].cvlan = be_cvlan;
797 ret->entries[idx].gre_id = gre_id;
798 ret->entries[idx].rss = toeplitz_hash((uint8_t *)&be_cvlan, 4);
800 plog_dbg("elem %u: be_svlan=%x, be_cvlan=%x, rss_input=%x, rss=%x, gre_id=%x\n",
801 idx, be_svlan, be_cvlan, be_cvlan, ret->entries[idx].rss, gre_id);
813 int lua_to_user_table(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, uint16_t **user_table)
817 if ((pop = lua_getfrom(L, from, name)) < 0)
820 if (!lua_istable(L, -1)) {
821 set_err("Data is not a table\n");
825 uint32_t svlan, cvlan;
826 uint16_t be_svlan, be_cvlan;
829 *user_table = prox_zmalloc(0x1000000 * sizeof(uint16_t), socket);
830 PROX_PANIC(*user_table == NULL, "Error creating user table");
833 while (lua_next(L, -2)) {
834 if (lua_to_int(L, TABLE, "svlan_id", &svlan) ||
835 lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
836 lua_to_int(L, TABLE, "user_id", &user)) {
837 concat_err("Failed to read user table config\n");
841 be_svlan = rte_bswap16((uint16_t)svlan);
842 be_cvlan = rte_bswap16((uint16_t)cvlan);
844 (*user_table)[PKT_TO_LUTQINQ(be_svlan, be_cvlan)] = user;
853 int lua_to_ip6_tun_binding(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct ipv6_tun_binding_table **data)
855 struct ipv6_tun_binding_table *ret;
862 if ((pop = lua_getfrom(L, from, name)) < 0)
865 if (!lua_istable(L, -1)) {
866 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
871 n_entries = lua_tointeger(L, -1);
874 memsize = sizeof(struct ipv6_tun_binding_table);
875 memsize += n_entries * sizeof(struct ipv6_tun_binding_entry);
877 ret = prox_zmalloc(memsize, socket);
880 while (lua_next(L, -2)) {
881 if (lua_to_ip6(L, TABLE, "ip6", ret->entry[idx].endpoint_addr.bytes) ||
882 lua_to_mac(L, TABLE, "mac", &ret->entry[idx].next_hop_mac) ||
883 lua_to_ip(L, TABLE, "ip", &ret->entry[idx].public_ipv4) ||
884 lua_to_int(L, TABLE, "port", &port))
887 ret->entry[idx].public_port = port;
891 ret->num_binding_entries = idx;
893 plog_info("\tRead %d IPv6 Tunnel Binding entries\n", idx);
901 int lua_to_cpe_table_data(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct cpe_table_data **data)
903 struct cpe_table_data *ret;
906 if ((pop = lua_getfrom(L, from, name)) < 0)
909 if (!lua_istable(L, -1)) {
910 set_err("Can't read IPv6 tunnel bindings entry since ret is not a table\n");
914 /* Each entry in the input table expands to multiple entries
915 depending on the number of hosts within the subnet. For
916 this reason, go through the whole table and find out how
917 many entries will be added in total. */
918 struct ip4_subnet cidr;
919 uint32_t n_entries = 0;
920 uint32_t port_idx, gre_id, svlan, cvlan, user;
921 struct ether_addr mac;
925 while (lua_next(L, -2)) {
926 if (lua_to_cidr(L, TABLE, "cidr", &cidr))
928 n_entries += ip4_subet_get_n_hosts(&cidr);
932 ret = prox_zmalloc(sizeof(*ret) + n_entries * sizeof(struct cpe_table_entry), 0);
935 while (lua_next(L, -2)) {
936 if (lua_to_int(L, TABLE, "dest_id", &port_idx) ||
937 lua_to_int(L, TABLE, "gre_id", &gre_id) ||
938 lua_to_int(L, TABLE, "svlan_id", &svlan) ||
939 lua_to_int(L, TABLE, "cvlan_id", &cvlan) ||
940 lua_to_cidr(L, TABLE, "cidr", &cidr) ||
941 lua_to_mac(L, TABLE, "mac", &mac) ||
942 lua_to_int(L, TABLE, "user_id", &user))
945 uint32_t n_hosts = ip4_subet_get_n_hosts(&cidr);
947 for (uint32_t i = 0; i < n_hosts; ++i) {
948 ret->entries[idx].port_idx = port_idx;
949 ret->entries[idx].gre_id = gre_id;
950 ret->entries[idx].svlan = rte_bswap16(svlan);
951 ret->entries[idx].cvlan = rte_bswap16(cvlan);
952 ret->entries[idx].eth_addr = mac;
953 ret->entries[idx].user = user;
955 PROX_PANIC(ip4_subnet_to_host(&cidr, i, &ret->entries[idx].ip), "Invalid host in address\n");
956 ret->entries[idx].ip = rte_bswap32(ret->entries[idx].ip);
963 ret->n_entries = n_entries;
971 struct rte_acl_rule_data data;
972 struct rte_acl_field fields[9];
975 int lua_to_rules(struct lua_State *L, enum lua_place from, const char *name, struct rte_acl_ctx *ctx, uint32_t* n_max_rules, int use_qinq, uint16_t qinq_tag)
979 if ((pop = lua_getfrom(L, from, name)) < 0)
982 if (!lua_istable(L, -1)) {
983 set_err("Can't read rules since data is not a table\n");
987 struct val_mask svlan, cvlan, ip_proto;
988 struct ip4_subnet src_cidr, dst_cidr;
989 struct val_range sport, dport;
990 enum acl_action action;
991 uint32_t n_rules = 0;
993 while (lua_next(L, -2)) {
994 if (n_rules == *n_max_rules) {
995 set_err("Too many rules");
999 if (lua_to_val_mask(L, TABLE, "svlan_id", &svlan) ||
1000 lua_to_val_mask(L, TABLE, "cvlan_id", &cvlan))
1004 if (lua_to_val_mask(L, TABLE, "ip_proto", &ip_proto) ||
1005 lua_to_cidr(L, TABLE, "src_cidr", &src_cidr) ||
1006 lua_to_cidr(L, TABLE, "dst_cidr", &dst_cidr) ||
1007 lua_to_val_range(L, TABLE, "sport", &sport) ||
1008 lua_to_val_range(L, TABLE, "dport", &dport) ||
1009 lua_to_action(L, TABLE, "action", &action))
1012 struct acl4_rule rule;
1014 rule.data.userdata = action; /* allow, drop or rate_limit */
1015 rule.data.category_mask = 1;
1016 rule.data.priority = n_rules++;
1018 /* Configuration for rules is done in little-endian so no bswap is needed here.. */
1020 rule.fields[0].value.u8 = ip_proto.val;
1021 rule.fields[0].mask_range.u8 = ip_proto.mask;
1022 rule.fields[1].value.u32 = src_cidr.ip;
1023 rule.fields[1].mask_range.u32 = src_cidr.prefix;
1025 rule.fields[2].value.u32 = dst_cidr.ip;
1026 rule.fields[2].mask_range.u32 = dst_cidr.prefix;
1028 rule.fields[3].value.u16 = sport.beg;
1029 rule.fields[3].mask_range.u16 = sport.end;
1031 rule.fields[4].value.u16 = dport.beg;
1032 rule.fields[4].mask_range.u16 = dport.end;
1035 rule.fields[5].value.u16 = rte_bswap16(qinq_tag);
1036 rule.fields[5].mask_range.u16 = 0xffff;
1038 /* To mask out the TCI and only keep the VID, the mask should be 0x0fff */
1039 rule.fields[6].value.u16 = svlan.val;
1040 rule.fields[6].mask_range.u16 = svlan.mask;
1042 rule.fields[7].value.u16 = rte_bswap16(ETYPE_VLAN);
1043 rule.fields[7].mask_range.u16 = 0xffff;
1045 rule.fields[8].value.u16 = cvlan.val;
1046 rule.fields[8].mask_range.u16 = cvlan.mask;
1049 /* Reuse first ethertype from vlan to check if packet is IPv4 packet */
1050 rule.fields[5].value.u16 = rte_bswap16(ETYPE_IPv4);
1051 rule.fields[5].mask_range.u16 = 0xffff;
1053 /* Other fields are ignored */
1054 rule.fields[6].value.u16 = 0;
1055 rule.fields[6].mask_range.u16 = 0;
1056 rule.fields[7].value.u16 = 0;
1057 rule.fields[7].mask_range.u16 = 0;
1058 rule.fields[8].value.u16 = 0;
1059 rule.fields[8].mask_range.u16 = 0;
1062 rte_acl_add_rules(ctx, (struct rte_acl_rule*) &rule, 1);
1066 *n_max_rules -= n_rules;
1071 static inline uint32_t ipv4_hash_crc(const void *data, __rte_unused uint32_t data_len, uint32_t init_val)
1073 const union ipv4_5tuple_host *k;
1079 p = (const uint32_t *)&k->port_src;
1081 init_val = rte_hash_crc_4byte(t, init_val);
1082 init_val = rte_hash_crc_4byte(k->ip_src, init_val);
1083 init_val = rte_hash_crc_4byte(k->ip_dst, init_val);
1084 init_val = rte_hash_crc_4byte(*p, init_val);
1088 int lua_to_tuples(struct lua_State *L, enum lua_place from, const char *name, uint8_t socket, struct rte_hash **lookup_hash, uint8_t **out_if)
1093 if ((pop = lua_getfrom(L, from, name)) < 0)
1096 if (!lua_istable(L, -1)) {
1097 plog_err("Can't read rules since data is not a table\n");
1102 uint32_t n_tot_tuples = lua_tointeger(L, -1);
1105 struct rte_hash_parameters ipv4_l3fwd_hash_params = {
1107 .entries = n_tot_tuples * 4,
1108 .key_len = sizeof(union ipv4_5tuple_host),
1109 #if RTE_VERSION < RTE_VERSION_NUM(2, 1, 0, 0)
1110 .bucket_entries = 4,
1112 .hash_func = ipv4_hash_crc,
1113 .hash_func_init_val = 0,
1116 /* create lb_5tuple hash - same hash is shared between cores on same socket */
1117 snprintf(s, sizeof(s), "ipv4_l3fwd_hash_%d", socket);
1118 if ((*lookup_hash = rte_hash_find_existing(s)) == NULL) {
1119 ipv4_l3fwd_hash_params.name = s;
1120 ipv4_l3fwd_hash_params.socket_id = socket;
1121 *lookup_hash = rte_hash_create(&ipv4_l3fwd_hash_params);
1122 PROX_PANIC(*lookup_hash == NULL, "Unable to create the lb_5tuple hash\n");
1126 while (lua_next(L, -2)) {
1127 uint32_t if_out, ip_src, ip_dst, port_src, port_dst, proto;
1128 union ipv4_5tuple_host newkey;
1130 if (lua_to_int(L, TABLE, "if_out", &if_out) ||
1131 lua_to_int(L, TABLE, "ip_src", &ip_src) ||
1132 lua_to_int(L, TABLE, "ip_dst", &ip_dst) ||
1133 lua_to_int(L, TABLE, "port_src", &port_src) ||
1134 lua_to_int(L, TABLE, "port_dst", &port_dst) ||
1135 lua_to_int(L, TABLE, "proto", &proto)) {
1136 plog_err("Failed to read user table config\n");
1140 newkey.ip_dst = rte_cpu_to_be_32(ip_dst);
1141 newkey.ip_src = rte_cpu_to_be_32(ip_src);
1142 newkey.port_dst = rte_cpu_to_be_16((uint16_t)port_dst);
1143 newkey.port_src = rte_cpu_to_be_16((uint16_t)port_src);
1144 newkey.proto = (uint8_t)proto;
1148 int32_t ret = rte_hash_add_key(*lookup_hash, (void *) &newkey);
1149 PROX_PANIC(ret < 0, "Unable to add entry (err code %d)\n", ret);
1150 (*out_if)[ret] = (uint8_t) if_out;