From 72adc18af784915e7cc4c207655a38e49e33232e Mon Sep 17 00:00:00 2001 From: Jett Jacobs <62487934+jettjacobs@users.noreply.github.com> Date: Mon, 27 Sep 2021 13:44:01 -0400 Subject: [PATCH 01/13] Added Skeleton NF --- examples/skeleton/Makefile | 67 +++++++++ examples/skeleton/README.md | 31 ++++ examples/skeleton/go.sh | 20 +++ examples/skeleton/skeleton.c | 282 +++++++++++++++++++++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 examples/skeleton/Makefile create mode 100644 examples/skeleton/README.md create mode 100644 examples/skeleton/go.sh create mode 100644 examples/skeleton/skeleton.c diff --git a/examples/skeleton/Makefile b/examples/skeleton/Makefile new file mode 100644 index 000000000..edd7e5211 --- /dev/null +++ b/examples/skeleton/Makefile @@ -0,0 +1,67 @@ +# openNetVM +# https://github.com/sdnfv/openNetVM +# +# BSD LICENSE +# +# Copyright(c) +# 2015-2017 George Washington University +# 2015-2017 University of California Riverside +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# The name of the author may not be used to endorse or promote +# products derived from this software without specific prior +# written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + + +# Default target, can be overriden by command line or environment +include $(RTE_SDK)/mk/rte.vars.mk +RTE_TARGET ?= x86_64-native-linuxapp-gcc + +# binary name +APP = skeleton + +# all source are stored in SRCS-y +SRCS-y := skeleton.c + +ONVM= $(SRCDIR)/../../onvm + +CFLAGS += $(WERROR_FLAGS) -O3 $(USER_FLAGS) + +CFLAGS += -I$(ONVM)/onvm_nflib +CFLAGS += -I$(ONVM)/lib +LDFLAGS += $(ONVM)/onvm_nflib/$(RTE_TARGET)/libonvm.a +LDFLAGS += $(ONVM)/lib/$(RTE_TARGET)/lib/libonvmhelper.a -lm + +# workaround for a gcc bug with noreturn attribute +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) +CFLAGS_main.o += -Wno-return-type +endif + +include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/skeleton/README.md b/examples/skeleton/README.md new file mode 100644 index 000000000..bef504178 --- /dev/null +++ b/examples/skeleton/README.md @@ -0,0 +1,31 @@ +Skeleton +== +This is an example NF that acts as a basic skeleton NF. + +Compilation and Execution +-- +``` +cd examples +make +cd skeleton +./go.sh SERVICE_ID [PRINT_DELAY] + +OR + +./go.sh -F CONFIG_FILE -- -- [-p PRINT_DELAY] + +OR + +sudo ./build/skeleton -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- [-p PRINT_DELAY] +``` + +App Specific Arguments +-- + - `-p `: number of packets between each print, e.g. `-p 1` prints every packets. + +Config File Support +-- +This NF supports the NF generating arguments from a config file. For +additional reading, see [Examples.md](../../docs/Examples.md) + +See `../example_config.json` for all possible options that can be set. diff --git a/examples/skeleton/go.sh b/examples/skeleton/go.sh new file mode 100644 index 000000000..03fc3bb36 --- /dev/null +++ b/examples/skeleton/go.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +#The go.sh script is a convinient way to run start_nf.sh without specifying NF_NAME + +NF_DIR=${PWD##*/} + +if [ ! -f ../start_nf.sh ]; then + echo "ERROR: The ./go.sh script can only be used from the NF folder" + echo "If running from other directory use examples/start_nf.sh" + exit 1 +fi + +# only check for running manager if not in Docker +if [[ -z $(pgrep -u root -f "/onvm/onvm_mgr/.*/onvm_mgr") ]] && ! grep -q "docker" /proc/1/cgroup +then + echo "NF cannot start without a running manager" + exit 1 +fi + +../start_nf.sh "$NF_DIR" "$@" diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c new file mode 100644 index 000000000..85349e6eb --- /dev/null +++ b/examples/skeleton/skeleton.c @@ -0,0 +1,282 @@ +/********************************************************************* + * openNetVM + * https://sdnfv.github.io + * + * BSD LICENSE + * + * Copyright(c) + * 2015-2021 George Washington University + * 2015-2021 University of California Riverside + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * skeleton.c - Template NF for development. + ********************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "onvm_nflib.h" +#include "onvm_pkt_helper.h" + +// Define NF Tag Appropriately +#define NF_TAG "skeleton" + +/* number of package between each print */ +static uint32_t print_delay = 1000000; + +// State structs hold any variables which are universal to all files within the NF +// The following struct is an example from text_messaging NF: +struct skeleton_state { + // Insert stored data which is not specific to any function (similar to global data) + int tests_passed; + int test_phase; + int test_msg_count; + int ring_count; + int mempool_count; + uint16_t address; + struct rte_mempool* msg_pool; + struct rte_ring *msg_q; + int test_status[3]; + uint64_t start_time; +}; + +/* + * Print a usage message + */ +static void +usage(const char *progname) { + printf("Usage:\n"); + printf("%s [EAL args] -- [NF_LIB args] -- -p \n", progname); + printf("%s -F [EAL args] -- [NF_LIB args] -- [NF args]\n\n", progname); + printf("Flags:\n"); + printf(" - `-p `: number of packets between each print, e.g. `-p 1` prints every packets.\n"); +} + +/* + * Parse the application arguments. + */ +static int +parse_app_args(int argc, char *argv[], const char *progname) { + int c; + + // Handles command line arguments + while ((c = getopt(argc, argv, "p:")) != -1) { + switch (c) { + case 'p': + print_delay = strtoul(optarg, NULL, 10); + break; + case '?': + usage(progname); + if (optopt == 'p') + RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); + else if (isprint(optopt)) + RTE_LOG(INFO, APP, "Unknown option `-%c'.\n", optopt); + else + RTE_LOG(INFO, APP, "Unknown option character `\\x%x'.\n", optopt); + return -1; + default: + usage(progname); + return -1; + } + } + return optind; +} + +// Function for NF with displays - Example from bridge.c +static void +do_stats_display(struct rte_mbuf *pkt) { + + // [EDIT CODE IF NF USES DISPLAY] + + const char clr[] = {27, '[', '2', 'J', '\0'}; + const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; + static uint64_t pkt_process = 0; + + struct rte_ipv4_hdr *ip; + + pkt_process += print_delay; + + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); + + printf("PACKETS\n"); + printf("-----\n"); + printf("Port : %d\n", pkt->port); + printf("Size : %d\n", pkt->pkt_len); + printf("Type : %d\n", pkt->packet_type); + printf("Number of packet processed : %" PRIu64 "\n", pkt_process); + + ip = onvm_pkt_ipv4_hdr(pkt); + if (ip != NULL) { + onvm_pkt_print(pkt); + } else { + printf("Not IP4\n"); + } + + printf("\n\n"); +} + + +static int +packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, + __attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx) { + + // Timed display counter - keep/edit if NF uses display + static uint32_t counter = 0; + if (counter++ == print_delay) { + do_stats_display(pkt); + counter = 0; + } + + // [EDIT PACKET HANDLER CODE BELOW] + + /* Important Variables + meta->action + Defines what to do with the packet. Actions defined in onvm_common.h + meta->destination + Defines the service ID of the NF which will receive the packet. + */ + if (pkt->port == 0) { + meta->destination = 1; + } else { + meta->destination = 0; + } + + // Send the packet out of the NIC port + meta->action = ONVM_NF_ACTION_OUT; + + // Return 0 on success, -1 on failure + return 0; +} + +static int +action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ + + // Gets called every run loop even if there weren't any packets + + // [ADD ACTION CODE] - Remove __attribute__((unused)) + return 0; +} + +static void +setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ + + // Gets called once before NF will get any packets/messages + + // Excerpt from text_messaging setup; note nf_local_ctx->nf->data with corresponding struct + struct rte_mempool *pktmbuf_pool; + struct test_msg_data *test_state; + static struct rte_mempool *nf_msg_pool; + pktmbuf_pool = rte_mempool_lookup(PKTMBUF_POOL_NAME); + if (pktmbuf_pool == NULL) { + onvm_nflib_stop(nf_local_ctx); + rte_exit(EXIT_FAILURE, "Cannot find mbuf pool!\n"); + } + nf_msg_pool = rte_mempool_lookup(_NF_MSG_POOL_NAME); + if (nf_msg_pool == NULL) + rte_exit(EXIT_FAILURE, "No NF Message mempool - bye\n"); + + nf_local_ctx->nf->data = (void *)test_state; + + // [REMOVE EXCERPT, ADD SETUP CODE] +} + +static void +handle_msg(__attribute__((unused))void *msg_data, __attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx) { + + // Gets called if there is a message sent to the NF + + // [ADD MESSAGE HANDLER CODE] - Remove __attribute__((unused)) +} + +int +main(int argc, char *argv[]) { + + // Handles command line arguments + int arg_offset; + // Local context holds NF and status + struct onvm_nf_local_ctx *nf_local_ctx; + // Function table holds pointers to NF setup, msg_handler, user_actions, and pkt_handler + struct onvm_nf_function_table *nf_function_table; + // Handles command line arguments + const char *progname = argv[0]; + + // Initializing local context and start default signal handler + nf_local_ctx = onvm_nflib_init_nf_local_ctx(); + onvm_nflib_start_signal_handler(nf_local_ctx, NULL); + + // [EDIT FUNCTION TABLE AS NEEDED] + // Address declarations of NF functions for function table: + nf_function_table = onvm_nflib_init_nf_function_table(); + nf_function_table->pkt_handler = &packet_handler; + nf_function_table->setup = &setup; + nf_function_table->user_actions = &action; + nf_function_table->msg_handler = &handle_msg; + + // If a termination signal is received or initiation is interrupted, exit + if ((arg_offset = onvm_nflib_init(argc, argv, NF_TAG, nf_local_ctx, nf_function_table)) < 0) { + onvm_nflib_stop(nf_local_ctx); + if (arg_offset == ONVM_SIGNAL_TERMINATION) { + printf("Exiting due to user termination\n"); + return 0; + } else { + rte_exit(EXIT_FAILURE, "Failed ONVM init\n"); + } + } + + // Command line arguments + argc -= arg_offset; + argv += arg_offset; + + // Invalid command-line argument handling + if (parse_app_args(argc, argv, progname) < 0) { + onvm_nflib_stop(nf_local_ctx); + rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); + } + + // Begin running NF + onvm_nflib_run(nf_local_ctx); + + // Once the NF has stopped running, free and stop + onvm_nflib_stop(nf_local_ctx); + printf("If we reach here, program is ending\n"); + return 0; +} From d5600b0d71a4df306d0808e7f0fd28722c3dd7db Mon Sep 17 00:00:00 2001 From: Jett Jacobs <62487934+jettjacobs@users.noreply.github.com> Date: Mon, 27 Sep 2021 13:46:30 -0400 Subject: [PATCH 02/13] Update Makefile --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index 3ce592312..9e6c92872 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -40,7 +40,7 @@ $(error "Please define RTE_SDK environment variable") endif # To add new examples, append the directory name to this variable -examples = bridge basic_monitor simple_forward speed_tester flow_table test_flow_dir aes_encrypt aes_decrypt flow_tracker load_balancer arp_response nf_router scaling_example load_generator payload_scan firewall simple_fwd_tb l2fwd +examples = bridge basic_monitor simple_forward speed_tester flow_table test_flow_dir aes_encrypt aes_decrypt flow_tracker load_balancer arp_response nf_router scaling_example load_generator payload_scan firewall simple_fwd_tb l2fwd skeleton ifeq ($(NDPI_HOME),) $(warning "Skipping ndpi_stats NF as NDPI_HOME is not set") From b7efec66d53ac9263e40f339102f8ba0c5da6a4d Mon Sep 17 00:00:00 2001 From: Jett Jacobs <62487934+jettjacobs@users.noreply.github.com> Date: Mon, 27 Sep 2021 14:21:51 -0400 Subject: [PATCH 03/13] Update skeleton.c --- examples/skeleton/skeleton.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 85349e6eb..33d4f5004 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -63,7 +63,7 @@ static uint32_t print_delay = 1000000; // State structs hold any variables which are universal to all files within the NF -// The following struct is an example from text_messaging NF: +// The following struct is an example from test_messaging NF: struct skeleton_state { // Insert stored data which is not specific to any function (similar to global data) int tests_passed; @@ -201,7 +201,7 @@ setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ // Gets called once before NF will get any packets/messages - // Excerpt from text_messaging setup; note nf_local_ctx->nf->data with corresponding struct + // Excerpt from test_messaging setup; note nf_local_ctx->nf->data with corresponding struct struct rte_mempool *pktmbuf_pool; struct test_msg_data *test_state; static struct rte_mempool *nf_msg_pool; From 80fc4755ac0e96e9d25997eb75e03331f9bce75c Mon Sep 17 00:00:00 2001 From: Jett Jacobs Date: Sat, 2 Oct 2021 13:54:30 -0400 Subject: [PATCH 04/13] Skeleton NF 1.2 --- examples/skeleton/skeleton.c | 59 ++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 33d4f5004..8f7f99a16 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -76,6 +76,7 @@ struct skeleton_state { struct rte_ring *msg_q; int test_status[3]; uint64_t start_time; + uint32_t counter; }; /* @@ -155,12 +156,16 @@ do_stats_display(struct rte_mbuf *pkt) { } +// Gets called every time a packet arrives static int packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, __attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx) { - // Timed display counter - keep/edit if NF uses display - static uint32_t counter = 0; + /* + Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) + After the reception of each packet, the counter is incremented. Once we reach a defined + number of packets, display and reset the counter + */ if (counter++ == print_delay) { do_stats_display(pkt); counter = 0; @@ -174,49 +179,57 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, meta->destination Defines the service ID of the NF which will receive the packet. */ + + /* Skeleton NF simply bridges two ports, swapping packets between them. [APP LOGIC HERE] */ + if (pkt->port == 0) { meta->destination = 1; } else { meta->destination = 0; } - // Send the packet out of the NIC port + // Specify an action meta->action = ONVM_NF_ACTION_OUT; + + /* ONVM_NF_ACTION_* Options + ONVM_NF_ACTION_DROP - drop packet + NVM_NF_ACTION_NEXT - to whatever the next action is configured by the SDN controller in the flow table + ONVM_NF_ACTION_TONF - send to the NF specified in the argument field (assume it is on the same host) + ONVM_NF_ACTION_OUT - send the packet out the NIC port set in the argument field + */ // Return 0 on success, -1 on failure return 0; } +// Gets called every run loop even if there weren't any packets static int action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ - // Gets called every run loop even if there weren't any packets - // [ADD ACTION CODE] - Remove __attribute__((unused)) return 0; } +// Gets called once before NF will get any packets/messages static void setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ - // Gets called once before NF will get any packets/messages - - // Excerpt from test_messaging setup; note nf_local_ctx->nf->data with corresponding struct - struct rte_mempool *pktmbuf_pool; - struct test_msg_data *test_state; - static struct rte_mempool *nf_msg_pool; - pktmbuf_pool = rte_mempool_lookup(PKTMBUF_POOL_NAME); - if (pktmbuf_pool == NULL) { - onvm_nflib_stop(nf_local_ctx); - rte_exit(EXIT_FAILURE, "Cannot find mbuf pool!\n"); - } - nf_msg_pool = rte_mempool_lookup(_NF_MSG_POOL_NAME); - if (nf_msg_pool == NULL) - rte_exit(EXIT_FAILURE, "No NF Message mempool - bye\n"); - - nf_local_ctx->nf->data = (void *)test_state; - - // [REMOVE EXCERPT, ADD SETUP CODE] + // Declare and initialize struct skeleton_state to hold all data within the NF. + // Assign the nf_local_ctx->nf->data pointer to the struct. + // Initialize packet counter + struct skeleton_state *skeleton_data; + skeleton_data = (struct skeleton_state *) rte_zmalloc ("skeleton", sizeof(struct skeleton_state), 0); + nf_local_ctx->nf->data = (void *) skeleton_data; + nf_local_ctx->nf->data->counter = 0; + + /* + void* rte_malloc + const char * type, A string identifying the type of allocated objects. Can be NULL. + size_t size, Size (in bytes) to be allocated. + unsigned align If 0, the return is a pointer that is suitably aligned for any kind of variable + */ +) + // [ADD SETUP CODE] } static void From d5d1c8fcf230b351e0ef16ec391a9a31220c48a2 Mon Sep 17 00:00:00 2001 From: Jett Jacobs Date: Fri, 8 Oct 2021 13:42:01 -0400 Subject: [PATCH 05/13] Skeleton NF 1.3 --- examples/skeleton/Makefile | 2 +- examples/skeleton/skeleton.c | 161 ++++++++++++++++++----------------- 2 files changed, 85 insertions(+), 78 deletions(-) diff --git a/examples/skeleton/Makefile b/examples/skeleton/Makefile index edd7e5211..6505a1485 100644 --- a/examples/skeleton/Makefile +++ b/examples/skeleton/Makefile @@ -43,7 +43,7 @@ endif include $(RTE_SDK)/mk/rte.vars.mk RTE_TARGET ?= x86_64-native-linuxapp-gcc -# binary name +# binary name [EDIT & ADD NF TAG TO "examples" VARIABLE WITHIN MAKEFILE OF EXAMPLES DIRECTORY] APP = skeleton # all source are stored in SRCS-y diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 8f7f99a16..c31bb24a7 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -35,7 +35,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * skeleton.c - Template NF for development. + * skeleton.c - Template NF for development. [EDIT] ********************************************************************/ #include @@ -56,25 +56,20 @@ #include "onvm_nflib.h" #include "onvm_pkt_helper.h" -// Define NF Tag Appropriately +// Define NF Tag Appropriately [EDIT] #define NF_TAG "skeleton" -/* number of package between each print */ -static uint32_t print_delay = 1000000; - -// State structs hold any variables which are universal to all files within the NF -// The following struct is an example from test_messaging NF: +/* + * State structs [EDIT] + * Holds any variables which are universal to all files within the NF + * Listed below are common variables used within the struct + */ struct skeleton_state { - // Insert stored data which is not specific to any function (similar to global data) int tests_passed; int test_phase; - int test_msg_count; - int ring_count; - int mempool_count; + int pkt_process uint16_t address; - struct rte_mempool* msg_pool; - struct rte_ring *msg_q; - int test_status[3]; + uint32_t print_delay; uint64_t start_time; uint32_t counter; }; @@ -85,7 +80,9 @@ struct skeleton_state { static void usage(const char *progname) { printf("Usage:\n"); - printf("%s [EAL args] -- [NF_LIB args] -- -p \n", progname); + printf("%s [EAL args] -- [NF_LIB args]\n", progname); + + // Additional Usage Messages [EDIT] printf("%s -F [EAL args] -- [NF_LIB args] -- [NF args]\n\n", progname); printf("Flags:\n"); printf(" - `-p `: number of packets between each print, e.g. `-p 1` prints every packets.\n"); @@ -98,7 +95,6 @@ static int parse_app_args(int argc, char *argv[], const char *progname) { int c; - // Handles command line arguments while ((c = getopt(argc, argv, "p:")) != -1) { switch (c) { case 'p': @@ -121,19 +117,20 @@ parse_app_args(int argc, char *argv[], const char *progname) { return optind; } -// Function for NF with displays - Example from bridge.c +/* + * Function for NFs with Displays + * [EDIT IF NF USES DISPLAY; ELSE DELETE] + */ static void do_stats_display(struct rte_mbuf *pkt) { - // [EDIT CODE IF NF USES DISPLAY] - const char clr[] = {27, '[', '2', 'J', '\0'}; const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; - static uint64_t pkt_process = 0; + skeleton_data->pkt_process = 0; struct rte_ipv4_hdr *ip; - pkt_process += print_delay; + skeleton_data->pkt_process += skeleton_data->print_delay; /* Clear screen and move to top left */ printf("%s%s", clr, topLeft); @@ -156,31 +153,29 @@ do_stats_display(struct rte_mbuf *pkt) { } -// Gets called every time a packet arrives +/* + * Handles each packet upon arrival [EDIT] + */ static int packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, __attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx) { /* - Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) - After the reception of each packet, the counter is incremented. Once we reach a defined - number of packets, display and reset the counter - */ + * Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) + * After the reception of each packet, the counter is incremented. Once we reach a defined + * number of packets, display and reset the counter + */ if (counter++ == print_delay) { do_stats_display(pkt); counter = 0; } - - // [EDIT PACKET HANDLER CODE BELOW] - /* Important Variables - meta->action - Defines what to do with the packet. Actions defined in onvm_common.h - meta->destination - Defines the service ID of the NF which will receive the packet. - */ - - /* Skeleton NF simply bridges two ports, swapping packets between them. [APP LOGIC HERE] */ + /* + * meta->action + * Defines what to do with the packet. Actions defined in onvm_common.h + * meta->destination + * Defines the service ID of the NF which will receive the packet. + */ if (pkt->port == 0) { meta->destination = 1; @@ -188,83 +183,95 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, meta->destination = 0; } - // Specify an action + /* + * Specify an action: + * ONVM_NF_ACTION_DROP - Drop packet + * NVM_NF_ACTION_NEXT - Go to whatever the next action is configured by the SDN controller in the flow table + * ONVM_NF_ACTION_TONF - Send the packet to the NF specified in the argument field (assume it is on the same host) + * ONVM_NF_ACTION_OUT - Send the packet out the NIC port set in the argument field + */ meta->action = ONVM_NF_ACTION_OUT; - - /* ONVM_NF_ACTION_* Options - ONVM_NF_ACTION_DROP - drop packet - NVM_NF_ACTION_NEXT - to whatever the next action is configured by the SDN controller in the flow table - ONVM_NF_ACTION_TONF - send to the NF specified in the argument field (assume it is on the same host) - ONVM_NF_ACTION_OUT - send the packet out the NIC port set in the argument field - */ - - // Return 0 on success, -1 on failure + + /* Return 0 on success, -1 on failure */ return 0; } -// Gets called every run loop even if there weren't any packets +/* + * Performs action continuously; called every run loop regardless of packet reception [EDIT] + */ static int action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ - // [ADD ACTION CODE] - Remove __attribute__((unused)) + /* Remove __attribute__((unused)) once implemented */ + return 0; } -// Gets called once before NF will get any packets/messages +/* + * Initial setup function; called before NF receives any packets/messages [EDIT] + */ static void setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ - // Declare and initialize struct skeleton_state to hold all data within the NF. - // Assign the nf_local_ctx->nf->data pointer to the struct. - // Initialize packet counter + /* + * (1) Declare and initialize state struct to hold non-local data within the NF. Use rte_zmalloc + * void * rte_zmalloc (const char * type, size_t size, unsigned align) + * type: A string identifying the type of allocated objects. Can be NULL. + * size: Size (in bytes) to be allocated. + * align: If 0, the return is a pointer that is suitably aligned for any kind of variable + * (2) Assign the nf_local_ctx->nf->data pointer to the struct. + * (3) Initialize other predefined data or counters; examples include: + * nf_local_ctx->nf->data->counter = 0; + * skeleton_data->print_delay = 10000 + */ + struct skeleton_state *skeleton_data; skeleton_data = (struct skeleton_state *) rte_zmalloc ("skeleton", sizeof(struct skeleton_state), 0); nf_local_ctx->nf->data = (void *) skeleton_data; - nf_local_ctx->nf->data->counter = 0; - - /* - void* rte_malloc - const char * type, A string identifying the type of allocated objects. Can be NULL. - size_t size, Size (in bytes) to be allocated. - unsigned align If 0, the return is a pointer that is suitably aligned for any kind of variable - */ -) - // [ADD SETUP CODE] } +/* + * Handles each message upon arrival [EDIT] + */ static void handle_msg(__attribute__((unused))void *msg_data, __attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx) { - // Gets called if there is a message sent to the NF - - // [ADD MESSAGE HANDLER CODE] - Remove __attribute__((unused)) + /* Remove __attribute__((unused)) once implemented */ + } +/* + * Creates function table and local context. Runs NF. + */ int main(int argc, char *argv[]) { - // Handles command line arguments + /* Handles command line arguments */ int arg_offset; - // Local context holds NF and status + + /* Local context holds NF and status */ struct onvm_nf_local_ctx *nf_local_ctx; - // Function table holds pointers to NF setup, msg_handler, user_actions, and pkt_handler + + /* Declare function table: Holds pointers to the NF methods - setup, msg_handler, user_actions, and pkt_handler */ struct onvm_nf_function_table *nf_function_table; - // Handles command line arguments + + /* Handles command line arguments */ const char *progname = argv[0]; - // Initializing local context and start default signal handler + /* Initialize local context and start default signal handler */ nf_local_ctx = onvm_nflib_init_nf_local_ctx(); onvm_nflib_start_signal_handler(nf_local_ctx, NULL); - // [EDIT FUNCTION TABLE AS NEEDED] - // Address declarations of NF functions for function table: + /* Initialize function table and respective pointers to NF methods: + * [EDIT] + */ nf_function_table = onvm_nflib_init_nf_function_table(); nf_function_table->pkt_handler = &packet_handler; nf_function_table->setup = &setup; nf_function_table->user_actions = &action; nf_function_table->msg_handler = &handle_msg; - // If a termination signal is received or initiation is interrupted, exit + /* If a termination signal is received or initiation is interrupted, exit */ if ((arg_offset = onvm_nflib_init(argc, argv, NF_TAG, nf_local_ctx, nf_function_table)) < 0) { onvm_nflib_stop(nf_local_ctx); if (arg_offset == ONVM_SIGNAL_TERMINATION) { @@ -275,20 +282,20 @@ main(int argc, char *argv[]) { } } - // Command line arguments + /* Command line arguments */ argc -= arg_offset; argv += arg_offset; - // Invalid command-line argument handling + /* Invalid command-line argument handling */ if (parse_app_args(argc, argv, progname) < 0) { onvm_nflib_stop(nf_local_ctx); rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); } - // Begin running NF + /* Begin running NF */ onvm_nflib_run(nf_local_ctx); - // Once the NF has stopped running, free and stop + /* Once the NF has stopped running, free and stop */ onvm_nflib_stop(nf_local_ctx); printf("If we reach here, program is ending\n"); return 0; From 322dee45f9d79f9491b5ba2fc5e5534df6b72ae7 Mon Sep 17 00:00:00 2001 From: Jett Jacobs Date: Fri, 8 Oct 2021 13:43:39 -0400 Subject: [PATCH 06/13] Comment Adjustment --- examples/skeleton/skeleton.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index c31bb24a7..4be1175c9 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -262,9 +262,7 @@ main(int argc, char *argv[]) { nf_local_ctx = onvm_nflib_init_nf_local_ctx(); onvm_nflib_start_signal_handler(nf_local_ctx, NULL); - /* Initialize function table and respective pointers to NF methods: - * [EDIT] - */ + /* Initialize function table and respective pointers to NF methods: */ nf_function_table = onvm_nflib_init_nf_function_table(); nf_function_table->pkt_handler = &packet_handler; nf_function_table->setup = &setup; From b37b0099a311830063afb5d81e86bedaf915f194 Mon Sep 17 00:00:00 2001 From: Jett Jacobs Date: Fri, 8 Oct 2021 13:51:55 -0400 Subject: [PATCH 07/13] Comment Adjustment 2 --- examples/skeleton/skeleton.c | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 4be1175c9..2d8f76246 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -177,6 +177,7 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, * Defines the service ID of the NF which will receive the packet. */ + /* The following example bridges two ports, swapping packets between them. [EDIT APP LOGIC BELOW] */ if (pkt->port == 0) { meta->destination = 1; } else { From 0e37e189f4b176250417617896454475c598a079 Mon Sep 17 00:00:00 2001 From: Jett Jacobs Date: Fri, 8 Oct 2021 13:58:25 -0400 Subject: [PATCH 08/13] Comment Adjustment 3 --- examples/skeleton/skeleton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 2d8f76246..29447af1d 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -177,7 +177,7 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, * Defines the service ID of the NF which will receive the packet. */ - /* The following example bridges two ports, swapping packets between them. [EDIT APP LOGIC BELOW] */ + /* The following example bridges two ports, swapping packets between them. [EDIT] */ if (pkt->port == 0) { meta->destination = 1; } else { From b67c270b51d803d4c22689d99a71d407b8a853b3 Mon Sep 17 00:00:00 2001 From: jett Date: Wed, 13 Oct 2021 15:39:57 -0500 Subject: [PATCH 09/13] modified skeleton --- examples/skeleton/go.sh | 0 examples/skeleton/skeleton.c | 144 +++++++++++++++++++---------------- 2 files changed, 77 insertions(+), 67 deletions(-) mode change 100644 => 100755 examples/skeleton/go.sh diff --git a/examples/skeleton/go.sh b/examples/skeleton/go.sh old mode 100644 new mode 100755 diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 29447af1d..97edf0cd4 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -52,6 +52,7 @@ #include #include #include +#include #include "onvm_nflib.h" #include "onvm_pkt_helper.h" @@ -65,13 +66,10 @@ * Listed below are common variables used within the struct */ struct skeleton_state { - int tests_passed; - int test_phase; - int pkt_process - uint16_t address; - uint32_t print_delay; + uint64_t start_time; - uint32_t counter; + uint32_t print_delay; + // uint32_t counter; }; /* @@ -97,9 +95,9 @@ parse_app_args(int argc, char *argv[], const char *progname) { while ((c = getopt(argc, argv, "p:")) != -1) { switch (c) { - case 'p': - print_delay = strtoul(optarg, NULL, 10); - break; + // case 'p': + // print_delay = strtoul(optarg, NULL, 10); + // break; case '?': usage(progname); if (optopt == 'p') @@ -121,80 +119,83 @@ parse_app_args(int argc, char *argv[], const char *progname) { * Function for NFs with Displays * [EDIT IF NF USES DISPLAY; ELSE DELETE] */ -static void -do_stats_display(struct rte_mbuf *pkt) { +// static void +// do_stats_display(struct rte_mbuf *pkt) { - const char clr[] = {27, '[', '2', 'J', '\0'}; - const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; - skeleton_data->pkt_process = 0; +// const char clr[] = {27, '[', '2', 'J', '\0'}; +// const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; +// static uint64_t pkt_process = 0; - struct rte_ipv4_hdr *ip; +// struct rte_ipv4_hdr *ip; - skeleton_data->pkt_process += skeleton_data->print_delay; +// pkt_process += 1000000; - /* Clear screen and move to top left */ - printf("%s%s", clr, topLeft); +// /* Clear screen and move to top left */ +// printf("%s%s", clr, topLeft); - printf("PACKETS\n"); - printf("-----\n"); - printf("Port : %d\n", pkt->port); - printf("Size : %d\n", pkt->pkt_len); - printf("Type : %d\n", pkt->packet_type); - printf("Number of packet processed : %" PRIu64 "\n", pkt_process); +// printf("PACKETS\n"); +// printf("-----\n"); +// printf("Port : %d\n", pkt->port); +// printf("Size : %d\n", pkt->pkt_len); +// printf("Type : %d\n", pkt->packet_type); +// printf("Number of packet processed : %" PRIu64 "\n", pkt_process); - ip = onvm_pkt_ipv4_hdr(pkt); - if (ip != NULL) { - onvm_pkt_print(pkt); - } else { - printf("Not IP4\n"); - } +// ip = onvm_pkt_ipv4_hdr(pkt); +// if (ip != NULL) { +// onvm_pkt_print(pkt); +// } else { +// printf("Not IP4\n"); +// } - printf("\n\n"); -} +// printf("\n\n"); +// } /* * Handles each packet upon arrival [EDIT] */ static int -packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, +packet_handler(__attribute__((unused))struct rte_mbuf *pkt, __attribute__((unused)) struct onvm_pkt_meta *meta, __attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx) { - /* - * Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) - * After the reception of each packet, the counter is incremented. Once we reach a defined - * number of packets, display and reset the counter - */ - if (counter++ == print_delay) { - do_stats_display(pkt); - counter = 0; - } + meta->action = ONVM_NF_ACTION_DROP; + return 0; - /* - * meta->action - * Defines what to do with the packet. Actions defined in onvm_common.h - * meta->destination - * Defines the service ID of the NF which will receive the packet. - */ - - /* The following example bridges two ports, swapping packets between them. [EDIT] */ - if (pkt->port == 0) { - meta->destination = 1; - } else { - meta->destination = 0; - } + // /* + // * Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) + // * After the reception of each packet, the counter is incremented. Once we reach a defined + // * number of packets, display and reset the counter + // */ + // if (counter++ == print_delay) { + // do_stats_display(pkt); + // counter = 0; + // } - /* - * Specify an action: - * ONVM_NF_ACTION_DROP - Drop packet - * NVM_NF_ACTION_NEXT - Go to whatever the next action is configured by the SDN controller in the flow table - * ONVM_NF_ACTION_TONF - Send the packet to the NF specified in the argument field (assume it is on the same host) - * ONVM_NF_ACTION_OUT - Send the packet out the NIC port set in the argument field - */ - meta->action = ONVM_NF_ACTION_OUT; - - /* Return 0 on success, -1 on failure */ - return 0; + // /* + // * meta->action + // * Defines what to do with the packet. Actions defined in onvm_common.h + // * meta->destination + // * Defines the service ID of the NF which will receive the packet. + // */ + + // /* The following example bridges two ports, swapping packets between them. [EDIT] */ + // if (pkt->port == 0) { + // meta->destination = 1; + // } else { + // meta->destination = 0; + // } + + // /* + // * Specify an action: + // * ONVM_NF_ACTION_DROP - Drop packet + // * NVM_NF_ACTION_NEXT - Go to whatever the next action is configured by the SDN controller in the flow table + // * ONVM_NF_ACTION_TONF - Send the packet to the NF specified in the argument field (assume it is on the same host) + // * ONVM_NF_ACTION_OUT - Send the packet out the NIC port set in the argument field + // */ + // meta->action = ONVM_NF_ACTION_OUT; + + // /* Return 0 on success, -1 on failure */ + // return 0; } /* @@ -203,7 +204,13 @@ packet_handler(struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, static int action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ - /* Remove __attribute__((unused)) once implemented */ + struct skeleton_state *skeleton_data; + skeleton_data = (struct skeleton_state *)nf_local_ctx->nf->data; + + __uint64_t time = (rte_get_tsc_cycles() - skeleton_data->start_time) / rte_get_timer_hz(); + if (time%5 == 0) { + printf("%ld\n",time); + } return 0; } @@ -229,6 +236,9 @@ setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ struct skeleton_state *skeleton_data; skeleton_data = (struct skeleton_state *) rte_zmalloc ("skeleton", sizeof(struct skeleton_state), 0); nf_local_ctx->nf->data = (void *) skeleton_data; + + skeleton_data->start_time = rte_get_tsc_cycles(); + skeleton_data->print_delay = 5; } /* From 6fdcc09a76562065dde6ca9d911485d0779120ea Mon Sep 17 00:00:00 2001 From: jett Date: Fri, 29 Oct 2021 12:22:12 -0600 Subject: [PATCH 10/13] Added timer/packet-based print counters --- examples/skeleton/skeleton.c | 185 ++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 91 deletions(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 97edf0cd4..0ef834417 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -67,9 +67,11 @@ */ struct skeleton_state { + int displayType; uint64_t start_time; - uint32_t print_delay; - // uint32_t counter; + uint32_t delay; + uint32_t current_time; + uint32_t packets_processed; }; /* @@ -83,21 +85,29 @@ usage(const char *progname) { // Additional Usage Messages [EDIT] printf("%s -F [EAL args] -- [NF_LIB args] -- [NF args]\n\n", progname); printf("Flags:\n"); - printf(" - `-p `: number of packets between each print, e.g. `-p 1` prints every packets.\n"); + printf(" - `-p `: number of packets between each print, e.g. `-p 1` prints every packets.\n"); } /* * Parse the application arguments. */ static int -parse_app_args(int argc, char *argv[], const char *progname) { +parse_app_args(int argc, char *argv[], const char *progname, struct skeleton_state *skeleton_data) { int c; - - while ((c = getopt(argc, argv, "p:")) != -1) { + + /* User can specify how they would like to display data. */ + + skeleton_data->displayType = -1; // displayType -1 = No Display + while ((c = getopt(argc, argv, "p:v:")) != -1) { switch (c) { - // case 'p': - // print_delay = strtoul(optarg, NULL, 10); - // break; + case 'p': + skeleton_data->delay = strtoul(optarg, NULL, 10); + skeleton_data->displayType = 0; // displayType 0 = Time-Based Delays + break; + case 'v': + skeleton_data->delay = strtoul(optarg, NULL, 10); + skeleton_data->displayType = 1; // displayType 1 = Packet-Based Delays + break; case '?': usage(progname); if (optopt == 'p') @@ -119,99 +129,89 @@ parse_app_args(int argc, char *argv[], const char *progname) { * Function for NFs with Displays * [EDIT IF NF USES DISPLAY; ELSE DELETE] */ -// static void -// do_stats_display(struct rte_mbuf *pkt) { +static void +do_stats_display(struct skeleton_state *skeleton_data) { -// const char clr[] = {27, '[', '2', 'J', '\0'}; -// const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; -// static uint64_t pkt_process = 0; - -// struct rte_ipv4_hdr *ip; - -// pkt_process += 1000000; + const char clr[] = {27, '[', '2', 'J', '\0'}; + const char topLeft[] = {27, '[', '1', ';', '1', 'H', '\0'}; -// /* Clear screen and move to top left */ -// printf("%s%s", clr, topLeft); + /* Clear screen and move to top left */ + printf("%s%s", clr, topLeft); -// printf("PACKETS\n"); -// printf("-----\n"); -// printf("Port : %d\n", pkt->port); -// printf("Size : %d\n", pkt->pkt_len); -// printf("Type : %d\n", pkt->packet_type); -// printf("Number of packet processed : %" PRIu64 "\n", pkt_process); + printf("PACKETS\n"); + printf("-----\n"); + printf("Number of packet processed : %d\n", skeleton_data->packets_processed); + printf("Time : %d\n", skeleton_data->current_time); -// ip = onvm_pkt_ipv4_hdr(pkt); -// if (ip != NULL) { -// onvm_pkt_print(pkt); -// } else { -// printf("Not IP4\n"); -// } - -// printf("\n\n"); -// } + printf("\n\n"); +} /* * Handles each packet upon arrival [EDIT] */ static int -packet_handler(__attribute__((unused))struct rte_mbuf *pkt, __attribute__((unused)) struct onvm_pkt_meta *meta, - __attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx) { +packet_handler(__attribute__((unused)) struct rte_mbuf *pkt, struct onvm_pkt_meta *meta, + struct onvm_nf_local_ctx *nf_local_ctx) { - meta->action = ONVM_NF_ACTION_DROP; - return 0; + struct skeleton_state *skeleton_data; + skeleton_data = (struct skeleton_state *)nf_local_ctx->nf->data; + skeleton_data->packets_processed++; - // /* - // * Timed display counter (counter stored in skeleton_state - keep/edit if NF uses display) - // * After the reception of each packet, the counter is incremented. Once we reach a defined - // * number of packets, display and reset the counter - // */ - // if (counter++ == print_delay) { - // do_stats_display(pkt); - // counter = 0; - // } + /* + * Timed display current_time (current_time stored in skeleton_state - keep/edit if NF uses display) + * After the reception of each packet, the current_time is incremented. Once we reach a defined + * number of packets, display and reset the current_time + */ - // /* - // * meta->action - // * Defines what to do with the packet. Actions defined in onvm_common.h - // * meta->destination - // * Defines the service ID of the NF which will receive the packet. - // */ - - // /* The following example bridges two ports, swapping packets between them. [EDIT] */ - // if (pkt->port == 0) { - // meta->destination = 1; - // } else { - // meta->destination = 0; - // } + if (skeleton_data->displayType == 1) { + if (skeleton_data->packets_processed % skeleton_data->delay == 0) { + do_stats_display(skeleton_data); + } + } - // /* - // * Specify an action: - // * ONVM_NF_ACTION_DROP - Drop packet - // * NVM_NF_ACTION_NEXT - Go to whatever the next action is configured by the SDN controller in the flow table - // * ONVM_NF_ACTION_TONF - Send the packet to the NF specified in the argument field (assume it is on the same host) - // * ONVM_NF_ACTION_OUT - Send the packet out the NIC port set in the argument field - // */ - // meta->action = ONVM_NF_ACTION_OUT; - - // /* Return 0 on success, -1 on failure */ - // return 0; + /* + * meta->action + * Defines what to do with the packet. Actions defined in onvm_common.h + * meta->destination + * Defines the service ID of the NF which will receive the packet. + * + * Possible actions: + * ONVM_NF_ACTION_DROP - Drop packet + * NVM_NF_ACTION_NEXT - Go to whatever the next action is configured by the SDN controller in the flow table + * ONVM_NF_ACTION_TONF - Send the packet to the NF specified in the argument field (assume it is on the same host) + * ONVM_NF_ACTION_OUT - Send the packet out the NIC port set in the argument field + */ + meta->action = ONVM_NF_ACTION_DROP; + + /* Return 0 on success, -1 on failure */ + return 0; } /* * Performs action continuously; called every run loop regardless of packet reception [EDIT] */ static int -action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ +action(struct onvm_nf_local_ctx *nf_local_ctx){ struct skeleton_state *skeleton_data; skeleton_data = (struct skeleton_state *)nf_local_ctx->nf->data; + /* + * Get the current time, and, if the user has specified a timer-based print delay, + * check whether it is time to print + */ __uint64_t time = (rte_get_tsc_cycles() - skeleton_data->start_time) / rte_get_timer_hz(); - if (time%5 == 0) { - printf("%ld\n",time); + if (skeleton_data->displayType == 0) { + __uint64_t delay = skeleton_data->delay; + __uint64_t current_time = skeleton_data->current_time; + if ((time%delay == 0) && (time != current_time)) { + do_stats_display(skeleton_data); + } } + /* Update the current time */ + skeleton_data->current_time = time; return 0; } @@ -219,26 +219,17 @@ action(__attribute__((unused)) struct onvm_nf_local_ctx *nf_local_ctx){ * Initial setup function; called before NF receives any packets/messages [EDIT] */ static void -setup(__attribute__((unused))struct onvm_nf_local_ctx *nf_local_ctx){ +setup(struct onvm_nf_local_ctx *nf_local_ctx){ /* - * (1) Declare and initialize state struct to hold non-local data within the NF. Use rte_zmalloc - * void * rte_zmalloc (const char * type, size_t size, unsigned align) - * type: A string identifying the type of allocated objects. Can be NULL. - * size: Size (in bytes) to be allocated. - * align: If 0, the return is a pointer that is suitably aligned for any kind of variable - * (2) Assign the nf_local_ctx->nf->data pointer to the struct. - * (3) Initialize other predefined data or counters; examples include: - * nf_local_ctx->nf->data->counter = 0; - * skeleton_data->print_delay = 10000 + * Initialize variables within state struct that must be defined + * before receiving packets/messages */ - - struct skeleton_state *skeleton_data; - skeleton_data = (struct skeleton_state *) rte_zmalloc ("skeleton", sizeof(struct skeleton_state), 0); - nf_local_ctx->nf->data = (void *) skeleton_data; + struct skeleton_state *skeleton_data = nf_local_ctx->nf->data; skeleton_data->start_time = rte_get_tsc_cycles(); - skeleton_data->print_delay = 5; + skeleton_data->current_time = 0; + skeleton_data->packets_processed = 0; } /* @@ -295,8 +286,20 @@ main(int argc, char *argv[]) { argc -= arg_offset; argv += arg_offset; + /* + * (1) Declare and initialize state struct to hold non-local data within the NF. Use rte_zmalloc + * void * rte_zmalloc (const char * type, size_t size, unsigned align) + * type: A string identifying the type of allocated objects. Can be NULL. + * size: Size (in bytes) to be allocated. + * align: If 0, the return is a pointer that is suitably aligned for any kind of variable + * (2) Assign the nf_local_ctx->nf->data pointer to the struct. + */ + struct skeleton_state *skeleton_data; + skeleton_data = (struct skeleton_state *) rte_zmalloc ("skeleton", sizeof(struct skeleton_state), 0); + nf_local_ctx->nf->data = (void *) skeleton_data; + /* Invalid command-line argument handling */ - if (parse_app_args(argc, argv, progname) < 0) { + if (parse_app_args(argc, argv, progname, skeleton_data) < 0) { onvm_nflib_stop(nf_local_ctx); rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n"); } From 84c791754a13086f9f95adc754be2e3cfcb2dd86 Mon Sep 17 00:00:00 2001 From: jett Date: Fri, 29 Oct 2021 13:35:35 -0600 Subject: [PATCH 11/13] [UPDATE] Command-Line Bugs --- examples/skeleton/README.md | 5 +++-- examples/skeleton/skeleton.c | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/skeleton/README.md b/examples/skeleton/README.md index bef504178..ce15f37c8 100644 --- a/examples/skeleton/README.md +++ b/examples/skeleton/README.md @@ -8,7 +8,7 @@ Compilation and Execution cd examples make cd skeleton -./go.sh SERVICE_ID [PRINT_DELAY] +./go.sh SERVICE_ID [-p TIME_PRINT_DELAY | -v PACKET_PRINT_DELAY] OR @@ -21,7 +21,8 @@ sudo ./build/skeleton -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- App Specific Arguments -- - - `-p `: number of packets between each print, e.g. `-p 1` prints every packets. + - `-p `: time between each print, e.g. `-p 1` prints after every second. + - `-v `: number of packets between each print, e.g. `-v 1` prints after every packet. Config File Support -- diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 0ef834417..274aabe92 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -122,7 +122,7 @@ parse_app_args(int argc, char *argv[], const char *progname, struct skeleton_sta return -1; } } - return optind; + return optind;ƒ } /* From 50a5524cda1cdd7b2dc00d38cacbbce1488bafaa Mon Sep 17 00:00:00 2001 From: jett Date: Fri, 29 Oct 2021 14:04:39 -0600 Subject: [PATCH 12/13] Compilation Fix --- examples/skeleton/skeleton.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 274aabe92..0ef834417 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -122,7 +122,7 @@ parse_app_args(int argc, char *argv[], const char *progname, struct skeleton_sta return -1; } } - return optind;ƒ + return optind; } /* From ffe76d71c4b770fb9fed9f4ae67aeec269bfe8ed Mon Sep 17 00:00:00 2001 From: jett Date: Fri, 29 Oct 2021 15:22:53 -0600 Subject: [PATCH 13/13] [UPDATE] Command-Line Argument Debugging --- examples/skeleton/README.md | 2 +- examples/skeleton/skeleton.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/skeleton/README.md b/examples/skeleton/README.md index ce15f37c8..fdd66f5d8 100644 --- a/examples/skeleton/README.md +++ b/examples/skeleton/README.md @@ -16,7 +16,7 @@ OR OR -sudo ./build/skeleton -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- [-p PRINT_DELAY] +sudo ./build/skeleton -l CORELIST -n 3 --proc-type=secondary -- -r SERVICE_ID -- [-p TIME_PRINT_DELAY | -v PACKET_PRINT_DELAY] ``` App Specific Arguments diff --git a/examples/skeleton/skeleton.c b/examples/skeleton/skeleton.c index 0ef834417..36044b552 100644 --- a/examples/skeleton/skeleton.c +++ b/examples/skeleton/skeleton.c @@ -102,16 +102,26 @@ parse_app_args(int argc, char *argv[], const char *progname, struct skeleton_sta switch (c) { case 'p': skeleton_data->delay = strtoul(optarg, NULL, 10); + if (skeleton_data->delay < 1) { + RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); + return -1; + } skeleton_data->displayType = 0; // displayType 0 = Time-Based Delays - break; + return optind; case 'v': skeleton_data->delay = strtoul(optarg, NULL, 10); + if (skeleton_data->delay < 1) { + RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); + return -1; + } skeleton_data->displayType = 1; // displayType 1 = Packet-Based Delays - break; + return optind; case '?': usage(progname); if (optopt == 'p') RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); + else if (optopt == 'v') + RTE_LOG(INFO, APP, "Option -%c requires an argument.\n", optopt); else if (isprint(optopt)) RTE_LOG(INFO, APP, "Unknown option `-%c'.\n", optopt); else @@ -206,7 +216,9 @@ action(struct onvm_nf_local_ctx *nf_local_ctx){ __uint64_t delay = skeleton_data->delay; __uint64_t current_time = skeleton_data->current_time; if ((time%delay == 0) && (time != current_time)) { + skeleton_data->current_time = time; do_stats_display(skeleton_data); + return 0; } } @@ -230,6 +242,9 @@ setup(struct onvm_nf_local_ctx *nf_local_ctx){ skeleton_data->start_time = rte_get_tsc_cycles(); skeleton_data->current_time = 0; skeleton_data->packets_processed = 0; + if (skeleton_data->displayType > -1) { + do_stats_display(skeleton_data); + } } /*