NF API

OpenNetVM supports 2 modes, by default NFs use the packet_handler callback function that processes packets 1 by 1. The second is the advanced rings mode which gives the NF full control of its rings and allows the developer to do anything they want.

Default Callback mode API init sequence:

The Bridge NF is a simple example illustrating this process.

  1. First step is initializing the onvm context

1struct onvm_nf_local_ctx *nf_local_ctx;
2nf_local_ctx = onvm_nflib_init_nf_local_ctx();

This configures basic meta data the NF.

  1. Start the signal handler

1onvm_nflib_start_signal_handler(nf_local_ctx, NULL);

This ensures signals will be caught to correctly shut down the NF (i.e., to notify the manager).

  1. Define the function table for the NF

1struct onvm_nf_function_table *nf_function_table;
2nf_function_table = onvm_nflib_init_nf_function_table();
3nf_function_table->pkt_handler = &packet_handler;
4nf_function_table->setup = &nf_setup;

The pkt_handler call back will be executed on each packet arrival. The setup function is called only once after the NF is initialized.

  1. Initialize ONVM and adjust the argc, argv based on the return value.

 1if ((arg_offset = onvm_nflib_init(argc, argv, NF_TAG, nf_local_ctx, nf_function_table)) < 0) {
 2    onvm_nflib_stop(nf_local_ctx);
 3    if (arg_offset == ONVM_SIGNAL_TERMINATION) {
 4        printf("Exiting due to user termination\n");
 5        return 0;
 6    } else {
 7        rte_exit(EXIT_FAILURE, "Failed ONVM init\n");
 8    }
 9}
10
11argc -= arg_offset;
12argv += arg_offset;

This initializes DPDK and notifies the Manager that a new NF is starting.

  1. Parse NF specific args

1nf_info = nf_context->nf_info;
2if (parse_app_args(argc, argv, progname) < 0) {
3    onvm_nflib_stop(nf_context);
4    rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
5}
  1. Run the NF

1onvm_nflib_run(nf_local_ctx);

This will cause the NF to enter the run loop, trigger a callback on each new packet.

  1. Stop the NF

1onvm_nflib_stop(nf_local_ctx);

Advanced rings API init sequence:

The scaling NF provides a clear separation of the two modes and can be found here.

  1. First step is initializing the onvm context

1struct onvm_nf_local_ctx *nf_local_ctx;
2nf_local_ctx = onvm_nflib_init_nf_local_ctx();
  1. Start the signal handler

1onvm_nflib_start_signal_handler(nf_local_ctx, NULL);
  1. Contrary to default rings Next we don’t need to define the function table

  2. Initialize ONVM and adjust the argc, argv based on the return value.

 1if ((arg_offset = onvm_nflib_init(argc, argv, NF_TAG, nf_local_ctx, NULL)) < 0) {
 2    onvm_nflib_stop(nf_local_ctx);
 3    if (arg_offset == ONVM_SIGNAL_TERMINATION) {
 4        printf("Exiting due to user termination\n");
 5        return 0;
 6    } else {
 7        rte_exit(EXIT_FAILURE, "Failed ONVM init\n");
 8    }
 9}
10
11argc -= arg_offset;
12argv += arg_offset;
  1. Parse NF specific args

1nf_info = nf_context->nf_info;
2if (parse_app_args(argc, argv, progname) < 0) {
3    onvm_nflib_stop(nf_context);
4    rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
5}
  1. To start packet processing run this function to let onvm mgr know that NF is running (instead of onvm_nflib_run in default mode

1onvm_nflib_nf_ready(nf_context->nf);
  1. Stop the NF

1onvm_nflib_stop(nf_local_ctx);

Optional configuration

If the NF needs additional NF state data it can be put into the data field, this is NF specific and won’t be altered by onvm_nflib functions. This can be defined after the onvm_nflib_init has finished

1nf_local_ctx->nf->data = (void *)rte_malloc("nf_state_data", sizeof(struct custom_state_data), 0);