diff options
48 files changed, 6814 insertions, 3034 deletions
diff --git a/VNFs/UDP_Replay/Makefile b/VNFs/UDP_Replay/Makefile index e2375779..08fcbba4 100644 --- a/VNFs/UDP_Replay/Makefile +++ b/VNFs/UDP_Replay/Makefile @@ -35,6 +35,7 @@ VPATH += $(VNF_CORE)/common/VIL/pipeline_passthrough VPATH += $(SRCDIR)/pipeline VPATH += $(VNF_CORE)/common/VIL/pipeline_txrx VPATH += $(VNF_CORE)/common/VIL/l2l3_stack +VPATH += $(VNF_CORE)/common/VIL/gateway INC += $(wildcard *.h) INC += $(wildcard pipeline/*.h) @@ -47,6 +48,7 @@ INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_master/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_passthrough/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_txrx/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/l2l3_stack/*.h) +INC += $(wildcard $(VNF_CORE)/common/VIL/gateway/*.h) CFLAGS += -I$(SRCDIR) -mrtm -mhle -I$(SRCDIR)/pipeline -I$(VNF_CORE)/common/vnf_common CFLAGS += -I$(VNF_CORE)/common/VIL/conntrack -I$(VNF_CORE)/common/VIL/l2l3_stack @@ -54,6 +56,7 @@ CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_common -I$(VNF_CORE)/common/VIL/pipe CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_master -I$(VNF_CORE)/common/VIL/pipeline_passthrough CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_txrx CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_arpicmp +CFLAGS += -I$(VNF_CORE)/common/VIL/gateway # all source are stored in SRCS-y SRCS-y := main.c @@ -84,6 +87,7 @@ SRCS-y += pipeline_loadb.c SRCS-y += pipeline_loadb_be.c SRCS-y += vnf_common.c SRCS-y += pipeline_arpicmp_be.c +SRCS-y += gateway.c CFLAGS += -O3 $(USER_FLAGS) CFLAGS += $(WERROR_FLAGS) diff --git a/VNFs/UDP_Replay/main.c b/VNFs/UDP_Replay/main.c index 1b37c181..587057fc 100644 --- a/VNFs/UDP_Replay/main.c +++ b/VNFs/UDP_Replay/main.c @@ -94,6 +94,7 @@ performance of the solution should be sufficient for testing the UDP NAT perform #include "lib_icmpv6.h" #include "app.h" #include "vnf_common.h" +#include "gateway.h" #define IN6ADDRSZ 16 #define INADDRSZ 4 #define APP_LOOKUP_EXACT_MATCH 0 @@ -200,6 +201,7 @@ cmdline_parse_ctx_t main_ctx[]; uint32_t timer_lcore; uint32_t exit_loop = 1; port_config_t *port_config; + #define MEMPOOL_SIZE 32 * 1024 #define BUFFER_SIZE 2048 #define CACHE_SIZE 256 @@ -436,160 +438,6 @@ app_link_down_internal(__rte_unused struct app_params *app, struct app_link_para cp->state = 0; } -/* int - * inet_pton_ipv4(src, dst) - * like inet_aton() but without all the hexadecimal and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton_ipv4(const char *src, unsigned char *dst) -{ - static const char digits[] = "0123456789"; - int saw_digit, octets, ch; - unsigned char tmp[INADDRSZ], *tp; - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - const char *pch; - if ((pch = strchr(digits, ch)) != NULL) { - unsigned int new = *tp * 10 + (pch - digits); - if (new > 255) - return 0; - if (!saw_digit) { - if (++octets > 4) - return 0; - saw_digit = 1; - } - *tp = (unsigned char)new; - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return 0; - *++tp = 0; - saw_digit = 0; - } else - return 0; - } - if (octets < 4) - return 0; - memcpy(dst, tmp, INADDRSZ); - return 1; -} - -/* int - * inet_pton_ipv6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ -static int inet_pton_ipv6(const char *src, unsigned char *dst) -{ - static const char xdigits_l[] = "0123456789abcdef", - xdigits_u[] = "0123456789ABCDEF"; - unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0; - const char *xdigits = 0, *curtok = 0; - int ch = 0, saw_xdigit = 0, count_xdigit = 0; - unsigned int val = 0; - unsigned dbloct_count = 0; - memset((tp = tmp), '\0', IN6ADDRSZ); - endp = tp + IN6ADDRSZ; - colonp = NULL; - if (*src == ':') - if (*++src != ':') - return 0; - curtok = src; - saw_xdigit = count_xdigit = 0; - val = 0; - while ((ch = *src++) != '\0') { - const char *pch; - if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) - pch = strchr((xdigits = xdigits_u), ch); - if (pch != NULL) { - if (count_xdigit >= 4) - return 0; - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return 0; - saw_xdigit = 1; - count_xdigit++; - continue; - } - if (ch == ':') { - curtok = src; - if (!saw_xdigit) { - if (colonp) - return 0; - colonp = tp; - continue; - } else if (*src == '\0') { - return 0; - } - if (tp + sizeof(int16_t) > endp) - return 0; - *tp++ = (unsigned char)((val >> 8) & 0xff); - *tp++ = (unsigned char)(val & 0xff); - saw_xdigit = 0; - count_xdigit = 0; - val = 0; - dbloct_count++; - continue; - } - if (ch == '.' && ((tp + INADDRSZ) <= endp) && - inet_pton_ipv4(curtok, tp) > 0) { - tp += INADDRSZ; - saw_xdigit = 0; - dbloct_count += 2; - break; /* '\0' was seen by inet_pton4(). */ - } - return 0; - } - if (saw_xdigit) { - if (tp + sizeof(int16_t) > endp) - return 0; - *tp++ = (unsigned char)((val >> 8) & 0xff); - *tp++ = (unsigned char)(val & 0xff); - dbloct_count++; - } - if (colonp != NULL) { - if (dbloct_count == 8) - return 0; - const int n = tp - colonp; - int i; - for (i = 1; i <= n; i++) { - endp[-i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; - } - if (tp != endp) - return 0; - memcpy(dst, tmp, IN6ADDRSZ); - return 1; -} -static int my_inet_pton_ipv6(int af, const char *src, void *dst) -{ - switch (af) { - case AF_INET: - return inet_pton_ipv4(src, dst); - case AF_INET6: - return inet_pton_ipv6(src, dst); - default: - errno = EAFNOSUPPORT; - return -1; - } -} void convert_ipstr_to_numeric(void) { uint32_t i; @@ -2921,6 +2769,7 @@ main(int argc, char **argv) ifm_init(); nb_ports = rte_eth_dev_count(); num_ports = nb_ports; + gw_init(num_ports); if (nb_ports > RTE_MAX_ETHPORTS) nb_ports = RTE_MAX_ETHPORTS; diff --git a/VNFs/vACL/Makefile b/VNFs/vACL/Makefile index febfc7b6..0995f905 100644 --- a/VNFs/vACL/Makefile +++ b/VNFs/vACL/Makefile @@ -30,7 +30,6 @@ include $(RTE_SDK)/mk/rte.vars.mk # binary name APP = vACL - VPATH += $(VNF_CORE)/common/vnf_common VPATH += $(VNF_CORE)/common/VIL/conntrack VPATH += $(VNF_CORE)/common/VIL/pipeline_common @@ -41,6 +40,7 @@ VPATH += $(SRCDIR)/pipeline VPATH += $(VNF_CORE)/common/VIL/l2l3_stack VPATH += $(VNF_CORE)/common/VIL/pipeline_txrx VPATH += $(VNF_CORE)/common/VIL/pipeline_arpicmp +VPATH += $(VNF_CORE)/common/VIL/gateway INC += $(wildcard *.h) INC += $(wildcard pipeline/*.h) @@ -53,6 +53,7 @@ INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_master/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_passthrough/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_txrx/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/l2l3_stack/*.h) +INC += $(wildcard $(VNF_CORE)/common/VIL/gateway/*.h) CFLAGS += -I$(SRCDIR) -mrtm -mhle -I$(SRCDIR)/pipeline -I$(VNF_CORE)/common/vnf_common CFLAGS += -I$(VNF_CORE)/common/VIL/l2l3_stack -I$(VNF_CORE)/common/VIL/conntrack @@ -60,10 +61,18 @@ CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_common -I$(VNF_CORE)/common/VIL/pipe CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_master -I$(VNF_CORE)/common/VIL/pipeline_passthrough CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_txrx CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_arpicmp +CFLAGS += -I$(VNF_CORE)/common/VIL/gateway + +TOP = $(RTE_SDK)/../civetweb +CFLAGS += -I$(TOP)/include $(COPT) -DUSE_WEBSOCKET -DUSE_IPV6 -DUSE_SSL_DH=1 +CFLAGS += -DREST_API_SUPPORT +LDFLAGS += -ljson -lcrypto -lssl +LDFLAGS += -L$(RTE_SDK)/../civetweb/ -lcivetweb # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rest_api.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c @@ -99,6 +108,8 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_arpicmp.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_arpicmp_be.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += gateway.c + CFLAGS += -O3 CFLAGS += -DIPV6 diff --git a/VNFs/vACL/config/IPv4_hwlb_acl.tc b/VNFs/vACL/config/IPv4_hwlb_acl.tc index 79b48ed3..b8e2b152 100644 --- a/VNFs/vACL/config/IPv4_hwlb_acl.tc +++ b/VNFs/vACL/config/IPv4_hwlb_acl.tc @@ -20,9 +20,9 @@ link 1 down link 1 config 172.16.40.10 8 link 1 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 202.16.100.20 0xff000000 -routeadd 1 172.16.40.20 0xff000000 +;routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 202.16.100.20 0xff000000 +routeadd net 1 172.16.40.20 0xff000000 ; IPv4 static ARP ;p 1 arpadd 1 172.16.40.20 00:00:00:00:00:04 diff --git a/VNFs/vACL/config/IPv4_swlb_acl.tc b/VNFs/vACL/config/IPv4_swlb_acl.tc index 7274847a..f736fc4a 100644 --- a/VNFs/vACL/config/IPv4_swlb_acl.tc +++ b/VNFs/vACL/config/IPv4_swlb_acl.tc @@ -20,9 +20,9 @@ link 1 down link 1 config 172.16.40.10 8 link 1 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 202.16.100.20 0xff000000 -routeadd 1 172.16.40.20 0xff000000 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 202.16.100.20 0xff000000 +routeadd net 1 172.16.40.20 0xff000000 ; IPv4 static ARP ;p 1 arpadd 1 172.16.40.20 00:00:00:00:00:04 @@ -39,4 +39,4 @@ p action add 1 count ; IPv4 rules p acl add 1 202.16.100.20 8 172.16.40.20 8 0 65535 0 65535 0 0 1 p acl add 1 172.16.40.20 8 202.16.100.20 8 0 65535 0 65535 0 0 0 -p acl applyruleset
\ No newline at end of file +p acl applyruleset diff --git a/VNFs/vACL/config/IPv6_hwlb_acl.tc b/VNFs/vACL/config/IPv6_hwlb_acl.tc index 41761108..da43b8d8 100644 --- a/VNFs/vACL/config/IPv6_hwlb_acl.tc +++ b/VNFs/vACL/config/IPv6_hwlb_acl.tc @@ -20,9 +20,9 @@ link 1 down link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64 link 1 up -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -routeadd 0 fec0::6a05:caff:fe30:21b0 64 -routeadd 1 2012::6a05:caff:fe30:2081 64 +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +routeadd net 0 fec0::6a05:caff:fe30:21b0 64 +routeadd net 1 2012::6a05:caff:fe30:2081 64 ; IPv6 static ARP ;p 1 arpadd 0 fec0::6a05:caff:fe30:21b0 00:00:00:00:00:01 diff --git a/VNFs/vACL/config/IPv6_swlb_acl.tc b/VNFs/vACL/config/IPv6_swlb_acl.tc index c964609a..8ffc3cc3 100644 --- a/VNFs/vACL/config/IPv6_swlb_acl.tc +++ b/VNFs/vACL/config/IPv6_swlb_acl.tc @@ -20,9 +20,9 @@ link 1 down link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64 link 1 up -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -routeadd 0 fec0::6a05:caff:fe30:21b0 64 -routeadd 1 2012::6a05:caff:fe30:2081 64 +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +routeadd net 0 fec0::6a05:caff:fe30:21b0 64 +routeadd net 1 2012::6a05:caff:fe30:2081 64 ; IPv6 static ARP ;p 1 arpadd 0 fec0::6a05:caff:fe30:21b0 00:00:00:00:00:01 @@ -39,4 +39,4 @@ p action add 1 count ; IPv6 rules p acl add 1 fec0::6a05:caff:fe30:21b0 64 2012::6a05:caff:fe30:2081 64 0 65535 0 65535 0 0 1 p acl add 1 2012::6a05:caff:fe30:2081 64 fec0::6a05:caff:fe30:21b0 64 0 65535 0 65535 0 0 0 -p acl applyruleset
\ No newline at end of file +p acl applyruleset diff --git a/VNFs/vACL/main.c b/VNFs/vACL/main.c index 9ebf6fc3..a6ba00b6 100644 --- a/VNFs/vACL/main.c +++ b/VNFs/vACL/main.c @@ -15,12 +15,14 @@ */ #include "app.h" +#include "pipeline_acl.h" static struct app_params app; int main(int argc, char **argv) { + struct mg_context *ctx = NULL; rte_openlog_stream(stderr); /* Config */ @@ -28,6 +30,12 @@ main(int argc, char **argv) app_config_args(&app, argc, argv); + if (is_rest_support()) { + /* initialize the rest api */ + set_vnf_type("VACL"); + ctx = rest_api_init(&app); + } + app_config_preproc(&app); app_config_parse(&app, app.parser_file); @@ -40,11 +48,21 @@ main(int argc, char **argv) /* Init */ app_init(&app); + if (is_rest_support() && (ctx != NULL)) { + /* rest api's for cgnapt */ + rest_api_acl_init(ctx, &app); + } + /* Run-time */ rte_eal_mp_remote_launch( app_thread, (void *) &app, CALL_MASTER); + if (is_rest_support() && (ctx != NULL)) { + mg_stop(ctx); + printf("Civet server stopped.\n"); + } + return 0; } diff --git a/VNFs/vACL/pipeline/pipeline_acl.c b/VNFs/vACL/pipeline/pipeline_acl.c index 1a4ed4f5..f1935622 100644 --- a/VNFs/vACL/pipeline/pipeline_acl.c +++ b/VNFs/vACL/pipeline/pipeline_acl.c @@ -49,6 +49,13 @@ #include "pipeline_acl_be.h" #include "rte_cnxn_tracking.h" +int acl_load_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int acl_clear_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int acl_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata); +uint32_t rules_loaded = 0; +extern struct cmdline *pipe_cl; +struct app_params *myapp; + /** * A structure defining the ACL rule for the TAILQ Tables. */ @@ -4176,3 +4183,293 @@ struct pipeline_type pipeline_acl = { .be_ops = &pipeline_acl_be_ops, .fe_ops = &pipeline_acl_fe_ops, }; + +void all_acl_stats(struct mg_connection *conn) +{ + + struct app_params *app = myapp; + int i, j; + struct rte_ACL_counter_block acl_counter_sums; + struct rte_CT_counter_block ct_counter_sums; + struct rte_CT_counter_block *ct_counters; + struct action_counter_block action_counter_sum[action_array_max]; + + memset(&acl_counter_sums, 0, sizeof(acl_counter_sums)); + memset(&ct_counter_sums, 0, sizeof(ct_counter_sums)); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "ACL Stats\n"); + for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) { + struct rte_ACL_counter_block *acl_ctrs = + &rte_acl_counter_table[i]; + ct_counters = rte_acl_counter_table[i].ct_counters; + mg_printf(conn, "acl entry[%i] tpkts_processed: %" PRIu64 + ", pkts_drop: %" PRIu64 ", pkts_received: %" PRIu64 + ", bytes_processed: %" PRIu64 "\n", i, + acl_ctrs->tpkts_processed, acl_ctrs->pkts_drop, + acl_ctrs->pkts_received, acl_ctrs->bytes_processed); + + acl_counter_sums.tpkts_processed += acl_ctrs->tpkts_processed; + acl_counter_sums.bytes_processed += acl_ctrs->bytes_processed; + acl_counter_sums.pkts_drop += acl_ctrs->pkts_drop; + acl_counter_sums.pkts_received += acl_ctrs->pkts_received; + ct_counter_sums.pkts_forwarded += ct_counters->pkts_forwarded; + ct_counter_sums.pkts_drop += ct_counters->pkts_drop; + } + + mg_printf(conn, "ACL TOTAL: tpkts_processed: %" PRIu64 ", pkts_drop: %" PRIu64 + ", pkts_received: %" PRIu64 ", bytes_processed: %" PRIu64 "\n\n", + acl_counter_sums.tpkts_processed, + acl_counter_sums.pkts_drop, + acl_counter_sums.pkts_received, + acl_counter_sums.bytes_processed); + + mg_printf(conn, "CT TOTAL: ct_packets_forwarded: %" PRIu64 + ", ct_packets_dropped: %" PRIu64 "\n\n", + ct_counter_sums.pkts_forwarded, ct_counter_sums.pkts_drop); + + for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) { + for (j = 0; j < action_array_max; j++) { + if (action_array_active[j].action_bitmap & + acl_action_count) { + action_counter_sum[j].packetCount += + action_counter_table[i][j].packetCount; + action_counter_sum[j].byteCount += + action_counter_table[i][j].byteCount; + } + } + } + + for (j = 0; j < action_array_max; j++) { + if (action_array_active[j].action_bitmap & acl_action_count) + mg_printf(conn, "Action ID: %02u, packetCount: %" PRIu64 + ", byteCount: %" PRIu64 "\n", j, + action_counter_sum[j].packetCount, + action_counter_sum[j].byteCount); + } + mg_printf(conn, "<p>Command Passed</p>"); + mg_printf(conn, "</body></html>\n"); +} + +int acl_stats_handler(struct mg_connection *conn, void *cbdata) +{ + uint32_t num_links = 0, len = 0; + char buf[1024]; + const struct mg_request_info *ri = mg_get_request_info(conn); + struct app_params *app = myapp; + int i; + + if (!strcmp(ri->request_method, "GET")) { + all_acl_stats(conn); + mg_printf(conn, "%s\n", &buf[0]); + return 1; + } + + if (strcmp(ri->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the GET handler\n", + ri->request_method); + } + + for (i = 0; i <= rte_ACL_hi_counter_block_in_use; i++) { + rte_acl_counter_table[i].tpkts_processed = 0; + rte_acl_counter_table[i].bytes_processed = 0; + rte_acl_counter_table[i].pkts_drop = 0; + rte_acl_counter_table[i].pkts_received = 0; + rte_acl_counter_table[i].pkts_drop_ttl = 0; + rte_acl_counter_table[i].pkts_drop_bad_size = 0; + rte_acl_counter_table[i].pkts_drop_fragmented = 0; + rte_acl_counter_table[i].pkts_drop_without_arp_entry = 0; + rte_acl_counter_table[i].ct_counters->pkts_forwarded = 0; + rte_acl_counter_table[i].ct_counters->pkts_drop = 0; + } + + memset(&action_counter_table, 0, sizeof(action_counter_table)); + + mg_printf(conn, "%s\n", &buf[0]); + return 1; + +} + +int acl_version_handler(struct mg_connection *conn, void *cbdata) +{ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<p>Command Passed</p>"); + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +int acl_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + + const struct mg_request_info *req_info = mg_get_request_info(conn); + if (strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Only GET method allowed"); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are the methods that are supported </h2>"); + mg_printf(conn, "<h3> /load </h3>"); + mg_printf(conn, "<h3> /clear </h3>"); + mg_printf(conn, "<html><body>"); + + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +static int acl_field_found(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, "\r\n\r\n%s:\r\n", key); + mg_printf(conn, "Inside vfw_field_found %s \n", filename); + + if (filename && *filename) { + snprintf(path, pathlen, "/tmp/%s", filename); + struct app_params *app = myapp; + int status; + int fd; + + mg_printf(conn, "path: %s\n", path); + + /* Make sure the file exists before clearing rules and actions */ + fd = open(path, O_RDONLY); + if (fd < 0) { + mg_printf(conn, "Cannot open file \"%s\"\n", filename); + return FORM_FIELD_STORAGE_GET; + } + close(fd); + + return FORM_FIELD_STORAGE_STORE; + } + + return FORM_FIELD_STORAGE_GET; +} + +static int acl_field_get(const char *key, const char *value, size_t valuelen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + if (key[0]) { + mg_printf(conn, "%s = ", key); + } + mg_write(conn, value, valuelen); + + return 0; +} + +static int acl_field_stored(const char *path, long long file_size, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + int status; + + mg_printf(conn, + "stored as %s (%lu bytes)\r\n\r\n", + path, + (unsigned long)file_size); + + /* Clear all rules and actions */ + status = app_pipeline_acl_clearrules(myapp); + + if (status != 0) { + mg_printf(conn, "Command failed\n"); + return 1; + } + + /* Process commands in script file */ + app_loadrules_file(pipe_cl->ctx, path); + rules_loaded = 1; + + return 0; +} + +int acl_load_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + int ret; + const struct mg_request_info *req_info = mg_get_request_info(conn); + struct mg_form_data_handler fdh = {acl_field_found, acl_field_get, + acl_field_stored, 0}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Rule file is %s\n", rules_loaded? "LOADED":"NOT LOADED"); + } + + if (strcmp(req_info->request_method, "PUT")) { + mg_printf(conn, "Only PUT method allowed"); + return 1; + } + + fdh.user_data = (void *)conn; + + /* Call the form handler */ + mg_printf(conn, "Form data:"); + ret = mg_handle_form_request(conn, &fdh); + mg_printf(conn, "\r\n%i fields found", ret); + + return 1; +} + +int acl_clear_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + struct app_params *app = myapp; + int status; + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + status = app_pipeline_acl_clearrules(app); + + if (status != 0) { + mg_printf(conn, "Command failed\n"); + return 1; + } + + mg_printf(conn, "Command Success\n"); + mg_printf(conn, "</body></html>\n"); + return 1; +} + +void rest_api_acl_init(struct mg_context *ctx, struct app_params *app) +{ + myapp = app; + + /* vCGNAPT commands */ + mg_set_request_handler(ctx, "/vnf/config/rules", acl_rules_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/rules/load", acl_load_rules_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/rules/clear", acl_clear_rules_handler, 0); + mg_set_request_handler(ctx, "/vnf/status", acl_version_handler, 0); + mg_set_request_handler(ctx, "/vnf/stats", acl_stats_handler, 0); + +} diff --git a/VNFs/vACL/pipeline/pipeline_acl.h b/VNFs/vACL/pipeline/pipeline_acl.h index 80a85cae..93b92c45 100644 --- a/VNFs/vACL/pipeline/pipeline_acl.h +++ b/VNFs/vACL/pipeline/pipeline_acl.h @@ -28,6 +28,8 @@ #include "pipeline.h" #include "pipeline_acl_be.h" +#include <civetweb.h> +#include <json/json.h> /* ACL IPV4 and IPV6 enable flags for debugging (Default both on) */ extern int acl_ipv4_enabled; @@ -47,6 +49,8 @@ extern void *acl_rule_table_ipv6_standby; #define acl_delete_command 1 #define IPV6_32BIT_LENGTH 4 +void rest_api_acl_init(struct mg_context *ctx, struct app_params *app); + /** * Add ACL rule to the ACL rule table. * Rules are added standby table. diff --git a/VNFs/vACL/pipeline/pipeline_acl_be.c b/VNFs/vACL/pipeline/pipeline_acl_be.c index b6e6076d..d3fa0519 100644 --- a/VNFs/vACL/pipeline/pipeline_acl_be.c +++ b/VNFs/vACL/pipeline/pipeline_acl_be.c @@ -47,6 +47,8 @@ #include "pipeline_actions_common.h" #include "lib_arp.h" #include "lib_icmpv6.h" +#include "gateway.h" + static uint8_t acl_prv_que_port_index[PIPELINE_MAX_PORT_IN]; extern void convert_prefixlen_to_netmask_ipv6(uint32_t depth, uint8_t netmask_ipv6[]); @@ -83,14 +85,6 @@ struct pipeline_acl { struct acl_table_entry *acl_entries_ipv4[RTE_PORT_IN_BURST_SIZE_MAX]; struct acl_table_entry *acl_entries_ipv6[RTE_PORT_IN_BURST_SIZE_MAX]; - /* Local ARP & ND Tables */ - struct lib_arp_route_table_entry - local_lib_arp_route_table[MAX_ARP_RT_ENTRY]; - uint8_t local_lib_arp_route_ent_cnt; - struct lib_nd_route_table_entry - local_lib_nd_route_table[MAX_ND_RT_ENTRY]; - uint8_t local_lib_nd_route_ent_cnt; - } __rte_cache_aligned; /** @@ -147,74 +141,6 @@ static pipeline_msg_req_handler custom_handlers[] = { uint64_t arp_pkts_mask; uint8_t ACL_DEBUG; -uint32_t local_get_nh_ipv4(uint32_t ip, - uint32_t *port, - uint32_t *nhip, struct pipeline_acl *p_acl) -{ - int i; - - for (i = 0; i < p_acl->local_lib_arp_route_ent_cnt; i++) { - if (((p_acl->local_lib_arp_route_table[i].ip & - p_acl->local_lib_arp_route_table[i].mask) == - (ip & p_acl->local_lib_arp_route_table[i].mask))) { - *port = p_acl->local_lib_arp_route_table[i].port; - - *nhip = p_acl->local_lib_arp_route_table[i].nh; - return 1; - } - } - return 0; -} - -static uint32_t local_get_nh_ipv6(uint8_t *ip, - uint32_t *port, - uint8_t nhip[], struct pipeline_acl *p_acl) -{ - int i = 0; - uint8_t netmask_ipv6[16],netip_nd[16],netip_in[16]; - uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0; - memset (netmask_ipv6, 0, sizeof(netmask_ipv6)); - memset (netip_nd, 0, sizeof(netip_nd)); - memset (netip_in, 0, sizeof(netip_in)); - - for (i = 0; i < p_acl->local_lib_nd_route_ent_cnt; i++) { - - convert_prefixlen_to_netmask_ipv6 - (p_acl->local_lib_nd_route_table[i].depth, netmask_ipv6); - - for (k = 0; k < 16; k++) - if (p_acl->local_lib_nd_route_table[i].ipv6[k] & - netmask_ipv6[k]) { - depthflags++; - netip_nd[k] = p_acl-> - local_lib_nd_route_table[i].ipv6[k]; - } - - - for (l = 0; l < 16; l++) - if (ip[l] & netmask_ipv6[l]) { - depthflags1++; - netip_in[l] = ip[l]; - } - - int j = 0; - - if ((depthflags == depthflags1) && (memcmp(netip_nd, netip_in, - sizeof(netip_nd)) == 0)){ - *port = p_acl->local_lib_nd_route_table[i].port; - - for (j = 0; j < 16; j++) - nhip[j] = - p_acl->local_lib_nd_route_table[i]. - nhipv6[j]; - return 1; - } - - depthflags = 0; - depthflags1 = 0; - } - return 0; -} static uint8_t check_arp_icmp(struct rte_mbuf *pkt, uint64_t pkt_mask, struct pipeline_acl *p_acl) @@ -396,675 +322,689 @@ void print_pkt_acl(struct rte_mbuf *pkt) */ static int pkt_work_acl_key(struct rte_pipeline *p, - struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) + struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) { - struct pipeline_acl *p_acl = arg; - - p_acl->counters->pkts_received = - p_acl->counters->pkts_received + n_pkts; - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_received: %" PRIu64 - " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); - - uint64_t lookup_hit_mask = 0; - uint64_t lookup_hit_mask_ipv4 = 0; - uint64_t lookup_hit_mask_ipv6 = 0; - uint64_t lookup_miss_mask = 0; - uint64_t conntrack_mask = 0; - uint64_t connexist_mask = 0; - uint32_t dest_address = 0; - arp_pkts_mask = 0; - int dest_if = 0; - int status; - uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); - uint64_t keep_mask = pkts_mask; - uint16_t port; - uint32_t ret; - - p_acl->in_port_time_stamp = rte_get_tsc_cycles(); - - if (acl_ipv4_enabled) { - if (ACL_DEBUG) - printf("ACL IPV4 Lookup Mask Before = %p\n", - (void *)pkts_mask); - status = - rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts, - pkts_mask, &lookup_hit_mask_ipv4, - (void **) - p_acl->acl_entries_ipv4); - if (ACL_DEBUG) - printf("ACL IPV4 Lookup Mask After = %p\n", - (void *)lookup_hit_mask_ipv4); - } - - if (acl_ipv6_enabled) { - if (ACL_DEBUG) - printf("ACL IPV6 Lookup Mask Before = %p\n", - (void *)pkts_mask); - status = - rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts, - pkts_mask, &lookup_hit_mask_ipv6, - (void **) - p_acl->acl_entries_ipv6); - if (ACL_DEBUG) - printf("ACL IPV6 Lookup Mask After = %p\n", - (void *)lookup_hit_mask_ipv6); - } - - /* Merge lookup results since we process both IPv4 and IPv6 below */ - lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; - if (ACL_DEBUG) - printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); - - lookup_miss_mask = pkts_mask & (~lookup_hit_mask); - pkts_mask = lookup_hit_mask; - p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", - p_acl->counters->pkts_drop, - __builtin_popcountll(lookup_miss_mask)); - - uint64_t pkts_to_process = lookup_hit_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - if (enable_hwlb) - if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { - pkts_mask &= ~(1LLU << pos); - continue; - } - - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - - if (hdr_chk == IPv4_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - " %lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, - dscp_offset); - *dscp = - action_array_active[action_id].dscp_priority - << 2; - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack enabled: " - "%p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } - - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist enabled " - "conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } - - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DSCP_OFST_IPV6; - uint16_t *dscp = - RTE_MBUF_METADATA_UINT16_PTR(pkt, - dscp_offset); - uint16_t dscp_value = - (rte_bswap16 - (RTE_MBUF_METADATA_UINT16 - (pkt, dscp_offset)) & 0XF00F); - uint8_t dscp_store = - action_array_active[action_id].dscp_priority - << 2; - uint16_t dscp_temp = dscp_store; - - dscp_temp = dscp_temp << 4; - *dscp = rte_bswap16(dscp_temp | dscp_value); - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack enabled: " - " %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } - - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist enabled " - "conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } - } - - /* Only call connection tracker if required */ - if (conntrack_mask > 0) { - if (ACL_DEBUG) - printf - ("ACL Call Conntrack Before = %p Connexist = %p\n", - (void *)conntrack_mask, (void *)connexist_mask); - conntrack_mask = - rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control - (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); - if (ACL_DEBUG) - printf("ACL Call Conntrack After = %p\n", - (void *)conntrack_mask); - - /* Only change pkt mask for pkts that have conntrack enabled */ - /* Need to loop through packets to check if conntrack enabled */ - pkts_to_process = pkts_mask; - for (; pkts_to_process;) { - uint32_t action_id = 0; - uint8_t pos = - (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, - MBUF_HDR_ROOM - + - ETH_HDR_SIZE); - - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - if (hdr_chk == IPv4_HDR_VERSION) { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - action_id = entry->action_id; - } else { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - action_id = entry->action_id; - } - - if ((action_array_active[action_id].action_bitmap & - acl_action_conntrack) - || (action_array_active[action_id].action_bitmap & - acl_action_connexist)) { - - if (conntrack_mask & pkt_mask) { - if (ACL_DEBUG) - printf("ACL Conntrack Accept " - "packet = %p\n", - (void *)pkt_mask); - } else { - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL Conntrack Drop " - "packet = %p\n", - (void *)pkt_mask); - pkts_mask &= ~pkt_mask; - p_acl->counters->pkts_drop++; - } - } - } - } - - pkts_to_process = pkts_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - - if (hdr_chk == IPv4_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - uint16_t phy_port = pkt->port; - uint32_t *port_out_id = - RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - output_port)); - if (ACL_DEBUG) - printf - ("phy_port = %i, links_map[phy_port] = %i\n", - phy_port, p_acl->links_map[phy_port]); - - /* header room + eth hdr size + dst_adr offset in ip header */ - uint32_t dst_addr_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST; - uint32_t *dst_addr = - RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset); - uint8_t *eth_dest = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM); - uint8_t *eth_src = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6); - struct ether_addr hw_addr; - uint32_t dest_address = rte_bswap32(*dst_addr); - uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET - + - offsetof - (struct - mbuf_acl_meta_data, - nhip)); - uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); - *nhip = 0; - struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port - (dest_address, &dest_if, (struct ether_addr *) eth_dest); - *port_out_id = p_acl->port_out_id[dest_if]; - if (arp_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), - (struct ether_addr *)eth_src); - update_nhip_access(dest_if); - if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { - printf("sending buffered packets\n"); - arp_send_buffered_pkts(ret_arp_data, - (struct ether_addr *)eth_dest, *port_out_id); - - } - p_acl->counters->tpkts_processed++; - p_acl->counters->bytes_processed += - packet_length; - } else { - if (unlikely(ret_arp_data == NULL)) { - if (ACL_DEBUG) - printf("%s: NHIP Not Found, " - "outport_id: %d\n", __func__, - *port_out_id); - - /* Drop the pkt */ - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } + struct pipeline_acl *p_acl = arg; + + p_acl->counters->pkts_received = + p_acl->counters->pkts_received + n_pkts; + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_received: %" PRIu64 + " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); + + uint64_t lookup_hit_mask = 0; + uint64_t lookup_hit_mask_ipv4 = 0; + uint64_t lookup_hit_mask_ipv6 = 0; + uint64_t lookup_miss_mask = 0; + uint64_t conntrack_mask = 0; + uint64_t connexist_mask = 0; + uint32_t dest_address = 0; + arp_pkts_mask = 0; + int status; + uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); + uint64_t keep_mask = pkts_mask; + uint16_t port; + uint32_t ret; + + p_acl->in_port_time_stamp = rte_get_tsc_cycles(); + + if (acl_ipv4_enabled) { + if (ACL_DEBUG) + printf("ACL IPV4 Lookup Mask Before = %p\n", + (void *)pkts_mask); + status = + rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts, + pkts_mask, &lookup_hit_mask_ipv4, + (void **) + p_acl->acl_entries_ipv4); + if (ACL_DEBUG) + printf("ACL IPV4 Lookup Mask After = %p\n", + (void *)lookup_hit_mask_ipv4); + } + + if (acl_ipv6_enabled) { + if (ACL_DEBUG) + printf("ACL IPV6 Lookup Mask Before = %p\n", + (void *)pkts_mask); + status = + rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts, + pkts_mask, &lookup_hit_mask_ipv6, + (void **) + p_acl->acl_entries_ipv6); + if (ACL_DEBUG) + printf("ACL IPV6 Lookup Mask After = %p\n", + (void *)lookup_hit_mask_ipv6); + } + + /* Merge lookup results since we process both IPv4 and IPv6 below */ + lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; + if (ACL_DEBUG) + printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); + + lookup_miss_mask = pkts_mask & (~lookup_hit_mask); + pkts_mask = lookup_hit_mask; + p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", + p_acl->counters->pkts_drop, + __builtin_popcountll(lookup_miss_mask)); + + uint64_t pkts_to_process = lookup_hit_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + if (enable_hwlb) + if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { + pkts_mask &= ~(1LLU << pos); + continue; + } + + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + + if (hdr_chk == IPv4_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + " %lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, + dscp_offset); + *dscp = + action_array_active[action_id].dscp_priority + << 2; + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack enabled: " + "%p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if (ret_arp_data->status == INCOMPLETE || - ret_arp_data->status == PROBE) { - if (ret_arp_data->num_pkts >= NUM_DESC) { - /* Drop the pkt */ - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - arp_queue_unresolved_packet(ret_arp_data, - pkt); - continue; - } - } - } + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist enabled " + "conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } - } /* end of if (hdr_chk == IPv4_HDR_VERSION) */ - - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - //uint16_t phy_port = entry->head.port_id; - uint16_t phy_port = pkt->port; - uint32_t *port_out_id = - RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - output_port)); - /*if (is_phy_port_privte(phy_port)) - *port_out_id = ACL_PUB_PORT_ID; - else - *port_out_id = ACL_PRV_PORT_ID;*/ - - /* *port_out_id = p_acl->links_map[phy_port]; */ - if (ACL_DEBUG) - printf("phy_port = %i, " - "links_map[phy_port] = %i\n", - phy_port, p_acl->links_map[phy_port]); - - /* header room + eth hdr size + dst_adr offset in ip header */ - uint32_t dst_addr_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DST_ADR_OFST_IPV6; - uint8_t *eth_dest = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM); - uint8_t *eth_src = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6); - struct ether_addr hw_addr; - uint8_t dest_address[16]; - uint8_t nhip[16]; - - nhip[0] = - RTE_MBUF_METADATA_UINT8(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - nhip)); - uint8_t *dst_addr[16]; - uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); - int i = 0; - - for (i = 0; i < 16; i++) { - dst_addr[i] = - RTE_MBUF_METADATA_UINT8_PTR(pkt, - dst_addr_offset - + i); - } - memcpy(dest_address, *dst_addr, sizeof(dest_address)); - memset(nhip, 0, sizeof(nhip)); - - struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port - (dest_address, &dest_if, &hw_addr, &nhip[0]); - *port_out_id = p_acl->port_out_id[dest_if]; - if (nd_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), - (struct ether_addr *)eth_src); - update_nhip_access(dest_if); - - if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { - printf("sending buffered packets\n"); - p_acl->counters->tpkts_processed += - ret_nd_data->num_pkts; - nd_send_buffered_pkts(ret_nd_data, - (struct ether_addr *)eth_dest, *port_out_id); - } - p_acl->counters->tpkts_processed++; - p_acl->counters->bytes_processed += - packet_length; - } else { - if (unlikely(ret_nd_data == NULL)) { - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } + if (hdr_chk == IPv6_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + + IP_HDR_DSCP_OFST_IPV6; + uint16_t *dscp = + RTE_MBUF_METADATA_UINT16_PTR(pkt, + dscp_offset); + uint16_t dscp_value = + (rte_bswap16 + (RTE_MBUF_METADATA_UINT16 + (pkt, dscp_offset)) & 0XF00F); + uint8_t dscp_store = + action_array_active[action_id].dscp_priority + << 2; + uint16_t dscp_temp = dscp_store; + + dscp_temp = dscp_temp << 4; + *dscp = rte_bswap16(dscp_temp | dscp_value); + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack enabled: " + " %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if (ret_nd_data->status == INCOMPLETE || - ret_nd_data->status == PROBE) { - if (ret_nd_data->num_pkts >= NUM_DESC) { - /* Drop the pkt */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - nd_queue_unresolved_packet(ret_nd_data, - pkt); - continue; - } - } + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist enabled " + "conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } + } + + /* Only call connection tracker if required */ + if (conntrack_mask > 0) { + if (ACL_DEBUG) + printf + ("ACL Call Conntrack Before = %p Connexist = %p\n", + (void *)conntrack_mask, (void *)connexist_mask); + conntrack_mask = + rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control + (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); + if (ACL_DEBUG) + printf("ACL Call Conntrack After = %p\n", + (void *)conntrack_mask); + + /* Only change pkt mask for pkts that have conntrack enabled */ + /* Need to loop through packets to check if conntrack enabled */ + pkts_to_process = pkts_mask; + for (; pkts_to_process;) { + uint32_t action_id = 0; + uint8_t pos = + (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, + MBUF_HDR_ROOM + + + ETH_HDR_SIZE); + + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + if (hdr_chk == IPv4_HDR_VERSION) { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + action_id = entry->action_id; + } else { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + action_id = entry->action_id; + } + + if ((action_array_active[action_id].action_bitmap & + acl_action_conntrack) + || (action_array_active[action_id].action_bitmap & + acl_action_connexist)) { + + if (conntrack_mask & pkt_mask) { + if (ACL_DEBUG) + printf("ACL Conntrack Accept " + "packet = %p\n", + (void *)pkt_mask); + } else { + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf("ACL Conntrack Drop " + "packet = %p\n", + (void *)pkt_mask); + pkts_mask &= ~pkt_mask; + p_acl->counters->pkts_drop++; + } + } + } + } + + pkts_to_process = pkts_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + + if (hdr_chk == IPv4_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + uint16_t phy_port = pkt->port; + uint32_t *port_out_id = + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + + offsetof(struct + mbuf_acl_meta_data, + output_port)); + if (ACL_DEBUG) + printf + ("phy_port = %i, links_map[phy_port] = %i\n", + phy_port, p_acl->links_map[phy_port]); + uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); + + uint32_t dest_if = INVALID_DESTIF; + uint32_t src_phy_port = pkt->port; + + if(is_gateway()){ + + /* Gateway Proc Starts */ + struct ether_hdr *ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + MBUF_HDR_ROOM); + + struct ipv4_hdr *ipv4hdr = (struct ipv4_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); + + struct arp_entry_data *ret_arp_data = NULL; + struct ether_addr dst_mac; + uint32_t nhip = 0; + uint32_t dst_ip_addr = rte_bswap32(ipv4hdr->dst_addr); + + gw_get_nh_port_ipv4(dst_ip_addr, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &dst_mac); + + /* Gateway Proc Ends */ + if (arp_cache_dest_mac_present(dest_if)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dest_if), &ehdr->s_addr); + + *port_out_id = p_acl->port_out_id[dest_if]; + + update_nhip_access(dest_if); + if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { + printf("sending buffered packets\n"); + arp_send_buffered_pkts(ret_arp_data, &ehdr->d_addr, + p_acl->port_out_id[dest_if]); + + } + p_acl->counters->tpkts_processed++; + p_acl->counters->bytes_processed += + packet_length; + } else { + if (unlikely(ret_arp_data == NULL)) { + if (ACL_DEBUG) + printf("%s: NHIP Not Found, " + "outport_id: %d\n", __func__, + p_acl->port_out_id[dest_if]); + + /* Drop the pkt */ + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } + + if (ret_arp_data->status == INCOMPLETE || + ret_arp_data->status == PROBE) { + if (ret_arp_data->num_pkts >= NUM_DESC) { + /* Drop the pkt */ + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } else { + arp_pkts_mask |= pkt_mask; + arp_queue_unresolved_packet(ret_arp_data, + pkt); + continue; + } + } + } + + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dest_if = prv_to_pub_map[src_phy_port]; + else + dest_if = pub_to_prv_map[src_phy_port]; + + *port_out_id = p_acl->port_out_id[dest_if]; + } + + } /* end of if (hdr_chk == IPv4_HDR_VERSION) */ + + if (hdr_chk == IPv6_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + //uint16_t phy_port = entry->head.port_id; + uint16_t phy_port = pkt->port; + uint32_t *port_out_id = + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + + offsetof(struct + mbuf_acl_meta_data, + output_port)); + if (ACL_DEBUG) + printf("phy_port = %i, " + "links_map[phy_port] = %i\n", + phy_port, p_acl->links_map[phy_port]); + + uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); + + uint32_t dest_if = INVALID_DESTIF; + uint32_t src_phy_port = pkt->port; + + if(is_gateway()){ + + /* Gateway Proc Starts */ + struct ipv6_hdr *ipv6hdr = (struct ipv6_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); + + struct ether_hdr *ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + MBUF_HDR_ROOM); + + struct ether_addr dst_mac; + uint8_t nhipv6[IPV6_ADD_SIZE]; + uint8_t dest_ipv6_address[IPV6_ADD_SIZE]; + struct nd_entry_data *ret_nd_data = NULL; + + memset(nhipv6, 0, IPV6_ADD_SIZE); + rte_mov16(dest_ipv6_address, (uint8_t *)ipv6hdr->dst_addr); + + gw_get_nh_port_ipv6(dest_ipv6_address, + &dest_if, nhipv6); + + ret_nd_data = get_dest_mac_addr_ipv6(nhipv6, dest_if, &dst_mac); + + /* Gateway Proc Ends */ + + if (nd_cache_dest_mac_present(dest_if)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dest_if), &ehdr->s_addr); + + *port_out_id = p_acl->port_out_id[dest_if]; + + update_nhip_access(dest_if); + + if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { + printf("sending buffered packets\n"); + p_acl->counters->tpkts_processed += + ret_nd_data->num_pkts; + nd_send_buffered_pkts(ret_nd_data, &ehdr->d_addr, + p_acl->port_out_id[dest_if]); + } + p_acl->counters->tpkts_processed++; + p_acl->counters->bytes_processed += + packet_length; + } else { + if (unlikely(ret_nd_data == NULL)) { + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } + + if (ret_nd_data->status == INCOMPLETE || + ret_nd_data->status == PROBE) { + if (ret_nd_data->num_pkts >= NUM_DESC) { + /* Drop the pkt */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } else { + arp_pkts_mask |= pkt_mask; + nd_queue_unresolved_packet(ret_nd_data, + pkt); + continue; + } + } + } - } + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dest_if = prv_to_pub_map[src_phy_port]; + else + dest_if = pub_to_prv_map[src_phy_port]; - } /* if (hdr_chk == IPv6_HDR_VERSION) */ + *port_out_id = p_acl->port_out_id[dest_if]; + } + } - } + } /* if (hdr_chk == IPv6_HDR_VERSION) */ - pkts_drop_mask = keep_mask & ~pkts_mask; - rte_pipeline_ah_packet_drop(p, pkts_drop_mask); - keep_mask = pkts_mask; + pkts_drop_mask = keep_mask & ~pkts_mask; + rte_pipeline_ah_packet_drop(p, pkts_drop_mask); + keep_mask = pkts_mask; - if (arp_pkts_mask) { - keep_mask &= ~(arp_pkts_mask); - rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); - } + if (arp_pkts_mask) { + keep_mask &= ~(arp_pkts_mask); + rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); + } - /* don't bother measuring if traffic very low, might skew stats */ - uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); + /* don't bother measuring if traffic very low, might skew stats */ + uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); - if (packets_this_iteration > 1) { - uint64_t latency_this_iteration = - rte_get_tsc_cycles() - p_acl->in_port_time_stamp; + if (packets_this_iteration > 1) { + uint64_t latency_this_iteration = + rte_get_tsc_cycles() - p_acl->in_port_time_stamp; - p_acl->counters->sum_latencies += latency_this_iteration; - p_acl->counters->count_latencies++; - } + p_acl->counters->sum_latencies += latency_this_iteration; + p_acl->counters->count_latencies++; + } - if (ACL_DEBUG) - printf("Leaving pkt_work_acl_key pkts_mask = %p\n", - (void *)pkts_mask); + if (ACL_DEBUG) + printf("Leaving pkt_work_acl_key pkts_mask = %p\n", + (void *)pkts_mask); - return 0; + return 0; } /** @@ -1093,674 +1033,559 @@ pkt_work_acl_key(struct rte_pipeline *p, */ static int pkt_work_acl_ipv4_key(struct rte_pipeline *p, - struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) + struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) { - struct pipeline_acl *p_acl = arg; - - p_acl->counters->pkts_received = - p_acl->counters->pkts_received + n_pkts; - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_received: %" PRIu64 - " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); - - uint64_t lookup_hit_mask = 0; - uint64_t lookup_hit_mask_ipv4 = 0; - uint64_t lookup_hit_mask_ipv6 = 0; - uint64_t lookup_miss_mask = 0; - uint64_t conntrack_mask = 0; - uint64_t connexist_mask = 0; - uint32_t dest_address = 0; - arp_pkts_mask = 0; - int dest_if = 0; - int status; - uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); - uint64_t keep_mask = pkts_mask; - uint16_t port; - uint32_t ret; - - p_acl->in_port_time_stamp = rte_get_tsc_cycles(); - - if (acl_ipv4_enabled) { - if (ACL_DEBUG) - printf("ACL IPV4 Lookup Mask Before = %p\n", - (void *)pkts_mask); - status = - rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts, - pkts_mask, &lookup_hit_mask_ipv4, - (void **) - p_acl->acl_entries_ipv4); - if (ACL_DEBUG) - printf("ACL IPV4 Lookup Mask After = %p\n", - (void *)lookup_hit_mask_ipv4); - } - - /* Merge lookup results since we process both IPv4 and IPv6 below */ - lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; - if (ACL_DEBUG) - printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); - - lookup_miss_mask = pkts_mask & (~lookup_hit_mask); - pkts_mask = lookup_hit_mask; - p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", - p_acl->counters->pkts_drop, - __builtin_popcountll(lookup_miss_mask)); - - uint64_t pkts_to_process = lookup_hit_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - if (enable_hwlb) - if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { - pkts_mask &= ~(1LLU << pos); - continue; - } - - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - - if (hdr_chk == IPv4_HDR_VERSION) { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - " %lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, - dscp_offset); - *dscp = - action_array_active[action_id].dscp_priority - << 2; - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack " - "enabled: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } + struct pipeline_acl *p_acl = arg; + + p_acl->counters->pkts_received = + p_acl->counters->pkts_received + n_pkts; + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_received: %" PRIu64 + " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); + + uint64_t lookup_hit_mask = 0; + uint64_t lookup_hit_mask_ipv4 = 0; + uint64_t lookup_hit_mask_ipv6 = 0; + uint64_t lookup_miss_mask = 0; + uint64_t conntrack_mask = 0; + uint64_t connexist_mask = 0; + uint32_t dest_address = 0; + arp_pkts_mask = 0; + int status; + uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); + uint64_t keep_mask = pkts_mask; + uint16_t port; + uint32_t ret; + + p_acl->in_port_time_stamp = rte_get_tsc_cycles(); + + if (acl_ipv4_enabled) { + if (ACL_DEBUG) + printf("ACL IPV4 Lookup Mask Before = %p\n", + (void *)pkts_mask); + status = + rte_table_acl_ops.f_lookup(acl_rule_table_ipv4_active, pkts, + pkts_mask, &lookup_hit_mask_ipv4, + (void **) + p_acl->acl_entries_ipv4); + if (ACL_DEBUG) + printf("ACL IPV4 Lookup Mask After = %p\n", + (void *)lookup_hit_mask_ipv4); + } + + /* Merge lookup results since we process both IPv4 and IPv6 below */ + lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; + if (ACL_DEBUG) + printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); + + lookup_miss_mask = pkts_mask & (~lookup_hit_mask); + pkts_mask = lookup_hit_mask; + p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", + p_acl->counters->pkts_drop, + __builtin_popcountll(lookup_miss_mask)); + + uint64_t pkts_to_process = lookup_hit_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + if (enable_hwlb) + if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { + pkts_mask &= ~(1LLU << pos); + continue; + } + + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + + if (hdr_chk == IPv4_HDR_VERSION) { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + " %lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, + dscp_offset); + *dscp = + action_array_active[action_id].dscp_priority + << 2; + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack " + "enabled: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist " - "enabled conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist " + "enabled conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } #if 0 - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf - ("ACL before drop pkt_mask %lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf - ("ACL after drop pkt_mask %lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DSCP_OFST_IPV6; - uint16_t *dscp = - RTE_MBUF_METADATA_UINT16_PTR(pkt, - dscp_offset); - uint16_t dscp_value = - (rte_bswap16 - (RTE_MBUF_METADATA_UINT16 - (pkt, dscp_offset)) & 0XF00F); - uint8_t dscp_store = - action_array_active[action_id].dscp_priority - << 2; - uint16_t dscp_temp = dscp_store; - - dscp_temp = dscp_temp << 4; - *dscp = rte_bswap16(dscp_temp | dscp_value); - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack " - "enabled: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } + if (hdr_chk == IPv6_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf + ("ACL before drop pkt_mask %lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf + ("ACL after drop pkt_mask %lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + + IP_HDR_DSCP_OFST_IPV6; + uint16_t *dscp = + RTE_MBUF_METADATA_UINT16_PTR(pkt, + dscp_offset); + uint16_t dscp_value = + (rte_bswap16 + (RTE_MBUF_METADATA_UINT16 + (pkt, dscp_offset)) & 0XF00F); + uint8_t dscp_store = + action_array_active[action_id].dscp_priority + << 2; + uint16_t dscp_temp = dscp_store; + + dscp_temp = dscp_temp << 4; + *dscp = rte_bswap16(dscp_temp | dscp_value); + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack " + "enabled: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist enabled " - "conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist enabled " + "conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } #endif - } - /* Only call connection tracker if required */ - if (conntrack_mask > 0) { - if (ACL_DEBUG) - printf - ("ACL Call Conntrack Before = %p Connexist = %p\n", - (void *)conntrack_mask, (void *)connexist_mask); - conntrack_mask = - rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control - (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); - if (ACL_DEBUG) - printf("ACL Call Conntrack After = %p\n", - (void *)conntrack_mask); - - /* Only change pkt mask for pkts that have conntrack enabled */ - /* Need to loop through packets to check if conntrack enabled */ - pkts_to_process = pkts_mask; - for (; pkts_to_process;) { - uint32_t action_id = 0; - uint8_t pos = - (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, - MBUF_HDR_ROOM - + - ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - if (hdr_chk == IPv4_HDR_VERSION) { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - action_id = entry->action_id; - } else { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - action_id = entry->action_id; - } - - if ((action_array_active[action_id].action_bitmap & - acl_action_conntrack) - || (action_array_active[action_id].action_bitmap & - acl_action_connexist)) { - - if (conntrack_mask & pkt_mask) { - if (ACL_DEBUG) - printf("ACL Conntrack Accept " - "packet = %p\n", - (void *)pkt_mask); - } else { + } + /* Only call connection tracker if required */ + if (conntrack_mask > 0) { + if (ACL_DEBUG) + printf + ("ACL Call Conntrack Before = %p Connexist = %p\n", + (void *)conntrack_mask, (void *)connexist_mask); + conntrack_mask = + rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control + (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); + if (ACL_DEBUG) + printf("ACL Call Conntrack After = %p\n", + (void *)conntrack_mask); + + /* Only change pkt mask for pkts that have conntrack enabled */ + /* Need to loop through packets to check if conntrack enabled */ + pkts_to_process = pkts_mask; + for (; pkts_to_process;) { + uint32_t action_id = 0; + uint8_t pos = + (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, + MBUF_HDR_ROOM + + + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + if (hdr_chk == IPv4_HDR_VERSION) { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + action_id = entry->action_id; + } else { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + action_id = entry->action_id; + } + + if ((action_array_active[action_id].action_bitmap & + acl_action_conntrack) + || (action_array_active[action_id].action_bitmap & + acl_action_connexist)) { + + if (conntrack_mask & pkt_mask) { + if (ACL_DEBUG) + printf("ACL Conntrack Accept " + "packet = %p\n", + (void *)pkt_mask); + } else { /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL Conntrack Drop " - "packet = %p\n", - (void *)pkt_mask); - pkts_mask &= ~pkt_mask; - p_acl->counters->pkts_drop++; - } - } - } - } - - pkts_to_process = pkts_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - - if (hdr_chk == IPv4_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - //uint16_t phy_port = entry->head.port_id; - uint16_t phy_port = pkt->port; - uint32_t *port_out_id = - RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - output_port)); - /* *port_out_id = p_acl->links_map[phy_port]; */ -/* if (is_phy_port_privte(phy_port)) - *port_out_id = ACL_PUB_PORT_ID; - else - *port_out_id = ACL_PRV_PORT_ID;*/ - if (ACL_DEBUG) - printf - ("phy_port = %i, links_map[phy_port] = %i\n", - phy_port, p_acl->links_map[phy_port]); - - /* header room + eth hdr size + dst_adr offset in ip header */ - uint32_t dst_addr_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DST_ADR_OFST; - uint32_t *dst_addr = - RTE_MBUF_METADATA_UINT32_PTR(pkt, dst_addr_offset); - uint8_t *eth_dest = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM); - uint8_t *eth_src = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6); - struct ether_addr hw_addr; - uint32_t dest_address = rte_bswap32(*dst_addr); - uint32_t *nhip = RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET - + - offsetof - (struct - mbuf_acl_meta_data, - nhip)); - uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); - *nhip = 0; - dest_address = rte_bswap32(*dst_addr); - struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port - (dest_address, &dest_if, (struct ether_addr *)eth_dest); - *port_out_id = p_acl->port_out_id[dest_if]; - - if (arp_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), - (struct ether_addr *)eth_src); - update_nhip_access(dest_if); - if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { - printf("sending buffered packets\n"); - arp_send_buffered_pkts(ret_arp_data, - (struct ether_addr *)eth_dest, *port_out_id); - - } - p_acl->counters->tpkts_processed++; - p_acl->counters->bytes_processed += - packet_length; - } else { - if (unlikely(ret_arp_data == NULL)) { - - if (ACL_DEBUG) - printf("%s: NHIP Not Found, " - "outport_id: %d\n", __func__, - *port_out_id); - - /* Drop the pkt */ - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } - - if (ret_arp_data->status == INCOMPLETE || - ret_arp_data->status == PROBE) { - if (ret_arp_data->num_pkts >= NUM_DESC) { - /* Drop the pkt */ - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - arp_queue_unresolved_packet(ret_arp_data, pkt); - continue; - } - } - } - } -#if 0 - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t *port_out_id = - RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - output_port)); - if (is_phy_port_privte(phy_port)) - *port_out_id = ACL_PUB_PORT_ID; - else - *port_out_id = ACL_PRV_PORT_ID; - - /* *port_out_id = p_acl->links_map[phy_port]; */ - if (ACL_DEBUG) - printf - ("phy_port = %i, links_map[phy_port] = %i\n", - phy_port, p_acl->links_map[phy_port]); - - /* header room + eth hdr size + dst_adr offset in ip header */ - uint32_t dst_addr_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DST_ADR_OFST_IPV6; - uint8_t *eth_dest = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM); - uint8_t *eth_src = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6); - struct ether_addr hw_addr; - uint8_t dest_address[16]; - uint8_t nhip[16]; - - nhip[0] = - RTE_MBUF_METADATA_UINT8(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - nhip)); - uint8_t *dst_addr[16]; - uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); - int i = 0; - - for (i = 0; i < 16; i++) { - dst_addr[i] = - RTE_MBUF_METADATA_UINT8_PTR(pkt, - dst_addr_offset - + i); - } - memcpy(dest_address, *dst_addr, sizeof(dest_address)); - memset(nhip, 0, sizeof(nhip)); - if (is_phy_port_privte(phy_port)) - port = ACL_PUB_PORT_ID; - else - port = ACL_PRV_PORT_ID; - - if (get_dest_mac_address_ipv6_port - (dest_address, port, &hw_addr, &nhip[0])) { - if (ACL_DEBUG) { - - printf - ("MAC found for port %d - %02x:%02x:%02x:%02x:%02x:%02x\n", - phy_port, hw_addr.addr_bytes[0], - hw_addr.addr_bytes[1], - hw_addr.addr_bytes[2], - hw_addr.addr_bytes[3], - hw_addr.addr_bytes[4], - hw_addr.addr_bytes[5]); - printf - ("Dest MAC before - %02x:%02x:%02x:%02x:%02x:%02x\n", - eth_dest[0], eth_dest[1], - eth_dest[2], eth_dest[3], - eth_dest[4], eth_dest[5]); - } - memcpy(eth_dest, &hw_addr, - sizeof(struct ether_addr)); - if (ACL_DEBUG) { - printf("PktP %p, dest_macP %p\n", pkt, - eth_dest); - printf - ("Dest MAC after - %02x:%02x:%02x:%02x:%02x:%02x\n", - eth_dest[0], eth_dest[1], - eth_dest[2], eth_dest[3], - eth_dest[4], eth_dest[5]); - } - if (is_phy_port_privte(phy_port)) - memcpy(eth_src, - get_link_hw_addr(dest_if), - sizeof(struct ether_addr)); - else - memcpy(eth_src, - get_link_hw_addr(dest_if), - sizeof(struct ether_addr)); - - /* - * memcpy(eth_src, get_link_hw_addr(p_acl->links_map[phy_port]), - * sizeof(struct ether_addr)); - */ - p_acl->counters->tpkts_processed++; - p_acl->counters->bytes_processed += - packet_length; - } - - else { - - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - " %lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - } - } -#endif - - } + if (ACL_DEBUG) + printf("ACL Conntrack Drop " + "packet = %p\n", + (void *)pkt_mask); + pkts_mask &= ~pkt_mask; + p_acl->counters->pkts_drop++; + } + } + } + } + + pkts_to_process = pkts_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + + if (hdr_chk == IPv4_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + //uint16_t phy_port = entry->head.port_id; + uint16_t phy_port = pkt->port; + uint32_t *port_out_id = + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + + offsetof(struct + mbuf_acl_meta_data, + output_port)); + if (ACL_DEBUG) + printf + ("phy_port = %i, links_map[phy_port] = %i\n", + phy_port, p_acl->links_map[phy_port]); + + uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); + + uint32_t dest_if = INVALID_DESTIF; + uint32_t src_phy_port = pkt->port; + + if(is_gateway()){ + + /* Gateway Proc Starts */ + struct ether_hdr *ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + MBUF_HDR_ROOM); + + struct ipv4_hdr *ipv4hdr = (struct ipv4_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); + + struct arp_entry_data *ret_arp_data = NULL; + struct ether_addr dst_mac; + uint32_t dest_if = INVALID_DESTIF; + uint32_t nhip = 0; + uint32_t src_phy_port = pkt->port; + uint32_t dst_ip_addr = rte_bswap32(ipv4hdr->dst_addr); + + gw_get_nh_port_ipv4(dst_ip_addr, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &dst_mac); + + /* Gateway Proc Ends */ + if (arp_cache_dest_mac_present(dest_if)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dest_if), &ehdr->s_addr); + + *port_out_id = p_acl->port_out_id[dest_if]; + + update_nhip_access(dest_if); + if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { + printf("sending buffered packets\n"); + arp_send_buffered_pkts(ret_arp_data, &ehdr->d_addr, + p_acl->port_out_id[dest_if]); + } + p_acl->counters->tpkts_processed++; + p_acl->counters->bytes_processed += packet_length; + } else { + if (unlikely(ret_arp_data == NULL)) { + + if (ACL_DEBUG) + printf("%s: NHIP Not Found, " + "outport_id: %d\n", __func__, + p_acl->port_out_id[dest_if]); + + /* Drop the pkt */ + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } + + if (ret_arp_data->status == INCOMPLETE || + ret_arp_data->status == PROBE) { + if (ret_arp_data->num_pkts >= NUM_DESC) { + /* Drop the pkt */ + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } else { + arp_pkts_mask |= pkt_mask; + arp_queue_unresolved_packet(ret_arp_data, pkt); + continue; + } + } + } - pkts_drop_mask = keep_mask & ~pkts_mask; - rte_pipeline_ah_packet_drop(p, pkts_drop_mask); - keep_mask = pkts_mask; + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dest_if = prv_to_pub_map[src_phy_port]; + else + dest_if = pub_to_prv_map[src_phy_port]; - if (arp_pkts_mask) { - keep_mask &= ~(arp_pkts_mask); - rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); - } + *port_out_id = p_acl->port_out_id[dest_if]; + } - /* don't bother measuring if traffic very low, might skew stats */ - uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); - - if (packets_this_iteration > 1) { - uint64_t latency_this_iteration = - rte_get_tsc_cycles() - p_acl->in_port_time_stamp; - p_acl->counters->sum_latencies += latency_this_iteration; - p_acl->counters->count_latencies++; - } - if (ACL_DEBUG) - printf("Leaving pkt_work_acl_key pkts_mask = %p\n", - (void *)pkts_mask); + } - return 0; + } + pkts_drop_mask = keep_mask & ~pkts_mask; + rte_pipeline_ah_packet_drop(p, pkts_drop_mask); + keep_mask = pkts_mask; + + if (arp_pkts_mask) { + keep_mask &= ~(arp_pkts_mask); + rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); + } + + /* don't bother measuring if traffic very low, might skew stats */ + uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); + + if (packets_this_iteration > 1) { + uint64_t latency_this_iteration = + rte_get_tsc_cycles() - p_acl->in_port_time_stamp; + p_acl->counters->sum_latencies += latency_this_iteration; + p_acl->counters->count_latencies++; + } + if (ACL_DEBUG) + printf("Leaving pkt_work_acl_key pkts_mask = %p\n", + (void *)pkts_mask); + + return 0; } /** @@ -1789,563 +1614,567 @@ pkt_work_acl_ipv4_key(struct rte_pipeline *p, */ static int pkt_work_acl_ipv6_key(struct rte_pipeline *p, - struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) + struct rte_mbuf **pkts, uint32_t n_pkts, void *arg) { - struct pipeline_acl *p_acl = arg; - - p_acl->counters->pkts_received = - p_acl->counters->pkts_received + n_pkts; - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_received: %" PRIu64 - " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); - - uint64_t lookup_hit_mask = 0; - uint64_t lookup_hit_mask_ipv4 = 0; - uint64_t lookup_hit_mask_ipv6 = 0; - uint64_t lookup_miss_mask = 0; - uint64_t conntrack_mask = 0; - uint64_t connexist_mask = 0; - uint32_t dest_address = 0; - arp_pkts_mask = 0; - int dest_if = 0; - int status; - uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); - uint64_t keep_mask = pkts_mask; - uint16_t port; - uint32_t ret; - - p_acl->in_port_time_stamp = rte_get_tsc_cycles(); - - if (acl_ipv6_enabled) { - if (ACL_DEBUG) - printf("ACL IPV6 Lookup Mask Before = %p\n", - (void *)pkts_mask); - status = - rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts, - pkts_mask, &lookup_hit_mask_ipv6, - (void **) - p_acl->acl_entries_ipv6); - if (ACL_DEBUG) - printf("ACL IPV6 Lookup Mask After = %p\n", - (void *)lookup_hit_mask_ipv6); - } - - /* Merge lookup results since we process both IPv4 and IPv6 below */ - lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; - if (ACL_DEBUG) - printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); - - lookup_miss_mask = pkts_mask & (~lookup_hit_mask); - pkts_mask = lookup_hit_mask; - p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); - if (ACL_DEBUG) - printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", - p_acl->counters->pkts_drop, - __builtin_popcountll(lookup_miss_mask)); - - uint64_t pkts_to_process = lookup_hit_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - if (enable_hwlb) - if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { - pkts_mask &= ~(1LLU << pos); - continue; - } - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; + struct pipeline_acl *p_acl = arg; + + p_acl->counters->pkts_received = + p_acl->counters->pkts_received + n_pkts; + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_received: %" PRIu64 + " n_pkts: %u\n", p_acl->counters->pkts_received, n_pkts); + + uint64_t lookup_hit_mask = 0; + uint64_t lookup_hit_mask_ipv4 = 0; + uint64_t lookup_hit_mask_ipv6 = 0; + uint64_t lookup_miss_mask = 0; + uint64_t conntrack_mask = 0; + uint64_t connexist_mask = 0; + uint32_t dest_address = 0; + arp_pkts_mask = 0; + int status; + uint64_t pkts_drop_mask, pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t); + uint64_t keep_mask = pkts_mask; + uint16_t port; + uint32_t ret; + + p_acl->in_port_time_stamp = rte_get_tsc_cycles(); + + if (acl_ipv6_enabled) { + if (ACL_DEBUG) + printf("ACL IPV6 Lookup Mask Before = %p\n", + (void *)pkts_mask); + status = + rte_table_acl_ops.f_lookup(acl_rule_table_ipv6_active, pkts, + pkts_mask, &lookup_hit_mask_ipv6, + (void **) + p_acl->acl_entries_ipv6); + if (ACL_DEBUG) + printf("ACL IPV6 Lookup Mask After = %p\n", + (void *)lookup_hit_mask_ipv6); + } + + /* Merge lookup results since we process both IPv4 and IPv6 below */ + lookup_hit_mask = lookup_hit_mask_ipv4 | lookup_hit_mask_ipv6; + if (ACL_DEBUG) + printf("ACL Lookup Mask After = %p\n", (void *)lookup_hit_mask); + + lookup_miss_mask = pkts_mask & (~lookup_hit_mask); + pkts_mask = lookup_hit_mask; + p_acl->counters->pkts_drop += __builtin_popcountll(lookup_miss_mask); + if (ACL_DEBUG) + printf("pkt_work_acl_key pkts_drop: %" PRIu64 " n_pkts: %u\n", + p_acl->counters->pkts_drop, + __builtin_popcountll(lookup_miss_mask)); + + uint64_t pkts_to_process = lookup_hit_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + if (enable_hwlb) + if (!check_arp_icmp(pkt, pkt_mask, p_acl)) { + pkts_mask &= ~(1LLU << pos); + continue; + } + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; #if 0 - if (hdr_chk == IPv4_HDR_VERSION) { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf - ("ACL before drop pkt_mask %lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf - ("ACL after drop pkt_mask %lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, - dscp_offset); - *dscp = - action_array_active[action_id].dscp_priority - << 2; - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack enabled: " - " %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } + if (hdr_chk == IPv4_HDR_VERSION) { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + IP_HDR_DSCP_OFST; + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf + ("ACL before drop pkt_mask %lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf + ("ACL after drop pkt_mask %lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint8_t *dscp = RTE_MBUF_METADATA_UINT8_PTR(pkt, + dscp_offset); + *dscp = + action_array_active[action_id].dscp_priority + << 2; + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack enabled: " + " %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist enabled " - "conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist enabled " + "conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } #endif - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - uint16_t phy_port = entry->head.port_id; - uint32_t action_id = entry->action_id; - - if (ACL_DEBUG) - printf("action_id = %u\n", action_id); - - if (action_array_active[action_id].action_bitmap & - acl_action_count) { - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount++; - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount += - rte_pktmbuf_pkt_len(pkt); - if (ACL_DEBUG) - printf("Action Count Packet Count: %" - PRIu64 " Byte Count: %" PRIu64 - "\n", - action_counter_table - [p_acl->action_counter_index] - [action_id].packetCount, - action_counter_table - [p_acl->action_counter_index] - [action_id].byteCount); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_drop) { - /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", - pkts_mask, pos); - p_acl->counters->pkts_drop++; - - } - - if (action_array_active[action_id].action_bitmap & - acl_action_fwd) { - phy_port = - action_array_active[action_id].fwd_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action FWD Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_nat) { - phy_port = - action_array_active[action_id].nat_port; - entry->head.port_id = phy_port; - if (ACL_DEBUG) - printf("Action NAT Port ID: %u\n", - phy_port); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_dscp) { - - /* Set DSCP priority */ - uint32_t dscp_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DSCP_OFST_IPV6; - uint16_t *dscp = - RTE_MBUF_METADATA_UINT16_PTR(pkt, - dscp_offset); - uint16_t dscp_value = - (rte_bswap16 - (RTE_MBUF_METADATA_UINT16 - (pkt, dscp_offset)) & 0XF00F); - uint8_t dscp_store = - action_array_active[action_id].dscp_priority - << 2; - uint16_t dscp_temp = dscp_store; - - dscp_temp = dscp_temp << 4; - *dscp = rte_bswap16(dscp_temp | dscp_value); - if (ACL_DEBUG) - printf - ("Action DSCP DSCP Priority: %u\n", - *dscp); - } - - if (action_array_active[action_id].action_bitmap & - acl_action_packet_accept) { - if (ACL_DEBUG) - printf("Action Accept\n"); - - if (action_array_active[action_id].action_bitmap - & acl_action_conntrack) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - if (ACL_DEBUG) - printf("ACL Conntrack enabled: " - " %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)pkt_mask); - } - - if (action_array_active[action_id].action_bitmap - & acl_action_connexist) { - - /* Set conntrack bit for this pkt */ - conntrack_mask |= pkt_mask; - - /* Set connexist bit for this pkt for public -> private */ - /* Private -> public packet will open the connection */ - if (action_array_active - [action_id].private_public == - acl_public_private) - connexist_mask |= pkt_mask; - - if (ACL_DEBUG) - printf("ACL Connexist enabled " - "conntrack: %p connexist: %p pkt_mask: %p\n", - (void *)conntrack_mask, - (void *)connexist_mask, - (void *)pkt_mask); - } - } - } - } - /* Only call connection tracker if required */ - if (conntrack_mask > 0) { - if (ACL_DEBUG) - printf - ("ACL Call Conntrack Before = %p Connexist = %p\n", - (void *)conntrack_mask, (void *)connexist_mask); - conntrack_mask = - rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control - (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); - if (ACL_DEBUG) - printf("ACL Call Conntrack After = %p\n", - (void *)conntrack_mask); - - /* Only change pkt mask for pkts that have conntrack enabled */ - /* Need to loop through packets to check if conntrack enabled */ - pkts_to_process = pkts_mask; - for (; pkts_to_process;) { - uint32_t action_id = 0; - uint8_t pos = - (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, - MBUF_HDR_ROOM - + - ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - if (hdr_chk == IPv4_HDR_VERSION) { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv4[pos]; - action_id = entry->action_id; - } else { - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - action_id = entry->action_id; - } + if (hdr_chk == IPv6_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + uint16_t phy_port = entry->head.port_id; + uint32_t action_id = entry->action_id; + + if (ACL_DEBUG) + printf("action_id = %u\n", action_id); + + if (action_array_active[action_id].action_bitmap & + acl_action_count) { + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount++; + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount += + rte_pktmbuf_pkt_len(pkt); + if (ACL_DEBUG) + printf("Action Count Packet Count: %" + PRIu64 " Byte Count: %" PRIu64 + "\n", + action_counter_table + [p_acl->action_counter_index] + [action_id].packetCount, + action_counter_table + [p_acl->action_counter_index] + [action_id].byteCount); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_drop) { + /* Drop packet by changing the mask */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", + pkts_mask, pos); + p_acl->counters->pkts_drop++; + + } + + if (action_array_active[action_id].action_bitmap & + acl_action_fwd) { + phy_port = + action_array_active[action_id].fwd_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action FWD Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_nat) { + phy_port = + action_array_active[action_id].nat_port; + entry->head.port_id = phy_port; + if (ACL_DEBUG) + printf("Action NAT Port ID: %u\n", + phy_port); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_dscp) { + + /* Set DSCP priority */ + uint32_t dscp_offset = + MBUF_HDR_ROOM + ETH_HDR_SIZE + + IP_HDR_DSCP_OFST_IPV6; + uint16_t *dscp = + RTE_MBUF_METADATA_UINT16_PTR(pkt, + dscp_offset); + uint16_t dscp_value = + (rte_bswap16 + (RTE_MBUF_METADATA_UINT16 + (pkt, dscp_offset)) & 0XF00F); + uint8_t dscp_store = + action_array_active[action_id].dscp_priority + << 2; + uint16_t dscp_temp = dscp_store; + + dscp_temp = dscp_temp << 4; + *dscp = rte_bswap16(dscp_temp | dscp_value); + if (ACL_DEBUG) + printf + ("Action DSCP DSCP Priority: %u\n", + *dscp); + } + + if (action_array_active[action_id].action_bitmap & + acl_action_packet_accept) { + if (ACL_DEBUG) + printf("Action Accept\n"); + + if (action_array_active[action_id].action_bitmap + & acl_action_conntrack) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + if (ACL_DEBUG) + printf("ACL Conntrack enabled: " + " %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)pkt_mask); + } - if ((action_array_active[action_id].action_bitmap & - acl_action_conntrack) - || (action_array_active[action_id].action_bitmap & - acl_action_connexist)) { - - if (conntrack_mask & pkt_mask) { - if (ACL_DEBUG) - printf("ACL Conntrack Accept " - "packet = %p\n", - (void *)pkt_mask); - } else { + if (action_array_active[action_id].action_bitmap + & acl_action_connexist) { + + /* Set conntrack bit for this pkt */ + conntrack_mask |= pkt_mask; + + /* Set connexist bit for this pkt for public -> private */ + /* Private -> public packet will open the connection */ + if (action_array_active + [action_id].private_public == + acl_public_private) + connexist_mask |= pkt_mask; + + if (ACL_DEBUG) + printf("ACL Connexist enabled " + "conntrack: %p connexist: %p pkt_mask: %p\n", + (void *)conntrack_mask, + (void *)connexist_mask, + (void *)pkt_mask); + } + } + } + } + /* Only call connection tracker if required */ + if (conntrack_mask > 0) { + if (ACL_DEBUG) + printf + ("ACL Call Conntrack Before = %p Connexist = %p\n", + (void *)conntrack_mask, (void *)connexist_mask); + conntrack_mask = + rte_ct_cnxn_tracker_batch_lookup_with_new_cnxn_control + (p_acl->cnxn_tracker, pkts, conntrack_mask, connexist_mask); + if (ACL_DEBUG) + printf("ACL Call Conntrack After = %p\n", + (void *)conntrack_mask); + + /* Only change pkt mask for pkts that have conntrack enabled */ + /* Need to loop through packets to check if conntrack enabled */ + pkts_to_process = pkts_mask; + for (; pkts_to_process;) { + uint32_t action_id = 0; + uint8_t pos = + (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = RTE_MBUF_METADATA_UINT8(pkt, + MBUF_HDR_ROOM + + + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + if (hdr_chk == IPv4_HDR_VERSION) { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv4[pos]; + action_id = entry->action_id; + } else { + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + action_id = entry->action_id; + } + + if ((action_array_active[action_id].action_bitmap & + acl_action_conntrack) + || (action_array_active[action_id].action_bitmap & + acl_action_connexist)) { + + if (conntrack_mask & pkt_mask) { + if (ACL_DEBUG) + printf("ACL Conntrack Accept " + "packet = %p\n", + (void *)pkt_mask); + } else { /* Drop packet by changing the mask */ - if (ACL_DEBUG) - printf - ("ACL Conntrack Drop packet = %p\n", - (void *)pkt_mask); - pkts_mask &= ~pkt_mask; - p_acl->counters->pkts_drop++; - } - } - } - } - - pkts_to_process = pkts_mask; - /* bitmap of packets left to process for ARP */ - - for (; pkts_to_process;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); - uint64_t pkt_mask = 1LLU << pos; - /* bitmask representing only this packet */ - - pkts_to_process &= ~pkt_mask; - /* remove this packet from remaining list */ - struct rte_mbuf *pkt = pkts[pos]; - - uint8_t hdr_chk = - RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); - hdr_chk = hdr_chk >> IP_VERSION_CHECK; - - if (hdr_chk == IPv6_HDR_VERSION) { - - struct acl_table_entry *entry = - (struct acl_table_entry *) - p_acl->acl_entries_ipv6[pos]; - //uint16_t phy_port = entry->head.port_id; - uint16_t phy_port = pkt->port; - uint32_t *port_out_id = - RTE_MBUF_METADATA_UINT32_PTR(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - output_port)); - /* if (is_phy_port_privte(phy_port)) - *port_out_id = ACL_PUB_PORT_ID; - else - *port_out_id = ACL_PRV_PORT_ID;*/ - - /* *port_out_id = p_acl->links_map[phy_port]; */ - if (ACL_DEBUG) - printf - ("phy_port = %i,links_map[phy_port] = %i\n", - phy_port, p_acl->links_map[phy_port]); - - /* header room + eth hdr size + dst_adr offset in ip header */ - uint32_t dst_addr_offset = - MBUF_HDR_ROOM + ETH_HDR_SIZE + - IP_HDR_DST_ADR_OFST_IPV6; - uint8_t *eth_dest = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM); - uint8_t *eth_src = - RTE_MBUF_METADATA_UINT8_PTR(pkt, MBUF_HDR_ROOM + 6); - struct ether_addr hw_addr; - uint8_t dest_address[16]; - uint8_t nhip[16]; - - nhip[0] = - RTE_MBUF_METADATA_UINT8(pkt, - META_DATA_OFFSET + - offsetof(struct - mbuf_acl_meta_data, - nhip)); - uint8_t *dst_addr[16]; - uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); - int i = 0; - - for (i = 0; i < 16; i++) { - dst_addr[i] = - RTE_MBUF_METADATA_UINT8_PTR(pkt, - dst_addr_offset - + i); - } - memcpy(dest_address, *dst_addr, sizeof(dest_address)); - memset(nhip, 0, sizeof(nhip)); - struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port - (dest_address, &dest_if, &hw_addr, &nhip[0]); - *port_out_id = p_acl->port_out_id[dest_if]; - - if (nd_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), - (struct ether_addr *)eth_src); - update_nhip_access(dest_if); - - if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { - printf("sending buffered packets\n"); - p_acl->counters->tpkts_processed += - ret_nd_data->num_pkts; - nd_send_buffered_pkts(ret_nd_data, - (struct ether_addr *)eth_dest, *port_out_id); - } - p_acl->counters->tpkts_processed++; - p_acl->counters->bytes_processed += - packet_length; - } else { - if (unlikely(ret_nd_data == NULL)) { - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } + if (ACL_DEBUG) + printf + ("ACL Conntrack Drop packet = %p\n", + (void *)pkt_mask); + pkts_mask &= ~pkt_mask; + p_acl->counters->pkts_drop++; + } + } + } + } + + pkts_to_process = pkts_mask; + /* bitmap of packets left to process for ARP */ + + for (; pkts_to_process;) { + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_process); + uint64_t pkt_mask = 1LLU << pos; + /* bitmask representing only this packet */ + + pkts_to_process &= ~pkt_mask; + /* remove this packet from remaining list */ + struct rte_mbuf *pkt = pkts[pos]; + + uint8_t hdr_chk = + RTE_MBUF_METADATA_UINT8(pkt, MBUF_HDR_ROOM + ETH_HDR_SIZE); + hdr_chk = hdr_chk >> IP_VERSION_CHECK; + + if (hdr_chk == IPv6_HDR_VERSION) { + + struct acl_table_entry *entry = + (struct acl_table_entry *) + p_acl->acl_entries_ipv6[pos]; + //uint16_t phy_port = entry->head.port_id; + uint16_t phy_port = pkt->port; + uint32_t *port_out_id = + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + + offsetof(struct + mbuf_acl_meta_data, + output_port)); + + if (ACL_DEBUG) + printf + ("phy_port = %i,links_map[phy_port] = %i\n", + phy_port, p_acl->links_map[phy_port]); + + uint32_t packet_length = rte_pktmbuf_pkt_len(pkt); + + uint32_t dest_if = INVALID_DESTIF; + uint32_t src_phy_port = pkt->port; + + if(is_gateway()){ + + /* Gateway Proc Starts */ + struct ipv6_hdr *ipv6hdr = (struct ipv6_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); + + struct ether_hdr *ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, + META_DATA_OFFSET + MBUF_HDR_ROOM); + + struct ether_addr dst_mac; + uint32_t dest_if = INVALID_DESTIF; + uint8_t nhipv6[IPV6_ADD_SIZE]; + uint8_t dest_ipv6_address[IPV6_ADD_SIZE]; + uint32_t src_phy_port; + struct nd_entry_data *ret_nd_data = NULL; + + memset(nhipv6, 0, IPV6_ADD_SIZE); + src_phy_port = pkt->port; + rte_mov16(dest_ipv6_address, (uint8_t *)ipv6hdr->dst_addr); + + gw_get_nh_port_ipv6(dest_ipv6_address, + &dest_if, nhipv6); + + ret_nd_data = get_dest_mac_addr_ipv6(nhipv6, dest_if, &dst_mac); + + /* Gateway Proc Ends */ + + if (nd_cache_dest_mac_present(dest_if)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dest_if), &ehdr->s_addr); + + *port_out_id = p_acl->port_out_id[dest_if]; + + update_nhip_access(dest_if); + + if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { + printf("sending buffered packets\n"); + p_acl->counters->tpkts_processed += + ret_nd_data->num_pkts; + nd_send_buffered_pkts(ret_nd_data, &ehdr->d_addr, + p_acl->port_out_id[dest_if]); + } + p_acl->counters->tpkts_processed++; + p_acl->counters->bytes_processed += packet_length; + } else { + if (unlikely(ret_nd_data == NULL)) { + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } + + if (ret_nd_data->status == INCOMPLETE || + ret_nd_data->status == PROBE) { + if (ret_nd_data->num_pkts >= NUM_DESC) { + /* Drop the pkt */ + if (ACL_DEBUG) + printf("ACL before drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + pkts_mask &= ~(1LLU << pos); + if (ACL_DEBUG) + printf("ACL after drop pkt_mask " + "%lu, pkt_num %d\n", pkts_mask, pos); + p_acl->counters->pkts_drop++; + continue; + } else { + arp_pkts_mask |= pkt_mask; + nd_queue_unresolved_packet(ret_nd_data, + pkt); + continue; + } + } + } - if (ret_nd_data->status == INCOMPLETE || - ret_nd_data->status == PROBE) { - if (ret_nd_data->num_pkts >= NUM_DESC) { - /* Drop the pkt */ - if (ACL_DEBUG) - printf("ACL before drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - pkts_mask &= ~(1LLU << pos); - if (ACL_DEBUG) - printf("ACL after drop pkt_mask " - "%lu, pkt_num %d\n", pkts_mask, pos); - p_acl->counters->pkts_drop++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - nd_queue_unresolved_packet(ret_nd_data, - pkt); - continue; - } - } + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dest_if = prv_to_pub_map[src_phy_port]; + else + dest_if = pub_to_prv_map[src_phy_port]; - } + *port_out_id = p_acl->port_out_id[dest_if]; - } + } + } - } /* end of for loop */ + } /* end of for loop */ - pkts_drop_mask = keep_mask & ~pkts_mask; - rte_pipeline_ah_packet_drop(p, pkts_drop_mask); - keep_mask = pkts_mask; + pkts_drop_mask = keep_mask & ~pkts_mask; + rte_pipeline_ah_packet_drop(p, pkts_drop_mask); + keep_mask = pkts_mask; - if (arp_pkts_mask) { - keep_mask &= ~(arp_pkts_mask); - rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); - } + if (arp_pkts_mask) { + keep_mask &= ~(arp_pkts_mask); + rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); + } - /* don't bother measuring if traffic very low, might skew stats */ - uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); + /* don't bother measuring if traffic very low, might skew stats */ + uint32_t packets_this_iteration = __builtin_popcountll(pkts_mask); - if (packets_this_iteration > 1) { - uint64_t latency_this_iteration = - rte_get_tsc_cycles() - p_acl->in_port_time_stamp; - p_acl->counters->sum_latencies += latency_this_iteration; - p_acl->counters->count_latencies++; - } - if (ACL_DEBUG) - printf("Leaving pkt_work_acl_key pkts_mask = %p\n", - (void *)pkts_mask); + if (packets_this_iteration > 1) { + uint64_t latency_this_iteration = + rte_get_tsc_cycles() - p_acl->in_port_time_stamp; + p_acl->counters->sum_latencies += latency_this_iteration; + p_acl->counters->count_latencies++; + } + if (ACL_DEBUG) + printf("Leaving pkt_work_acl_key pkts_mask = %p\n", + (void *)pkts_mask); - return 0; + return 0; } static struct rte_acl_field_def field_format_ipv4[] = { diff --git a/VNFs/vACL/vnf_template.txt b/VNFs/vACL/vnf_template.txt new file mode 100644 index 00000000..ed8253be --- /dev/null +++ b/VNFs/vACL/vnf_template.txt @@ -0,0 +1,82 @@ +[MASTER] +type = MASTER +core = 0 + +[ARPICMP] +type = ARPICMP +core = 1 +pktq_in = SWQ0 +pktq_out = TXQ0.0 TXQ1.0 +pktq_in_prv = RXQ0.0 +prv_to_pub_map = (0,1) +prv_que_handler = (0) + +[TIMER] +type = TIMER +core = 2 +n_flows = 1048576 + +[TXRX-BEGIN] +type = TXRX +core = 2 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = SWQ0 SWQ1 SWQ2 +pipeline_txrx_type = RXRX +dest_if_offset=176 + +[TXRX-END] +type = TXRX +core = 5 +pktq_in = SWQ5 SWQ6 +pktq_out = TXQ0.1 TXQ1.1 +pipeline_txrx_type = TXTX + +[LOADB] +type = LOADB +core = 3 +pktq_in = SWQ0 SWQ1 +pktq_out = SWQ3 SWQ4 +outport_offset = 136 +phyport_offset = 204 +n_vnf_threads = 1 +prv_que_handler = (0) + +[VACL] +type = ACL +core = 4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ5 SWQ6 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 + +[VCGNAPT] +type = CGNAPT +core = 3 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = TXQ0.1 TXQ1.1 SWQ0 +phyport_offset = 204 +n_flows = 1048576 +key_offset = 192;64 +key_size = 8 +hash_offset = 200;72 +timer_period = 100 +max_clients_per_ip = 65535 +max_port_per_client = 10 +public_ip_port_range = 98103214:(1, 65535) +vnf_set = (3,4,5) +pkt_type = ipv4 +cgnapt_meta_offset = 128 +prv_que_handler = (0,) + +[VFW] +type = VFW +core = s0c4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ7 SWQ8;TXQ0.0 TXQ1.0 +n_rules = 10000 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 +tcp_time_wait = 10 + diff --git a/VNFs/vCGNAPT/Makefile b/VNFs/vCGNAPT/Makefile index e349f627..41cacfb7 100644 --- a/VNFs/vCGNAPT/Makefile +++ b/VNFs/vCGNAPT/Makefile @@ -41,6 +41,7 @@ VPATH += $(SRCDIR)/pipeline VPATH += $(VNF_CORE)/common/VIL/pipeline_txrx VPATH += $(VNF_CORE)/common/VIL/alg VPATH += $(VNF_CORE)/common/VIL/l2l3_stack +VPATH += $(VNF_CORE)/common/VIL/gateway INC += $(wildcard *.h) INC += $(wildcard pipeline/*.h) @@ -54,6 +55,7 @@ INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_passthrough/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_txrx/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/conntrack/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/alg/*.h) +INC += $(wildcard $(VNF_CORE)/common/VIL/gateway/*.h) CFLAGS += -I$(SRCDIR) -mrtm -mhle -I$(SRCDIR)/pipeline -I$(VNF_CORE)/common/vnf_common CFLAGS += -I$(VNF_CORE)/common/VIL/l2l3_stack -I$(VNF_CORE)/common/VIL/conntrack @@ -61,10 +63,18 @@ CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_common -I$(VNF_CORE)/common/VIL/pipe CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_master -I$(VNF_CORE)/common/VIL/pipeline_passthrough CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_txrx -I$(VNF_CORE)/common/VIL/alg CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_arpicmp +CFLAGS += -I$(VNF_CORE)/common/VIL/gateway + +TOP = $(RTE_SDK)/../civetweb +CFLAGS += -I$(TOP)/include $(COPT) -DUSE_WEBSOCKET -DUSE_IPV6 -DUSE_SSL_DH=1 +CFLAGS += -DREST_API_SUPPORT +LDFLAGS += -ljson -lcrypto -lssl +LDFLAGS += -L$(RTE_SDK)/../civetweb/ -lcivetweb # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rest_api.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c @@ -106,6 +116,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cgnapt_pcp_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += cgnapt_pcp_fe.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib_sip_alg.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib_ftp_alg.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += gateway.c CFLAGS += -O3 CFLAGS += -DIPV6 diff --git a/VNFs/vCGNAPT/config/sample_hwlb_2port_2WT.tc b/VNFs/vCGNAPT/config/sample_hwlb_2port_2WT.tc index 47ee0633..3cb90c9a 100644 --- a/VNFs/vCGNAPT/config/sample_hwlb_2port_2WT.tc +++ b/VNFs/vCGNAPT/config/sample_hwlb_2port_2WT.tc @@ -19,12 +19,13 @@ link 1 up ;p 1 arpadd 0 0064:ff9b:0:0:0:0:ca10:6414 00:00:00:00:00:01 ;p 1 arpadd 1 0064:ff9b:0:0:0:0:ac10:2814 00:00:00:00:00:02 -routeadd 0 202.16.100.20 0xff000000 -routeadd 2 172.16.40.20 0xff000000 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 202.16.100.20 0xff000000 +routeadd net 1 172.16.40.20 0xff000000 -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 0064:ff9b:0:0:0:0:ca10:6414 64 -;routeadd 1 0064:ff9b:0:0:0:0:ac10:6414 64 +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +;routeadd net 0 0064:ff9b:0:0:0:0:ca10:6414 64 +;routeadd net 1 0064:ff9b:0:0:0:0:ac10:6414 64 set fwd rxonly diff --git a/VNFs/vCGNAPT/config/sample_swlb_2port_2WT.tc b/VNFs/vCGNAPT/config/sample_swlb_2port_2WT.tc index 05ed058d..d7465690 100644 --- a/VNFs/vCGNAPT/config/sample_swlb_2port_2WT.tc +++ b/VNFs/vCGNAPT/config/sample_swlb_2port_2WT.tc @@ -20,8 +20,8 @@ link 1 up ;p 1 arpadd 1 0064:ff9b:0:0:0:0:ac10:2814 00:00:00:00:00:02 routeadd 0 202.16.100.20 0xff000000 -routeadd 2 172.16.40.20 0xff000000 +routeadd 1 172.16.40.20 0xff000000 -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 0064:ff9b:0:0:0:0:ca10:6414 64 -;routeadd 1 0064:ff9b:0:0:0:0:ac10:6414 64 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +;routeadd net 0 0064:ff9b:0:0:0:0:ca10:6414 64 +;routeadd net 1 0064:ff9b:0:0:0:0:ac10:6414 64 diff --git a/VNFs/vCGNAPT/init.c b/VNFs/vCGNAPT/init.c index 76621d51..d61e419c 100644 --- a/VNFs/vCGNAPT/init.c +++ b/VNFs/vCGNAPT/init.c @@ -75,6 +75,7 @@ app_init_core_mask(struct app_params *app) p->socket_id, p->core_id, p->hyper_th_id); + printf("lcore_id:%d\n", lcore_id); if (lcore_id < 0) rte_panic("Cannot create CPU core mask\n"); diff --git a/VNFs/vCGNAPT/main.c b/VNFs/vCGNAPT/main.c index 9ebf6fc3..83fc37ff 100644 --- a/VNFs/vCGNAPT/main.c +++ b/VNFs/vCGNAPT/main.c @@ -15,12 +15,14 @@ */ #include "app.h" +#include "pipeline_cgnapt.h" static struct app_params app; int main(int argc, char **argv) { + struct mg_context *ctx = NULL; rte_openlog_stream(stderr); /* Config */ @@ -28,6 +30,12 @@ main(int argc, char **argv) app_config_args(&app, argc, argv); + /* initialize the rest api */ + if (is_rest_support()) { + set_vnf_type("VCGNAPT"); + ctx = rest_api_init(&app); + } + app_config_preproc(&app); app_config_parse(&app, app.parser_file); @@ -40,11 +48,21 @@ main(int argc, char **argv) /* Init */ app_init(&app); + if (is_rest_support() && (ctx != NULL)) { + /* rest api's for cgnapt */ + rest_api_cgnapt_init(ctx, &app); + } + /* Run-time */ rte_eal_mp_remote_launch( app_thread, (void *) &app, CALL_MASTER); + if (is_rest_support() && (ctx != NULL)) { + mg_stop(ctx); + printf("Civet server stopped.\n"); + } + return 0; } diff --git a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.c b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.c index fb0b95d1..0c6bf48d 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.c +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.c @@ -29,6 +29,12 @@ #include <cmdline_parse_string.h> #include <cmdline_parse_ipaddr.h> #include <cmdline_parse_etheraddr.h> +#include <cmdline_rdline.h> +#include <cmdline_socket.h> +#include <cmdline.h> + +#include <fcntl.h> +#include <unistd.h> #include "app.h" #include "pipeline_common_fe.h" @@ -40,6 +46,8 @@ #include "cgnapt_pcp_fe.h" #endif +#define MAX_BUF_SIZE 2048 + /** * A structure defining the CG-NAPT entry that is stored on * front end. @@ -66,6 +74,12 @@ struct pipeline_cgnapt_t { }; +int nat_load_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int nat_handler(struct mg_connection *conn, __rte_unused void *cbdata); +uint32_t rules_loaded = 0; +extern struct cmdline *pipe_cl; +struct app_params *myapp; + /** * Init function for CG-NAPT FE. * @@ -1405,7 +1419,8 @@ cmd_cgnapt_stats_parsed( __rte_unused struct cmdline *cl, __rte_unused void *data) { - all_cgnapt_stats(); + char buf[2048]; + all_cgnapt_stats(&buf[0]); } static cmdline_parse_token_string_t cmd_cgnapt_stats_p_string = @@ -1457,7 +1472,8 @@ cmd_cgnapt_clear_stats_parsed( __rte_unused struct cmdline *cl, __rte_unused void *data) { - all_cgnapt_clear_stats(); + char buf[2048]; + all_cgnapt_clear_stats(&buf[0]); } static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_p_string = @@ -1475,6 +1491,212 @@ static cmdline_parse_token_string_t cmd_cgnapt_clear_stats_stats_string = TOKEN_STRING_INITIALIZER(struct cmd_cgnapt_clear_stats_result, stats_string, "stats"); +int cgnapt_stats_handler(struct mg_connection *conn, void *cbdata) +{ + uint32_t num_links = 0, len = 0; + char buf[1024]; + const struct mg_request_info *ri = mg_get_request_info(conn); + struct app_params *app = myapp; + int i; + + if (!strcmp(ri->request_method, "GET")) { + all_cgnapt_stats(&buf[0]); + mg_printf(conn, "%s\n", &buf[0]); + return 1; + } + + if (strcmp(ri->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the GET handler\n", + ri->request_method); + } + + all_cgnapt_clear_stats(&buf[0]); + mg_printf(conn, "%s\n", &buf[0]); + return 1; + +} + +int cgnapt_cmd_ver_handler(struct mg_connection *conn, void *cbdata) +{ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<p>Command Passed</p>"); + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +/* + * loadrules + */ + +/** + * Open file and process all commands in the file. + * + * @param ctx + * A pointer to the CLI context + * @param file_name + * A pointer to the file to process. + * + */ +static void cgnapt_loadrules_file(cmdline_parse_ctx_t *ctx, const char *file_name) +{ + struct cmdline *file_cl; + int fd; + + fd = open(file_name, O_RDONLY); + if (fd < 0) { + printf("Cannot open file \"%s\"\n", file_name); + return; + } + + file_cl = cmdline_new(ctx, "", fd, 1); + cmdline_interact(file_cl); + close(fd); +} + + +int nat_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + + const struct mg_request_info *req_info = mg_get_request_info(conn); + if (strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Only GET method allowed"); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are the methods that are supported </h2>"); + mg_printf(conn, "<h3> /load </h3>"); + mg_printf(conn, "<html><body>"); + + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +static int nat_field_found(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, "\r\n\r\n%s:\r\n", key); + mg_printf(conn, "Inside vfw_field_found %s \n", filename); + + if (filename && *filename) { + snprintf(path, pathlen, "/tmp/%s", filename); + struct app_params *app = myapp; + int status; + int fd; + + mg_printf(conn, "path: %s\n", path); + + /* Make sure the file exists before clearing rules and actions */ + fd = open(path, O_RDONLY); + if (fd < 0) { + mg_printf(conn, "Cannot open file \"%s\"\n", filename); + return FORM_FIELD_STORAGE_GET; + } + + close(fd); + return FORM_FIELD_STORAGE_STORE; + } + + return FORM_FIELD_STORAGE_GET; +} + +static int nat_field_get(const char *key, const char *value, size_t valuelen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + if (key[0]) { + mg_printf(conn, "%s = ", key); + } + mg_write(conn, value, valuelen); + + return 0; +} + +static int nat_field_stored(const char *path, long long file_size, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + int status; + + mg_printf(conn, + "stored as %s (%lu bytes)\r\n\r\n", + path, + (unsigned long)file_size); + + /* Process commands in script file */ + cgnapt_loadrules_file(pipe_cl->ctx, path); + rules_loaded = 1; + + return 0; +} + +int nat_load_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + int ret; + const struct mg_request_info *req_info = mg_get_request_info(conn); + struct mg_form_data_handler fdh = {nat_field_found, nat_field_get, + nat_field_stored, 0}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Rule file is %s\n", rules_loaded? "LOADED":"NOT LOADED"); + } + + if (strcmp(req_info->request_method, "PUT")) { + mg_printf(conn, "Only PUT method allowed"); + return 1; + } + + fdh.user_data = (void *)conn; + + /* Call the form handler */ + mg_printf(conn, "Form data:"); + ret = mg_handle_form_request(conn, &fdh); + mg_printf(conn, "\r\n%i fields found", ret); + + return 1; +} + +void rest_api_cgnapt_init(struct mg_context *ctx, struct app_params *app) +{ + myapp = app; + + /* vCGNAPT commands */ + mg_set_request_handler(ctx, "/vnf/config/nat", nat_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/nat/load", nat_load_handler, 0); + mg_set_request_handler(ctx, "/vnf/status", cgnapt_cmd_ver_handler, 0); + mg_set_request_handler(ctx, "/vnf/stats", cgnapt_stats_handler, 0); + +} + static cmdline_parse_inst_t cmd_clear_stats = { .f = cmd_cgnapt_clear_stats_parsed, .data = NULL, diff --git a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.h b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.h index 5491648a..6497de27 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.h +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt.h @@ -28,6 +28,8 @@ #include "pipeline.h" #include "pipeline_cgnapt_common.h" +#include <civetweb.h> +#include <json/json.h> /** * Add NAPT rule to the NAPT rule table. @@ -129,6 +131,12 @@ int app_pipeline_cgnapt_nsp_del_entry(struct app_params *app, uint32_t pipeline_id, struct pipeline_cgnapt_nsp_t *nsp); +#ifdef REST_API_SUPPORT +/* REST api's are defined here */ +int cgnapt_cmd_ver_handler(struct mg_connection *conn, void *cbdata); +int cgnapt_stats_handler(struct mg_connection *conn, void *cbdata); +void rest_api_cgnapt_init(struct mg_context *ctx, struct app_params *app); +#endif /* * Pipeline type diff --git a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c index eb0aca96..7758c5b3 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c @@ -64,6 +64,7 @@ #include "vnf_common.h" #include "lib_sip_alg.h" #include "lib_icmpv6.h" +#include "gateway.h" #include "pipeline_common_fe.h" #ifdef CT_CGNAT @@ -177,21 +178,6 @@ uint8_t well_known_prefix[16] = { 0x00, 0x00, 0x00, 0x00 }; -static uint32_t local_get_nh_ipv4( - uint32_t ip, - uint32_t *port, - uint32_t *nhip, - struct pipeline_cgnapt *p_nat); -static void do_local_nh_ipv4_cache( - uint32_t dest_if, - struct pipeline_cgnapt *p_nat); - -static uint32_t local_get_nh_ipv6( - uint8_t *ip, - uint32_t *port, - uint8_t nhip[], - struct pipeline_cgnapt *p_nat); - static uint8_t check_arp_icmp( struct rte_mbuf *pkt, uint64_t pkt_mask, @@ -219,123 +205,6 @@ uint64_t nextPowerOf2(uint64_t n) return n; } -void remove_local_cache(uint8_t port) -{ - link_hw_laddr_valid[port] = 0; -} - -/** - * Function to get IPv4-IP NH from thread local array - * - * @params ip - * IPv4 - IP - * @params port - * NH port number - * @params nhip - * NHIP of IPv4 type - * @params p_nat - * CGNAPT pipeline ptr - * - * @return - * 1 on success, 0 for failure - */ - -static uint32_t local_get_nh_ipv4( - uint32_t ip, - uint32_t *port, - uint32_t *nhip, - struct pipeline_cgnapt *p_nat) -{ - int i; - for (i = 0; i < p_nat->local_lib_arp_route_ent_cnt; i++) { - if (((p_nat->local_lib_arp_route_table[i].ip & - p_nat->local_lib_arp_route_table[i].mask) == - (ip & p_nat->local_lib_arp_route_table[i].mask))) { - *port = p_nat->local_lib_arp_route_table[i].port; - - *nhip = p_nat->local_lib_arp_route_table[i].nh; - return 1; - } - } - return 0; -} - -/** - * Function to make local copy for NH of type IPv4 - * - * @params dest_if - * Physical port number - * @params p_nat - * CGNAPT pipeline ptr - * - */ - -static void do_local_nh_ipv4_cache( - uint32_t dest_if, - struct pipeline_cgnapt *p_nat) -{ - return; -} - - -/** - * Function to get IPv6-IP NH from thread local array - * - * @params ip - * Pointer to starting addr of IPv6 - * @params port - * NH port number - * @params nhip - * NHIP of IPv6 type - * @params p_nat - * CGNAPT pipeline ptr - * - * @return - * 1 on success, 0 for failure - */ - -static uint32_t local_get_nh_ipv6( - uint8_t *ip, - uint32_t *port, - uint8_t nhip[], - struct pipeline_cgnapt *p_nat) -{ - int i = 0; - uint8_t netmask_ipv6[16]; - uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0; - - for (i = 0; i < p_nat->local_lib_nd_route_ent_cnt; i++) { - - convert_prefixlen_to_netmask_ipv6( - p_nat->local_lib_nd_route_table[i].depth, - netmask_ipv6); - - for (k = 0; k < 16; k++) - if (p_nat->local_lib_nd_route_table[i].ipv6[k] & - netmask_ipv6[k]) - depthflags++; - - for (l = 0; l < 16; l++) - if (ip[l] & netmask_ipv6[l]) - depthflags1++; - - int j = 0; - if (depthflags == depthflags1) { - *port = p_nat->local_lib_nd_route_table[i].port; - - for (j = 0; j < 16; j++) - nhip[j] = p_nat->local_lib_nd_route_table[i]. - nhipv6[j]; - return 1; - } - - depthflags = 0; - depthflags1 = 0; - } - return 0; -} - - #ifdef SIP_ALG /* Commented code may be required for future usage, Please keep it*/ #if 0 @@ -2078,7 +1947,7 @@ static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p, uint8_t nh_ipv6[16]; uint32_t nhip = 0; - uint32_t dest_if = 0xff; + uint32_t dest_if = INVALID_DESTIF; uint32_t ret; uint16_t *outport_id = @@ -2091,52 +1960,54 @@ static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p, && rte_be_to_cpu_16(*dst_port) == 53) { p_nat->invalid_packets |= 1LLU << pkt_index; p_nat->naptDroppedPktCount++; - #ifdef CGNAPT_DEBUGGING +#ifdef CGNAPT_DEBUGGING p_nat->naptDroppedPktCount6++; - #endif +#endif continue; } dest_address = rte_bswap32(*dst_addr); - ret = local_get_nh_ipv4(dest_address, &dest_if, - &nhip, p_nat); - if (!ret) { - dest_if = get_prv_to_pub_port(&dest_address, - IP_VERSION_4); - if (dest_if == INVALID_DESTIF) { - p_nat->invalid_packets |= - 1LLU << pkt_index; - p_nat->naptDroppedPktCount++; - #ifdef CGNAPT_DEBUGGING - p_nat->naptDroppedPktCount6++; - #endif - continue; - } - do_local_nh_ipv4_cache(dest_if, p_nat); - } + /* Gateway Proc Starts */ - *outport_id = p_nat->outport_id[dest_if]; - struct arp_entry_data *ret_arp_data; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + struct arp_entry_data *ret_arp_data = NULL; + uint32_t src_phy_port = *src_port; - if (unlikely(ret_arp_data == NULL)) { + gw_get_nh_port_ipv4(dest_address, + &dest_if, &nhip); - #ifdef CGNAPT_DEBUGGING - printf("%s: NHIP Not Found, nhip: %x, " - "outport_id: %d\n", __func__, nhip, - *outport_id); - #endif - /* Drop the pkt */ - p_nat->invalid_packets |= pkt_mask; + if (dest_if == INVALID_DESTIF) { + p_nat->invalid_packets |= + 1LLU << pkt_index; p_nat->naptDroppedPktCount++; - - #ifdef CGNAPT_DEBUGGING - p_nat->naptDroppedPktCount4++; - #endif +#ifdef CGNAPT_DEBUGGING + p_nat->naptDroppedPktCount6++; +#endif continue; } + *outport_id = p_nat->outport_id[dest_if]; + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, &hw_addr); + + if (unlikely(ret_arp_data == NULL)) { + + #ifdef CGNAPT_DEBUGGING + printf("%s: NHIP Not Found, nhip: %x, " + "outport_id: %d\n", __func__, nhip, + *outport_id); + #endif + /* Drop the pkt */ + p_nat->invalid_packets |= pkt_mask; + p_nat->naptDroppedPktCount++; + + #ifdef CGNAPT_DEBUGGING + p_nat->naptDroppedPktCount4++; + #endif + continue; + } + + /* Gateway Proc Ends */ + if (ret_arp_data->status == COMPLETE) { if (ret_arp_data->num_pkts) { @@ -2267,21 +2138,28 @@ static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p, &entry->data.u.prv_ipv6[0], 16); memset(nh_ipv6, 0, 16); struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port((uint8_t *) - &dst_addr[0], &dest_if, - &hw_addr, &nh_ipv6[0]); + + dest_if = INVALID_DESTIF; + + uint32_t src_phy_port = pkts[pkt_index]->port; + + gw_get_nh_port_ipv6((uint8_t *) &dst_addr[0], + &dest_if, &nh_ipv6[0]); + + ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0], + dest_if, &hw_addr); *outport_id = p_nat->outport_id[dest_if]; if (nd_cache_dest_mac_present(dest_if)) { ether_addr_copy(get_link_hw_addr(dest_if), - (struct ether_addr *)eth_src); + (struct ether_addr *)eth_src); update_nhip_access(dest_if); if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { p_nat->naptedPktCount += ret_nd_data->num_pkts; nd_send_buffered_pkts(ret_nd_data, - (struct ether_addr *)eth_dest, - *outport_id); + (struct ether_addr *)eth_dest, + *outport_id); } } else { if (unlikely(ret_nd_data == NULL)) { @@ -2335,46 +2213,49 @@ static int cgnapt_in_port_ah_mix(struct rte_pipeline *rte_p, } else { *dst_addr = rte_bswap32(entry->data.u.prv_ip); dest_address = entry->data.u.prv_ip; - ret = local_get_nh_ipv4(dest_address, &dest_if, - &nhip, p_nat); - if (!ret) { - dest_if = get_pub_to_prv_port( - &dest_address, IP_VERSION_4); + /* Gateway Proc Starts */ + + struct arp_entry_data *ret_arp_data = NULL; + dest_if = INVALID_DESTIF; + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, + &dest_if, &nhip); + if (dest_if == INVALID_DESTIF) { p_nat->invalid_packets |= 1LLU << pkt_index; p_nat->naptDroppedPktCount++; - #ifdef CGNAPT_DEBUGGING +#ifdef CGNAPT_DEBUGGING p_nat->naptDroppedPktCount6++; - #endif +#endif continue; } - do_local_nh_ipv4_cache(dest_if, p_nat); - }; *outport_id = p_nat->outport_id[dest_if]; - struct arp_entry_data *ret_arp_data; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, + dest_if, (struct ether_addr *)eth_dest); if (unlikely(ret_arp_data == NULL)) { - #ifdef CGNAPT_DEBUGGING +#ifdef CGNAPT_DEBUGGING printf("%s: NHIP Not Found, nhip: %x, " - "outport_id: %d\n", __func__, nhip, - *outport_id); - #endif - + "outport_id: %d\n", __func__, nhip, + *outport_id); +#endif /* Drop the pkt */ p_nat->invalid_packets |= pkt_mask; p_nat->naptDroppedPktCount++; - #ifdef CGNAPT_DEBUGGING +#ifdef CGNAPT_DEBUGGING p_nat->naptDroppedPktCount4++; - #endif +#endif continue; } + /* Gateway Proc Ends */ + if (ret_arp_data->status == COMPLETE) { if (ret_arp_data->num_pkts) { @@ -3713,7 +3594,7 @@ pkt_work_cgnapt_ipv4_prv( uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4); - uint32_t dest_if = 0xff; /* Added for Multiport */ + uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */ uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset); @@ -3822,7 +3703,6 @@ pkt_work_cgnapt_ipv4_prv( if (entry->data.ttl == NAPT_ENTRY_STALE) entry->data.ttl = NAPT_ENTRY_VALID; - struct ether_addr hw_addr; uint32_t dest_address = 0; /* Egress */ @@ -3840,8 +3720,14 @@ pkt_work_cgnapt_ipv4_prv( dest_address = rte_bswap32(*dst_addr); uint32_t nhip = 0; struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); + *outport_id = p_nat->outport_id[dest_if]; if (arp_cache_dest_mac_present(dest_if)) { @@ -3850,7 +3736,7 @@ pkt_work_cgnapt_ipv4_prv( if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { p_nat->naptedPktCount += ret_arp_data->num_pkts; arp_send_buffered_pkts(ret_arp_data, - (struct ether_addr *)eth_dest, *outport_id); + (struct ether_addr *)eth_dest, *outport_id); } } else { @@ -4083,7 +3969,7 @@ pkt_work_cgnapt_ipv4_pub( uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4); - uint32_t dest_if = 0xff; /* Added for Multiport */ + uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */ uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset); @@ -4166,7 +4052,6 @@ pkt_work_cgnapt_ipv4_pub( if (entry->data.ttl == NAPT_ENTRY_STALE) entry->data.ttl = NAPT_ENTRY_VALID; - struct ether_addr hw_addr; uint32_t dest_address = 0; /* Multiport Changes */ @@ -4188,8 +4073,13 @@ pkt_work_cgnapt_ipv4_pub( dest_address = entry->data.u.prv_ip; struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); *outport_id = p_nat->outport_id[dest_if]; if (arp_cache_dest_mac_present(dest_if)) { @@ -4441,7 +4331,7 @@ pkt4_work_cgnapt_ipv4_prv( __rte_unused void *arg, struct pipeline_cgnapt *p_nat) { - uint32_t dest_if = 0xff; /* Added for Multiport */ + uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */ struct rte_mbuf *pkt; uint8_t i; uint8_t pkt_num; @@ -4602,7 +4492,6 @@ pkt4_work_cgnapt_ipv4_prv( if (entry->data.ttl == NAPT_ENTRY_STALE) entry->data.ttl = NAPT_ENTRY_VALID; - struct ether_addr hw_addr; uint32_t dest_address = 0; /*Multiport Changes */ uint32_t nhip = 0; @@ -4626,9 +4515,15 @@ pkt4_work_cgnapt_ipv4_prv( dest_address = rte_bswap32(*dst_addr); struct arp_entry_data *ret_arp_data = NULL; uint64_t start, end; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); + *outport_id = p_nat->outport_id[dest_if]; + if (arp_cache_dest_mac_present(dest_if)) { ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src); @@ -4882,7 +4777,7 @@ pkt4_work_cgnapt_ipv4_pub( uint8_t protocol = RTE_MBUF_METADATA_UINT8(pkt, PROT_OFST_IP4); - uint32_t dest_if = 0xff; /* Added for Multiport */ + uint32_t dest_if = INVALID_DESTIF; /* Added for Multiport */ uint16_t *outport_id = RTE_MBUF_METADATA_UINT16_PTR(pkt, cgnapt_meta_offset); @@ -4971,7 +4866,6 @@ pkt4_work_cgnapt_ipv4_pub( if (entry->data.ttl == NAPT_ENTRY_STALE) entry->data.ttl = NAPT_ENTRY_VALID; - struct ether_addr hw_addr; uint32_t dest_address = 0; /* Multiport Changes */ uint32_t nhip = 0; @@ -4991,23 +4885,29 @@ pkt4_work_cgnapt_ipv4_pub( } dest_address = entry->data.u.prv_ip; struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); + *outport_id = p_nat->outport_id[dest_if]; - if (arp_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src); - update_nhip_access(dest_if); + if (arp_cache_dest_mac_present(dest_if)) { + ether_addr_copy(get_link_hw_addr(dest_if), + (struct ether_addr *)eth_src); + update_nhip_access(dest_if); - if (ret_arp_data && ret_arp_data->num_pkts) { - p_nat->naptedPktCount += ret_arp_data->num_pkts; - arp_send_buffered_pkts(ret_arp_data, - (struct ether_addr *)eth_dest, *outport_id); - } + if (ret_arp_data && ret_arp_data->num_pkts) { + p_nat->naptedPktCount += ret_arp_data->num_pkts; + arp_send_buffered_pkts(ret_arp_data, + (struct ether_addr *)eth_dest, *outport_id); + } - } else { + } else { - if (unlikely(ret_arp_data == NULL)) { + if (unlikely(ret_arp_data == NULL)) { #ifdef CGNAPT_DEBUGGING printf("%s: NHIP Not Found, nhip: %x, " @@ -6058,7 +5958,6 @@ pkt_work_cgnapt_ipv6_prv( struct ipv6_hdr ipv6_hdr; - struct ether_addr hw_addr; uint32_t dest_address = 0; uint32_t nhip = 0; /* Egress */ @@ -6164,9 +6063,16 @@ pkt_work_cgnapt_ipv6_prv( #endif struct arp_entry_data *ret_arp_data; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); + *outport_id = p_nat->outport_id[dest_if]; + if (arp_cache_dest_mac_present(dest_if)) { ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src); @@ -6342,11 +6248,16 @@ pkt_work_cgnapt_ipv6_pub( memset(nh_ipv6, 0, 16); struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port( - &dest_addr_ipv6[0], - &dest_if, - (struct ether_addr *)eth_dest, - &nh_ipv6[0]); + + dest_if = INVALID_DESTIF; + + uint32_t src_phy_port = pkt->port; + + gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0], + &dest_if, &nh_ipv6[0]); + + ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0], + dest_if, (struct ether_addr *)eth_dest); *outport_id = p_nat->outport_id[dest_if]; @@ -6536,7 +6447,6 @@ pkt4_work_cgnapt_ipv6_prv( p_nat->entries[pkt_num] = &(entry->head); struct ipv6_hdr ipv6_hdr; - struct ether_addr hw_addr; uint32_t dest_address = 0; uint8_t nh_ipv6[16]; uint32_t nhip = 0; @@ -6645,15 +6555,18 @@ pkt4_work_cgnapt_ipv6_prv( { struct arp_entry_data *ret_arp_data; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, (struct ether_addr *)eth_dest); + uint32_t src_phy_port = *src_port; + + gw_get_nh_port_ipv4(dest_address, &dest_if, &nhip); + + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dest_if, + (struct ether_addr *)eth_dest); *outport_id = p_nat->outport_id[dest_if]; if (arp_cache_dest_mac_present(dest_if)) { ether_addr_copy(get_link_hw_addr(dest_if), (struct ether_addr *)eth_src); update_nhip_access(dest_if); - if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { p_nat->naptedPktCount += ret_arp_data->num_pkts; arp_send_buffered_pkts(ret_arp_data, @@ -6846,10 +6759,15 @@ pkt4_work_cgnapt_ipv6_pub( memset(nh_ipv6, 0, 16); struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port - (&dest_addr_ipv6[0], &dest_if, - (struct ether_addr *)eth_dest, &nh_ipv6[0]); + dest_if = INVALID_DESTIF; + + uint32_t src_phy_port = pkt->port; + gw_get_nh_port_ipv6((uint8_t *) &dest_addr_ipv6[0], + &dest_if, &nh_ipv6[0]); + + ret_nd_data = get_dest_mac_addr_ipv6(&nh_ipv6[0], + dest_if, (struct ether_addr *)eth_dest); *outport_id = p_nat->outport_id[dest_if]; if (nd_cache_dest_mac_present(dest_if)) { @@ -10551,9 +10469,9 @@ void *pipeline_cgnapt_msg_req_ver_handler(__rte_unused struct pipeline *p, * Function to show CGNAPT stats * */ -void all_cgnapt_stats(void) +void all_cgnapt_stats(char *buf) { - int i; + int i, len = 0; struct pipeline_cgnapt *p_nat; uint64_t receivedPktCount = 0; uint64_t missedPktCount = 0; @@ -10563,7 +10481,7 @@ void all_cgnapt_stats(void) uint64_t enaptedPktCount = 0; uint64_t arpicmpPktCount = 0; - printf("\nCG-NAPT Packet Stats:\n"); + len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n"); for (i = 0; i < n_cgnapt_pipeline; i++) { p_nat = all_pipeline_cgnapt[i]; @@ -10575,6 +10493,16 @@ void all_cgnapt_stats(void) enaptedPktCount += p_nat->enaptedPktCount; arpicmpPktCount += p_nat->arpicmpPktCount; + len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num); + len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount); + len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount); + len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount); + len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount); + len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount); + len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount); + len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount); + + printf("\nCG-NAPT Packet Stats:\n"); printf("pipeline %d stats:\n", p_nat->pipeline_num); printf("Received %" PRIu64 ",", p_nat->receivedPktCount); printf("Missed %" PRIu64 ",", p_nat->missedPktCount); @@ -10585,33 +10513,34 @@ void all_cgnapt_stats(void) printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount); + #ifdef CGNAPT_DEBUGGING - printf("\n Drop detail 1:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",", p_nat->naptDroppedPktCount1); - printf("\n Drop detail 2:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",", p_nat->naptDroppedPktCount2); - printf("\n Drop detail 3:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",", p_nat->naptDroppedPktCount3); - printf("\n Drop detail 4:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",", p_nat->naptDroppedPktCount4); - printf("\n Drop detail 5:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",", p_nat->naptDroppedPktCount5); - printf("\n Drop detail 6:%" PRIu64 "", + len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "", p_nat->naptDroppedPktCount6); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount1, p_nat->missedpktcount2); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount3, p_nat->missedpktcount4); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount5, p_nat->missedpktcount6); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount7, p_nat->missedpktcount8); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount9, p_nat->missedpktcount10); @@ -10619,7 +10548,16 @@ void all_cgnapt_stats(void) } - printf("\nTotal pipeline stats:\n"); + len += sprintf(buf + len, "\nTotal pipeline stats:\n"); + len += sprintf(buf + len, "Received %" PRIu64 ",", receivedPktCount); + len += sprintf(buf + len, "Missed %" PRIu64 ",", missedPktCount); + len += sprintf(buf + len, "Dropped %" PRIu64 ",", naptDroppedPktCount); + len += sprintf(buf + len, "Translated %" PRIu64 ",", naptedPktCount); + len += sprintf(buf + len, "ingress %" PRIu64 ",", inaptedPktCount); + len += sprintf(buf + len, "egress %" PRIu64 "\n", enaptedPktCount); + len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", arpicmpPktCount); + + printf("\nTotal pipeline stats:\n"); printf("Received %" PRIu64 ",", receivedPktCount); printf("Missed %" PRIu64 ",", missedPktCount); printf("Dropped %" PRIu64 ",", naptDroppedPktCount); @@ -10627,24 +10565,27 @@ void all_cgnapt_stats(void) printf("ingress %" PRIu64 ",", inaptedPktCount); printf("egress %" PRIu64 "\n", enaptedPktCount); printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount); + + if (!rest_api_supported()) + printf("%s\n", buf); } -void all_cgnapt_clear_stats(void) +void all_cgnapt_clear_stats(char *buf) { - int i; + int i, len = 0; struct pipeline_cgnapt *p_nat; - printf("\nCG-NAPT Packet Stats:\n"); + len += sprintf(buf + len, "\nCG-NAPT Packet Stats:\n"); for (i = 0; i < n_cgnapt_pipeline; i++) { p_nat = all_pipeline_cgnapt[i]; - printf("pipeline %d stats:\n", p_nat->pipeline_num); - printf("Received %" PRIu64 ",", p_nat->receivedPktCount); - printf("Missed %" PRIu64 ",", p_nat->missedPktCount); - printf("Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount); - printf("Translated %" PRIu64 ",", p_nat->naptedPktCount); - printf("ingress %" PRIu64 ",", p_nat->inaptedPktCount); - printf("egress %" PRIu64 "\n", p_nat->enaptedPktCount); - printf("arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount); + len += sprintf(buf + len, "pipeline %d stats:\n", p_nat->pipeline_num); + len += sprintf(buf + len, "Received %" PRIu64 ",", p_nat->receivedPktCount); + len += sprintf(buf + len, "Missed %" PRIu64 ",", p_nat->missedPktCount); + len += sprintf(buf + len, "Dropped %" PRIu64 ",", p_nat->naptDroppedPktCount); + len += sprintf(buf + len, "Translated %" PRIu64 ",", p_nat->naptedPktCount); + len += sprintf(buf + len, "ingress %" PRIu64 ",", p_nat->inaptedPktCount); + len += sprintf(buf + len, "egress %" PRIu64 "\n", p_nat->enaptedPktCount); + len += sprintf(buf + len, "arpicmp pkts %" PRIu64 "\n", p_nat->arpicmpPktCount); p_nat->receivedPktCount = 0; p_nat->missedPktCount = 0; @@ -10655,38 +10596,41 @@ void all_cgnapt_clear_stats(void) p_nat->arpicmpPktCount = 0; #ifdef CGNAPT_DEBUGGING - printf("\n Drop detail 1:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 1:%" PRIu64 ",", p_nat->naptDroppedPktCount1); - printf("\n Drop detail 2:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 2:%" PRIu64 ",", p_nat->naptDroppedPktCount2); - printf("\n Drop detail 3:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 3:%" PRIu64 ",", p_nat->naptDroppedPktCount3); - printf("\n Drop detail 4:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 4:%" PRIu64 ",", p_nat->naptDroppedPktCount4); - printf("\n Drop detail 5:%" PRIu64 ",", + len += sprintf(buf + len, "\n Drop detail 5:%" PRIu64 ",", p_nat->naptDroppedPktCount5); - printf("\n Drop detail 6:%" PRIu64 "", + len += sprintf(buf + len, "\n Drop detail 6:%" PRIu64 "", p_nat->naptDroppedPktCount6); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount1, p_nat->missedpktcount2); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount3, p_nat->missedpktcount4); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount5, p_nat->missedpktcount6); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount7, p_nat->missedpktcount8); - printf("\nPkt_miss: %" PRIu64 " %" PRIu64 "", + len += sprintf(buf + len, "\nPkt_miss: %" PRIu64 " %" PRIu64 "", p_nat->missedpktcount9, p_nat->missedpktcount10); #endif } + + if (!rest_api_supported()) + printf("%s\n", buf); } /** diff --git a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.h b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.h index 943d0fc7..7fde0c5a 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.h +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.h @@ -418,14 +418,6 @@ struct pipeline_cgnapt { uint8_t vnf_set; /* to identify as separate LB-CGNAPT set */ - /* Local ARP & ND Tables */ - struct lib_arp_route_table_entry - local_lib_arp_route_table[MAX_ARP_RT_ENTRY]; - uint8_t local_lib_arp_route_ent_cnt; - struct lib_nd_route_table_entry - local_lib_nd_route_table[MAX_ND_RT_ENTRY]; - uint8_t local_lib_nd_route_ent_cnt; - /* For internal debugging purpose */ #ifdef CGNAPT_TIMING_INST uint64_t in_port_exit_timestamp; diff --git a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_common.h b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_common.h index 4f4253cd..a7cd88a4 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_common.h +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_common.h @@ -265,7 +265,7 @@ struct pipeline_cgnapt_entry_dbg_msg_req { extern struct pipeline_be_ops pipeline_cgnapt_be_ops; void print_num_ip_clients(void); -void all_cgnapt_stats(void); -void all_cgnapt_clear_stats(void); +void all_cgnapt_stats(char *); +void all_cgnapt_clear_stats(char *); void print_static_cgnapt_entries(void); #endif diff --git a/VNFs/vCGNAPT/vnf_template.txt b/VNFs/vCGNAPT/vnf_template.txt new file mode 100644 index 00000000..385c5312 --- /dev/null +++ b/VNFs/vCGNAPT/vnf_template.txt @@ -0,0 +1,80 @@ +[MASTER] +type = MASTER +core = 0 + +[ARPICMP] +type = ARPICMP +core = 1 +pktq_in = SWQ0 +pktq_out = TXQ0.0 TXQ1.0 +pktq_in_prv = RXQ0.0 +prv_to_pub_map = (0,1) +prv_que_handler = (0) + +[TIMER] +type = TIMER +core = 2 +n_flows = 1048576 + +[TXRX-BEGIN] +type = TXRX +core = 2 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = SWQ0 SWQ1 SWQ2 +pipeline_txrx_type = RXRX +dest_if_offset=176 + +[TXRX-END] +type = TXRX +core = 5 +pktq_in = SWQ5 SWQ6 +pktq_out = TXQ0.1 TXQ1.1 +pipeline_txrx_type = TXTX + +[LOADB] +type = LOADB +core = 3 +pktq_in = SWQ0 SWQ1 +pktq_out = SWQ3 SWQ4 +outport_offset = 136 +phyport_offset = 204 +n_vnf_threads = 1 +prv_que_handler = (0) + +[VACL] +type = ACL +core = 4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ5 SWQ6 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 + +[VCGNAPT] +type = CGNAPT +core = 3 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = TXQ0.1 TXQ1.1 SWQ0 +phyport_offset = 204 +n_flows = 1048576 +key_offset = 192;64 +key_size = 8 +hash_offset = 200;72 +timer_period = 100 +max_clients_per_ip = 65535 +max_port_per_client = 10 +pkt_type = ipv4 +cgnapt_meta_offset = 128 +prv_que_handler = (0,) + +[VFW] +type = VFW +core = s0c4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ7 SWQ8;TXQ0.0 TXQ1.0 +n_rules = 10000 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 +tcp_time_wait = 10 + diff --git a/VNFs/vFW/Makefile b/VNFs/vFW/Makefile index c96246b9..b011eca2 100644 --- a/VNFs/vFW/Makefile +++ b/VNFs/vFW/Makefile @@ -41,6 +41,7 @@ VPATH += $(SRCDIR)/pipeline VPATH += $(VNF_CORE)/common/VIL/pipeline_txrx VPATH += $(VNF_CORE)/common/VIL/acl VPATH += $(VNF_CORE)/common/VIL/l2l3_stack +VPATH += $(VNF_CORE)/common/VIL/gateway INC += $(wildcard *.h) INC += $(wildcard pipeline/*.h) @@ -54,6 +55,7 @@ INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_master/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_passthrough/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/pipeline_txrx/*.h) INC += $(wildcard $(VNF_CORE)/common/VIL/acl/*.h) +INC += $(wildcard $(VNF_CORE)/common/VIL/gateway/*.h) CFLAGS += -I$(SRCDIR) -mrtm -mhle -I$(SRCDIR)/pipeline -I$(VNF_CORE)/common/vnf_common CFLAGS += -I$(VNF_CORE)/common/VIL/conntrack -I$(VNF_CORE)/common/VIL/l2l3_stack @@ -62,10 +64,17 @@ CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_master -I$(VNF_CORE)/common/VIL/pipe CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_txrx CFLAGS += -I$(VNF_CORE)/common/VIL/acl CFLAGS += -I$(VNF_CORE)/common/VIL/pipeline_arpicmp +CFLAGS += -I$(VNF_CORE)/common/VIL/gateway + +TOP = $(RTE_SDK)/../civetweb +CFLAGS += -I$(TOP)/include $(COPT) -DUSE_WEBSOCKET -DUSE_IPV6 -DUSE_SSL_DH=1 -DREST_API_SUPPORT=1 +LDFLAGS += -ljson -lcrypto -lssl +LDFLAGS += -L$(RTE_SDK)/../civetweb/ -lcivetweb # all source are stored in SRCS-y SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) := main.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += rest_api.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_parse_tm.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += config_check.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += init.c @@ -104,6 +113,7 @@ SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_arpicmp_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += pipeline_txrx_be.c SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += lib_acl.c +SRCS-$(CONFIG_RTE_LIBRTE_PIPELINE) += gateway.c CFLAGS += -O3 diff --git a/VNFs/vFW/config/VFW_HWLB_MultiPortPair_script.tc b/VNFs/vFW/config/VFW_HWLB_MultiPortPair_script.tc index 46355bee..b27c66fa 100644 --- a/VNFs/vFW/config/VFW_HWLB_MultiPortPair_script.tc +++ b/VNFs/vFW/config/VFW_HWLB_MultiPortPair_script.tc @@ -32,18 +32,17 @@ link 3 config 172.16.40.10 8 ;link 3 config 2016:0000:0000:0000:6a05:caff:fe30:2071 64 link 3 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 203.16.100.20 0xff000000 -routeadd 1 202.16.100.20 0xff000000 -routeadd 2 173.16.40.20 0xff000000 -routeadd 3 172.16.40.20 0xff000000 - -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 fec0:0000:0000:0000:6a05:caff:fe30:21a0 64 -;routeadd 1 fec1:0000:0000:0000:6a05:caff:fe30:21a0 64 -;routeadd 2 2012:0000:0000:0000:6a05:caff:fe30:2071 64 -;routeadd 3 2016:0000:0000:0000:6a05:caff:fe30:2071 64 - +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 203.16.100.20 0xff000000 +routeadd net 1 202.16.100.20 0xff000000 +routeadd net 2 173.16.40.20 0xff000000 +routeadd net 3 172.16.40.20 0xff000000 + +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +;routeadd net 0 fec0:0000:0000:0000:6a05:caff:fe30:21a0 64 +;routeadd net 1 fec1:0000:0000:0000:6a05:caff:fe30:21a0 64 +;routeadd net 2 2012:0000:0000:0000:6a05:caff:fe30:2071 64 +;routeadd net 3 2016:0000:0000:0000:6a05:caff:fe30:2071 64 ; IPv4 Static ARP ;p 1 arpadd 0 203.16.100.20 00:00:00:00:00:01 diff --git a/VNFs/vFW/config/VFW_HWLB_SinglePortPair_script.tc b/VNFs/vFW/config/VFW_HWLB_SinglePortPair_script.tc index f20796ac..35bb519d 100644 --- a/VNFs/vFW/config/VFW_HWLB_SinglePortPair_script.tc +++ b/VNFs/vFW/config/VFW_HWLB_SinglePortPair_script.tc @@ -22,13 +22,13 @@ link 1 config 172.16.40.10 8 ;link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64 link 1 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 202.16.100.20 0xff000000 -routeadd 1 172.16.40.20 0xff000000 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 202.16.100.20 0xff000000 +routeadd net 1 172.16.40.20 0xff000000 -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 fec0::6a05:caff:fe30:21b0 64 -;routeadd 1 2012::6a05:caff:fe30:2081 64 +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +;routeadd net 0 fec0::6a05:caff:fe30:21b0 64 +;routeadd net 1 2012::6a05:caff:fe30:2081 64 ; IPv4 static ARP ;p 1 arpadd 1 172.16.40.20 00:00:00:00:00:04 diff --git a/VNFs/vFW/config/VFW_SWLB_MultiPortPair_script.tc b/VNFs/vFW/config/VFW_SWLB_MultiPortPair_script.tc index 392320e3..ff502e55 100644 --- a/VNFs/vFW/config/VFW_SWLB_MultiPortPair_script.tc +++ b/VNFs/vFW/config/VFW_SWLB_MultiPortPair_script.tc @@ -32,17 +32,17 @@ link 3 config 172.16.40.10 8 ;link 3 config 2016:0000:0000:0000:6a05:caff:fe30:2071 64 link 3 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 203.16.100.20 0xff000000 -routeadd 1 202.16.100.20 0xff000000 -routeadd 2 173.16.40.20 0xff000000 -routeadd 3 172.16.40.20 0xff000000 - -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 fec0:0000:0000:0000:6a05:caff:fe30:21a0 64 -;routeadd 1 fec1:0000:0000:0000:6a05:caff:fe30:21a0 64 -;routeadd 2 2012:0000:0000:0000:6a05:caff:fe30:2071 64 -;routeadd 3 2016:0000:0000:0000:6a05:caff:fe30:2071 64 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +routeadd net 0 203.16.100.20 0xff000000 +routeadd net 1 202.16.100.20 0xff000000 +routeadd net 2 173.16.40.20 0xff000000 +routeadd net 3 172.16.40.20 0xff000000 + +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +;routeadd net 0 fec0:0000:0000:0000:6a05:caff:fe30:21a0 64 +;routeadd net 1 fec1:0000:0000:0000:6a05:caff:fe30:21a0 64 +;routeadd net 2 2012:0000:0000:0000:6a05:caff:fe30:2071 64 +;routeadd net 3 2016:0000:0000:0000:6a05:caff:fe30:2071 64 ; IPv4 Static ARP ;p 1 arpadd 0 203.16.100.20 00:00:00:00:00:01 diff --git a/VNFs/vFW/config/VFW_SWLB_SinglePortPair_script.tc b/VNFs/vFW/config/VFW_SWLB_SinglePortPair_script.tc index d85e17b9..b9dd226b 100644 --- a/VNFs/vFW/config/VFW_SWLB_SinglePortPair_script.tc +++ b/VNFs/vFW/config/VFW_SWLB_SinglePortPair_script.tc @@ -22,17 +22,21 @@ link 1 config 172.16.40.10 8 ;link 1 config 2012:0000:0000:0000:6a05:caff:fe30:2071 64 link 1 up -; routeadd <port #> <ipv4 nhip address in decimal> <Mask> -routeadd 0 202.16.100.20 0xff000000 -routeadd 1 172.16.40.20 0xff000000 +; routeadd <net/host> <port #> <ipv4 nhip address in decimal> <Mask/NotApplicable> +;routeadd host 0 202.16.100.20 +;routeadd host 1 172.16.40.20 +routeadd net 0 202.16.100.20 0xff000000 +routeadd net 1 172.16.40.20 0xff000000 -;routeadd <port #> <ipv6 nhip address in hex> <Depth> -;routeadd 0 fec0::6a05:caff:fe30:21b0 64 -;routeadd 1 2012::6a05:caff:fe30:2081 64 +;routeadd <net/host> <port #> <ipv6 nhip address in hex> <Depth/NotApplicable> +;routeadd host 0 fec0::6a05:caff:fe30:21b0 +;routeadd host 1 2012::6a05:caff:fe30:2081 +routeadd net 0 fec0::6a05:caff:fe30:21b0 64 +routeadd net 1 2012::6a05:caff:fe30:2081 64 ; IPv4 static ARP -;p 1 arpadd 1 172.16.40.20 00:00:00:00:00:04 -;p 1 arpadd 0 202.16.100.20 00:00:00:00:00:01 +p 1 arpadd 1 172.16.40.20 00:00:00:00:00:02 +p 1 arpadd 0 202.16.100.20 00:00:00:00:00:01 ; IPv6 static ARP ;p 1 arpadd 0 fec0::6a05:caff:fe30:21b0 00:00:00:00:00:01 diff --git a/VNFs/vFW/init.c b/VNFs/vFW/init.c index 4e98b335..0edc5e32 100644 --- a/VNFs/vFW/init.c +++ b/VNFs/vFW/init.c @@ -705,7 +705,7 @@ app_init_link(struct app_params *app) port_config = rte_zmalloc(NULL, (app->n_links * size), RTE_CACHE_LINE_SIZE); if (port_config == NULL) - rte_panic("port_config is NULL: Memory Allocation failure\n"); + rte_panic("port_config is NULL: Memory Allocation failure num_links %d %d\n", app->n_links, app->n_links * size); for (i = 0; i < app->n_links; i++) { struct app_link_params *p_link = &app->link_params[i]; diff --git a/VNFs/vFW/main.c b/VNFs/vFW/main.c index 9ebf6fc3..aec04ac5 100644 --- a/VNFs/vFW/main.c +++ b/VNFs/vFW/main.c @@ -15,12 +15,15 @@ */ #include "app.h" +#include <civetweb.h> static struct app_params app; +extern void rest_api_vfw_init(struct mg_context *ctx, struct app_params *app); int main(int argc, char **argv) { + struct mg_context *ctx = NULL; rte_openlog_stream(stderr); /* Config */ @@ -28,6 +31,12 @@ main(int argc, char **argv) app_config_args(&app, argc, argv); + if (is_rest_support()) { + /* initialize the rest api */ + set_vnf_type("VFW"); + ctx = rest_api_init(&app); + } + app_config_preproc(&app); app_config_parse(&app, app.parser_file); @@ -40,11 +49,21 @@ main(int argc, char **argv) /* Init */ app_init(&app); + if (is_rest_support() && (ctx != NULL)) { + /* rest api's for cgnapt */ + rest_api_vfw_init(ctx, &app); + } + /* Run-time */ rte_eal_mp_remote_launch( app_thread, (void *) &app, CALL_MASTER); + if (is_rest_support() && (ctx != NULL)) { + mg_stop(ctx); + printf("Civet server stopped.\n"); + } + return 0; } diff --git a/VNFs/vFW/pipeline/pipeline_vfw.c b/VNFs/vFW/pipeline/pipeline_vfw.c index f235bc59..df94b5f7 100644 --- a/VNFs/vFW/pipeline/pipeline_vfw.c +++ b/VNFs/vFW/pipeline/pipeline_vfw.c @@ -29,6 +29,7 @@ #include <string.h> #include <sys/queue.h> #include <netinet/in.h> +#include <arpa/inet.h> #include <rte_common.h> #include <rte_hexdump.h> @@ -45,10 +46,16 @@ #include "app.h" #include "pipeline_common_fe.h" +#include "pipeline_master.h" #include "pipeline_vfw.h" #include "pipeline_vfw_be.h" #include "rte_cnxn_tracking.h" +struct app_params *myapp; +#define MAX_BUF_SIZE 2048 +extern struct cmdline *pipe_cl; +extern int my_inet_pton_ipv6(int af, const char *src, void *dst); + /** * A structure defining the VFW rule for the TAILQ Tables. */ @@ -4619,6 +4626,477 @@ cmdline_parse_token_num_t cmd_vfw_synproxy_flag = TOKEN_NUM_INITIALIZER(struct cmd_vfw_synproxy_flag_result, synproxy_flag, UINT8); +static uint32_t rules_loaded; +static int vfw_field_found(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data); + +static int vfw_field_get(const char *key, const char *value, size_t valuelen, + void *user_data); +static int vfw_field_stored(const char *path, long long file_size, void *user_data); + +int vfw_clearrules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + struct app_params *app = myapp; + int status; + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "</body></html>\n"); + + status = app_pipeline_vfw_clearrules(app); + + if (status != 0) { + mg_printf(conn, "Command failed\n"); + return 1; + } + + mg_printf(conn, "Command Success\n"); + return 1; +} + +int vfw_clearstats_handler(__rte_unused struct mg_connection *conn, + __rte_unused void *cbdata) +{ + int i; + struct rte_CT_counter_block *ct_counters; + + for (i = 0; i <= rte_VFW_hi_counter_block_in_use; i++) { + ct_counters = rte_vfw_counter_table[i].ct_counters; + rte_vfw_counter_table[i].bytes_processed = 0; + rte_vfw_counter_table[i].pkts_drop_without_rule = 0; + rte_vfw_counter_table[i].pkts_received = 0; + rte_vfw_counter_table[i].pkts_drop_ttl = 0; + rte_vfw_counter_table[i].pkts_drop_bad_size = 0; + rte_vfw_counter_table[i].pkts_drop_fragmented = 0; + rte_vfw_counter_table[i].pkts_drop_unsupported_type = 0; + rte_vfw_counter_table[i].pkts_drop_without_arp_entry = 0; + rte_vfw_counter_table[i].internal_time_sum = 0; + rte_vfw_counter_table[i].external_time_sum = 0; + rte_vfw_counter_table[i].time_measurements = 0; + rte_vfw_counter_table[i].ct_counters->pkts_forwarded = 0; + rte_vfw_counter_table[i].ct_counters->pkts_drop = 0; + rte_vfw_counter_table[i].pkts_fw_forwarded = 0; + rte_vfw_counter_table[i].pkts_acl_forwarded = 0; + ct_counters->current_active_sessions = 0; + ct_counters->sessions_activated = 0; + ct_counters->sessions_reactivated = 0; + ct_counters->sessions_established = 0; + ct_counters->sessions_closed = 0; + ct_counters->sessions_timedout = 0; + ct_counters->pkts_drop_invalid_conn = 0; + ct_counters->pkts_drop_invalid_state = 0; + ct_counters->pkts_drop_invalid_rst = 0; + ct_counters->pkts_drop_outof_window = 0; + } + + memset(&action_counter_table, 0, sizeof(action_counter_table)); + rte_vfw_reset_running_averages(); + return 1; +} + +int vfw_stats_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + const struct mg_request_info *ri = mg_get_request_info(conn); + int i, j; + struct rte_VFW_counter_block vfw_counter_sums; + struct rte_CT_counter_block ct_counter_sums; + struct rte_CT_counter_block *ct_counters; + struct action_counter_block action_counter_sum[action_array_max]; + uint64_t sum_pkts_drop_fw = 0; + + if (!strcmp(ri->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "Command Passed \n"); + vfw_clearstats_handler(conn, cbdata); + mg_printf(conn, "</body></html>\n"); + return 1; + } + + if (strcmp(ri->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the GET handler\n", + ri->request_method); + return 1; + } + + memset(&vfw_counter_sums, 0, sizeof(vfw_counter_sums)); + memset(&ct_counter_sums, 0, sizeof(ct_counter_sums)); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "VFW Stats\n"); + for (i = 0; i <= rte_VFW_hi_counter_block_in_use; i++) { + struct rte_VFW_counter_block *vfw_ctrs = + &rte_vfw_counter_table[i]; + ct_counters = rte_vfw_counter_table[i].ct_counters; + + uint64_t average_internal_time = + vfw_ctrs->time_measurements == + 0 ? 0 : vfw_ctrs->internal_time_sum / + vfw_ctrs->time_measurements; + uint64_t average_external_time = + vfw_ctrs->time_measurements == + 0 ? 0 : vfw_ctrs->external_time_sum / + vfw_ctrs->time_measurements; + uint64_t average_pkts_in_batch = + vfw_ctrs->num_pkts_measurements == + 0 ? 0 : vfw_ctrs->num_batch_pkts_sum / + vfw_ctrs->num_pkts_measurements; + uint64_t pkts_drop_fw = vfw_ctrs->pkts_drop_ttl + + vfw_ctrs->pkts_drop_bad_size + + vfw_ctrs->pkts_drop_fragmented + + vfw_ctrs->pkts_drop_unsupported_type; + + mg_printf(conn, "{\"VFW_counters\" : {\"id\" : \"%s\", \" pkts_received\": %" + PRIu64 ", \" pkts_fw_forwarded\": %" + PRIu64 ", \" pkts_drop_fw\": %" + PRIu64 ", \" pkts_acl_forwarded\": %" + PRIu64 ", \"pkts_drop_without_rule\" : %" + PRIu64 ", \"average_pkts_in_batch\" : %" + PRIu64 ", \"average_internal_time_in_clocks\" : %" + PRIu64 ", \"average_external_time_in_clocks\" : %" + PRIu64 ", \"total_time_measures\" : %" + PRIu32 ", \"ct_packets_forwarded\" : %" + PRIu64 ", \"ct_packets_dropped\" : %" + PRIu64 ", \"bytes_processed \": %" + PRIu64 ", \"ct_sessions\" : {" + "\"active\" : %" PRIu64 ", \"open_attempt\" : %" + PRIu64 ", \"re-open_attempt\" : %" + PRIu64 ", \"established\" : %" + PRIu64 ", \"closed\" : %" + PRIu64 ", \"timeout\" : %" + PRIu64 "}, \"ct_drops\" : {" + "\"out_of_window\" : %" PRIu64 ", \"invalid_conn\" : %" + PRIu64 ", \"invalid_state_transition\" : %" + PRIu64 " \"RST\" : %" + PRIu64 "}}\n", + vfw_ctrs->name, + vfw_ctrs->pkts_received, + vfw_ctrs->pkts_fw_forwarded, + pkts_drop_fw, + vfw_ctrs->pkts_acl_forwarded, + vfw_ctrs->pkts_drop_without_rule, + average_pkts_in_batch, + average_internal_time, + average_external_time, + vfw_ctrs->time_measurements, + ct_counters->pkts_forwarded, + ct_counters->pkts_drop, + vfw_ctrs->bytes_processed, + ct_counters->current_active_sessions, + ct_counters->sessions_activated, + ct_counters->sessions_reactivated, + ct_counters->sessions_established, + ct_counters->sessions_closed, + ct_counters->sessions_timedout, + ct_counters->pkts_drop_outof_window, + ct_counters->pkts_drop_invalid_conn, + ct_counters->pkts_drop_invalid_state, + ct_counters->pkts_drop_invalid_rst); + + vfw_counter_sums.bytes_processed += + vfw_ctrs->bytes_processed; + + vfw_counter_sums.internal_time_sum += + vfw_ctrs->internal_time_sum; + vfw_counter_sums.external_time_sum += + vfw_ctrs->external_time_sum; + vfw_counter_sums.time_measurements += + vfw_ctrs->time_measurements; + + vfw_counter_sums.pkts_drop_ttl += vfw_ctrs->pkts_drop_ttl; + vfw_counter_sums.pkts_drop_bad_size += + vfw_ctrs->pkts_drop_bad_size; + vfw_counter_sums.pkts_drop_fragmented += + vfw_ctrs->pkts_drop_fragmented; + vfw_counter_sums.pkts_drop_unsupported_type += + vfw_ctrs->pkts_drop_unsupported_type; + vfw_counter_sums.pkts_drop_without_arp_entry += + vfw_ctrs->pkts_drop_without_arp_entry; + + vfw_counter_sums.pkts_drop_without_rule += + vfw_ctrs->pkts_drop_without_rule; + vfw_counter_sums.pkts_received += vfw_ctrs->pkts_received; + vfw_counter_sums.pkts_fw_forwarded += + vfw_ctrs->pkts_fw_forwarded; + vfw_counter_sums.pkts_acl_forwarded += + vfw_ctrs->pkts_acl_forwarded; + sum_pkts_drop_fw += pkts_drop_fw; + ct_counter_sums.pkts_forwarded += ct_counters->pkts_forwarded; + ct_counter_sums.pkts_drop += ct_counters->pkts_drop; + ct_counter_sums.current_active_sessions += + ct_counters->current_active_sessions; + ct_counter_sums.sessions_activated += + ct_counters->sessions_activated; + ct_counter_sums.sessions_reactivated += + ct_counters->sessions_reactivated; + ct_counter_sums.sessions_established += + ct_counters->sessions_established; + ct_counter_sums.sessions_closed += ct_counters->sessions_closed; + ct_counter_sums.sessions_timedout += + ct_counters->sessions_timedout; + ct_counter_sums.pkts_drop_invalid_conn += + ct_counters->pkts_drop_invalid_conn; + ct_counter_sums.pkts_drop_invalid_state += + ct_counters->pkts_drop_invalid_state; + ct_counter_sums.pkts_drop_invalid_rst += + ct_counters->pkts_drop_invalid_rst; + ct_counter_sums.pkts_drop_outof_window += + ct_counters->pkts_drop_outof_window; + + } + + mg_printf(conn, "VFW TOTAL: pkts_received: %" + PRIu64 ", \"pkts_fw_forwarded\": %" + PRIu64 ", \"pkts_drop_fw\": %" + PRIu64 ", \"fw_drops\" : {" + "\"TTL_zero\" : %" PRIu64 ", \"bad_size\" : %" + PRIu64 ", \"fragmented_packet\" : %" + PRIu64 ", \"unsupported_packet_types\" : %" + PRIu64 ", \"no_arp_entry\" : %" + PRIu64 "}, \"pkts_acl_forwarded\": %" + PRIu64 ", \"pkts_drop_without_rule\": %" + PRIu64 ", \"packets_last_sec\" : %" + PRIu32 ", \"average_packets_per_sec\" : %" + PRIu32 ", \"bytes_last_sec\" : %" + PRIu32 ", \"average_bytes_per_sec\" : %" + PRIu32 ", \"bytes_processed \": %" + PRIu64 "\n", + vfw_counter_sums.pkts_received, + vfw_counter_sums.pkts_fw_forwarded, + sum_pkts_drop_fw, + vfw_counter_sums.pkts_drop_ttl, + vfw_counter_sums.pkts_drop_bad_size, + vfw_counter_sums.pkts_drop_fragmented, + vfw_counter_sums.pkts_drop_unsupported_type, + vfw_counter_sums.pkts_drop_without_arp_entry, + vfw_counter_sums.pkts_acl_forwarded, + vfw_counter_sums.pkts_drop_without_rule, + rte_vfw_performance_measures.pkts_last_second, + rte_vfw_performance_measures.ave_pkts_per_second, + rte_vfw_performance_measures.bytes_last_second, + rte_vfw_performance_measures.ave_bytes_per_second, + vfw_counter_sums.bytes_processed); + + mg_printf(conn, "\"CT TOTAL: ct_packets_forwarded\" : %" + PRIu64 ", \" ct_packets_dropped\" : %" + PRIu64 ", \"ct_sessions\" : {" + "\"active\" : %" PRIu64 ", \"open_attempt\" : %" + PRIu64 ", \"re-open_attempt\" : %" + PRIu64 ", \"established\" : %" + PRIu64 ", \"closed\" : %" + PRIu64 ", \"timeout\" : %" + PRIu64 "}, \"ct_drops\" : {" + "\"out_of_window\" : %" PRIu64 ", \"invalid_conn\" : %" + PRIu64 ", \"invalid_state_transition\" : %" + PRIu64 " \"RST\" : %" + PRIu64 "}\n", + ct_counter_sums.pkts_forwarded, + ct_counter_sums.pkts_drop, + ct_counter_sums.current_active_sessions, + ct_counter_sums.sessions_activated, + ct_counter_sums.sessions_reactivated, + ct_counter_sums.sessions_established, + ct_counter_sums.sessions_closed, + ct_counter_sums.sessions_timedout, + ct_counter_sums.pkts_drop_outof_window, + ct_counter_sums.pkts_drop_invalid_conn, + ct_counter_sums.pkts_drop_invalid_state, + ct_counter_sums.pkts_drop_invalid_rst); + + for (i = 0; i <= rte_VFW_hi_counter_block_in_use; i++) { + for (j = 0; j < action_array_max; j++) { + if (action_array_active[j]. + action_bitmap & lib_acl_action_count) { + action_counter_sum[j].packetCount += + action_counter_table[i][j].packetCount; + action_counter_sum[j].byteCount += + action_counter_table[i][j].byteCount; + } + } + } + + for (j = 0; j < action_array_max; j++) { + if (action_array_active[j].action_bitmap & lib_acl_action_count) + mg_printf(conn, "Action ID: %02u, packetCount: %" PRIu64 + ", byteCount: %" PRIu64 "\n", j, + action_counter_sum[j].packetCount, + action_counter_sum[j].byteCount); + } + mg_printf(conn, "</body></html>"); + + return 1; + +} + +int vfw_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + + const struct mg_request_info *req_info = mg_get_request_info(conn); + if (strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Only GET method allowed"); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are the methods that are supported </h2>"); + mg_printf(conn, "<h3> /load </h3>"); + mg_printf(conn, "<h3> /clear </h3>"); + mg_printf(conn, "<html><body>"); + + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +static int vfw_field_found(const char *key, + const char *filename, + char *path, + size_t pathlen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, "\r\n\r\n%s:\r\n", key); + mg_printf(conn, "Inside vfw_field_found %s \n", filename); + + if (filename && *filename) { + snprintf(path, pathlen, "/tmp/%s", filename); + int fd; + + mg_printf(conn, "path: %s\n", path); + + /* Make sure the file exists before clearing rules and actions */ + fd = open(path, O_RDONLY); + if (fd < 0) { + mg_printf(conn, "Cannot open file \"%s\"\n", filename); + return FORM_FIELD_STORAGE_GET; + } + close(fd); + + return FORM_FIELD_STORAGE_STORE; + } + + return FORM_FIELD_STORAGE_GET; +} + +static int vfw_field_get(const char *key, const char *value, size_t valuelen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + if (key[0]) { + mg_printf(conn, "%s = ", key); + } + mg_write(conn, value, valuelen); + + return 0; +} + +static int vfw_field_stored(const char *path, long long file_size, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + int status; + + mg_printf(conn, + "stored as %s (%lu bytes)\r\n\r\n", + path, + (unsigned long)file_size); + + /* Clear all rules and actions */ + status = app_pipeline_vfw_clearrules(myapp); + if (status != 0) { + mg_printf(conn, "Command clearrules failed\n"); + return 1; + } + + /* Process commands in script file */ + app_loadrules_file(pipe_cl->ctx, path); + rules_loaded = 1; + + return 0; +} + +int vfw_cmd_ver_handler(__rte_unused struct mg_connection *conn, __rte_unused void *cbdata) +{ + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<p>Command Passed</p>"); + mg_printf(conn, "</body></html>\n"); + + return 1; +} + +int vfw_load_rules_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + int ret; + const struct mg_request_info *req_info = mg_get_request_info(conn); + struct mg_form_data_handler fdh = {vfw_field_found, vfw_field_get, + vfw_field_stored, 0}; + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: " + "text/plain\r\nConnection: close\r\n\r\n"); + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, "Rule file is %s\n", rules_loaded? "LOADED":"NOT LOADED"); + } + + if (strcmp(req_info->request_method, "PUT")) { + mg_printf(conn, "Only PUT method allowed"); + return 1; + } + + fdh.user_data = (void *)conn; + + /* Call the form handler */ + mg_printf(conn, "Form data:"); + ret = mg_handle_form_request(conn, &fdh); + mg_printf(conn, "\r\n%i fields found", ret); + + //mg_handle_form_request(conn, &fdh); + //mg_printf(conn, "\r\n script file handled"); + //rules_loaded = 1; + + return 1; +} + +void rest_api_vfw_init(struct mg_context *ctx, struct app_params *app) +{ + myapp = app; + + /* vFW commands */ + mg_set_request_handler(ctx, "/vnf/config/rules", vfw_rules_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/rules/load", vfw_load_rules_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/rules/clear", vfw_clearrules_handler, 0); + mg_set_request_handler(ctx, "/vnf/stats", vfw_stats_handler, 0); + mg_set_request_handler(ctx, "/vnf/status", vfw_cmd_ver_handler, 0); + +} + cmdline_parse_inst_t cmd_vfw_synproxy = { .f = cmd_vfw_synproxy_flag_parsed, .data = NULL, diff --git a/VNFs/vFW/pipeline/pipeline_vfw.h b/VNFs/vFW/pipeline/pipeline_vfw.h index 3b1b25f0..96e7ad33 100644 --- a/VNFs/vFW/pipeline/pipeline_vfw.h +++ b/VNFs/vFW/pipeline/pipeline_vfw.h @@ -30,6 +30,9 @@ #include "app.h" #include "pipeline_vfw_be.h" +#include <civetweb.h> +#include <json/json.h> + /* VFW IPV4 and IPV6 enable flags for debugging (Default both on) */ extern int vfw_ipv4_enabled; extern int vfw_ipv6_enabled; @@ -142,4 +145,16 @@ app_pipeline_action_delete(struct app_params *app, extern struct pipeline_type pipeline_vfw; +#ifdef REST_API_SUPPORT +/* REST Api's defined here */ +int vfw_rules_handler(struct mg_connection *conn, void *cbdata); +int vfw_load_rules_handler(struct mg_connection *conn, void *cbdata); +int vfw_clearrules_handler(struct mg_connection *conn, void *cbdata); +int vfw_stats_handler(struct mg_connection *conn, void *cbdata); +int vfw_clearstats_handler(__rte_unused struct mg_connection *conn, + __rte_unused void *cbdata); +int vfw_cmd_ver_handler(struct mg_connection *conn, __rte_unused void *cbdata); +void rest_api_vfw_init(struct mg_context *ctx, struct app_params *app); +#endif + #endif diff --git a/VNFs/vFW/pipeline/pipeline_vfw_be.c b/VNFs/vFW/pipeline/pipeline_vfw_be.c index fed424e5..f0eab34b 100644 --- a/VNFs/vFW/pipeline/pipeline_vfw_be.c +++ b/VNFs/vFW/pipeline/pipeline_vfw_be.c @@ -24,7 +24,7 @@ */ #define EN_SWP_ACL 1 -#define EN_SWP_ARP 1 +//#define EN_SWP_ARP 1 #include <stdio.h> #include <stdlib.h> @@ -64,6 +64,7 @@ #include "lib_arp.h" #include "lib_icmpv6.h" #include "pipeline_common_fe.h" +#include "gateway.h" uint32_t timer_lcore; @@ -94,13 +95,6 @@ struct pipeline_vfw { uint8_t traffic_type; uint8_t links_map[PIPELINE_MAX_PORT_IN]; uint8_t outport_id[PIPELINE_MAX_PORT_IN]; - /* Local ARP & ND Tables */ - struct lib_arp_route_table_entry - local_lib_arp_route_table[MAX_ARP_RT_ENTRY]; - uint8_t local_lib_arp_route_ent_cnt; - struct lib_nd_route_table_entry - local_lib_nd_route_table[MAX_ND_RT_ENTRY]; - uint8_t local_lib_nd_route_ent_cnt; } __rte_cache_aligned; /** @@ -799,10 +793,12 @@ pkt4_work_vfw_arp_ipv4_packets(struct rte_mbuf **pkts, if (ret_arp_data->num_pkts >= NUM_DESC) { /* ICMP req sent, drop packet by * changing the mask */ - vfw_pipe->counters->pkts_drop_without_arp_entry++; + vfw_pipe->counters-> + pkts_drop_without_arp_entry++; continue; } else { - arp_pkts_mask |= pkt_mask; + //arp_pkts_mask |= pkt_mask; + *arp_hijack_mask |= pkt_mask; arp_queue_unresolved_packet(ret_arp_data, pkt); continue; } @@ -895,7 +891,8 @@ pkt_work_vfw_arp_ipv4_packets(struct rte_mbuf *pkts, if (ret_arp_data->num_pkts >= NUM_DESC) { /* ICMP req sent, drop packet by * changing the mask */ - vfw_pipe->counters->pkts_drop_without_arp_entry++; + vfw_pipe->counters-> + pkts_drop_without_arp_entry++; return; } else { arp_pkts_mask |= pkt_mask; @@ -999,7 +996,8 @@ pkt4_work_vfw_arp_ipv6_packets(struct rte_mbuf **pkts, if (ret_nd_data->num_pkts >= NUM_DESC) { /* Drop the pkt */ *pkts_mask &= ~pkt_mask; - vfw_pipe->counters->pkts_drop_without_arp_entry++; + vfw_pipe->counters-> + pkts_drop_without_arp_entry++; continue; } else { arp_pkts_mask |= pkt_mask; @@ -1099,7 +1097,8 @@ pkt_work_vfw_arp_ipv6_packets(struct rte_mbuf *pkts, if (ret_nd_data->num_pkts >= NUM_DESC) { /* Drop the pkt */ *pkts_mask &= ~pkt_mask; - vfw_pipe->counters->pkts_drop_without_arp_entry++; + vfw_pipe->counters-> + pkts_drop_without_arp_entry++; return; } else { arp_pkts_mask |= pkt_mask; @@ -1116,211 +1115,257 @@ pkt_work_vfw_arp_ipv6_packets(struct rte_mbuf *pkts, #else /** - * walk every valid mbuf (denoted by pkts_mask) and apply arp to the packet. + * walk every valid mbuf (denoted by pkts_mask) and forward the packet. * To support synproxy, some (altered) packets may need to be sent back where * they came from. The ip header has already been adjusted, but the ethernet * header has not, so this must be performed here. - * Return an updated pkts_mask, since arp may drop some packets + * Return an updated pkts_mask and arp_hijack_mask since arp may drop some packets * * @param pkts - * A pointer to the packet. + * A pointer to the packet array. * @param pkts_mask - * Packet mask - * @param synproxy_reply_mask - * Reply Packet mask for Synproxy + * Packets mask to be processed + * @param arp_hijack_mask + * Packets to be hijacked for arp buffering * @param vfw_pipe * A pointer to VFW pipeline. */ -static uint64_t -rte_vfw_arp_ipv4_packets(struct rte_mbuf **pkts, - uint64_t pkts_mask, - uint64_t synproxy_reply_mask, - struct pipeline_vfw *vfw_pipe) +static void vfw_fwd_pkts_ipv4(struct rte_mbuf **pkts, uint64_t *pkts_mask, + uint64_t *arp_hijack_mask, struct pipeline_vfw *vfw_pipe) { - uint64_t pkts_to_arp = pkts_mask; + uint64_t pkts_to_arp = *pkts_mask; - uint32_t ret; - uint32_t dest_if = INVALID_DESTIF; - for (; pkts_to_arp;) { - struct ether_addr hw_addr; - struct mbuf_tcp_meta_data *meta_data_addr; - struct ether_hdr *ehdr; - struct rte_mbuf *pkt; - uint16_t phy_port; - - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_arp); - /* bitmask representing only this packet */ - uint64_t pkt_mask = 1LLU << pos; - /* remove this packet from remaining list */ - pkts_to_arp &= ~pkt_mask; - pkt = pkts[pos]; - int must_reverse = ((synproxy_reply_mask & pkt_mask) != 0); + for (; pkts_to_arp;) { - phy_port = pkt->port; - meta_data_addr = (struct mbuf_tcp_meta_data *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, META_DATA_OFFSET); - ehdr = rte_vfw_get_ether_addr(pkt); + struct mbuf_tcp_meta_data *meta_data_addr; + struct ether_hdr *ehdr; + struct rte_mbuf *pkt; + uint32_t src_phy_port; + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_arp); + /* bitmask representing only this packet */ + uint64_t pkt_mask = 1LLU << pos; + /* remove this packet from remaining list */ + pkts_to_arp &= ~pkt_mask; + pkt = pkts[pos]; - struct ipv4_hdr *ihdr = (struct ipv4_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); - uint32_t nhip = 0; + if(VFW_DEBUG) { + printf("----------------\n"); + print_pkt(pkt); + } - uint32_t dest_address = rte_bswap32(ihdr->dst_addr); - if (must_reverse) - rte_sp_exchange_mac_addresses(ehdr); - struct arp_entry_data *ret_arp_data = NULL; - ret_arp_data = get_dest_mac_addr_port(dest_address, - &dest_if, &ehdr->d_addr); - meta_data_addr->output_port = vfw_pipe->outport_id[dest_if]; - if (arp_cache_dest_mac_present(dest_if)) { + meta_data_addr = (struct mbuf_tcp_meta_data *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, META_DATA_OFFSET); - ether_addr_copy(get_link_hw_addr(dest_if), &ehdr->s_addr); - update_nhip_access(dest_if); - if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { + ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, ETHERNET_START); - arp_send_buffered_pkts(ret_arp_data, - &ehdr->d_addr, vfw_pipe->outport_id[dest_if]); + src_phy_port = pkt->port; + uint32_t dst_phy_port = INVALID_DESTIF; - } + if(is_gateway()){ + struct ipv4_hdr *ipv4hdr = (struct ipv4_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); - } else { - if (unlikely(ret_arp_data == NULL)) { + /* Gateway Proc Starts */ - if (VFW_DEBUG) - printf("%s: NHIP Not Found, nhip:%x , " - "outport_id: %d\n", __func__, nhip, - vfw_pipe->outport_id[dest_if]); + struct arp_entry_data *ret_arp_data = NULL; + struct ether_addr dst_mac; + uint32_t nhip = 0; + uint32_t dst_ip_addr = rte_bswap32(ipv4hdr->dst_addr); - /* Drop the pkt */ - vfw_pipe->counters-> - pkts_drop_without_arp_entry++; - continue; - } - if (ret_arp_data->status == INCOMPLETE || - ret_arp_data->status == PROBE) { - if (ret_arp_data->num_pkts >= NUM_DESC) { - /* ICMP req sent, drop packet by - * changing the mask */ - vfw_pipe->counters->pkts_drop_without_arp_entry++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - arp_queue_unresolved_packet(ret_arp_data, pkt); - continue; - } -} - } + gw_get_nh_port_ipv4(dst_ip_addr, &dst_phy_port, &nhip); - } + ret_arp_data = get_dest_mac_addr_ipv4(nhip, dst_phy_port, &dst_mac); + + /* Gateway Proc Ends */ + + if (arp_cache_dest_mac_present(dst_phy_port)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dst_phy_port), &ehdr->s_addr); + + meta_data_addr->output_port = vfw_pipe->outport_id[dst_phy_port]; + + update_nhip_access(dst_phy_port); + + if (unlikely(ret_arp_data && ret_arp_data->num_pkts)) { + + arp_send_buffered_pkts(ret_arp_data, &ehdr->d_addr, + vfw_pipe->outport_id[dst_phy_port]); + } + + } else { + if (unlikely(ret_arp_data == NULL)) { + + printf("NHIP Not Found\n"); + + /* Drop the pkt */ + vfw_pipe->counters-> + pkts_drop_without_arp_entry++; + continue; + } + if (ret_arp_data->status == INCOMPLETE || + ret_arp_data->status == PROBE) { + if (ret_arp_data->num_pkts >= NUM_DESC) { + /* ICMP req sent, drop packet by + * changing the mask */ + vfw_pipe->counters->pkts_drop_without_arp_entry++; + continue; + } else { + *arp_hijack_mask |= pkt_mask; + arp_queue_unresolved_packet(ret_arp_data, pkt); + continue; + } + } + } + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dst_phy_port = prv_to_pub_map[src_phy_port]; + else + dst_phy_port = pub_to_prv_map[src_phy_port]; + + meta_data_addr->output_port = vfw_pipe->outport_id[dst_phy_port]; + + if(VFW_DEBUG) { + printf("IP_PKT_FWD: src_phy_port=%d, dst_phy_port=%d\n", + src_phy_port, dst_phy_port); + } + } + + if(VFW_DEBUG) + print_pkt(pkt); + } - return pkts_mask; } + /** - * walk every valid mbuf (denoted by pkts_mask) and apply arp to the packet. + * walk every valid mbuf (denoted by pkts_mask) and forward the packet. * To support synproxy, some (altered) packets may need to be sent back where * they came from. The ip header has already been adjusted, but the ethernet * header has not, so this must be performed here. - * Return an updated pkts_mask, since arp may drop some packets + * Return an updated pkts_mask and arp_hijack_mask since arp may drop some packets * * @param pkts - * A pointer to the packet. + * A pointer to the packet array. * @param pkts_mask - * Packet mask - * @param synproxy_reply_mask - * Reply Packet mask for Synproxy + * Packets mask to be processed + * @param arp_hijack_mask + * Packets to be hijacked for arp buffering * @param vfw_pipe * A pointer to VFW pipeline. */ - - static uint64_t -rte_vfw_arp_ipv6_packets(struct rte_mbuf **pkts, - uint64_t pkts_mask, - uint64_t synproxy_reply_mask, - struct pipeline_vfw *vfw_pipe) +static void vfw_fwd_pkts_ipv6(struct rte_mbuf **pkts, uint64_t *pkts_mask, + uint64_t *arp_hijack_mask, struct pipeline_vfw *vfw_pipe) { - uint64_t pkts_to_arp = pkts_mask; - uint8_t nh_ipv6[IPV6_ADD_SIZE]; - uint32_t ret; - uint32_t dest_if = INVALID_DESTIF; + uint64_t pkts_to_arp = *pkts_mask; - for (; pkts_to_arp;) { - struct ether_addr hw_addr; - struct mbuf_tcp_meta_data *meta_data_addr; - struct ether_hdr *ehdr; - struct rte_mbuf *pkt; - uint16_t phy_port; + for (; pkts_to_arp;) { - uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_arp); - /* bitmask representing only this packet */ - uint64_t pkt_mask = 1LLU << pos; - /* remove this packet from remaining list */ - pkts_to_arp &= ~pkt_mask; - pkt = pkts[pos]; - int must_reverse = ((synproxy_reply_mask & pkt_mask) != 0); + struct mbuf_tcp_meta_data *meta_data_addr; + struct ether_hdr *ehdr; + struct rte_mbuf *pkt; + uint32_t src_phy_port; - phy_port = pkt->port; - meta_data_addr = (struct mbuf_tcp_meta_data *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, META_DATA_OFFSET); - ehdr = rte_vfw_get_ether_addr(pkt); + struct nd_entry_data *ret_nd_data = NULL; - struct ipv6_hdr *ihdr = (struct ipv6_hdr *) - RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); + uint8_t pos = (uint8_t) __builtin_ctzll(pkts_to_arp); + /* bitmask representing only this packet */ + uint64_t pkt_mask = 1LLU << pos; + /* remove this packet from remaining list */ + pkts_to_arp &= ~pkt_mask; + pkt = pkts[pos]; - uint8_t nhip[IPV6_ADD_SIZE]; - uint8_t dest_address[IPV6_ADD_SIZE]; + if(VFW_DEBUG) { + printf("----------------\n"); + print_pkt(pkt); + } - memset(nhip, 0, IPV6_ADD_SIZE); - if (must_reverse) - rte_sp_exchange_mac_addresses(ehdr); + meta_data_addr = (struct mbuf_tcp_meta_data *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, META_DATA_OFFSET); - rte_mov16(dest_address, ihdr->dst_addr); - memset(nh_ipv6, 0, IPV6_ADD_SIZE); - struct nd_entry_data *ret_nd_data = NULL; - ret_nd_data = get_dest_mac_address_ipv6_port( - &dest_address[0], - &dest_if, - &hw_addr, - &nh_ipv6[0]); + ehdr = (struct ether_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, ETHERNET_START); - meta_data_addr->output_port = vfw_pipe-> - outport_id[dest_if]; - if (nd_cache_dest_mac_present(dest_if)) { - ether_addr_copy(get_link_hw_addr(dest_if), - &ehdr->s_addr); - update_nhip_access(dest_if); + src_phy_port = pkt->port; + uint32_t dst_phy_port = INVALID_DESTIF; - if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { - nd_send_buffered_pkts(ret_nd_data, - &ehdr->d_addr, meta_data_addr->output_port); - } + if(is_gateway()){ + struct ipv6_hdr *ipv6hdr = (struct ipv6_hdr *) + RTE_MBUF_METADATA_UINT32_PTR(pkt, IP_START); - } else { - if (unlikely(ret_nd_data == NULL)) { - pkts_mask &= ~pkt_mask; - vfw_pipe->counters-> - pkts_drop_without_arp_entry++; - continue; - } - if (ret_nd_data->status == INCOMPLETE || - ret_nd_data->status == PROBE) { - if (ret_nd_data->num_pkts >= NUM_DESC) { - /* Drop the pkt */ - pkts_mask &= ~pkt_mask; - vfw_pipe->counters-> - pkts_drop_without_arp_entry++; - continue; - } else { - arp_pkts_mask |= pkt_mask; - nd_queue_unresolved_packet(ret_nd_data, pkt); - continue; - } - } - } + /* Gateway Proc Starts */ - } + struct ether_addr dst_mac; + uint32_t dst_phy_port = INVALID_DESTIF; + uint8_t nhipv6[IPV6_ADD_SIZE]; + uint8_t dest_ipv6_address[IPV6_ADD_SIZE]; + memset(nhipv6, 0, IPV6_ADD_SIZE); + src_phy_port = pkt->port; + rte_mov16(dest_ipv6_address, (uint8_t *)ipv6hdr->dst_addr); + + gw_get_nh_port_ipv6(dest_ipv6_address, &dst_phy_port, nhipv6); + + ret_nd_data = get_dest_mac_addr_ipv6(nhipv6, dst_phy_port, &dst_mac); + + /* Gateway Proc Ends */ + + if (nd_cache_dest_mac_present(dst_phy_port)) { + + ether_addr_copy(&dst_mac, &ehdr->d_addr); + ether_addr_copy(get_link_hw_addr(dst_phy_port), &ehdr->s_addr); + + meta_data_addr->output_port = vfw_pipe->outport_id[dst_phy_port]; - return pkts_mask; + update_nhip_access(dst_phy_port); + + if (unlikely(ret_nd_data && ret_nd_data->num_pkts)) { + nd_send_buffered_pkts(ret_nd_data, &ehdr->d_addr, + vfw_pipe->outport_id[dst_phy_port]); + } + + } else { + if (unlikely(ret_nd_data == NULL)) { + + printf("NHIP Not Found\n"); + + /* Drop the pkt */ + vfw_pipe->counters->pkts_drop_without_arp_entry++; + continue; + } + if (ret_nd_data->status == INCOMPLETE || + ret_nd_data->status == PROBE) { + if (ret_nd_data->num_pkts >= NUM_DESC) { + /* ICMP req sent, drop packet by + * changing the mask */ + vfw_pipe->counters->pkts_drop_without_arp_entry++; + continue; + } else { + *arp_hijack_mask |= pkt_mask; + nd_queue_unresolved_packet(ret_nd_data, pkt); + continue; + } + } + } + + } else { + /* IP Pkt forwarding based on pub/prv mapping */ + if(is_phy_port_privte(src_phy_port)) + dst_phy_port = prv_to_pub_map[src_phy_port]; + else + dst_phy_port = pub_to_prv_map[src_phy_port]; + + meta_data_addr->output_port = vfw_pipe->outport_id[dst_phy_port]; + + if(VFW_DEBUG) { + printf("IP_PKT_FWD: src_phy_port=%d, dst_phy_port=%d\n", + src_phy_port, dst_phy_port); + } + } + if(VFW_DEBUG) + print_pkt(pkt); + } } #endif @@ -1516,9 +1561,9 @@ vfw_port_in_action_ipv4(struct rte_pipeline *p, uint64_t packet_mask_in = RTE_LEN2MASK(n_pkts, uint64_t); uint64_t pkts_drop_mask; - uint64_t hijack_mask = 0; - arp_pkts_mask = 0; - uint64_t synproxy_reply_mask = 0; /* for synproxy */ + uint64_t synp_hijack_mask = 0; + uint64_t arp_hijack_mask = 0; +// uint64_t synproxy_reply_mask; /* for synproxy */ uint64_t keep_mask = packet_mask_in; uint64_t conntrack_mask = 0, connexist_mask = 0; @@ -1598,8 +1643,8 @@ vfw_port_in_action_ipv4(struct rte_pipeline *p, if (likely(cnxn_tracking_is_active)) { rte_ct_cnxn_tracker_batch_lookup_type(ct, pkts, &keep_mask, &ct_helper, IPv4_HEADER_SIZE); - synproxy_reply_mask = ct_helper.reply_pkt_mask; - hijack_mask = ct_helper.hijack_mask; +// synproxy_reply_mask = ct_helper.reply_pkt_mask; + synp_hijack_mask = ct_helper.hijack_mask; } @@ -1637,9 +1682,9 @@ vfw_port_in_action_ipv4(struct rte_pipeline *p, #else rte_prefetch0((void*)in_port_dir_a); rte_prefetch0((void*)prv_to_pub_map); - rte_prefetch0((void*) & vfw_pipe->local_lib_arp_route_table); - keep_mask = rte_vfw_arp_ipv4_packets(pkts, keep_mask, - synproxy_reply_mask, vfw_pipe); + + vfw_fwd_pkts_ipv4(pkts, &keep_mask, &arp_hijack_mask, vfw_pipe); + #endif if (vfw_debug > 1) { @@ -1651,9 +1696,14 @@ vfw_port_in_action_ipv4(struct rte_pipeline *p, (void *)keep_mask); } - /* Update mask before returning, so that bad packets are dropped */ - if (arp_pkts_mask) { - rte_pipeline_ah_packet_hijack(p, arp_pkts_mask); + /* Hijack the Synproxy and ARP buffered packets */ + + if (unlikely(arp_hijack_mask || synp_hijack_mask)) { + +// printf("Pkts hijacked arp = %lX, synp = %lX\n", +// arp_hijack_mask, synp_hijack_mask); + + rte_pipeline_ah_packet_hijack(p,(arp_hijack_mask | synp_hijack_mask)); } pkts_drop_mask = packet_mask_in & ~keep_mask; @@ -1663,9 +1713,6 @@ vfw_port_in_action_ipv4(struct rte_pipeline *p, rte_pipeline_ah_packet_drop(p, pkts_drop_mask); } - if (unlikely(hijack_mask != 0)) - rte_pipeline_ah_packet_hijack(p, hijack_mask); - vfw_pipe->counters->num_batch_pkts_sum += n_pkts; vfw_pipe->counters->num_pkts_measurements++; @@ -1705,8 +1752,10 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, uint64_t packet_mask_in = RTE_LEN2MASK(n_pkts, uint64_t); uint64_t pkts_drop_mask; - uint64_t hijack_mask = 0; - uint64_t synproxy_reply_mask = 0; /* for synproxy */ + uint64_t synp_hijack_mask = 0; + uint64_t arp_hijack_mask = 0; +// uint64_t hijack_mask = 0; +// uint64_t synproxy_reply_mask = 0; /* for synproxy */ uint64_t keep_mask = packet_mask_in; uint64_t conntrack_mask = 0, connexist_mask = 0; @@ -1782,8 +1831,8 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, if (likely(cnxn_tracking_is_active)) { rte_ct_cnxn_tracker_batch_lookup_type(ct, pkts, &keep_mask, &ct_helper, IPv6_HEADER_SIZE); - synproxy_reply_mask = ct_helper.reply_pkt_mask; - hijack_mask = ct_helper.hijack_mask; +// synproxy_reply_mask = ct_helper.reply_pkt_mask; + synp_hijack_mask = ct_helper.hijack_mask; } @@ -1795,7 +1844,7 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, ETHERNET_START)); } rte_prefetch0((void*)in_port_dir_a); - rte_prefetch0(vfw_pipe->local_lib_nd_route_table); + // rte_prefetch0(vfw_pipe->local_lib_nd_route_table); uint32_t i; for (i = 0; i < (n_pkts & (~0x3LLU)); i += 4) { @@ -1820,9 +1869,9 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, } #else rte_prefetch0((void*)in_port_dir_a); - rte_prefetch0((void*) & vfw_pipe->local_lib_arp_route_table); - keep_mask = rte_vfw_arp_ipv6_packets(pkts, keep_mask, - synproxy_reply_mask, vfw_pipe); + + vfw_fwd_pkts_ipv6(pkts, &keep_mask, &arp_hijack_mask, vfw_pipe); + #endif if (vfw_debug > 1) { @@ -1834,6 +1883,16 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, (void *)keep_mask); } + /* Hijack the Synproxy and ARP buffered packets */ + + if (unlikely(arp_hijack_mask || synp_hijack_mask)) { + +// printf("Pkts hijacked arp = %lX, synp = %lX\n", +// arp_hijack_mask, synp_hijack_mask); + + rte_pipeline_ah_packet_hijack(p,(arp_hijack_mask | synp_hijack_mask)); + } + /* Update mask before returning, so that bad packets are dropped */ pkts_drop_mask = packet_mask_in & ~keep_mask; @@ -1843,9 +1902,6 @@ vfw_port_in_action_ipv6(struct rte_pipeline *p, rte_pipeline_ah_packet_drop(p, pkts_drop_mask); } - if (unlikely(hijack_mask != 0)) - rte_pipeline_ah_packet_hijack(p, hijack_mask); - vfw_pipe->counters->num_batch_pkts_sum += n_pkts; vfw_pipe->counters->num_pkts_measurements++; diff --git a/VNFs/vFW/vnf_template.txt b/VNFs/vFW/vnf_template.txt new file mode 100644 index 00000000..ed8253be --- /dev/null +++ b/VNFs/vFW/vnf_template.txt @@ -0,0 +1,82 @@ +[MASTER] +type = MASTER +core = 0 + +[ARPICMP] +type = ARPICMP +core = 1 +pktq_in = SWQ0 +pktq_out = TXQ0.0 TXQ1.0 +pktq_in_prv = RXQ0.0 +prv_to_pub_map = (0,1) +prv_que_handler = (0) + +[TIMER] +type = TIMER +core = 2 +n_flows = 1048576 + +[TXRX-BEGIN] +type = TXRX +core = 2 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = SWQ0 SWQ1 SWQ2 +pipeline_txrx_type = RXRX +dest_if_offset=176 + +[TXRX-END] +type = TXRX +core = 5 +pktq_in = SWQ5 SWQ6 +pktq_out = TXQ0.1 TXQ1.1 +pipeline_txrx_type = TXTX + +[LOADB] +type = LOADB +core = 3 +pktq_in = SWQ0 SWQ1 +pktq_out = SWQ3 SWQ4 +outport_offset = 136 +phyport_offset = 204 +n_vnf_threads = 1 +prv_que_handler = (0) + +[VACL] +type = ACL +core = 4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ5 SWQ6 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 + +[VCGNAPT] +type = CGNAPT +core = 3 +pktq_in = RXQ0.0 RXQ1.0 +pktq_out = TXQ0.1 TXQ1.1 SWQ0 +phyport_offset = 204 +n_flows = 1048576 +key_offset = 192;64 +key_size = 8 +hash_offset = 200;72 +timer_period = 100 +max_clients_per_ip = 65535 +max_port_per_client = 10 +public_ip_port_range = 98103214:(1, 65535) +vnf_set = (3,4,5) +pkt_type = ipv4 +cgnapt_meta_offset = 128 +prv_que_handler = (0,) + +[VFW] +type = VFW +core = s0c4 +pktq_in = SWQ3 SWQ4 +pktq_out = SWQ7 SWQ8;TXQ0.0 TXQ1.0 +n_rules = 10000 +n_flows = 1000000 +pkt_type = ipv6 +traffic_type = 6 +tcp_time_wait = 10 + diff --git a/common/VIL/gateway/gateway.c b/common/VIL/gateway/gateway.c new file mode 100644 index 00000000..baf22cf5 --- /dev/null +++ b/common/VIL/gateway/gateway.c @@ -0,0 +1,218 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +/** + * @file + * Gateway packet forwarding Implementation. + * + * Implementation of gateway packet forwarding, next hop IP and + * associated processing. + * + */ + +#include <rte_mbuf.h> +#include <rte_malloc.h> +#include <rte_ethdev.h> +#include <rte_memcpy.h> + +#include "gateway.h" +#include "pipeline_common_fe.h" + +#define IP_VERSION_4 4 +#define IP_VERSION_6 6 +#define MAX_PORTS 32 + +/* Global stats counters used in ARP */ +extern uint32_t lib_nd_nh_found; +extern uint32_t lib_arp_nh_found; + +struct route_data *p_route_data[MAX_PORTS]; +struct nd_route_data *p_nd_route_data[MAX_PORTS]; + +/** +* VNF is configured with routing info or not +* vnf_gateway = 0: No Routes Added , 1: Routes defined +* Flag is part of the ARPICMP config parameter +*/ + +/* Initialized for IP Pkt forwarding */ +uint32_t vnf_gateway = 0; + +/* Initialized number of out ports to route */ +uint32_t num_out_ports = 0; + +/** + * Initialize the gateway for routing tables + * + * @param void + * None + * @return uint32_t + * 1 to MAX_PORTS + */ + +void gw_init(uint32_t num_ports) +{ + void *p; + uint32_t size; + uint32_t i; + + num_out_ports = num_ports; + + for(i = 0; i < num_ports; i++) { + /* IPv4 route table */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct route_data)); + p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + p_route_data[i] = (struct route_data *)p; + + /* IPv6 route touble */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct nd_route_data)); + p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + p_nd_route_data[i] = (struct nd_route_data *)p; + } +} +/* + * Get the the number of ports to route + * @param void + * None + * @return uint32_t + * Number of ports enabled in the VNF +*/ + +uint32_t gw_get_num_ports(void) +{ + return num_out_ports; +} + + +/** + * Check if the gateway is enabled + * + * @param void + * None + * @return uint32_t + * 0: No routes, 1: Route entries available + */ +uint32_t is_gateway(void) +{ + return vnf_gateway; +} + + +/** + * Get the next hop ip address and port number for IPv4 + * @param dst_ip_addr + * Destination IPv4 address + * @param dst_port + * A pointer to destination port + * @param nhip + * A pointer to next hop ip address + */ + +void gw_get_nh_port_ipv4(uint32_t dst_ip_addr, + uint32_t *dst_port, uint32_t *nhip) +{ + int i; + uint32_t j; + + *nhip = 0; + *dst_port = 0xff; + + for(j = 0; j < gw_get_num_ports(); j++){ + + for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) { + + if ((p_route_data[j]->route_table[i].nh_mask) == + (dst_ip_addr & + p_route_data[j]->route_table[i].mask)) { + + *dst_port = p_route_data[j]->route_table[i].port; + *nhip = p_route_data[j]->route_table[i].nh; + + lib_arp_nh_found++; + return; + } + } + } +} + +/** + * Get the next hop ip address and port number for IPv6 + * @param dst_ipv6_addr + * Destination IPv6 address + * @param dst_port + * A pointer to destination port + * @param nhipv6 + * A pointer to next hop ip address + */ + +void gw_get_nh_port_ipv6(uint8_t *dst_ipv6_addr, + uint32_t *dst_port, uint8_t *nhipv6) +{ + if (!dst_ipv6_addr) + return; + uint32_t j; + for(j = 0; j < gw_get_num_ports(); j++){ + + if(p_nd_route_data[j]->nd_route_ent_cnt){ + + memset(nhipv6, 0, IPV6_ADD_SIZE); + + int i=0; + uint8_t netmask_ipv6[IPV6_ADD_SIZE], netip_nd[IPV6_ADD_SIZE]; + uint8_t netip_in[IPV6_ADD_SIZE]; + uint8_t k = 0, depthflags = 0, depthflags1 = 0; + memset(netmask_ipv6, 0, sizeof(netmask_ipv6)); + memset(netip_nd, 0, sizeof(netip_nd)); + memset(netip_in, 0, sizeof(netip_in)); + + for (i = 0; i < p_nd_route_data[j]->nd_route_ent_cnt; i++) { + + convert_prefixlen_to_netmask_ipv6( + p_nd_route_data[j]->nd_route_table[i].depth, netmask_ipv6); + + for (k = 0; k < IPV6_ADD_SIZE; k++) { + if (p_nd_route_data[j]->nd_route_table[i].nhipv6[k] & + netmask_ipv6[k]) { + + depthflags++; + netip_nd[k] = p_nd_route_data[j]->nd_route_table[i].nhipv6[k]; + } + + if (dst_ipv6_addr[k] & netmask_ipv6[k]) { + depthflags1++; + netip_in[k] = dst_ipv6_addr[k]; + } + } + + if ((depthflags == depthflags1) && + (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) { + + *dst_port = p_nd_route_data[j]->nd_route_table[i].port; + + lib_nd_nh_found++; + + rte_mov16(nhipv6, (uint8_t *) + &(p_nd_route_data[j]->nd_route_table[i].nhipv6[0])); + + return; + } + + } + + } + } +} + diff --git a/common/VIL/gateway/gateway.h b/common/VIL/gateway/gateway.h new file mode 100644 index 00000000..47a3b8a7 --- /dev/null +++ b/common/VIL/gateway/gateway.h @@ -0,0 +1,104 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#ifndef __INCLUDE_GATEWAY_H__ +#define __INCLUDE_GATEWAY_H__ + +/** + * @file + * gateway.h + * + * Provide APIs for Packet fowarding in gateway configuration. + * + */ + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_ether.h> +#include <rte_ethdev.h> +#include <rte_ip.h> +#include <rte_udp.h> +#include <rte_mbuf.h> +#include <rte_byteorder.h> + +#include "pipeline.h" +#include "app.h" +#include "vnf_common.h" +#include "vnf_define.h" + +/** +* A structure for Route table entries of IPv4 +*/ +#define MAX_ROUTE_ENTRY_SIZE 32 +#define MAX_ND_ROUTE_ENTRY_SIZE 32 + +extern struct route_data *p_route_data[]; +extern struct nd_route_data *p_nd_route_data[]; + +extern uint32_t vnf_gateway; + +/** + * A structure for Route table entires of IPv4 + * + */ +struct route_table_entry { + uint32_t nh; /**< next hop */ + uint32_t mask; /**< mask */ + uint32_t port; /**< Physical port */ + uint32_t nh_mask; +} __rte_cache_aligned; + +/** + * Routing table for IPv4 + * + */ +struct route_data { + struct route_table_entry route_table[MAX_ROUTE_ENTRY_SIZE]; + uint8_t route_ent_cnt; +}; + +/** + * A structure for Route table entires of IPv6 + * + */ +struct nd_route_table_entry { + uint8_t nhipv6[16]; /**< next hop Ipv6 */ + uint8_t depth; /**< Depth */ + uint32_t port; /**< Port */ +}; + +/** + * Routing table for IPv6 + * + */ +struct nd_route_data { + struct nd_route_table_entry nd_route_table[MAX_ND_ROUTE_ENTRY_SIZE]; + uint8_t nd_route_ent_cnt; +}; + +extern void gw_init(uint32_t num_ports); + +extern uint32_t gw_get_num_ports(void); + +extern uint32_t is_gateway(void); + +extern void gw_get_nh_port_ipv4(uint32_t dst_ip_addr, + uint32_t *dst_port, uint32_t *nhip); + +extern void gw_get_nh_port_ipv6(uint8_t *dst_ipv6_addr, + uint32_t *dst_port, uint8_t *nhipv6); + +#endif diff --git a/common/VIL/l2l3_stack/lib_arp.c b/common/VIL/l2l3_stack/lib_arp.c index c37e486b..b8976d3a 100644 --- a/common/VIL/l2l3_stack/lib_arp.c +++ b/common/VIL/l2l3_stack/lib_arp.c @@ -40,6 +40,7 @@ #include "lib_arp.h" #include "l3fwd_lpm4.h" #include "vnf_common.h" +#include "gateway.h" #if (RTE_BYTE_ORDER == RTE_LITTLE_ENDIAN) #define CHECK_ENDIAN_16(x) rte_be_to_cpu_16(x) @@ -70,7 +71,7 @@ uint32_t nd_buffer = ARP_BUF_DEFAULT; #define IN6ADDRSZ 16 #define MAX_PORTS 32 -static int my_inet_pton_ipv6(int af, const char *src, void *dst); +int my_inet_pton_ipv6(int af, const char *src, void *dst); static int inet_pton_ipv6(const char *src, unsigned char *dst); static int inet_pton_ipv4(const char *src, unsigned char *dst); static void local_arp_cache_init(void); @@ -140,15 +141,6 @@ void update_nhip_access(uint8_t dest_if) p_arp_data->update_tsc[dest_if] = rte_rdtsc(); } -/** - * A structure defining the mbuf meta data for VFW. - */ -struct mbuf_arp_meta_data { -/* output port stored for RTE_PIPELINE_ACTION_PORT_META */ - uint32_t output_port; - struct rte_mbuf *next; /* next pointer for chained buffers */ -} __rte_cache_aligned; - static struct arp_entry_data arp_entry_data_default = { .status = COMPLETE, .num_pkts = 0, @@ -224,11 +216,6 @@ int timer_objs_mempool_count = 70000; #define MAX_NUM_ARP_ENTRIES 64 #define MAX_NUM_ND_ENTRIES 64 - -inline uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr); -void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[], - struct ether_addr *hw_addr); - #define MAX_ARP_DATA_ENTRY_TABLE 7 struct table_arp_entry_data arp_entry_data_table[MAX_ARP_DATA_ENTRY_TABLE] = { @@ -260,73 +247,6 @@ struct table_nd_entry_data nd_entry_data_table[MAX_ND_DATA_ENTRY_TABLE] = { {7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1}, 0}, }; -struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY] = { - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} }, - {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0, 0, - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } -}; - void print_trace(void); uint32_t get_arp_buf(void) @@ -368,132 +288,48 @@ void print_trace(void) free(strings); } -uint32_t get_nh(uint32_t ip, uint32_t *port, struct ether_addr *addr) -{ - int i = 0; - for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) { - if ((p_arp_data->lib_arp_route_table[i].nh_mask) == - (ip & p_arp_data->lib_arp_route_table[i].mask)) { - - *port = p_arp_data->lib_arp_route_table[i].port; - if (arp_cache_dest_mac_present(*port)) - ether_addr_copy( - get_local_link_hw_addr(*port, - p_arp_data->lib_arp_route_table[i].nh), addr); - return p_arp_data->lib_arp_route_table[i].nh; - } - } - lib_arp_no_nh_found++; - return 0; -} - -/*ND IPv6 */ -void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[], -struct ether_addr *hw_addr) -{ - int i = 0; - uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16]; - uint8_t k = 0, l = 0, depthflags = 0, depthflags1 = 0; - memset(netmask_ipv6, 0, sizeof(netmask_ipv6)); - memset(netip_nd, 0, sizeof(netip_nd)); - memset(netip_in, 0, sizeof(netip_in)); - if (!ipv6) - return; - for (i = 0; i < MAX_ARP_RT_ENTRY; i++) { - - convert_prefixlen_to_netmask_ipv6(lib_nd_route_table[i].depth, - netmask_ipv6); - - for (k = 0; k < 16; k++) { - if (lib_nd_route_table[i].ipv6[k] & netmask_ipv6[k]) { - depthflags++; - netip_nd[k] = lib_nd_route_table[i].ipv6[k]; - } - } - - for (l = 0; l < 16; l++) { - if (ipv6[l] & netmask_ipv6[l]) { - depthflags1++; - netip_in[l] = ipv6[l]; - } - } - int j = 0; - if ((depthflags == depthflags1) - && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) { - //&& (lib_nd_route_table[i].port == port)) - *port = lib_nd_route_table[i].port; - lib_nd_nh_found++; - - for (j = 0; j < 16; j++) - nhipv6[j] = lib_nd_route_table[i].nhipv6[j]; - - if (nd_cache_dest_mac_present(*port)) { - ether_addr_copy( - get_nd_local_link_hw_addr(*port, nhipv6), - (struct ether_addr *)hw_addr); - } - return; - } - - if (NDIPV6_DEBUG) - printf("No nh match\n"); - depthflags = 0; - depthflags1 = 0; - } - if (NDIPV6_DEBUG) - printf("No NH - ip 0x%x, \n", ipv6[0]); - lib_nd_no_nh_found++; -} /* Added for Multiport changes*/ -struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr, - uint32_t *phy_port, struct ether_addr *hw_addr) +struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip, + uint32_t phy_port, struct ether_addr *hw_addr) { struct arp_entry_data *ret_arp_data = NULL; - uint32_t nhip = 0; uint8_t index; - nhip = get_nh(ipaddr, phy_port, hw_addr); - if (unlikely(nhip == 0)) { - if (ARPICMP_DEBUG) - printf("ARPICMP no nh found for ip %x, port %d\n", - ipaddr, *phy_port); - return ret_arp_data; - } - /* as part of optimization we store mac address in cache * & thus can be sent without having to retrieve */ - if (arp_cache_dest_mac_present(*phy_port)) { + if (arp_cache_dest_mac_present(phy_port)) { + ether_addr_copy(get_local_cache_hw_addr(phy_port, nhip), hw_addr); return &arp_entry_data_default; } struct arp_key_ipv4 tmp_arp_key; - tmp_arp_key.port_id = *phy_port; /* Changed for Multi Port */ + tmp_arp_key.port_id = phy_port; /* Changed for Multi Port */ tmp_arp_key.ip = nhip; if (ARPICMP_DEBUG) printf("%s: nhip: %x, phyport: %d\n", __FUNCTION__, nhip, - *phy_port); + phy_port); ret_arp_data = retrieve_arp_entry(tmp_arp_key, DYNAMIC_ARP); if (ret_arp_data == NULL) { - if (ARPICMP_DEBUG && ipaddr) + if (ARPICMP_DEBUG && nhip) { RTE_LOG(INFO, LIBARP,"ARPICMP no arp entry found for ip %x," - " port %u\n", ipaddr, *phy_port); + " port %u\n", nhip, phy_port); print_arp_table(); } lib_arp_no_arp_entry_found++; } else if (ret_arp_data->status == COMPLETE) { rte_rwlock_write_lock(&ret_arp_data->queue_lock); ether_addr_copy(&ret_arp_data->eth_addr, hw_addr); - p_arp_data->arp_cache_hw_laddr_valid[*phy_port] = 1; - index = p_arp_data->arp_local_cache[*phy_port].num_nhip; - p_arp_data->arp_local_cache[*phy_port].nhip[index] = nhip; + p_arp_data->arp_cache_hw_laddr_valid[phy_port] = 1; + index = p_arp_data->arp_local_cache[phy_port].num_nhip; + p_arp_data->arp_local_cache[phy_port].nhip[index] = nhip; ether_addr_copy(hw_addr, - &p_arp_data->arp_local_cache[*phy_port].link_hw_laddr[index]); - p_arp_data->arp_local_cache[*phy_port].num_nhip++; + &p_arp_data->arp_local_cache[phy_port].link_hw_laddr[index]); + p_arp_data->arp_local_cache[phy_port].num_nhip++; rte_rwlock_write_unlock(&ret_arp_data->queue_lock); lib_arp_arp_entry_found++; if (ARPICMP_DEBUG) @@ -501,43 +337,26 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr, } if (ret_arp_data) - p_arp_data->update_tsc[*phy_port] = rte_rdtsc(); + p_arp_data->update_tsc[phy_port] = rte_rdtsc(); return ret_arp_data; } -struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], - uint32_t *phy_port, struct ether_addr *hw_addr, uint8_t nhipv6[]) + +struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[], + uint32_t phy_port, struct ether_addr *hw_addr) { - int i = 0, j = 0, flag = 0; + int i = 0; uint8_t index; lib_nd_get_mac_req++; - get_nh_ipv6(ipv6addr, phy_port, nhipv6, hw_addr); - for (j = 0; j < 16; j++) { - if (nhipv6[j]) - flag++; - } - - if (flag == 0) { - if (NDIPV6_DEBUG) - printf("NDIPV6 no nh found for ipv6 " - "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x" - "%02x%02x%02x%02x%02x%02x, port %d\n", - ipv6addr[0], ipv6addr[1], ipv6addr[2], - ipv6addr[3], ipv6addr[4], ipv6addr[5], - ipv6addr[6], ipv6addr[7], ipv6addr[8], - ipv6addr[9], ipv6addr[10], ipv6addr[11], - ipv6addr[12], ipv6addr[13], ipv6addr[14], - ipv6addr[15], *phy_port); - return 0; - } - struct nd_entry_data *ret_nd_data = NULL; struct nd_key_ipv6 tmp_nd_key; - tmp_nd_key.port_id = *phy_port; + tmp_nd_key.port_id = phy_port; - if (nd_cache_dest_mac_present(*phy_port)) { + if (nd_cache_dest_mac_present(phy_port)) { + ether_addr_copy(get_nd_local_link_hw_addr( + (uint8_t)phy_port, nhipv6), hw_addr); return &nd_entry_data_default; } @@ -548,28 +367,29 @@ struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], ret_nd_data = retrieve_nd_entry(tmp_nd_key, DYNAMIC_ND); if (ret_nd_data == NULL) { if (NDIPV6_DEBUG) { - printf("NDIPV6 no nd entry found for ip %x, port %d\n", - ipv6addr[0], *phy_port); + printf("NDIPV6 no entry found for ip %x, port %d\n", + nhipv6[0], phy_port); } lib_nd_no_arp_entry_found++; return NULL; } else if (ret_nd_data->status == COMPLETE) { rte_rwlock_write_lock(&ret_nd_data->queue_lock); ether_addr_copy(&ret_nd_data->eth_addr, hw_addr); - p_arp_data->nd_cache_hw_laddr_valid[*phy_port] = 1; - index = p_arp_data->nd_local_cache[*phy_port].num_nhip; - rte_mov16(&p_arp_data->nd_local_cache[*phy_port].nhip[index][0], - &nhipv6[0]); + p_arp_data->nd_cache_hw_laddr_valid[phy_port] = 1; + index = p_arp_data->nd_local_cache[phy_port].num_nhip; + for (i=0; i<16; i++) { + p_arp_data->nd_local_cache[phy_port].nhip[index][i] = nhipv6[i]; + } ether_addr_copy(hw_addr, - &p_arp_data->nd_local_cache[*phy_port].link_hw_laddr[index]); - p_arp_data->nd_local_cache[*phy_port].num_nhip++; + &p_arp_data->nd_local_cache[phy_port].link_hw_laddr[index]); + p_arp_data->nd_local_cache[phy_port].num_nhip++; lib_nd_nd_entry_found++; rte_rwlock_write_unlock(&ret_nd_data->queue_lock); } if (ret_nd_data) - p_arp_data->update_tsc[*phy_port] = rte_rdtsc(); + p_arp_data->update_tsc[phy_port] = rte_rdtsc(); return ret_nd_data; } @@ -822,8 +642,7 @@ struct arp_entry_data *retrieve_arp_entry(struct arp_key_ipv4 arp_key, uint8_t m (void **)&ret_arp_data); if (ret < 0 && (mode == DYNAMIC_ARP)) { if (ARPICMP_DEBUG) - RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n", - arp_key.ip); + RTE_LOG(INFO, LIBARP, "ARP entry not found for ip 0x%x\n",arp_key.ip); /* add INCOMPLETE arp entry */ ret_arp_data = rte_malloc_socket(NULL, sizeof(struct arp_entry_data), @@ -1045,10 +864,10 @@ void print_arp_table(void) void *next_data; uint32_t iter = 0; - printf("------------------------ ARP CACHE ------------------------------------\n"); - printf("-----------------------------------------------------------------------\n"); + printf ("------------------------ ARP CACHE -----------------------------------------\n"); + printf ("----------------------------------------------------------------------------\n"); printf("\tport hw addr status ip addr\n"); - printf("-----------------------------------------------------------------------\n"); + printf ("----------------------------------------------------------------------------\n"); while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter) >= 0) { @@ -1057,9 +876,9 @@ void print_arp_table(void) (struct arp_entry_data *)next_data; struct arp_key_ipv4 tmp_arp_key; memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4)); - printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X" - " %10s %d.%d.%d.%d\n", - tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0], + printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s %d.%d.%d.%d\n", + tmp_arp_data->port, + tmp_arp_data->eth_addr.addr_bytes[0], tmp_arp_data->eth_addr.addr_bytes[1], tmp_arp_data->eth_addr.addr_bytes[2], tmp_arp_data->eth_addr.addr_bytes[3], @@ -1073,22 +892,24 @@ void print_arp_table(void) } uint32_t i = 0; - printf("\nARP routing table has %d entries\n", p_arp_data->lib_arp_route_ent_cnt); - printf("\nIP_Address Mask Port NH_IP_Address\n"); - for (i = 0; i < p_arp_data->lib_arp_route_ent_cnt; i++) { - printf("0x%x 0x%x %d 0x%x\n", - p_arp_data->lib_arp_route_table[i].ip, - p_arp_data->lib_arp_route_table[i].mask, - p_arp_data->lib_arp_route_table[i].port, - p_arp_data->lib_arp_route_table[i].nh); + uint32_t j = 0; + + printf("\nARP routing table...\n"); + printf("\nIP_Address \t Mask \t\t Port\n"); + for (j = 0; j < gw_get_num_ports(); j++) { + for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) { + printf("0x%08x \t 0x%08x \t %d\n", + p_route_data[j]->route_table[i].nh, + p_route_data[j]->route_table[i].mask, + p_route_data[j]->route_table[i].port); + } } - - printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u," - " no_Entry %u, PopulateCall %u, Del %u, Dup %u\n", - lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found, - lib_arp_arp_entry_found, lib_arp_no_arp_entry_found, - lib_arp_populate_called, lib_arp_delete_called, - lib_arp_duplicate_found); + printf("\nARP Stats: Total Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, " + "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n", + lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found, + lib_arp_arp_entry_found, lib_arp_no_arp_entry_found, + lib_arp_populate_called, lib_arp_delete_called, + lib_arp_duplicate_found); printf("ARP table key len is %lu\n", sizeof(struct arp_key_ipv4)); } @@ -1099,11 +920,13 @@ void print_nd_table(void) const void *next_key; void *next_data; uint32_t iter = 0; - uint8_t ii = 0, j = 0, k = 0; - printf("-----------------------------------------------------------------------\n"); + uint8_t ii = 0, k = 0; + printf + ("------------------------------------------------------------------------------------------------------\n"); printf("\tport hw addr status ip addr\n"); - printf("-----------------------------------------------------------------------\n"); + printf + ("------------------------------------------------------------------------------------------------------\n"); while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >= 0) { @@ -1111,7 +934,7 @@ void print_nd_table(void) (struct nd_entry_data *)next_data; struct nd_key_ipv6 tmp_nd_key; memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6)); - printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s\n", + printf("\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s", tmp_nd_data->port, tmp_nd_data->eth_addr.addr_bytes[0], tmp_nd_data->eth_addr.addr_bytes[1], @@ -1120,7 +943,7 @@ void print_nd_table(void) tmp_nd_data->eth_addr.addr_bytes[4], tmp_nd_data->eth_addr.addr_bytes[5], arp_status[tmp_nd_data->status]); - printf("\t\t\t\t\t\t"); + printf("\t"); for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) { printf("%02X%02X ", tmp_nd_data->ipv6[ii], tmp_nd_data->ipv6[ii + 1]); @@ -1129,30 +952,24 @@ void print_nd_table(void) } uint32_t i = 0; - printf("\n\nND IPV6 routing table has %d entries\n", - nd_route_tbl_index); - printf("\nIP_Address Depth"); - printf(" Port NH_IP_Address\n"); - for (i = 0; i < nd_route_tbl_index; i++) { - printf("\n"); - - for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) { - RTE_LOG(INFO, LIBARP, "%02X%02X ", - lib_nd_route_table[i].ipv6[j], - lib_nd_route_table[i].ipv6[j + 1]); - } + printf("\n\nND IPV6 routing table ...\n"); + printf ("\nNH_IP_Address Depth Port \n"); + for(uint32_t p = 0; p < gw_get_num_ports(); p++ ) { + for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) { + // printf("\n"); + + for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) { + printf("%02X%02X ", p_nd_route_data[p]->nd_route_table[i].nhipv6[k], + p_nd_route_data[p]->nd_route_table[i].nhipv6[k + 1]); + } - printf - ("\n\t\t\t %d %d \n", - lib_nd_route_table[i].depth, lib_nd_route_table[i].port); - printf("\t\t\t\t\t\t\t\t\t"); - for (k = 0; k < ND_IPV6_ADDR_SIZE; k += 2) { - printf("%02X%02X ", lib_nd_route_table[i].nhipv6[k], - lib_nd_route_table[i].ipv6[k + 1]); + printf("\t%d %d \n", + p_nd_route_data[p]->nd_route_table[i].depth, + p_nd_route_data[p]->nd_route_table[i].port); } } - printf("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u," - " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u, Del %u, Dup %u\n", + printf ("\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u, no_NH %u, ok_Entry %u, " + "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n", lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found, lib_nd_nd_entry_found, lib_nd_no_arp_entry_found, lib_nd_populate_called, lib_nd_delete_called, @@ -1166,10 +983,13 @@ void remove_arp_entry(struct arp_entry_data *ret_arp_data, void *arg) struct arp_timer_key *arp_key = (struct arp_timer_key *)arg; lib_arp_delete_called++; - rte_timer_stop(ret_arp_data->timer); - rte_free(ret_arp_data->timer_key); - rte_free(ret_arp_data->buf_pkts); - ret_arp_data->buf_pkts = NULL; + if (ret_arp_data->timer) { + rte_timer_stop(ret_arp_data->timer); + rte_free(ret_arp_data->timer_key); + rte_free(ret_arp_data->buf_pkts); + ret_arp_data->buf_pkts = NULL; + } + if (ARPICMP_DEBUG) { RTE_LOG(INFO, LIBARP, "ARP Entry Deleted for IP :%d.%d.%d.%d , port %d\n", @@ -1249,6 +1069,7 @@ arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data, tmp = pkt; rte_pktmbuf_free(tmp); } + printf("arp send buffered pkts = %d\n",ret_arp_data->num_pkts); ret_arp_data->num_pkts = 0; rte_rwlock_write_unlock(&ret_arp_data->queue_lock); } @@ -1346,7 +1167,7 @@ populate_arp_entry(const struct ether_addr *hw_addr, uint32_t ipaddr, if (new_arp_data->status == STALE) { new_arp_data->status = PROBE; if (ifm_chk_port_ipv4_enabled - (new_arp_data->port)) { + (new_arp_data->port) != IFM_FAILURE) { request_arp(new_arp_data->port, new_arp_data->ip); } else { @@ -1501,7 +1322,8 @@ void populate_nd_entry(const struct ether_addr *hw_addr, uint8_t ipv6[], } if (mode == DYNAMIC_ND) { - if (new_nd_data && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) { + if (new_nd_data + && is_same_ether_addr(&new_nd_data->eth_addr, hw_addr)) { if (NDIPV6_DEBUG) { RTE_LOG(INFO, LIBARP, @@ -2075,7 +1897,7 @@ void process_arpicmp_pkt(struct rte_mbuf *pkt, l2_phy_interface_t *port) * author: * Paul Vixie, 1996. */ -static int my_inet_pton_ipv6(int af, const char *src, void *dst) +int my_inet_pton_ipv6(int af, const char *src, void *dst) { switch (af) { case AF_INET: @@ -2412,9 +2234,8 @@ static int arp_parse_args(struct pipeline_params *params) /* arp_route_tbl */ if (strcmp(arg_name, "arp_route_tbl") == 0) { arp_route_tbl_present = 1; - - uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = - 0, i = 0, j = 0, k = 0, l = 0; + uint32_t dest_ip = 0, mask = 0, tx_port = 0, nh_ip = 0, + i = 0, j = 0, k = 0; uint32_t arp_route_tbl_str_max_len = 10; char dest_ip_str[arp_route_tbl_str_max_len]; char mask_str[arp_route_tbl_str_max_len]; @@ -2425,11 +2246,11 @@ static int arp_parse_args(struct pipeline_params *params) i = 0; while ((i < (arp_route_tbl_str_max_len - 1)) && (token[i] != ',')) { - dest_ip_str[i] = token[i]; + nh_ip_str[i] = token[i]; i++; } - dest_ip_str[i] = '\0'; - dest_ip = strtoul(dest_ip_str, NULL, 16); + nh_ip_str[i] = '\0'; + nh_ip = strtoul(nh_ip_str, NULL, 16); i++; j = 0; @@ -2452,19 +2273,11 @@ static int arp_parse_args(struct pipeline_params *params) tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str); k++; - l = 0; - while ((l < (arp_route_tbl_str_max_len - 1)) - && (token[i + j + k + l] != ')')) { - nh_ip_str[l] = token[i + j + k + l]; - l++; - } - nh_ip_str[l] = '\0'; - nh_ip = strtoul(nh_ip_str, NULL, 16); //atoi(nh_ip_str); if (1) { RTE_LOG(INFO, LIBARP, "token: %s, " "dest_ip_str: %s, dest_ip %u, " - "mask_str: %s, mask %u, " + "mask_str: %s, mask %x, " "tx_port_str: %s, tx_port %u, " "nh_ip_str: %s, nh_ip %u\n", token, dest_ip_str, dest_ip, @@ -2480,15 +2293,15 @@ static int arp_parse_args(struct pipeline_params *params) } */ //Populate the static arp_route_table - struct lib_arp_route_table_entry *lentry = - &p_arp_data->lib_arp_route_table - [p_arp_data->lib_arp_route_ent_cnt]; - lentry->ip = dest_ip; + + struct route_table_entry *lentry = + &p_route_data[tx_port]->route_table + [p_route_data[tx_port]->route_ent_cnt]; lentry->mask = mask; lentry->port = tx_port; lentry->nh = nh_ip; lentry->nh_mask = nh_ip & mask; - p_arp_data->lib_arp_route_ent_cnt++; + p_route_data[tx_port]->route_ent_cnt++; token = strtok(NULL, "("); } @@ -2499,10 +2312,10 @@ static int arp_parse_args(struct pipeline_params *params) if (strcmp(arg_name, "nd_route_tbl") == 0) { nd_route_tbl_present = 1; - uint8_t dest_ipv6[16], depth = 0, tx_port = - 0, nh_ipv6[16], i = 0, j = 0, k = 0, l = 0; + uint8_t depth = 0, tx_port = 0, nh_ipv6[16]; + uint8_t i = 0, j = 0, k = 0; uint8_t nd_route_tbl_str_max_len = 128; //64; - char dest_ipv6_str[nd_route_tbl_str_max_len]; +// char dest_ipv6_str[nd_route_tbl_str_max_len]; char depth_str[nd_route_tbl_str_max_len]; char tx_port_str[nd_route_tbl_str_max_len]; char nh_ipv6_str[nd_route_tbl_str_max_len]; @@ -2511,13 +2324,12 @@ static int arp_parse_args(struct pipeline_params *params) i = 0; while ((i < (nd_route_tbl_str_max_len - 1)) && (token[i] != ',')) { - dest_ipv6_str[i] = token[i]; + nh_ipv6_str[i] = token[i]; i++; } - dest_ipv6_str[i] = '\0'; - my_inet_pton_ipv6(AF_INET6, dest_ipv6_str, - &dest_ipv6); - + nh_ipv6_str[i] = '\0'; + my_inet_pton_ipv6(AF_INET6, nh_ipv6_str, + &nh_ipv6); i++; j = 0; while ((j < (nd_route_tbl_str_max_len - 1)) @@ -2542,31 +2354,19 @@ static int arp_parse_args(struct pipeline_params *params) tx_port = strtoul(tx_port_str, NULL, 16); //atoi(tx_port_str); k++; - l = 0; - while ((l < (nd_route_tbl_str_max_len - 1)) - && (token[i + j + k + l] != ')')) { - nh_ipv6_str[l] = token[i + j + k + l]; - l++; - } - nh_ipv6_str[l] = '\0'; - my_inet_pton_ipv6(AF_INET6, nh_ipv6_str, - &nh_ipv6); + struct nd_route_table_entry *lentry = + &p_nd_route_data[tx_port]->nd_route_table + [p_nd_route_data[tx_port]->nd_route_ent_cnt]; //Populate the static arp_route_table - for (i = 0; i < 16; i++) { - lib_nd_route_table - [nd_route_tbl_index].ipv6[i] = - dest_ipv6[i]; - lib_nd_route_table - [nd_route_tbl_index].nhipv6[i] = - nh_ipv6[i]; - } - lib_nd_route_table[nd_route_tbl_index].depth = - depth; - lib_nd_route_table[nd_route_tbl_index].port = - tx_port; + for (i = 0; i < 16; i++) + lentry->nhipv6[i] = nh_ipv6[i]; + + lentry->depth = depth; + lentry->port = tx_port; + + p_nd_route_data[tx_port]->nd_route_ent_cnt++; - nd_route_tbl_index++; token = strtok(NULL, "("); } @@ -2614,13 +2414,19 @@ struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]) } x = &p_arp_data->nd_local_cache[out_port].link_hw_laddr[i]; + + if(ARPICMP_DEBUG) { + for (j = 0; j < 6; j++) + printf("%d %d", x->addr_bytes[j], + p_arp_data->nd_local_cache[out_port].link_hw_laddr[i].addr_bytes[j]); + } return x; } return x; } -struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip) +struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip) { int i, limit; uint32_t tmp; @@ -2642,7 +2448,7 @@ void lib_arp_init(struct pipeline_params *params, int i; uint32_t size; - struct pipeline_cgnapt *p; + struct arp_data *p; RTE_LOG(INFO, LIBARP, "ARP initialization ...\n"); @@ -2799,7 +2605,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg) rte_rwlock_write_lock(&ret_arp_data->queue_lock); if (ret_arp_data->status == PROBE || ret_arp_data->status == INCOMPLETE) { - if (ret_arp_data->retry_count == 3) { + if (ret_arp_data->retry_count == ARP_RETRY_COUNT) { remove_arp_entry(ret_arp_data, arg); } else { ret_arp_data->retry_count++; @@ -2815,7 +2621,7 @@ void arp_timer_callback(struct rte_timer *timer, void *arg) } if (ifm_chk_port_ipv4_enabled - (ret_arp_data->port)) { + (ret_arp_data->port) != IFM_FAILURE) { request_arp(ret_arp_data->port, ret_arp_data->ip); } else { @@ -2912,7 +2718,7 @@ void nd_timer_callback(struct rte_timer *timer, void *arg) rte_rwlock_write_lock(&ret_nd_data->queue_lock); if (ret_nd_data->status == PROBE || ret_nd_data->status == INCOMPLETE) { - if (ret_nd_data->retry_count == 3) { + if (ret_nd_data->retry_count == ARP_RETRY_COUNT) { remove_nd_entry_ipv6(ret_nd_data, arg); } else { ret_nd_data->retry_count++; diff --git a/common/VIL/l2l3_stack/lib_arp.h b/common/VIL/l2l3_stack/lib_arp.h index 9cb0205f..c635c94c 100644 --- a/common/VIL/l2l3_stack/lib_arp.h +++ b/common/VIL/l2l3_stack/lib_arp.h @@ -32,20 +32,9 @@ #define NUM_DESC (get_arp_buf()) #define ARP_BUF_DEFAULT 30000 #define PROBE_TIME 50 +#define ARP_RETRY_COUNT 100 #undef L3_STACK_SUPPORT -/** -* A structure for Route table entries of IPv4 -*/ - -struct lib_arp_route_table_entry { - uint32_t ip; /**< Ipv4 address*/ - uint32_t mask; /**< mask */ - uint32_t port; /**< Physical port */ - uint32_t nh; /**< next hop */ - uint32_t nh_mask; -}; - #define MAX_LOCAL_MAC_ADDRESS 32 #define MAX_PORTS 32 struct arp_cache { @@ -60,28 +49,35 @@ struct nd_cache { uint32_t num_nhip; }; -/** -* A structure for Route table entires of IPv6 -* -*/ -struct lib_nd_route_table_entry { - uint8_t ipv6[16]; /**< Ipv6 address */ - uint8_t depth; /**< Depth */ - uint32_t port; /**< Port */ - uint8_t nhipv6[16]; /**< next hop Ipv6 */ -}; - uint8_t arp_cache_dest_mac_present(uint32_t out_port); uint8_t nd_cache_dest_mac_present(uint32_t out_port); -extern struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY]; -extern struct lib_arp_route_table_entry lib_arp_route_table[MAX_ARP_RT_ENTRY]; -extern struct ether_addr *get_local_link_hw_addr(uint8_t out_port, uint32_t nhip); +extern struct ether_addr *get_local_cache_hw_addr(uint8_t out_port, uint32_t nhip); extern struct ether_addr *get_nd_local_link_hw_addr(uint8_t out_port, uint8_t nhip[]); extern struct arp_cache arp_local_cache[MAX_PORTS]; extern void prefetch(void); extern void update_nhip_access(uint8_t); uint32_t get_arp_buf(void); uint32_t get_nd_buf(void); +extern int my_inet_pton_ipv6(int af, const char *src, void *dst); +extern struct rte_hash *arp_hash_handle; +extern struct rte_hash *nd_hash_handle; +extern uint32_t lib_arp_get_mac_req; +extern uint32_t lib_arp_nh_found; +extern uint32_t lib_arp_no_nh_found; +extern uint32_t lib_arp_arp_entry_found; +extern uint32_t lib_arp_no_arp_entry_found; +extern uint32_t lib_arp_populate_called; +extern uint32_t lib_arp_delete_called; +extern uint32_t lib_arp_duplicate_found; +extern uint32_t arp_route_tbl_index; +extern uint32_t lib_nd_get_mac_req; +extern uint32_t lib_nd_nh_found; +extern uint32_t lib_nd_no_nh_found; +extern uint32_t lib_nd_nd_entry_found; +extern uint32_t lib_nd_no_arp_entry_found; +extern uint32_t lib_nd_populate_called; +extern uint32_t lib_nd_delete_called; +extern uint32_t lib_nd_duplicate_found; enum { ARP_FOUND, @@ -228,12 +224,6 @@ struct table_nd_entry_data { } __attribute__ ((packed)); struct arp_data { - struct lib_arp_route_table_entry - lib_arp_route_table[MAX_ARP_RT_ENTRY]; - uint8_t lib_arp_route_ent_cnt; - struct lib_nd_route_table_entry - lib_nd_route_table[MAX_ARP_RT_ENTRY]; - uint8_t lib_nd_route_ent_cnt; struct arp_cache arp_local_cache[MAX_PORTS]; struct nd_cache nd_local_cache[MAX_PORTS]; struct ether_addr link_hw_addr[MAX_LOCAL_MAC_ADDRESS]; @@ -257,7 +247,7 @@ struct arp_data { * 0 if failure, and 1 if success */ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr, - uint32_t *phy_port, struct ether_addr *hw_addr); + uint32_t phy_port, struct ether_addr *hw_addr); /** * To get the destination mac address for IPV6 address @@ -272,10 +262,6 @@ struct arp_entry_data *get_dest_mac_addr_port(const uint32_t ipaddr, * @return * 0 if failure, 1 ifsuccess */ - -struct nd_entry_data *get_dest_mac_address_ipv6_port(uint8_t ipv6addr[], uint32_t *phy_port, - struct ether_addr *hw_addr, - uint8_t nhipv6[]); int arp_queue_unresolved_packet(struct arp_entry_data * arp_data, struct rte_mbuf * m); extern void arp_send_buffered_pkts(struct arp_entry_data *ret_arp_data,struct ether_addr *hw_addr, uint8_t port_id); @@ -524,4 +510,10 @@ uint32_t get_nh(uint32_t, uint32_t *, struct ether_addr *addr); * next hop ipv6 */ void get_nh_ipv6(uint8_t ipv6[], uint32_t *port, uint8_t nhipv6[], struct ether_addr *hw_addr); + +struct arp_entry_data *get_dest_mac_addr_ipv4(const uint32_t nhip, + uint32_t phy_port, struct ether_addr *hw_addr); +struct nd_entry_data *get_dest_mac_addr_ipv6(uint8_t nhipv6[], + uint32_t phy_port, struct ether_addr *hw_addr); + #endif diff --git a/common/VIL/l2l3_stack/tsx.h b/common/VIL/l2l3_stack/tsx.h index 8b748165..01bde702 100644 --- a/common/VIL/l2l3_stack/tsx.h +++ b/common/VIL/l2l3_stack/tsx.h @@ -16,8 +16,14 @@ #ifndef _TSX_H_ #define _RSX_H_ #include <rte_atomic.h> + +#ifndef TRUE #define TRUE 1 +#endif + +#ifndef FALSE #define FALSE 0 +#endif volatile int mutex_val; diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c index 6b42ad77..607d13d1 100644 --- a/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c +++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp.c @@ -70,6 +70,14 @@ struct cmd_arp_add_result { }; +uint16_t str2flowtype(char *string); +int parse_flexbytes(const char *q_arg, uint8_t *flexbytes, + uint16_t max_num); +enum rte_eth_input_set_field str2inset(char *string); +int app_pipeline_arpicmp_entry_dbg(struct app_params *app, + uint32_t pipeline_id, uint8_t *msg); + + static void cmd_arp_add_parsed(void *parsed_result, __rte_unused struct cmdline *cl, __rte_unused void *data) @@ -952,8 +960,7 @@ cmdline_parse_inst_t cmd_set_fwd_mode = { #if 1 -static uint16_t -str2flowtype(char *string) +uint16_t str2flowtype(char *string) { uint8_t i = 0; static const struct { @@ -983,7 +990,7 @@ str2flowtype(char *string) return RTE_ETH_FLOW_UNKNOWN; } -static inline int +int parse_flexbytes(const char *q_arg, uint8_t *flexbytes, uint16_t max_num) { char s[256]; @@ -1442,7 +1449,7 @@ struct cmd_set_hash_input_set_result { cmdline_fixed_string_t select; }; -static enum rte_eth_input_set_field +enum rte_eth_input_set_field str2inset(char *string) { uint16_t i; @@ -1966,7 +1973,7 @@ cmdline_parse_inst_t cmd_set_sym_hash_ena_per_port = { }; #endif -static int +int app_pipeline_arpicmp_entry_dbg(struct app_params *app, uint32_t pipeline_id, uint8_t *msg) { diff --git a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c index 1dbf34a3..481f8521 100644 --- a/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c +++ b/common/VIL/pipeline_arpicmp/pipeline_arpicmp_be.c @@ -50,6 +50,7 @@ #include "lib_arp.h" #include "lib_icmpv6.h" #include "interface.h" +#include "gateway.h" /* Shared among all VNFs including LB */ struct app_params *myApp; @@ -811,7 +812,7 @@ static void *pipeline_arpicmp_init(struct pipeline_params *params, p_arp->receivedPktCount = 0; p_arp->droppedPktCount = 0; - + gw_init(rte_eth_dev_count()); lib_arp_init(params, app); /* Pipeline */ diff --git a/common/VIL/pipeline_common/pipeline_common_fe.c b/common/VIL/pipeline_common/pipeline_common_fe.c index 5d6976b5..6fc6109c 100644 --- a/common/VIL/pipeline_common/pipeline_common_fe.c +++ b/common/VIL/pipeline_common/pipeline_common_fe.c @@ -33,6 +33,9 @@ #include "pipeline_common_fe.h" #include "interface.h" #include "lib_arp.h" +#include "gateway.h" + +void app_run_file(cmdline_parse_ctx_t *ctx, const char *file_name); int app_pipeline_ping(struct app_params *app, @@ -541,12 +544,12 @@ app_link_down(struct app_params *app, */ struct cmd_routeadd_config_result { cmdline_fixed_string_t routeadd_string; + cmdline_fixed_string_t type_string; uint32_t port_id; cmdline_ipaddr_t ip; cmdline_fixed_string_t depth; }; -extern struct lib_nd_route_table_entry lib_nd_route_table[MAX_ND_RT_ENTRY]; extern struct arp_data *p_arp_data; extern uint32_t nd_route_tbl_index; @@ -556,25 +559,48 @@ extern uint32_t nd_route_tbl_index; int app_routeadd_config_ipv4(__attribute__((unused)) struct app_params *app, uint32_t port_id, uint32_t ip, uint32_t mask) { - if (port_id > MAX_PORTS) { - printf("Max ports allowed is %d\n", MAX_PORTS); + uint32_t i = 0; + if (port_id >= gw_get_num_ports()) { + printf("Max ports allowed is %d\n", gw_get_num_ports()); return 1; } - printf("port id:%d ip: %x mask:%x", port_id, ip, mask); + printf("port id:%d ip: %x mask:%x\n", port_id, ip, mask); + + struct route_table_entry *lentry = NULL; + + /* Check for matching entry */ + for(i = 0 ; i< p_route_data[port_id]->route_ent_cnt; i++) { + + lentry = &p_route_data[port_id]->route_table[i]; + + /* Entry already exists? */ + if(mask == 0) { + if(lentry->nh == ip) + return 1; + } else { + if( lentry->nh_mask == (ip & mask)) + return 1; + } + } + if(i < MAX_ROUTE_ENTRY_SIZE) { + + lentry = &p_route_data[port_id]->route_table[i]; - struct lib_arp_route_table_entry *lentry = - &p_arp_data->lib_arp_route_table - [port_id]; - if (!lentry->ip) - p_arp_data->lib_arp_route_ent_cnt++; - lentry->ip = ip; + p_route_data[port_id]->route_ent_cnt++; lentry->mask = mask; lentry->port = port_id; lentry->nh = ip; - lentry->nh_mask = ip & mask; + lentry->nh_mask = (ip & mask); + /* Set the VNF Gateway flag */ + vnf_gateway = 1; + return 0; + } else { + + printf("Error: Number of entries more than supported\n"); + return 1; + } - return 0; } /* @@ -585,8 +611,8 @@ int app_routeadd_config_ipv6(__attribute__((unused)) struct app_params *app, { int i; - if (port_id > MAX_ND_RT_ENTRY) { - printf("Max ports allowed is %d\n", MAX_ND_RT_ENTRY); + if (port_id >= gw_get_num_ports()) { + printf("Max ports allowed is %d\n", gw_get_num_ports()); return 1; } @@ -594,25 +620,72 @@ int app_routeadd_config_ipv6(__attribute__((unused)) struct app_params *app, nd_route_tbl_index++; printf("port id:%d depth:%d\n", port_id, depth); - printf("ipv6 address "); - for (i = 0; i < 16; i++) { - lib_nd_route_table[port_id].ipv6[i] = ipv6[i]; - lib_nd_route_table[port_id].nhipv6[i] = ipv6[i]; - printf("%x ", ipv6[i]); - } + printf("ipv6 address: "); + for(i = 0; i < IPV6_ADD_SIZE; i++) + printf("%02x ", ipv6[i]); printf("\n"); + struct nd_route_table_entry *lentry = NULL; + int k; + uint8_t netmask_ipv6[16], netip_nd[16], netip_in[16]; + uint8_t depthflags = 0, depthflags1 = 0; - lib_nd_route_table[port_id].depth = depth; - lib_nd_route_table[port_id].port = port_id; + i = 0; - printf("num ports :%d\n", nd_route_tbl_index); + /* Check for matching entry */ + for(i = 0 ; i< p_nd_route_data[port_id]->nd_route_ent_cnt; i++) { - return 0; + lentry = &p_nd_route_data[port_id]->nd_route_table[i]; + + memset(netmask_ipv6, 0, sizeof(netmask_ipv6)); + memset(netip_nd, 0, sizeof(netip_nd)); + memset(netip_in, 0, sizeof(netip_in)); + + /* Create netmask from depth */ + convert_prefixlen_to_netmask_ipv6(lentry->depth, netmask_ipv6); + + for (k = 0; k < 16; k++) { + if (lentry->nhipv6[k] & netmask_ipv6[k]) { + depthflags++; + netip_nd[k] = lentry->nhipv6[k]; + } + + if (ipv6[k] & netmask_ipv6[k]) { + depthflags1++; + netip_in[k] = ipv6[k]; + } + } + + if ((depthflags == depthflags1) + && (memcmp(netip_nd, netip_in, sizeof(netip_nd)) == 0)) { + /* Route already exists */ + printf("Route already exists \n"); + return 1; + } + } + + if(i < MAX_ND_ROUTE_ENTRY_SIZE) { + + lentry = &p_nd_route_data[port_id]->nd_route_table[i]; + + rte_mov16(lentry->nhipv6, ipv6); + + lentry->depth = depth; + lentry->port = port_id; + p_nd_route_data[port_id]->nd_route_ent_cnt++; + /* Set the VNF Gateway flag */ + vnf_gateway = 1; + + return 0; + } else { + + printf("Error: Number of entries more than supported\n"); + return 1; + } } /* - * cmd handler for handling route add entry at runtime. + * cmd handler for handling route abj entry at runtime. * the same handle takes care of both ipv4 & ipv6 */ static void @@ -629,15 +702,30 @@ cmd_routeadd_parsed( uint32_t i, ip = 0, depth = 0, mask = 0; uint8_t ipv6[16]; + printf("Adding route for %s \n", params->type_string); + if (params->ip.family == AF_INET) { ip = rte_bswap32((uint32_t) params->ip.addr.ipv4.s_addr); - mask = strtoul(params->depth, NULL, 16); - printf("ip:%x mask:%x port_id:%d\n", ip, mask, port_id); + + if(strcmp(params->type_string, "net") == 0) + { + mask = strtoul(params->depth, NULL, 16); + } else { + mask = 0xffffffff; + } + + printf("nhip:0x%08x mask:%x port_id:%d\n", ip, mask, port_id); } else { memcpy(ipv6, params->ip.addr.ipv6.s6_addr, 16); - depth = atoi(params->depth); - for (i=0;i<16;i++) - printf("%d ", ipv6[i]); + if(strcmp(params->type_string, "net") == 0) + { + depth = atoi(params->depth); + } else { + depth = 64; + } + + for (i=0; i < 16; i++) + printf("%02x ", ipv6[i]); printf("\n port_id:%d depth:%d \n", port_id, depth); } @@ -657,6 +745,14 @@ cmdline_parse_token_string_t cmd_routeadd_config_string = TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, routeadd_string, "routeadd"); +cmdline_parse_token_string_t cmd_routeadd_net_string = + TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, type_string, + "net"); + +cmdline_parse_token_string_t cmd_routeadd_host_string = + TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, type_string, + "host"); + cmdline_parse_token_num_t cmd_routeadd_config_port_id = TOKEN_NUM_INITIALIZER(struct cmd_routeadd_config_result, port_id, UINT32); @@ -666,15 +762,29 @@ cmdline_parse_token_ipaddr_t cmd_routeadd_config_ip = cmdline_parse_token_string_t cmd_routeadd_config_depth_string = TOKEN_STRING_INITIALIZER(struct cmd_routeadd_config_result, depth, NULL); -cmdline_parse_inst_t cmd_routeadd = { +cmdline_parse_inst_t cmd_routeadd_net = { .f = cmd_routeadd_parsed, .data = NULL, - .help_str = "Add Route entry", + .help_str = "Add Route entry for gateway", .tokens = { (void *) &cmd_routeadd_config_string, + (void *) &cmd_routeadd_net_string, (void *) &cmd_routeadd_config_port_id, - (void *) &cmd_routeadd_config_ip, - (void *) &cmd_routeadd_config_depth_string, + (void *) &cmd_routeadd_config_ip, + (void *) &cmd_routeadd_config_depth_string, + NULL, + }, +}; + +cmdline_parse_inst_t cmd_routeadd_host = { + .f = cmd_routeadd_parsed, + .data = NULL, + .help_str = "Add Route entry for host", + .tokens = { + (void *) &cmd_routeadd_config_string, + (void *) &cmd_routeadd_host_string, + (void *) &cmd_routeadd_config_port_id, + (void *) &cmd_routeadd_config_ip, NULL, }, }; @@ -1469,7 +1579,7 @@ static cmdline_parse_inst_t cmd_quit = { * run */ -static void +void app_run_file( cmdline_parse_ctx_t *ctx, const char *file_name) @@ -1525,7 +1635,8 @@ cmdline_parse_inst_t cmd_run = { static cmdline_parse_ctx_t pipeline_common_cmds[] = { (cmdline_parse_inst_t *) &cmd_quit, (cmdline_parse_inst_t *) &cmd_run, - (cmdline_parse_inst_t *) &cmd_routeadd, + (cmdline_parse_inst_t *) &cmd_routeadd_net, + (cmdline_parse_inst_t *) &cmd_routeadd_host, (cmdline_parse_inst_t *) &cmd_link_config, (cmdline_parse_inst_t *) &cmd_link_up, diff --git a/common/VIL/pipeline_master/pipeline_master_be.c b/common/VIL/pipeline_master/pipeline_master_be.c index 425e2334..cc50497e 100644 --- a/common/VIL/pipeline_master/pipeline_master_be.c +++ b/common/VIL/pipeline_master/pipeline_master_be.c @@ -28,6 +28,8 @@ #include "app.h" #include "pipeline_master_be.h" +struct cmdline *pipe_cl; + struct pipeline_master { struct app_params *app; struct cmdline *cl; @@ -59,6 +61,7 @@ pipeline_init(__rte_unused struct pipeline_params *params, void *arg) rte_free(p); return NULL; } + pipe_cl = p->cl; p->script_file_done = 0; if (app->script_file == NULL) @@ -85,6 +88,7 @@ static int pipeline_run(void *pipeline) { struct pipeline_master *p = (struct pipeline_master *) pipeline; + int status; if (p->script_file_done == 0) { diff --git a/common/vnf_common/app.h b/common/vnf_common/app.h index 51c40c97..752780d9 100644 --- a/common/vnf_common/app.h +++ b/common/vnf_common/app.h @@ -566,6 +566,17 @@ do { \ fprintf(stdout, "[APP] " fmt "\n", ## __VA_ARGS__); \ } while (0) +#ifdef REST_API_SUPPORT +static inline int rest_api_supported(void) +{ + return 1; +} +#else +static inline int rest_api_supported(void) +{ + return 0; +} +#endif static inline uint32_t app_link_get_n_rxq(struct app_params *app, struct app_link_params *link) { @@ -955,6 +966,11 @@ int app_config_check(struct app_params *app); int app_init(struct app_params *app); +struct mg_context *rest_api_init(struct app_params *app); +void set_vnf_type(const char *type); +uint32_t is_rest_support(void); +extern uint32_t rest_support; + int app_thread(void *arg); int app_pipeline_type_register(struct app_params *app, diff --git a/common/vnf_common/config_parse.c b/common/vnf_common/config_parse.c index 5f7ec8a6..eeb547e6 100644 --- a/common/vnf_common/config_parse.c +++ b/common/vnf_common/config_parse.c @@ -35,6 +35,7 @@ /** * Default config values **/ +uint32_t rest_support = 1; static struct app_params app_params_default = { .config_file = "./config/ip_pipeline.cfg", @@ -239,6 +240,11 @@ do { \ "Parse error in section \"%s\"", section_name); \ } while (0) +uint32_t is_rest_support(void) +{ + return rest_support; +} + int parser_read_arg_bool(const char *p) { @@ -3264,6 +3270,9 @@ app_config_args(struct app_params *app, int argc, char **argv) "more than once\n"); f_present = 1; + /* REST API not needed as user has supplied the config file */ + rest_support = 0; + if (!strlen(optarg)) rte_panic("Error: Config file name is null\n"); @@ -3271,6 +3280,7 @@ app_config_args(struct app_params *app, int argc, char **argv) if (app->config_file == NULL) rte_panic("Error: Memory allocation failure\n"); + break; case 's': diff --git a/common/vnf_common/rest_api.c b/common/vnf_common/rest_api.c new file mode 100644 index 00000000..62e9646a --- /dev/null +++ b/common/vnf_common/rest_api.c @@ -0,0 +1,2448 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/queue.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> + +#include <rte_common.h> +#include <rte_memory.h> +#include <rte_memzone.h> +#include <rte_launch.h> +#include <rte_eal.h> +#include <rte_per_lcore.h> +#include <rte_lcore.h> +#include <rte_hash.h> +#include <rte_ethdev.h> +#include <rte_cycles.h> +#include <rte_timer.h> +#include <rte_debug.h> +#include <rte_cfgfile.h> +#include <fcntl.h> +#include <unistd.h> +#include <cmdline_rdline.h> +#include <cmdline_parse.h> +#include <cmdline_parse_num.h> +#include <cmdline_parse_string.h> +#include <cmdline_parse_ipaddr.h> +#include <cmdline_parse_etheraddr.h> +#include <cmdline_socket.h> +#include <cmdline.h> + +#include "pipeline_common_fe.h" +#include "pipeline_arpicmp.h" + +#include <civetweb.h> +#include <json/json.h> +#include "app.h" +#include "lib_arp.h" +#include "interface.h" +#include "tsx.h" +#include "gateway.h" + +#define MAX_PIPELINES 30 +#define MAX_VNFS 3 +#define CFG_NAME_LEN 64 +#define MAX_CORES 64 +#define MAX_SOCKET 2 +#define MAX_BUF_SIZE 2048 +#define MAX_SIZE 24 +#define MAX_LINKS 64 +#define MAX_LB 20 +#define msleep(x) rte_delay_us(x * 1000) + +const char *pipelines[9] = {"MASTER", "ARPICMP", "TIMER", "TXRX-BEGIN", + "TXRX-END", "LOADB", "VACL", "VCGNAPT", "VFW"}; +const char *VNFS[] = {"VACL", "VCGNAPT", "VFW"}; +struct mg_context *ctx; +struct pub_ip_range { + char value[MAX_BUF_SIZE]; +}; + +struct stat_cfg { + uint8_t num_workers; + uint8_t num_lb; + uint8_t num_ports; + uint8_t hyper_thread; + uint8_t sock_in; + uint8_t sw_lb; + char vnf_type[MAX_SIZE]; + char pkt_type[MAX_SIZE]; + char pci_white_list[MAX_BUF_SIZE]; + struct pub_ip_range ip_range[MAX_LB]; +}; + +struct arp_params { + uint8_t family; + uint8_t action; + union { + uint32_t ip; + uint8_t ipv6[16]; + }; + uint32_t portid; + struct ether_addr mac_addr; +}; + +struct link_params { + uint32_t id; + uint32_t state; + union { + uint32_t ip; + uint8_t ipv6[16]; + }; + uint32_t depth; + uint32_t family; +}; + +struct route_params { + uint32_t enable; + union { + uint32_t ip; + uint8_t ipv6[16]; + }; + uint32_t depth; + uint32_t family; + char type[255]; +}; + +struct dbg_mode { + uint32_t cmd; + uint32_t d1; + uint32_t pipe_num; +}; + +struct dbg_mode current_dbg; +struct link_params current_link_parms[MAX_LINKS]; +struct stat_cfg current_cfg; +struct arp_params current_arp_parms; +struct route_params current_route_parms[MAX_LINKS]; + +static int static_cfg_set = 0; +uint8_t pipe_arr[MAX_PIPELINES]; +uint8_t num_pipelines; +uint8_t num_workers, pub_ip = 0, ip_range = 0, num_lb = 1, num_ports; +uint8_t num_entries, start_lb, end_lb, start_lbout; +uint8_t swq_index = 0, workers = 0; +uint8_t txq_index = 0, sw_lb = 1; +uint8_t rxq_index = 0; +uint8_t arp_index = 0, tx_start_port = 0, rx_start_port = 0; +uint8_t pipenum = 0, hyper_thread = 0; +char traffic_type[4] = "4"; +struct rte_cfgfile_entry entries[30]; +int n_entries1 = 0; +char loadb_in[256]; +char vnf_type[256]; +uint8_t sock_cpus[MAX_SOCKET][MAX_CORES]; +uint8_t sock_in = 0, sock0 = 0, sock1 = 0, sock_index = 0; +int hyper = 0; +uint32_t flow_dir_cfg = 0; +struct app_params *rapp; + +extern uint32_t nd_route_tbl_index; +extern struct arp_data *p_arp_data; +extern int USE_RTM_LOCKS; +extern rte_rwlock_t rwlock; +extern interface_main_t ifm; +extern struct cmdline *pipe_cl; +extern uint16_t str2flowtype(char *string); +extern void app_run_file(cmdline_parse_ctx_t *ctx, const char *file_name); +extern int parse_flexbytes(const char *q_arg, uint8_t *flexbytes, + uint16_t max_num); +extern int app_pipeline_arpicmp_entry_dbg(struct app_params *app, + uint32_t pipeline_id, uint8_t *msg); +extern unsigned eal_cpu_socket_id(unsigned cpu_id); +extern int app_routeadd_config_ipv4(__attribute__((unused)) + struct app_params *app, + uint32_t port_id, uint32_t ip, + uint32_t mask); +extern int app_routeadd_config_ipv6(__attribute__((unused)) + struct app_params *app, + uint32_t port_id, uint8_t ipv6[], + uint32_t depth); + +enum rte_eth_input_set_field str2inset(char *string); + +enum { + MASTER = 0, + ARPICMP, + TIMER, + TXRX_BEGIN, + TXRX_END, + LOADB, + VNF_VACL, + VNF_VCGNAPT, + VNF_VFW, + PIPE_MAX +}; + +struct json_data { + char key[256]; + char value[256]; +}; + +struct json_data static_cfg[40]; +uint32_t post_not_received = 1; + +int flow_director_handler(struct mg_connection *conn, + __rte_unused void *cbdata); +int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata); +void init_stat_cfg(void); +void bind_the_ports(struct mg_connection *conn, char *pci_white_list); +int route_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int dbg_pipelines_handler(struct mg_connection *conn, + __rte_unused void *cbdata); +int dbg_pipelines_id_handler(struct mg_connection *conn, + __rte_unused void *cbdata); +int get_pipelines_tokens(char *buf); +void get_swq_offset(uint8_t start, uint8_t num, char *buf); +void get_swq(uint8_t num, char *buf); +void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf); +void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf); +void fix_pipelines_data_types(FILE *f, const char *sect_name, + struct rte_cfgfile *tcfg); +void print_to_file(FILE *f, struct rte_cfgfile *tcfg); +int get_vnf_index(void); +void build_pipeline(void); +void get_pktq_in_prv(char *buf); +void get_prv_to_pub_map(char *buf); +void get_prv_que_handler(char *buf); +int static_cfg_handler(struct mg_connection *conn, void *cbdata); +int link_handler(struct mg_connection *conn, void *cbdata); +int linkid_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int arp_handler(struct mg_connection *conn, void *cbdata); +int arpls_handler(struct mg_connection *conn, void *cbdata); +int nd_handler(struct mg_connection *conn, void *cbdata); +int linkls_handler(struct mg_connection *conn, void *cbdata); +int set_hash_input_set_2(struct mg_connection *conn, uint32_t port_id, + const char *flow_type, const char *inset_field0, + const char *inset_field1, const char *select); +int set_hash_input_set_4(struct mg_connection *conn, uint32_t port_id, + char *flow_type, char *inset_field0, char *inset_field1, + char *inset_field2, char *inset_field3, const char *select); +int set_hash_global_config(struct mg_connection *conn, uint32_t port_id, + char *flow_type, const char *hash_func, const char *enable); +int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id); +int cmd_quit_handler(struct mg_connection *conn, void *cbdata); +int dbg_run_handler(struct mg_connection *conn, void *cbdata); +int dbg_handler(struct mg_connection *conn, __rte_unused void *cbdata); +int dbg_cmd_handler(struct mg_connection *conn, void *cbdata); +int run_field_found(const char *key, const char *filename, char *path, + size_t pathlen, void *user_data); +int run_field_get(const char *key, const char *value, size_t valuelen, + void *user_data); +int run_field_stored(const char *path, long long file_size, void *user_data); +void print_interface_details_rest(struct mg_connection *conn, uint32_t link); +void print_link_info(struct app_link_params *p, struct mg_connection *conn); +int get_link_tokens(char *buf); +void get_mac(struct ether_addr *mac_addr, char *buf); + +int run_field_found(const char *key, const char *filename, char *path, + size_t pathlen, void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, "\r\n\r\n%s:\r\n", key); + + if (filename && *filename) { + snprintf(path, pathlen, "%s", filename); + int fd; + + /* Make sure file exists before clearing rules and actions */ + fd = open(filename, O_RDONLY); + if (fd < 0) { + mg_printf(conn, "Cannot open file \"%s\"\n", filename); + return FORM_FIELD_STORAGE_GET; + } + + close(fd); + mg_printf(conn, "file to be loaded is %s\n", filename); + app_run_file(pipe_cl->ctx, filename); + + return FORM_FIELD_STORAGE_STORE; + } + + return FORM_FIELD_STORAGE_GET; +} + +int run_field_get(const char *key, const char *value, size_t valuelen, + void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + if (key[0]) { + mg_printf(conn, "%s = ", key); + } + mg_write(conn, value, valuelen); + + return 0; +} + +int run_field_stored(const char *path, long long file_size, void *user_data) +{ + struct mg_connection *conn = (struct mg_connection *)user_data; + + mg_printf(conn, + "stored as %s (%lu bytes)\r\n\r\n", + path, + (unsigned long)file_size); + + return 0; +} + +int dbg_run_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + struct mg_form_data_handler fdh = {run_field_found, run_field_get, + run_field_stored, NULL}; + + if (strcmp(req_info->request_method, "POST")) { + + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection:"); + mg_printf(conn," close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + + /* It would be possible to check the request info here before calling + * mg_handle_form_request. */ + (void)req_info; + + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: "); + mg_printf(conn, "text/plain\r\nConnection: close\r\n\r\n"); + if (strcmp(req_info->request_method, "PUT")) { + mg_printf(conn, "Only PUT method allowed"); + return 1; + } + + fdh.user_data = (void *)conn; + + /* Call the form handler */ + mg_handle_form_request(conn, &fdh); + mg_printf(conn, "\r\n script file handled"); + + return 1; +} + +int cmd_quit_handler(__rte_unused struct mg_connection *conn, + __rte_unused void *cbdata) +{ + cmdline_quit(pipe_cl); + return 0; +} + +int dbg_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + + const struct mg_request_info *ri = mg_get_request_info(conn); + + if (!strcmp(ri->request_method, "GET")) { + mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n"); + mg_printf(conn, "Connection: close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are the methods supported</h2>"); + mg_printf(conn, "<h3> /pipelines\n</h3>"); + mg_printf(conn, "<h3> /cmd \n</h3>"); + mg_printf(conn, "<h3> /run\n</h3>"); + mg_printf(conn, "</body></html>"); + } + + return 1; + +} + +int get_pipelines_tokens(char *buf) +{ + char *token; + uint32_t id; + + token = strtok(buf, "/ "); + if (strcmp(token, "pipelines")) { + return -1; + } + + token = strtok(NULL, "/ "); + id = atoi(token); + if (id > rapp->n_pipelines) { + return -1; + } + + return id; +} + + +int dbg_pipelines_id_handler(struct mg_connection *conn, + __rte_unused void *cbdata) +{ + struct app_eal_params *p = &rapp->eal_params; + const struct mg_request_info *ri = mg_get_request_info(conn); + //uint32_t id = (uint32_t *)cbdata; + + mg_printf(conn, "Inside dbg_pipelines_id_handler\n"); + + if (!strcmp(ri->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + if (p->log_level_present) { + mg_printf(conn, "<h2> The pipeline log level is %d</h2>", + p->log_level); + } else { + mg_printf(conn, "<h2> No log level found in the\ + pipeline</h2>"); + } + mg_printf(conn, "</body></html>"); + } + + return 1; + +} + + +int dbg_pipelines_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + + uint32_t i; + const struct mg_request_info *ri = mg_get_request_info(conn); + + if (!strcmp(ri->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are pipelines available</h2>"); + for (i = 0; i < rapp->n_pipelines; i++) { + mg_printf(conn, "<h3> pipeline %d: %s\n</h3>",i, + rapp->pipeline_params[i].type); + } + mg_printf(conn, "</body></html>"); + } + + return 1; + +} + +int dbg_cmd_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + struct app_params *app = rapp; + uint8_t msg[2]; + int status; + const struct mg_request_info *req_info = mg_get_request_info(conn); + char buf[MAX_BUF_SIZE]; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> The last command executed </h2>"); + mg_printf(conn, "<h3> cmd: %d\n </h3>", current_dbg.cmd); + mg_printf(conn, "<h3> d1 : %d\n </h3>", current_dbg.d1); + mg_printf(conn, "<h3> pipeline : %d\n </h3>", + current_dbg.pipe_num); + mg_printf(conn, "</body></html>\n"); + + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection:"); + mg_printf(conn, " close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "</body></html>\n"); + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "cmd")) { + current_dbg.cmd = atoi(json_object_get_string(val)); + } else if (!strcmp(key, "d1")) { + current_dbg.d1 = atoi(json_object_get_string(val)); + } else if (!strcmp(key, "pipeline")) { + current_dbg.pipe_num = atoi(json_object_get_string(val)); + } + } + + + msg[0] = current_dbg.cmd; + msg[1] = current_dbg.d1; + status = app_pipeline_arpicmp_entry_dbg(app, current_dbg.pipe_num, msg); + + if (status != 0) { + mg_printf(conn, "Dbg Command failed\n"); + return 1; + } + + return 1; +} + +int set_sym_hash_per_port(struct mg_connection *conn, uint32_t port_id) +{ + int ret; + struct rte_eth_hash_filter_info info; + + if (rte_eth_dev_filter_supported(port_id, + RTE_ETH_FILTER_HASH) < 0) { + mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port: %d\n", + port_id); + return 1; + } + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_SYM_HASH_ENA_PER_PORT; + + ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); + if (ret < 0) { + mg_printf(conn, "Cannot set symmetric hash enable per port on " + "port %u\n", port_id); + return 1; + } + + return 1; +} + +int set_hash_input_set_4(struct mg_connection *conn, uint32_t port_id, + char *flow_type, char *inset_field0, char *inset_field1, + char *inset_field2, char *inset_field3, const char *select) +{ + struct rte_eth_hash_filter_info info; + + if (enable_flow_dir) { + mg_printf(conn, "FDIR Filter is Defined!\n"); + mg_printf(conn, "Please undefine FDIR_FILTER flag and define " + "HWLD flag\n"); + return 1; + } + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(flow_type); + + info.info.input_set_conf.field[0] = str2inset(inset_field0); + info.info.input_set_conf.field[1] = str2inset(inset_field1); + info.info.input_set_conf.field[2] = str2inset(inset_field2); + info.info.input_set_conf.field[3] = str2inset(inset_field3); + + info.info.input_set_conf.inset_size = 4; + if (!strcmp(select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + + rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); + + mg_printf(conn, "Command Passed!\n"); + return 1; +} + +int set_hash_input_set_2(struct mg_connection *conn, uint32_t port_id, + const char *flow_type, const char *inset_field0, + const char *inset_field1, const char *select) +{ + struct rte_eth_hash_filter_info info; + const struct mg_request_info *req_info = mg_get_request_info(conn); + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "</body></html>\n"); + + if (enable_flow_dir) { + mg_printf(conn, "FDIR Filter is Defined!\n"); + mg_printf(conn, "Please undefine FDIR_FILTER flag and define " + "HWLD flag\n"); + return 1; + } + + if (enable_flow_dir) { + mg_printf(conn, "FDIR Filter is Defined!\n"); + mg_printf(conn, "Please undefine FDIR_FILTER flag and define " + "HWLD flag\n"); + return 1; + } + + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_INPUT_SET_SELECT; + info.info.input_set_conf.flow_type = str2flowtype(strdup(flow_type)); + + info.info.input_set_conf.field[0] = str2inset(strdup(inset_field0)); + info.info.input_set_conf.field[1] = str2inset(strdup(inset_field1)); + + info.info.input_set_conf.inset_size = 2; + + if (!strcmp(select, "select")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_SELECT; + else if (!strcmp(select, "add")) + info.info.input_set_conf.op = RTE_ETH_INPUT_SET_ADD; + + rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); + + mg_printf(conn, "Command Passed!\n"); + return 1; +} + +void print_interface_details_rest(struct mg_connection *conn, uint32_t link) +{ + l2_phy_interface_t *port; + int i = 0; + struct sockaddr_in ip; + mg_printf(conn, "\n\r"); + + if (USE_RTM_LOCKS) + rtm_lock(); + else + rte_rwlock_read_lock(&rwlock); + + i = link; + port = ifm.port_list[i]; + mg_printf(conn, "%u", port->pmdid); + if (port->ifname && strlen(port->ifname)) { + mg_printf(conn, " (%s)\t", port->ifname); + } else + mg_printf(conn, "\t\t"); + mg_printf(conn, "MAC:%02x:%02x:%02x:%02x:%02x:%02x Adminstate:%s" + " Operstate:%s \n\r<br/>", + port->macaddr[0], port->macaddr[1], + port->macaddr[2], port->macaddr[3], + port->macaddr[4], port->macaddr[5], + port->admin_status ? "UP" : "DOWN", + port->link_status ? "UP" : "DOWN"); + mg_printf(conn, "\t\t"); + mg_printf(conn, "Speed: %u, %s-duplex\n\r<br/>", port->link_speed, + port->link_duplex ? "full" : "half"); + mg_printf(conn, "\t\t"); + + if (port->ipv4_list != NULL) { + ip.sin_addr.s_addr = + (unsigned long)((ipv4list_t *) (port->ipv4_list))-> + ipaddr; + mg_printf(conn, "IP: %s/%d", inet_ntoa(ip.sin_addr), + ((ipv4list_t *) (port->ipv4_list))->addrlen); + } else { + mg_printf(conn, "IP: NA"); + } + + mg_printf(conn, "\r\n<br/>"); + mg_printf(conn, "\t\t"); + if (port->ipv6_list != NULL) { + uint8_t *addr = + ((ipv6list_t *) (port->ipv6_list))->ipaddr; + mg_printf(conn, "IPv6: %02x%02x:%02x%02x:%02x%02x:" + "%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr[0], addr[1], addr[2], addr[3], addr[4], + addr[5], addr[6], addr[7], addr[8], addr[9], + addr[10], addr[11], addr[12], addr[13], addr[14], + addr[15]); + } else { + mg_printf(conn, "IPv6: NA"); + } + + if (port->flags & IFM_SLAVE) { + mg_printf(conn, " IFM_SLAVE "); + mg_printf(conn, " MasterPort: %u", + port->bond_config->bond_portid); + } + if (port->flags & IFM_MASTER) { + mg_printf(conn, " IFM_MASTER "); + mg_printf(conn, " Mode: %u", port->bond_config->mode); + mg_printf(conn, " PrimaryPort: %u", + port->bond_config->primary); + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\t\tSlavePortCount: %u", + port->bond_config->slave_count); + mg_printf(conn, " SlavePorts:"); + int i; + for (i = 0; i < port->bond_config->slave_count; i++) { + mg_printf(conn, " %u ", + port->bond_config->slaves[i]); + } + mg_printf(conn, " ActivePortCount: %u", + port->bond_config->active_slave_count); + mg_printf(conn, " ActivePorts:"); + for (i = 0; i < port->bond_config->active_slave_count; + i++) { + mg_printf(conn, " %u ", + port->bond_config->active_slaves[i]); + } + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\t\t"); + mg_printf(conn, "Link_monitor_freq: %u ms ", + port->bond_config->internal_ms); + mg_printf(conn, " Link_up_prop_delay: %u ms ", + port->bond_config->link_up_delay_ms); + mg_printf(conn, " Link_down_prop_delay: %u ms ", + port->bond_config->link_down_delay_ms); + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\t\t"); + mg_printf(conn, "Xmit_policy: %u", + port->bond_config->xmit_policy); + } + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\t\t"); + mg_printf(conn, "n_rxpkts: %" PRIu64 " ,n_txpkts: %" PRIu64 " ,", + port->n_rxpkts, port->n_txpkts); + struct rte_eth_stats eth_stats; + rte_eth_stats_get(port->pmdid, ð_stats); + mg_printf(conn, "pkts_in: %" PRIu64 " ,", eth_stats.ipackets); + mg_printf(conn, "pkts_out: %" PRIu64 " ", eth_stats.opackets); + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\t\t"); + mg_printf(conn, "in_errs: %" PRIu64 " ,", eth_stats.ierrors); + mg_printf(conn, "in_missed: %" PRIu64 " ,", eth_stats.imissed); + mg_printf(conn, "out_errs: %" PRIu64 " ,", eth_stats.oerrors); + mg_printf(conn, "mbuf_errs: %" PRIu64 " ", eth_stats.rx_nombuf); + mg_printf(conn, "\n\r<br/>"); + mg_printf(conn, "\n\r"); + + if (USE_RTM_LOCKS) + rtm_unlock(); + else + rte_rwlock_read_unlock(&rwlock); +} + +void print_link_info(struct app_link_params *p, struct mg_connection *conn) +{ + struct rte_eth_stats stats; + struct ether_addr *mac_addr; + uint32_t netmask = (~0U) << (32 - p->depth); + uint32_t host = p->ip & netmask; + uint32_t bcast = host | (~netmask); + + memset(&stats, 0, sizeof(stats)); + rte_eth_stats_get(p->pmd_id, &stats); + + mac_addr = (struct ether_addr *) &p->mac_addr; + + if (strlen(p->pci_bdf)) + mg_printf(conn, "%s(%s): flags=%s\r\n<br/>", + p->name, + p->pci_bdf, + (p->state) ? "UP" : "DOWN"); + else + mg_printf(conn, "%s: flags=%s\r\n<br/>", + p->name, + (p->state) ? "UP" : "DOWN"); + if (p->ip) + mg_printf(conn, "\tinet %" PRIu32 ".%" PRIu32 + ".%" PRIu32 ".%" PRIu32 + " netmask %" PRIu32 ".%" PRIu32 + ".%" PRIu32 ".%" PRIu32 " " + "broadcast %" PRIu32 ".%" PRIu32 + ".%" PRIu32 ".%" PRIu32 "\r\n<br/>", + (p->ip >> 24) & 0xFF, + (p->ip >> 16) & 0xFF, + (p->ip >> 8) & 0xFF, + p->ip & 0xFF, + (netmask >> 24) & 0xFF, + (netmask >> 16) & 0xFF, + (netmask >> 8) & 0xFF, + netmask & 0xFF, + (bcast >> 24) & 0xFF, + (bcast >> 16) & 0xFF, + (bcast >> 8) & 0xFF, + bcast & 0xFF); + mg_printf(conn, "\tether %02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 + ":%02" PRIx32 ":%02" PRIx32 ":%02" PRIx32 "\r\n<br/>", + mac_addr->addr_bytes[0], + mac_addr->addr_bytes[1], + mac_addr->addr_bytes[2], + mac_addr->addr_bytes[3], + mac_addr->addr_bytes[4], + mac_addr->addr_bytes[5]); + + mg_printf(conn, "\tRX packets %" PRIu64 + " bytes %" PRIu64 + "\r\n<br/>", + stats.ipackets, + stats.ibytes); + + mg_printf(conn, "\tRX errors %" PRIu64 + " missed %" PRIu64 + " no-mbuf %" PRIu64 + "\r\n<br/>", + stats.ierrors, + stats.imissed, + stats.rx_nombuf); + + mg_printf(conn, "\tTX packets %" PRIu64 + " bytes %" PRIu64 "\r\n<br/>", + stats.opackets, + stats.obytes); + + mg_printf(conn, "\tTX errors %" PRIu64 + "\r\n<br/>", + stats.oerrors); + + mg_printf(conn, "\r\n<br/>"); +} + +int get_link_tokens(char *buf) +{ + char *token; + int linkid; + + token = strtok(buf, "/ "); + if (strcmp(token, "link")) { + return -1; + } + + token = strtok(NULL, "/ "); + linkid = atoi(token); + if (linkid > current_cfg.num_ports) { + return -1; + } + + return linkid; +} + +int linkls_handler(struct mg_connection *conn, void *cbdata) +{ + struct app_params *app = rapp; + + struct app_link_params *p; + + APP_PARAM_FIND_BY_ID(app->link_params, "LINK", *(uint32_t *)cbdata, p); + if (p) { + print_link_info(p, conn); + } + + print_interface_details_rest(conn, *(uint32_t *)cbdata); + return 1; +} + +static const char* arp_status[] = {"INCOMPLETE", "COMPLETE", "PROBE", "STALE"}; + +/* ND IPv6 */ +int nd_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + const void *next_key; + void *next_data; + uint32_t iter = 0; + uint8_t ii = 0; + mg_printf(conn, "----------------------------------------------------"); + mg_printf(conn, "-------------------------------------------------\n<br/>"); + mg_printf(conn, "\tport hw addr status ip addr\n<br/>"); + + mg_printf(conn, "-----------------------------------------------------"); + mg_printf(conn, "-------------------------------------------------\n<br/>"); + while (rte_hash_iterate(nd_hash_handle, &next_key, &next_data, &iter) >= + 0) { + + struct nd_entry_data *tmp_nd_data = + (struct nd_entry_data *)next_data; + struct nd_key_ipv6 tmp_nd_key; + memcpy(&tmp_nd_key, next_key, sizeof(struct nd_key_ipv6)); + mg_printf(conn, "\t%4d %02X:%02X:%02X:%02X:%02X:%02X %10s", + tmp_nd_data->port, + tmp_nd_data->eth_addr.addr_bytes[0], + tmp_nd_data->eth_addr.addr_bytes[1], + tmp_nd_data->eth_addr.addr_bytes[2], + tmp_nd_data->eth_addr.addr_bytes[3], + tmp_nd_data->eth_addr.addr_bytes[4], + tmp_nd_data->eth_addr.addr_bytes[5], + arp_status[tmp_nd_data->status]); + mg_printf(conn, "\t"); + for (ii = 0; ii < ND_IPV6_ADDR_SIZE; ii += 2) { + mg_printf(conn, "%02X%02X ", tmp_nd_data->ipv6[ii], + tmp_nd_data->ipv6[ii + 1]); + } + mg_printf(conn, "\n<br/>"); + } + + mg_printf(conn, "\nND IPV6 Stats: \nTotal Queries %u, ok_NH %u," + " no_NH %u, ok_Entry %u, " + "no_Entry %u, PopulateCall %u, Del %u, Dup %u\n<br/>", + lib_nd_get_mac_req, lib_nd_nh_found, lib_nd_no_nh_found, + lib_nd_nd_entry_found, lib_nd_no_arp_entry_found, + lib_nd_populate_called, lib_nd_delete_called, + lib_nd_duplicate_found); + mg_printf(conn, "ND table key len is %lu\n\n<br/>", sizeof(struct nd_key_ipv6)); + return 0; +} + +int arpls_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + const void *next_key; + void *next_data; + uint32_t iter = 0, len = 0; + char buf[1024]; + + len += sprintf + (buf + len, "---------------------- ARP CACHE ---------------------\n<br/>"); + len += sprintf + (buf + len, "------------------------------------------------------\n<br/>"); + len += sprintf(buf + len, "\tport hw addr status ip addr\n<br/>"); + len += sprintf + (buf + len, "------------------------------------------------------\n<br/>"); + + while (rte_hash_iterate(arp_hash_handle, &next_key, &next_data, &iter) + >= 0) { + + struct arp_entry_data *tmp_arp_data = + (struct arp_entry_data *)next_data; + struct arp_key_ipv4 tmp_arp_key; + memcpy(&tmp_arp_key, next_key, sizeof(struct arp_key_ipv4)); + len += sprintf + (buf + len, "\t%4d %02X:%02X:%02X:%02X:%02X:%02X" + " %10s %d.%d.%d.%d\n<br/>", + tmp_arp_data->port, tmp_arp_data->eth_addr.addr_bytes[0], + tmp_arp_data->eth_addr.addr_bytes[1], + tmp_arp_data->eth_addr.addr_bytes[2], + tmp_arp_data->eth_addr.addr_bytes[3], + tmp_arp_data->eth_addr.addr_bytes[4], + tmp_arp_data->eth_addr.addr_bytes[5], + arp_status[tmp_arp_data->status], + (tmp_arp_data->ip >> 24), + ((tmp_arp_data->ip & 0x00ff0000) >> 16), + ((tmp_arp_data->ip & 0x0000ff00) >> 8), + ((tmp_arp_data->ip & 0x000000ff))); + } + + uint32_t i = 0, j; + len += sprintf(buf + len, "\n<br/>IP_Address Mask Port\n<br/>"); + for (j = 0; j < gw_get_num_ports(); j++) { + for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) { + len += sprintf(buf + len, "0x%08x \t 0x%08x \t %d\n<br/>", + p_route_data[j]->route_table[i].nh, + p_route_data[j]->route_table[i].mask, + p_route_data[j]->route_table[i].port); + } + } + + len += sprintf + (buf + len, "\nARP Stats: Total Queries %u, ok_NH %u," + " no_NH %u, ok_Entry %u, no_Entry %u, PopulateCall %u," + " Del %u, Dup %u\n<br/>", + lib_arp_get_mac_req, lib_arp_nh_found, lib_arp_no_nh_found, + lib_arp_arp_entry_found, lib_arp_no_arp_entry_found, + lib_arp_populate_called, lib_arp_delete_called, + lib_arp_duplicate_found); + + len += sprintf(buf + len, "ARP table key len is %lu\n<br/>", + sizeof(struct arp_key_ipv4)); + mg_printf(conn, "%s\n<br/>", &buf[0]); + return 1; +} + +void get_mac(struct ether_addr *mac_addr, char *buf) +{ + uint32_t i = 0, j = 0, k = 0, MAC_NUM_BYTES = 6; + + char byteStr[MAC_NUM_BYTES][3]; + + char *token = strtok(buf, " "); + while (token) { + k = 0; + for (i = 0; i < MAC_NUM_BYTES; i++) { + for (j = 0; j < 2; j++) { + byteStr[i][j] = token[k++]; + } + byteStr[i][j] = '\0'; + k++; + } + token = strtok(NULL, " "); + } + + for (i = 0; i < MAC_NUM_BYTES; i++) { + mac_addr->addr_bytes[i] = strtoul(byteStr[i], NULL, 16); + } +} + +int arp_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + const struct mg_request_info *req_info = mg_get_request_info(conn); + char buf[MAX_BUF_SIZE]; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + /* prints arp table */ + mg_printf(conn, "<html><body>"); + arpls_handler(conn, cbdata); + + /* prints nd table */ + nd_handler(conn, cbdata); + mg_printf(conn, "</body></html>"); + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "ipv4")) { + current_arp_parms.ip = rte_bswap32(inet_addr( + json_object_get_string(val))); + current_arp_parms.family = AF_INET; + } else if (!strcmp(key, "ipv6")) { + my_inet_pton_ipv6(AF_INET6, + json_object_get_string(val), + ¤t_arp_parms.ipv6[0]); + current_arp_parms.family = AF_INET6; + } else if (!strcmp(key, "action")) { + if (!strcmp(json_object_get_string(val), "add")) + current_arp_parms.action = 1; + else if (!strcmp(json_object_get_string(val), "del")) + current_arp_parms.action = 2; + else if (!strcmp(json_object_get_string(val), "req")) + current_arp_parms.action = 3; + } else if (!strcmp(key, "portid")) { + current_arp_parms.portid = + atoi(json_object_get_string(val)); + } else if (!strcmp(key, "macaddr")) { + get_mac(¤t_arp_parms.mac_addr, + strdup(json_object_get_string(val))); + } + } + + struct arp_key_ipv4 arp_key; + struct arp_timer_key *callback_key; + struct arp_entry_data *new_arp_data; + struct nd_key_ipv6 nd_key; + struct nd_entry_data *new_nd_data; + + if (current_arp_parms.family == AF_INET) { + switch(current_arp_parms.action) { + case 1: + populate_arp_entry(¤t_arp_parms.mac_addr, + current_arp_parms.ip, current_arp_parms.portid, + STATIC_ARP); + break; + case 2: + callback_key = + (struct arp_timer_key*) rte_malloc(NULL, + sizeof(struct arp_timer_key*), + RTE_CACHE_LINE_SIZE); + arp_key.port_id = current_arp_parms.portid; + arp_key.ip = current_arp_parms.ip; + arp_key.filler1 = 0; + arp_key.filler2 = 0; + arp_key.filler3 = 0; + new_arp_data = retrieve_arp_entry(arp_key, + STATIC_ARP); + callback_key->port_id = current_arp_parms.portid; + callback_key->ip = current_arp_parms.ip; + + mg_printf(conn, "removing entry now\n"); + remove_arp_entry(new_arp_data, callback_key); + break; + case 3: + arp_key.ip = current_arp_parms.ip; + arp_key.port_id = current_arp_parms.portid; + arp_key.filler1 = 0; + arp_key.filler2 = 0; + arp_key.filler3 = 0; + + new_arp_data = retrieve_arp_entry(arp_key, STATIC_ARP); + + if (new_arp_data) { + mg_printf(conn, "<p>ARP entry exists for" + " ip 0x%x, port %d</p>", + current_arp_parms.ip, current_arp_parms.portid); + return 1; + } + + mg_printf(conn, "<p>ARP - requesting arp for ip 0x%x, port %d</p>", + current_arp_parms.ip, current_arp_parms.portid); + + request_arp(current_arp_parms.portid, current_arp_parms.ip); + break; + default: + break; + }; + } else { + switch(current_arp_parms.action) { + case 1: + populate_nd_entry(¤t_arp_parms.mac_addr, + current_arp_parms.ipv6, current_arp_parms.portid, STATIC_ND); + break; + case 2: + nd_key.port_id = current_arp_parms.portid; + memcpy(&nd_key.ipv6[0], ¤t_arp_parms.ipv6[0], 16); + nd_key.filler1 = 0; + nd_key.filler2 = 0; + nd_key.filler3 = 0; + new_nd_data = retrieve_nd_entry(nd_key, STATIC_ND); + remove_nd_entry_ipv6(new_nd_data, &nd_key); + case 3: + mg_printf(conn, "<p>ND REQ is not supported Yet!!!</p>"); + break; + default: + break; + }; + } + + mg_printf(conn, "<p>Command Passed</p>"); + mg_printf(conn, "</body></html>\n"); + return 1; +} + +int route_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + uint32_t portid = 0; + uint32_t i, j, status; + char buf[MAX_BUF_SIZE]; + uint32_t mask = 0, num = 31; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<pre>\nIP_Address Mask Port\n<br/>"); + + for (j = 0; j < gw_get_num_ports(); j++) { + for (i = 0; i < p_route_data[j]->route_ent_cnt; i++) { + mg_printf(conn, "0x%08x \t 0x%08x \t %d\n<br/>", + p_route_data[j]->route_table[i].nh, + p_route_data[j]->route_table[i].mask, + p_route_data[j]->route_table[i].port); + } + } + + mg_printf(conn, "\n\nND IPV6 routing table ...\n<br/>"); + mg_printf(conn, "\nNH_IP_Address " + " Depth Port \n<br/>"); + for(uint32_t p = 0; p < gw_get_num_ports(); p++ ) { + for (i = 0; i < p_nd_route_data[p]->nd_route_ent_cnt; i++) { + for (j = 0; j < ND_IPV6_ADDR_SIZE; j += 2) { + mg_printf(conn, "%02X%02X ", + p_nd_route_data[p]->nd_route_table[i].nhipv6[j], + p_nd_route_data[p]->nd_route_table[i].nhipv6[j + 1]); + } + + mg_printf(conn, "\t%d %d " + " \n<br/></pre>", + p_nd_route_data[p]->nd_route_table[i].depth, + p_nd_route_data[p]->nd_route_table[i].port); + } + } + + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "portid")) { + portid = atoi(json_object_get_string(val)); + if (portid > 64) { + mg_printf(conn, "Port not supported!!!\n"); + return 1; + } else if (current_route_parms[portid].enable) { + mg_printf(conn, "Already configured\n"); + } + } else if (!strcmp(key, "nhipv4")) { + current_route_parms[portid].ip = + rte_bswap32(inet_addr(json_object_get_string(val))); + current_route_parms[portid].family = AF_INET; + } else if (!strcmp(key, "nhipv6")) { + my_inet_pton_ipv6(AF_INET6, + json_object_get_string(val), ¤t_route_parms[portid].ipv6[0]); + current_route_parms[portid].family = AF_INET6; + } else if (!strcmp(key, "depth")) { + current_route_parms[portid].depth = atoi(json_object_get_string(val)); + current_route_parms[portid].enable = 1; + } else if (!strcmp(key, "type")) { + memcpy(current_route_parms[portid].type, json_object_get_string(val), + strlen(json_object_get_string(val))); + } + } + + if (current_route_parms[portid].family == AF_INET) { + if (!strcmp(current_route_parms[portid].type, "net")) { + for (i = 0; i < current_route_parms[portid].depth; i++) { + mask |= (1 << num); + num--; + } + } else + mask = 0xFFFFFFFF; + + status = app_routeadd_config_ipv4(rapp, portid, + current_route_parms[portid].ip, + mask); + if (status != 0) + mg_printf(conn, "Setting route entry failed\n"); + } else { + + if (!strcmp(current_route_parms[portid].type, "host")) { + current_route_parms[portid].depth = 128; + } + status = app_routeadd_config_ipv6(rapp, portid, + current_route_parms[portid].ipv6, + current_route_parms[portid].depth); + if (status != 0) + mg_printf(conn, "Setting route entry failed\n"); + } + + + mg_printf(conn, "</body></html>\n"); + return 1; +} + +int link_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + int i, status = 0, link = 0, link_read = 0; + char buf[MAX_BUF_SIZE]; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>\n"); + for (i = 0; i < MAX_LINKS; i++) { + if (current_link_parms[i].state) + mg_printf(conn, "link %d is enabled\r\n", i); + } + mg_printf(conn, "</body></html>\n"); + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "linkid")) { + link = atoi(json_object_get_string(val)); + mg_printf(conn, "linkid:%d \n", link); + if (link > 64) { + mg_printf(conn, "Link id not supported beyond 64\n"); + return 1; + } + current_link_parms[link].id = link; + link_read = 1; + } else if (!strcmp(key, "state")) { + if (link_read) { + current_link_parms[link].state = + atoi(json_object_get_string(val)); + } + mg_printf(conn, "state:%d \n", current_link_parms[link].state); + } + + } + + + if (current_link_parms[link].state == 0) { + /* link down */ + status = app_link_down(rapp, current_link_parms[link].id); + if (status != 0) { + mg_printf(conn, "<p>command failed</p>"); + } else { + mg_printf(conn, "<p>command Passed</p>"); + } + } else if (current_link_parms[link].state == 1) { + /* link up */ + mg_printf(conn, "setting up the link \n"); + status = app_link_up(rapp, current_link_parms[link].id); + if (status != 0) { + mg_printf(conn, "<p>command failed</p>"); + } else { + mg_printf(conn, "<p>command Passed</p>"); + } + + } + + sprintf(buf, "/vnf/config/link/%d", link); + mg_set_request_handler(ctx, buf, linkid_handler, (void *)&link); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + return 1; +} + +int linkid_handler(struct mg_connection *conn, void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + int status = 0; + char buf[MAX_BUF_SIZE]; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>\n"); + linkls_handler(conn, cbdata); + mg_printf(conn, "</body></html>\n"); + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + + uint32_t linkid = *(uint32_t *)cbdata; + mg_printf(conn, "link id :%d ", linkid); + + if (!current_link_parms[linkid].state) { + mg_printf(conn, "<p>link not enabled!! </p>"); + mg_printf(conn, "</body></html>\n"); + return 1; + } + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "ipv4")) { + current_link_parms[linkid].ip = + rte_bswap32(inet_addr(json_object_get_string(val))); + current_link_parms[linkid].family = AF_INET; + } else if (!strcmp(key, "ipv6")) { + my_inet_pton_ipv6(AF_INET6, + json_object_get_string(val), ¤t_link_parms[linkid].ipv6[0]); + current_link_parms[linkid].family = AF_INET6; + } else if (!strcmp(key, "depth")) { + current_link_parms[linkid].depth = atoi(json_object_get_string(val)); + } + } + + + /* bring the link down */ + status = app_link_down(rapp, linkid); + if (status != 0) { + mg_printf(conn, "<p>command down failed</p>"); + } else { + mg_printf(conn, "<p>command Passed</p>"); + } + + /* configure the ip address */ + if (current_link_parms[linkid].family == AF_INET) { + status = app_link_config(rapp, linkid, current_link_parms[linkid].ip, + current_link_parms[linkid].depth); + } else { + status = app_link_config_ipv6(rapp, linkid, + current_link_parms[linkid].ipv6, current_link_parms[linkid].depth); + } + + if (status != 0) { + mg_printf(conn, "<p>command config failed</p>"); + } else { + mg_printf(conn, "<p>command Passed</p>"); + } + + /* bring the link up */ + status = app_link_up(rapp, linkid); + if (status != 0) { + mg_printf(conn, "<p>command up failed</p>"); + } else { + mg_printf(conn, "<p>command Passed</p>"); + } + + + mg_printf(conn, "</body></html>\n"); + return 1; +} + +void set_vnf_type(const char *type) +{ + memcpy(current_cfg.vnf_type, type, strlen(type)); +} + +void init_stat_cfg(void) +{ + char buf[256] = "98103214:(1, 65535)"; + uint32_t i; + + current_cfg.num_workers = 4; + current_cfg.num_lb = 1; + current_cfg.num_ports = 2; + current_cfg.hyper_thread = 0; + current_cfg.sock_in = 0; + current_cfg.sw_lb = 1; + memcpy(current_cfg.pkt_type, "ipv4", 4); + + for (i=0;i<MAX_LB;i++) { + memcpy(current_cfg.ip_range[i].value, &buf, + sizeof(buf)); + } +} + +void bind_the_ports(struct mg_connection *conn, char *pci_white_list) +{ + char *token; + char buf[MAX_BUF_SIZE]; + int x = 0, ret; + + token = strtok(pci_white_list, " "); + + while(token != NULL) { + mg_printf(conn, "%s ****\n", token); + sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -u %s", token); + ret = system(buf); + if (ret) + mg_printf(conn, "wrong parameter sent\n"); + + sprintf(buf, "$RTE_SDK/usertools/dpdk-devbind.py -b igb_uio %s", token); + ret = system(buf); + if (ret) + mg_printf(conn, "wrong parameter sent\n"); + + token = strtok(NULL, " "); + + x++; + } + current_cfg.num_ports = x; +} + +int static_cfg_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + int i; + unsigned int len; + char buf[MAX_BUF_SIZE]; + + const struct mg_request_info *ri = mg_get_request_info(conn); + + if (!strcmp(ri->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2> These are the values set in config</h2>"); + mg_printf(conn, "<h3> num_workers: %d\n</h3>", + current_cfg.num_workers); + mg_printf(conn, "<h3> num_lb: %d\n</h3>", + current_cfg.num_lb); + mg_printf(conn, "<h3> num_ports: %d\n</h3>", + current_cfg.num_ports); + mg_printf(conn, "<h3> hyper_thread: %d\n</h3>", + current_cfg.hyper_thread); + mg_printf(conn, "<h3> socket_id : %d\n</h3>", + current_cfg.sock_in); + mg_printf(conn, "<h3> sw_lb: %d\n</h3>", + current_cfg.sw_lb); + mg_printf(conn, "<h3> vnf_type: %s\n</h3>", + current_cfg.vnf_type); + mg_printf(conn, "<h3> pkt_type: %s\n</h3>", + current_cfg.pkt_type); + mg_printf(conn, "<h3> pci_white_list: %s\n</h3>", + current_cfg.pci_white_list); + mg_printf(conn, "</body></html>\n"); + return 1; + } + + if (strcmp(ri->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + ri->request_method); + return 1; + } + + if (static_cfg_set) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + return 1; + } + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + len = 0; + struct json_object *values; + char *str; + + i = 0; + json_object_object_foreach(jobj, key, val) { + memcpy(static_cfg[i].key, key, strlen(key)); + memcpy(static_cfg[i].value, json_object_get_string(val), + strlen(json_object_get_string(val))); + sprintf(buf, "public_ip_port_range_%d", pub_ip); + if (!strcmp(static_cfg[i].key, buf)) { + memcpy(¤t_cfg.ip_range[pub_ip].value, + static_cfg[i].value, + sizeof(static_cfg[i].value)); + pub_ip++; + } + i++; + } + n_entries1 = i; + + json_object_object_get_ex(jobj, "num_worker", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + memcpy(¤t_cfg.ip_range[pub_ip++].value, str, + sizeof(str)); + } + + json_object_object_get_ex(jobj, "num_worker", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.num_workers = atoi(str); + } + + json_object_object_get_ex(jobj, "pkt_type", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + memcpy(¤t_cfg.pkt_type, str, + sizeof(current_cfg.pkt_type)); + } + + json_object_object_get_ex(jobj, "num_lb", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.num_lb = atoi(str); + } + + json_object_object_get_ex(jobj, "num_ports", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.num_ports = atoi(str); + } + + json_object_object_get_ex(jobj, "sw_lb", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.sw_lb = atoi(str); + } + + json_object_object_get_ex(jobj, "sock_in", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.sock_in = atoi(str); + } + + json_object_object_get_ex(jobj, "hyperthread", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + current_cfg.hyper_thread = atoi(str); + } + + json_object_object_get_ex(jobj, "vnf_type", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + memcpy(¤t_cfg.vnf_type, str, + sizeof(current_cfg.vnf_type)); + } + + json_object_object_get_ex(jobj, "pci_white_list", &values); + if (values) { + str = strdup(json_object_get_string(values)); + if (str) + memcpy(¤t_cfg.pci_white_list, str, + sizeof(current_cfg.pci_white_list)); + mg_printf(conn, " Binding the ports \n"); + bind_the_ports(conn, ¤t_cfg.pci_white_list[0]); + } + + len = sprintf(buf, "POST DATA RECEIVED\n"); + + mg_printf(conn, + "HTTP/1.1 200 OK\r\n" + "Content-Length: %u\r\n" + "Content-Type: text/plain\r\n" + "Connection: close\r\n\r\n", + len); + + mg_write(conn, buf, len); + post_not_received = 0; + static_cfg_set++; + return 1; +} + +int vnf_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "<h2>These are the methods that are supported</h2>"); + mg_printf(conn, "<h3> /vnf/config</h3>"); + mg_printf(conn, "<h3> /vnf/config/arp</h3>"); + mg_printf(conn, "<h3> /vnf/config/link</h3>"); + mg_printf(conn, "<h3> /vnf/config/route</h3>"); + mg_printf(conn, "<h3> /vnf/config/rules(vFW/vACL only)</h3>"); + mg_printf(conn, "<h3> /vnf/config/rules/load(vFW/vACL only)</h3>"); + mg_printf(conn, "<h3> /vnf/config/rules/clear(vFW/vACL only)</h3>"); + mg_printf(conn, "<h3> /vnf/config/nat(vCGNAPT only)</h3>"); + mg_printf(conn, "<h3> /vnf/config/nat/load(vFW/vACL only)</h3>"); + mg_printf(conn, "<h3> /vnf/config/dbg</h3>"); + mg_printf(conn, "<h3> /vnf/config/dbg/pipelines</h3>"); + mg_printf(conn, "<h3> /vnf/config/dbg/cmd</h3>"); + mg_printf(conn, "<h3> /vnf/log</h3>"); + mg_printf(conn, "<h3> /vnf/flowdirector</h3>"); + mg_printf(conn, "<h3> /vnf/status</h3>"); + mg_printf(conn, "<h3> /vnf/stats</h3>"); + mg_printf(conn, "<h3> /vnf/quit</h3>"); + mg_printf(conn, "</body></html>"); + + + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n"); + mg_printf(conn, "Content-Type: text/plain\r\n\r\n"); + mg_printf(conn, + "%s method not allowed in the POST handler\n", + req_info->request_method); + return 1; + } + + return 1; +} + +void get_pktq_in_prv(char *buf) +{ + int j; + uint32_t len = 0; + for (j = 0; j < current_cfg.num_ports; j+=2) { + len += sprintf(buf + len, "RXQ%d.0 ", j); + } +} + +void fix_pipelines_data_types(FILE *f, const char *sect_name, struct rte_cfgfile *tcfg) +{ + int i, j, n_entries, tmp = 0; + char str[256], str1[40]; + + n_entries = rte_cfgfile_section_num_entries(tcfg, sect_name); + + rte_cfgfile_section_entries(tcfg, sect_name, entries, n_entries); + + for (i = 0; i < n_entries; i++) { + for (j = 0; j < n_entries1; j++) { + if (strncmp(entries[i].name, static_cfg[i].key, + strlen(entries[i].name)) == 0) { + memcpy(entries[i].value, static_cfg[i].value, + strlen(entries[i].value)); + tmp++; + } + + if (strncmp(entries[i].name, "pkt_type", + strlen("pkt_type")) == 0) { + memcpy(entries[i].value, current_cfg.pkt_type, + strlen(entries[i].value)); + if (!strcmp(current_cfg.pkt_type, "ipv4")) + memcpy(&traffic_type, "4", 1); + else + memcpy(&traffic_type, "6", 1); + } + + if (strncmp(entries[i].name, "traffic_type", + sizeof("traffic_type")) == 0) { + memcpy(entries[i].value, &traffic_type, 4); + } + } + + if (strncmp(entries[i].name, "core", strlen(entries[i].name)) == 0) { + if ((strncmp(sect_name, "MASTER", strlen(sect_name)) == 0) && + !current_cfg.sock_in) { + continue; + } + + if ((current_cfg.hyper_thread) && hyper) { + sprintf(str, "s%dc%dh", current_cfg.sock_in, + sock_cpus[current_cfg.sock_in][sock_index]); + memcpy(entries[i].value, &str, 8); + sock_index++; + hyper = 0; + continue; + } + + sprintf(str, "s%dc%d", current_cfg.sock_in, + sock_cpus[current_cfg.sock_in][sock_index]); + + if (!current_cfg.hyper_thread) + sock_index++; + else + hyper = 1; + + if (current_cfg.sock_in) { + if (sock_index == sock1) + sock_index = 1; + } else { + if (sock_index == sock0) + sock_index = 1; + } + memcpy(entries[i].value, &str, 8); + } + } + num_entries = i; + + if (strncmp(sect_name, "ARPICMP", strlen(sect_name)) == 0) { + for (j = 0; j < n_entries1; j++) { + if ((strncmp(static_cfg[j].key, "arp_route_tbl", + strlen(static_cfg[j].key)) == 0) || + (strncmp(static_cfg[j].key, "nd_route_tbl", + strlen(static_cfg[j].key)) == 0)) { + memcpy(&entries[i].name, &static_cfg[j].key, + strlen(static_cfg[j].key)); + memcpy(&entries[i].value, &static_cfg[j].value, + strlen(static_cfg[j].value)); + i++; + } + } + num_entries = i; + /* update pktq_in/pktq_out */ + for (i=0; i < n_entries; i++) { + memset(str, 0, 256); + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers; + get_swq(tmp, &str[0]); + memcpy(&entries[i].value, &str, strlen(str)); + continue; + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_workers / 2; + //tmp = (current_cfg.sw_lb)? current_cfg.num_lb: current_cfg.num_ports; + get_txq(0, 1, current_cfg.num_ports, &str[0]); + memcpy(&entries[i].value, &str, strlen(str)); + continue; + } + + if (strncmp(entries[i].name, "pktq_in_prv", + strlen(entries[i].name)) == 0) { + get_pktq_in_prv(&str[0]); + memset(&entries[i].value, 0, sizeof(entries[i].value)); + memcpy(&entries[i].value, &str, strlen(str)); + continue; + } + + if (strncmp(entries[i].name, "prv_to_pub_map", + strlen(entries[i].name)) == 0) { + get_prv_to_pub_map(&str[0]); + memcpy(&entries[i].value, &str, strlen(str)); + continue; + } + + if (strncmp(entries[i].name, "prv_que_handler", + strlen(entries[i].name)) == 0) { + get_prv_que_handler(&str[0]); + memcpy(&entries[i].value, &str, strlen(str)); + continue; + } + } + } + + if (strncmp(sect_name, "TXRX-BEGIN", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + get_rxq(0, 1, 2, &str[0]); + memcpy(entries[i].value, &str, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + get_swq(2, &str[0]); + memcpy(loadb_in, str, sizeof(str)); + sprintf(str1," SWQ%d", arp_index++); + strcat(str, str1); + memcpy(entries[i].value, &str, sizeof(str)); + } + } + } + + if (strncmp(sect_name, "LOADB", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + memcpy(entries[i].value, &loadb_in, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + if (current_cfg.num_ports > 2) + tmp = (current_cfg.num_workers/current_cfg.num_lb * 2); + else + tmp = current_cfg.num_workers * 2; + start_lb = swq_index; + end_lb = tmp; + start_lbout = start_lb + end_lb; + get_swq(tmp, &str[0]); + memcpy(entries[i].value, &str, sizeof(str)); + } + if (strncmp(entries[i].name, "n_vnf_threads", + strlen(entries[i].name)) == 0) { + sprintf(str1, "%d", current_cfg.num_workers/current_cfg.num_lb); + memcpy(entries[i].value, &str1, sizeof(str1)); + } + } + } + + if (strncmp(sect_name, "VACL", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) { + get_swq_offset(start_lb, 2, &str[0]); + start_lb += 2; + } else + get_rxq(workers, 1, 2, &str[0]); + + memcpy(entries[i].value, &str, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) + get_swq(2, &str[0]); + else { + get_txq(workers+1, 1, 2, &str[0]); + sprintf(str1," SWQ%d", arp_index++); + strcat(str, str1); + } + memcpy(entries[i].value, &str, sizeof(str)); + } + } + + workers++; + if (current_cfg.sw_lb) { + if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) && + (workers != current_cfg.num_workers)) { + workers = 0; + } + } else { + if ((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) { + tx_start_port += 2; + rx_start_port += 2; + workers = 0; + } + } + } + + if (strncmp(sect_name, "VCGNAPT", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) { + get_swq_offset(start_lb, 2, &str[0]); + start_lb += 2; + } else + get_rxq(workers, 1, 2, &str[0]); + + memcpy(entries[i].value, &str, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) + get_swq(2, &str[0]); + else { + get_txq(workers+1, 1, 2, &str[0]); + sprintf(str1," SWQ%d", arp_index++); + strcat(str, str1); + } + memcpy(entries[i].value, &str, sizeof(str)); + } + } + + if (workers == 0) { + char *token; + sprintf(str1, "vnf_set"); + memcpy(entries[i].name, &str1, sizeof(str1)); + sprintf(str1, "(3,4,5)"); + memcpy(entries[i].value, &str1, sizeof(str1)); + num_entries++; + i++; + + token = strtok(current_cfg.ip_range[ip_range].value, "/"); + while(token) { + sprintf(str1, "public_ip_port_range"); + memcpy(entries[i].name, &str1, sizeof(str1)); + memcpy(entries[i].value, token, strlen(token)); + i++; + num_entries++; + token = strtok(NULL, "/"); + } + ip_range++; + } + + workers++; + if (current_cfg.sw_lb) { + if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) && + (workers != current_cfg.num_workers)) { + workers = 0; + } + } else { + //if (((workers % (current_cfg.num_workers/current_cfg.num_lb)) == 0) && + // (workers != current_cfg.num_workers)) { + if (workers == (current_cfg.num_workers/current_cfg.num_lb)) { + tx_start_port += 2; + rx_start_port += 2; + workers = 0; + } + } + } + + if (strncmp(sect_name, "VFW", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) { + get_swq_offset(start_lb, 2, &str[0]); + start_lb += 2; + } else + get_rxq(workers, 1, 2, &str[0]); + + memcpy(entries[i].value, &str, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + if (current_cfg.sw_lb) + get_swq(2, &str[0]); + else { + get_txq(workers+1, 1, 2, &str[0]); + sprintf(str1," SWQ%d", arp_index++); + strcat(str, str1); + } + memcpy(entries[i].value, &str, sizeof(str)); + } + } + + workers++; + if (current_cfg.sw_lb) { + if (((workers % current_cfg.num_workers/current_cfg.num_lb) == 0) + && (workers != current_cfg.num_workers)) { + workers = 0; + } + } else { + if (current_cfg.num_ports > 2) { + tx_start_port += 2; + rx_start_port += 2; + workers = 0; + } + } + } + + if (strncmp(sect_name, "TXRX-END", strlen(sect_name)) == 0) { + for (i=0; i < n_entries; i++) { + if (strncmp(entries[i].name, "pktq_in", + strlen(entries[i].name)) == 0) { + get_swq_offset(start_lbout, end_lb, &str[0]); + memcpy(entries[i].value, &str, sizeof(str)); + } + + if (strncmp(entries[i].name, "pktq_out", + strlen(entries[i].name)) == 0) { + get_txq(1, end_lb / 2, 2, &str[0]); + memcpy(entries[i].value, &str, sizeof(str)); + } + } + tx_start_port += 2; + rx_start_port += 2; + } + + fprintf(f, "[PIPELINE%d]\n", pipenum); + for (i=0;i<num_entries;i++) { + fprintf(f, "%s = %s\n", entries[i].name, entries[i].value); + } + fprintf(f, "\n"); + pipenum++; +} + +void print_to_file(FILE *f, struct rte_cfgfile *tcfg) +{ + int i; + for (i=0;i<num_pipelines;i++) { + fix_pipelines_data_types(f, pipelines[pipe_arr[i]], tcfg); + } + fclose(f); +} + +int get_vnf_index(void) +{ + + int i; + + for (i = 0; i < PIPE_MAX; i++) { + if (strncmp(pipelines[i], current_cfg.vnf_type, + strlen(current_cfg.vnf_type)) == 0) + return i; + } + return -1; +} + +void build_pipeline(void) +{ + int i = 2, j, k, vnf_index; + + pipe_arr[0] = 0; + pipe_arr[1] = 1; + vnf_index = get_vnf_index(); + if (vnf_index == -1) + printf("Wrong VNF TYPE\n"); + + if (vnf_index == VNF_VCGNAPT) + pipe_arr[i++] = 2; + + if (!current_cfg.sw_lb) { + for (k = 0; k < current_cfg.num_workers; k++) + pipe_arr[i++] = vnf_index; + num_pipelines = i; + return; + } + + for (j = 0; j < current_cfg.num_lb; j++) { + /* put TXRX-BEGIN & LOADB pipelines */ + pipe_arr[i++] = TXRX_BEGIN; + pipe_arr[i++] = LOADB; + + /* place the worker threads */ + int limit = current_cfg.num_workers / current_cfg.num_lb; + for (k = 0; k < limit; k++) + pipe_arr[i++] = vnf_index; + + /* end the TXRX pipeline */ + pipe_arr[i++] = TXRX_END; + } + num_pipelines = i; +} + +int set_hash_global_config(struct mg_connection *conn, uint32_t port_id, + char *flow_type, const char *hash_func, const char *enable) +{ + struct rte_eth_hash_filter_info info; + uint32_t ftype, idx, offset; + int ret; + + if (rte_eth_dev_filter_supported(port_id, + RTE_ETH_FILTER_HASH) < 0) { + mg_printf(conn, "RTE_ETH_FILTER_HASH not supported on port %d\n", + port_id); + return 1; + } + memset(&info, 0, sizeof(info)); + info.info_type = RTE_ETH_HASH_FILTER_GLOBAL_CONFIG; + if (!strcmp(hash_func, "toeplitz")) + info.info.global_conf.hash_func = + RTE_ETH_HASH_FUNCTION_TOEPLITZ; + else if (!strcmp(hash_func, "simple_xor")) + info.info.global_conf.hash_func = + RTE_ETH_HASH_FUNCTION_SIMPLE_XOR; + else if (!strcmp(hash_func, "default")) + info.info.global_conf.hash_func = + RTE_ETH_HASH_FUNCTION_DEFAULT; + + ftype = str2flowtype(flow_type); + idx = ftype / (CHAR_BIT * sizeof(uint32_t)); + offset = ftype % (CHAR_BIT * sizeof(uint32_t)); + info.info.global_conf.valid_bit_mask[idx] |= (1UL << offset); + if (!strcmp(enable, "enable")) + if(idx < RTE_SYM_HASH_MASK_ARRAY_SIZE) + info.info.global_conf.sym_hash_enable_mask[idx] |= + (1UL << offset); + ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_HASH, + RTE_ETH_FILTER_SET, &info); + if (ret < 0) + mg_printf(conn, "Cannot set global hash configurations by port %d\n", + port_id); + else + mg_printf(conn, "Global hash configurations have been set " + "succcessfully by port %d\n", port_id); + return 1; +} + +int flow_director_handler(struct mg_connection *conn, __rte_unused void *cbdata) +{ + /* Handler may access the request info using mg_get_request_info */ + const struct mg_request_info *req_info = mg_get_request_info(conn); + uint32_t port_id = 0, tuple = 0; + char trans_type[24], buf[MAX_BUF_SIZE]; + char *str, field0[MAX_SIZE], field1[MAX_SIZE], field2[MAX_SIZE], + field3[MAX_SIZE], flow_type[MAX_SIZE]; + + if (!strcmp(req_info->request_method, "GET")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + if (flow_dir_cfg) + mg_printf(conn, "<h3> Flow is configured </h3>"); + else + mg_printf(conn, "<h3> Flow is NOT configured </h3>"); + mg_printf(conn, "</body></html>"); + return 1; + } + + if (strcmp(req_info->request_method, "POST")) { + mg_printf(conn, + "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " + "close\r\n\r\n"); + mg_printf(conn, "<html><body>"); + mg_printf(conn, "This method is not supported\n"); + mg_printf(conn, "</body></html>"); + return 1; + + } + + mg_read(conn, buf, sizeof(buf)); + json_object * jobj = json_tokener_parse(buf); + json_object_object_foreach(jobj, key, val) { + if (!strcmp(key, "trans_type")) { + memcpy(&trans_type, str, sizeof(trans_type)); + if (!strcmp(key, "udp")) { + memcpy(field2,"udp-src-port", sizeof("udp-src-port")); + memcpy(field3,"udp-dst-port", sizeof("udp-dst-port")); + if (!strcmp(current_cfg.pkt_type, "ipv4")) { + memcpy(flow_type,"ipv4-udp", sizeof("ipv4-udp")); + memcpy(field0,"src-ipv4", sizeof("src-ipv4")); + memcpy(field1,"dst-ipv4", sizeof("dst-ipv4")); + } else if (!strcmp(current_cfg.pkt_type, "ipv6")) { + memcpy(flow_type,"ipv6-udp", sizeof("ipv6-udp")); + memcpy(field0,"src-ipv6", sizeof("src-ipv6")); + memcpy(field1,"dst-ipv6", sizeof("dst-ipv6")); + } + } else if (!strcmp(key, "tcp")) { + memcpy(field2,"tcp-src-port", sizeof("tcp-src-port")); + memcpy(field3,"tcp-dst-port", sizeof("tcp-dst-port")); + if (!strcmp(current_cfg.pkt_type, "ipv4")) { + memcpy(flow_type,"ipv4-tcp", sizeof("ipv4-tcp")); + memcpy(field0,"src-ipv4", sizeof("src-ipv4")); + memcpy(field1,"dst-ipv4", sizeof("dst-ipv4")); + } else if (!strcmp(current_cfg.pkt_type, "ipv6")) { + memcpy(flow_type,"ipv6-tcp", sizeof("ipv6-tcp")); + memcpy(field0,"src-ipv6", sizeof("src-ipv6")); + memcpy(field1,"dst-ipv6", sizeof("dst-ipv6")); + } + } + } else if (!strcmp(key, "tuple")) { + tuple = atoi(json_object_get_string(val)); + if ((tuple != 2) || (tuple != 5)) + return 1; + } + } + + if (tuple == 2) { + set_pkt_forwarding_mode("rxonly"); + for (port_id = 0; port_id < current_cfg.num_ports; port_id++) { + set_sym_hash_per_port(conn, port_id); + set_hash_global_config(conn, port_id, flow_type, + "simple_xor", "enable"); + } + + for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) { + set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv4", + "udp-src-port", "add"); + set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv4", + "udp-dst-port", "add"); + set_hash_input_set_2(conn, port_id, "ipv4-udp", "src-ipv6", + "udp-src-port", "add"); + set_hash_input_set_2(conn, port_id, "ipv4-udp", "dst-ipv6", + "udp-dst-port", "add"); + } + } else if (tuple == 5) { + set_pkt_forwarding_mode("rxonly"); + for (port_id = 0; port_id < current_cfg.num_ports; port_id++) { + set_sym_hash_per_port(conn, port_id); + set_hash_global_config(conn, port_id, flow_type, + "simple_xor", "enable"); + } + + for (port_id = 0; port_id < current_cfg.num_ports; port_id+=2) { + set_hash_input_set_4(conn, port_id, flow_type, field0, field1, + field2, field3, "add"); + } + } + flow_dir_cfg = 1; + return 1; +} + +void get_swq_offset(uint8_t start, uint8_t num, char *buf) +{ + int i; + uint32_t len = 0; + + for (i = start; i < start+num; i++) { + sprintf(buf + len, "SWQ%d ", i); + len = strlen(buf); + } +} + +void get_swq(uint8_t num, char *buf) +{ + int i; + uint32_t len = 0; + + for (i=0;i<num;i++) { + sprintf(buf + len, "SWQ%d ", swq_index++); + len = strlen(buf); + } +} + +void get_prv_to_pub_map(char *buf) +{ + int j; + uint32_t len = 0; + for (j = 0; j < current_cfg.num_ports; j+=2) { + sprintf(buf + len, "(%d,%d)", j, j+1); + len = strlen(buf); + } +} + +void get_prv_que_handler(char *buf) +{ + int j; + uint32_t len = 0; + sprintf(buf + len, "("); + len = strlen(buf); + for (j = 0; j < current_cfg.num_ports; j+=2) { + sprintf(buf + len, "%d,", j); + len = strlen(buf); + } + sprintf(buf + len, ")"); +} + +void get_txq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf) +{ + int i, j; + uint32_t len = 0; + for (i=tx_start_port;i<tx_start_port + ports;i+=2) + { + for (j=start_q;j<(start_q + queue_num);j++) + { + sprintf(buf + len, " TXQ%d.%d TXQ%d.%d", i, j, i+1, j); + len = strlen(buf); + } + } + +} + +void get_rxq(uint8_t start_q, uint8_t queue_num, uint8_t ports, char *buf) +{ + int i, j; + uint32_t len = 0; + + for (i=rx_start_port;i<rx_start_port + ports;i+=2) + { + for (j=start_q;j<(start_q + queue_num);j++) + { + sprintf(buf + len, " RXQ%d.%d RXQ%d.%d", i, j, i+1, j); + len = strlen(buf); + } + } + +} + +struct mg_context * +rest_api_init(struct app_params *app) +{ + struct rte_cfgfile *tcfg; + FILE *f; + char buf[256]; + const char *options[] = {"listening_ports", "80", NULL}; + uint32_t i, lcore_id = 0; + uint32_t sock, index; + + /* Server context handle */ + rapp = app; + + for (lcore_id=0;lcore_id<64;lcore_id++) { + //lcore_id = rte_get_next_lcore(lcore_id, 0, 0); + sock = eal_cpu_socket_id(lcore_id); + index = (sock == 0)? sock0++ : sock1++; + sock_cpus[sock][index] = lcore_id; + } + + + /* Initialize the icivetweb library */ + mg_init_library(0); + + /* Start the server */ + ctx = mg_start(NULL, 0, options); + if (ctx == NULL) { + printf("REST server did not start\n"); + printf("REST services will not be supported.. Try again "); + printf("by disabling other webservers\n"); + goto end; + } + + /* init handlers being called here */ + init_stat_cfg(); + + /* static config handler */ + mg_set_request_handler(ctx, "/vnf", vnf_handler, 0); + mg_set_request_handler(ctx, "/vnf/config", static_cfg_handler, 0); + + /* arp handler */ + mg_set_request_handler(ctx, "/vnf/config/arp", arp_handler, 0); + + /* route handler */ + mg_set_request_handler(ctx, "/vnf/config/route", route_handler, 0); + + + /* link related handlers */ + mg_set_request_handler(ctx, "/vnf/config/link", link_handler, 0); + //mg_set_request_handler(ctx, "/vnf/config/link/*", linkid_handler, 0); + + /* dbg related handlers */ + mg_set_request_handler(ctx, "/vnf/config/dbg", dbg_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/dbg/pipelines", dbg_pipelines_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/dbg/cmd", dbg_cmd_handler, 0); + mg_set_request_handler(ctx, "/vnf/config/dbg/run", dbg_run_handler, 0); + + mg_set_request_handler(ctx, "/vnf/quit", cmd_quit_handler, 0); + + printf("Waiting for config input for 30 secs\n"); + index = 0; + while(1) { + if (post_not_received == 0 || (index == 30)) + break; + sleep(1); + index++; + } + + if (index == 30 && (post_not_received != 0)) + printf("Input not received for 30 secs, going with default"); + + const char *name = "vnf_template.txt"; + /* Load application configuration file */ + tcfg = rte_cfgfile_load(name, 0); + if (tcfg == NULL) + printf("File could not be loaded\n"); + +// if (!current_cfg.sw_lb) +// current_cfg.num_lb = 1; + + /* build pipelines based on the input given */ + build_pipeline(); + + for (i = 0; i < num_pipelines; i++) { + sprintf(buf, "/vnf/config/dbg/pipelines/%d", i); + mg_set_request_handler(ctx, buf, dbg_pipelines_id_handler, (void *)&i); + } + + /* create a file for writing the config */ + if (!current_cfg.sw_lb) { + mg_set_request_handler(ctx, "/vnf/flowdirector", flow_director_handler, 0); + sprintf(buf, "%s_%s_%dP_%dT.cfg", current_cfg.vnf_type, "HWLB", + current_cfg.num_ports, current_cfg.num_workers); + } else + sprintf(buf, "%s_%s_%dP_%dLB_%dT.cfg", current_cfg.vnf_type, "SWLB", + current_cfg.num_ports, current_cfg.num_lb, current_cfg.num_workers); + + /* create a file which is more readable */ + f = fopen(buf, "w"); + + print_to_file(f, tcfg); + + app->config_file = strdup(buf); + app->parser_file = strdup(buf); + + printf("Config file loaded :%s %s\n", app->config_file, traffic_type); + +end: + return ctx; +} diff --git a/common/vnf_common/vnf_common.c b/common/vnf_common/vnf_common.c index 97f90210..93687fd6 100644 --- a/common/vnf_common/vnf_common.c +++ b/common/vnf_common/vnf_common.c @@ -17,6 +17,7 @@ #include <stdint.h> #include <stdio.h> #include "vnf_common.h" +#include "gateway.h" #include "pipeline_arpicmp_be.h" #ifndef VNF_ACL #include "lib_arp.h" @@ -47,13 +48,12 @@ uint8_t is_port_index_privte(uint16_t phy_port) uint32_t get_prv_to_pub_port(uint32_t *ip_addr, uint8_t type) { uint32_t dest_if = 0xff; - struct ether_addr addr; switch (type) { case 4: { uint32_t nhip; - nhip = get_nh(ip_addr[0], &dest_if, &addr); + gw_get_nh_port_ipv4(*ip_addr, &dest_if, &nhip); if (nhip) return dest_if; @@ -63,7 +63,8 @@ uint32_t get_prv_to_pub_port(uint32_t *ip_addr, uint8_t type) case 6: { uint8_t nhipv6[16]; - get_nh_ipv6((uint8_t *)ip_addr, &dest_if, &nhipv6[0], &addr); + gw_get_nh_port_ipv6((uint8_t *)ip_addr, &dest_if, nhipv6); + if (dest_if != 0xff) return dest_if; return 0xff; @@ -76,13 +77,13 @@ uint32_t get_prv_to_pub_port(uint32_t *ip_addr, uint8_t type) uint32_t get_pub_to_prv_port(uint32_t *ip_addr, uint8_t type) { uint32_t dest_if = 0xff; - struct ether_addr addr; switch (type) { case 4: { uint32_t nhip; - nhip = get_nh(ip_addr[0], &dest_if, &addr); + + gw_get_nh_port_ipv4(*ip_addr, &dest_if, &nhip); if (nhip) return dest_if; @@ -92,7 +93,8 @@ uint32_t get_pub_to_prv_port(uint32_t *ip_addr, uint8_t type) case 6: { uint8_t nhipv6[16]; - get_nh_ipv6((uint8_t *)ip_addr, &dest_if, &nhipv6[0], &addr); + + gw_get_nh_port_ipv6((uint8_t *)ip_addr, &dest_if, nhipv6); if (dest_if != 0xff) return dest_if; return 0xff; diff --git a/tools/vnf_build.sh b/tools/vnf_build.sh index 22a534ff..3b70166c 100755 --- a/tools/vnf_build.sh +++ b/tools/vnf_build.sh @@ -25,6 +25,7 @@ HUGEPGSZ=`cat /proc/meminfo | grep Hugepagesize | cut -d : -f 2 | tr -d ' '` MODPROBE="/sbin/modprobe" INSMOD="/sbin/insmod" DPDK_DOWNLOAD="Not initialized" +CIVETWEB_DOWNLOAD="Not initialized" DPDK_DIR=$VNF_CORE/dpdk DPDK_RTE_VER="17.02" @@ -134,6 +135,8 @@ step_2() FUNC[4]="install_dpdk" TEXT[5]="Setup hugepages" FUNC[5]="setup_hugepages" + TEXT[6]="Download civetweb" + FUNC[6]="download_civetweb_zip" } get_agreement_download() { @@ -176,7 +179,8 @@ install_libs() sudo apt-get update sudo apt-get -y install build-essential linux-headers-$(uname -r) git unzip libpcap0.8-dev gcc \ make libc6 libc6-dev g++-multilib libzmq3-dev libcurl4-openssl-dev net-tools wget gcc unzip \ - libpcap-dev libncurses-dev libedit-dev pciutils liblua5.2-dev libncursesw5-dev + libpcap-dev libncurses-dev libedit-dev pciutils liblua5.2-dev libncursesw5-dev libjson0 \ + libjson0-dev libssl-dev touch .download } @@ -197,6 +201,20 @@ download_dpdk_zip() mv $VNF_CORE/dpdk-$DPDK_RTE_VER $VNF_CORE/dpdk } +download_civetweb_zip() +{ + echo "Download CIVETWEB zip" + CIVETWEB_DOWNLOAD="https://sourceforge.net/projects/civetweb/files/1.9/CivetWeb_V1.9.zip" + if [ ! -e ${CIVETWEB_DOWNLOAD##*/} ] ; then + wget ${CIVETWEB_DOWNLOAD} + fi + unzip -o ${CIVETWEB_DOWNLOAD##*/} + mv $VNF_CORE/civetweb-master $VNF_CORE/civetweb + pushd $VNF_CORE/civetweb + make lib + popd +} + install_dpdk() { echo "Build DPDK" @@ -220,7 +238,7 @@ install_dpdk() patch -p1 < $VNF_CORE/patches/dpdk_custom_patch/set-log-level-to-info.patch fi - make -j install T=$RTE_TARGET + make -j16 install T=$RTE_TARGET if [ $? -ne 0 ] ; then echo "Failed to build dpdk, please check the errors." return @@ -309,6 +327,9 @@ non_interactive() echo "Download dpdk for VNF build..." download_dpdk_zip + echo "Download civetweb for VNF build..." + download_civetweb_zip + echo "Build dpdk..." install_dpdk |