diff options
author | Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com> | 2017-09-25 03:36:02 +0530 |
---|---|---|
committer | Anand B Jyoti <anand.b.jyoti@intel.com> | 2017-09-27 03:29:36 +0530 |
commit | 98b9571f6720a0da06b1d430e7338a0734023232 (patch) | |
tree | 35224c83fa80c0f6dd297c9cee52f5894ade3c56 /VNFs | |
parent | d451d3d2e6423523c300488f33adb4e593d6d2cb (diff) |
REST_API: rest api client implementation
JIRA: SAMPLEVNF-78
This patch implements rest api's for VNF clients. This
comprises of
* vnf api's for common functionality
* vnf api's for CGNAPT
* vnf api's for VFW
Change-Id: I56d22c64bf3ee5b0a2e536da8169ac7583499041
Signed-off-by: Vishwesh M Rudramuni <vishwesh.m.rudramuni@intel.com>
Diffstat (limited to 'VNFs')
-rw-r--r-- | VNFs/UDP_Replay/main.c | 155 | ||||
-rw-r--r-- | VNFs/vACL/Makefile | 10 | ||||
-rw-r--r-- | VNFs/vACL/main.c | 18 | ||||
-rw-r--r-- | VNFs/vACL/pipeline/pipeline_acl.c | 297 | ||||
-rw-r--r-- | VNFs/vACL/pipeline/pipeline_acl.h | 4 | ||||
-rw-r--r-- | VNFs/vACL/vnf_template.txt | 82 | ||||
-rw-r--r-- | VNFs/vCGNAPT/Makefile | 7 | ||||
-rw-r--r-- | VNFs/vCGNAPT/init.c | 1 | ||||
-rw-r--r-- | VNFs/vCGNAPT/main.c | 18 | ||||
-rw-r--r-- | VNFs/vCGNAPT/pipeline/pipeline_cgnapt.c | 226 | ||||
-rw-r--r-- | VNFs/vCGNAPT/pipeline/pipeline_cgnapt.h | 8 | ||||
-rw-r--r-- | VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c | 110 | ||||
-rw-r--r-- | VNFs/vCGNAPT/pipeline/pipeline_cgnapt_common.h | 4 | ||||
-rw-r--r-- | VNFs/vCGNAPT/vnf_template.txt | 80 | ||||
-rw-r--r-- | VNFs/vFW/Makefile | 6 | ||||
-rw-r--r-- | VNFs/vFW/init.c | 2 | ||||
-rw-r--r-- | VNFs/vFW/main.c | 19 | ||||
-rw-r--r-- | VNFs/vFW/pipeline/pipeline_vfw.c | 478 | ||||
-rw-r--r-- | VNFs/vFW/pipeline/pipeline_vfw.h | 15 | ||||
-rw-r--r-- | VNFs/vFW/vnf_template.txt | 82 |
20 files changed, 1409 insertions, 213 deletions
diff --git a/VNFs/UDP_Replay/main.c b/VNFs/UDP_Replay/main.c index 56513c1b..587057fc 100644 --- a/VNFs/UDP_Replay/main.c +++ b/VNFs/UDP_Replay/main.c @@ -201,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 @@ -437,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; diff --git a/VNFs/vACL/Makefile b/VNFs/vACL/Makefile index bba5a6bc..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 @@ -54,7 +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 +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 @@ -64,9 +63,16 @@ 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 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/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 a6feb730..41cacfb7 100644 --- a/VNFs/vCGNAPT/Makefile +++ b/VNFs/vCGNAPT/Makefile @@ -65,9 +65,16 @@ 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 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 f02fd164..f578587e 100644 --- a/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c +++ b/VNFs/vCGNAPT/pipeline/pipeline_cgnapt_be.c @@ -10469,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; @@ -10481,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]; @@ -10493,43 +10493,43 @@ void all_cgnapt_stats(void) enaptedPktCount += p_nat->enaptedPktCount; arpicmpPktCount += p_nat->arpicmpPktCount; - 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); #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); @@ -10537,32 +10537,35 @@ void all_cgnapt_stats(void) } - printf("\nTotal pipeline stats:\n"); - printf("Received %" PRIu64 ",", receivedPktCount); - printf("Missed %" PRIu64 ",", missedPktCount); - printf("Dropped %" PRIu64 ",", naptDroppedPktCount); - printf("Translated %" PRIu64 ",", naptedPktCount); - printf("ingress %" PRIu64 ",", inaptedPktCount); - printf("egress %" PRIu64 "\n", enaptedPktCount); - printf("arpicmp pkts %" PRIu64 "\n", arpicmpPktCount); + 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); + + 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; @@ -10573,38 +10576,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_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 1e79646d..b011eca2 100644 --- a/VNFs/vFW/Makefile +++ b/VNFs/vFW/Makefile @@ -66,9 +66,15 @@ 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 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/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 + |