WARP17 currently supports RAW TCP and HTTP 1.1 application traffic. Even though we are currently working on adding support for more application implementations, external contributions are welcome.
As a future development WARP17 will offer a socket API in order to allow applications to be easily plugged in. Until then any new application must be directly added to the WARP17 code. As an example, a good starting point is the HTTP 1.1 implementation itself.
In general, an application called foo should implement the following:
-
warp17-app-foo.protodefinition file inapi/: should contain the application configuration definitions (for clients and servers) and preferably application specific statistics definitions.warp17-app-foo.protoshould be included inwarp17-app.protoand the application theAppstructure:
message App { required AppProto app_proto = 1; /* Add different App configs below as optionals. */ optional RawClient app_raw_client = 2 [(warp17_union_anon) = true]; optional RawServer app_raw_server = 3 [(warp17_union_anon) = true]; optional HttpClient app_http_client = 4 [(warp17_union_anon) = true]; optional HttpServer app_http_server = 5 [(warp17_union_anon) = true]; optional Imix app_imix = 6 [(warp17_union_anon) = true]; optional Foo app_foo = 7 [(warp17_union_anon) = true]; }- the application specific statistics should also be added to the
AppStatsdefinition:
message AppStats { /* The user will do the translation. */ option (warp17_xlate_tpg) = false; optional RawStats as_raw = 1 [(warp17_union_anon) = true]; optional HttpStats as_http = 2 [(warp17_union_anon) = true]; optional ImixStats as_imix = 3 [(warp17_union_anon) = true]; optional FooStats as_foo = 4 [(warp17_union_anon) = true]; }- a new entry for the application type should be added to the
AppProtoenum inwarp17-common.proto:
enum AppProto { RAW_CLIENT = 0; RAW_SERVER = 1; HTTP_CLIENT = 2; HTTP_SERVER = 3; IMIX = 4; FOO = 5; APP_PROTO_MAX = 6; }- the new protocol buffer file (
warp17-app-foo.proto) should also be added toapi/Makefile.api:
PROTO-SRCS += warp17-app-raw.proto PROTO-SRCS += warp17-app-http.proto PROTO-SRCS += warp17-app-foo.proto- the file
Makefile.dpdkshould also be updated to include the new application implementation:
SRCS-y += tpg_test_app.c SRCS-y += tpg_test_http_1_1_app.c SRCS-y += tpg_test_raw_app.c SRCS-y += tpg_test_foo_app.c- include
warp17-app-foo.protointcp_generator.h:
#include "warp17-app-raw.proto.xlate.h" #include "warp17-app-http.proto.xlate.h" #include "warp17-app-foo.proto.xlate.h" -
RPC WARP17 to protobuf translation code:
- a new case entry in
tpg_xlate_tpg_union_Appwhere the application translation function should be called:
case APP_PROTO__HTTP_SERVER: out->app_http_server = rte_zmalloc("TPG_RPC_GEN", sizeof(*out->app_http_server), 0); if (!out->app_http_server) return -ENOMEM; tpg_xlate_tpg_HttpServer(&in->app_http_server, out->app_http_server); break; case APP_PROTO__FOO: out->app_foo = rte_zmalloc("TPG_RPC_GEN", sizeof(*out->app_foo), 0); if (!out->app_foo) return -ENOMEM; tpg_xlate_tpg_Foo(&in->app_foo, out->app_foo); break;- a new case entry in
tpg_xlate_tpgTestAppStats_by_protowhen translating application statistics:
case APP_PROTO__HTTP_SERVER: out->as_http = rte_zmalloc("TPG_RPC_GEN", sizeof(*out->as_http), 0); if (!out->as_http) return -ENOMEM; err = tpg_xlate_tpg_HttpStats(&in->as_http, out->as_http); if (err) return err; break; case APP_PROTO__FOO: out->as_foo = rte_zmalloc("TPG_RPC_GEN", sizeof(*out->as_foo), 0); if (!out->as_foo) return -ENOMEM; err = tpg_xlate_tpg_FooStats(&in->as_foo, out->as_foo); if (err) return err; break; - a new case entry in
-
appl/tpg_test_app.hinterface implementation:- application
fooshould be added to theapp_data_tdefinition ininc/appl/tpg_test_app.h. Typefoo_app_tshould be defined in the application headers and should represent a state storage for thefooapplication. The state is part of the L4 control block structures (TCB/UCB).
typedef struct app_data_s { [...] union { raw_app_t ad_raw; http_app_t ad_http; foo_app_t ad_foo; generic_app_t ad_generic; }; } app_data_t;-
foomust also provide callback functions corresponding to the callback types defined ininc/appl/tpg_test_app.h. The callbacks should be added to the callback arrays insrc/appl/tpg_test_app.c. These functions will be called by the test engine whenever application intervention is required:-
app_default_cfg_cb_t: should initialize thefooapplication config to default values -
app_validate_cfg_cb_t: should validate the config corresponding to thefooapplication -
app_print_cfg_cb_t: should display the part of the configuration corresponding to thefooapplication by using the supplied printer -
app_add_cfg_cb_t: will be called whenever a test case is added sofooinitialize everything needed for the test case. -
app_delete_cfg_cb_t: will be called whenever a test case is deleted sofoocan cleanup anything it initialized for the test case. -
app_pkts_per_send_cb_t: will be called when the test case is started to determine how many packets (on average) willfoobe sending for a single data message -
app_init_cb_t: will be called whenever a session is initialized and should initialize the application state. -
app_tc_start_stop_cb_t:fooshould define two callbacks (for test case start and stop). The application should initialize and cleanup any data that is required during the test case (e.g., predefined static data headers) -
app_conn_up_cb_t: will be called whenever a session has been established -
app_conn_down_cb_t: will be called whenever a session closed ( either because the underlying connection went down or because the application itself decided to close the connection) -
app_deliver_cb_t: will be called whenever there was data received for the application to process. The received data is passed as an mbuf chain. The callback should return the total number of bytes that were consumed. For example, in the case of TCP these bytes will be ACK-ed and removed from the receive window. -
app_send_cb_t: will be called whenever the test engine can send data on the current connection. The application can decide at any time that it would like to start sending or stop sending data by notifying the test engine through theTEST_NOTIF_APP_CLIENT/SERVER_SEND_STOP/STARTnotifications. Theapp_send_cb_tcallback should return anmbufchain pointing to the data it would like to send. In general, freeing thembufupon sending is the job of the TCP/IP stack so the application must make sure that it doesn't continue using the mbuf after passing it to the test engine. NOTE: However, for some applications, in order to avoid building packets every time, the implementation might prefer to reuse data templates (e.g., HTTP requests can be easily prebuilt when the test case is started). In such a situation the application can mark the mbufs as STATIC through theDATA_SET_STATICcall which will inform the test engine that it shouldn't free the data itself. The application must ensure in such a case that the data itself is never freed during the execution of the test case! -
app_data_sent_cb_t: will be called to notify the application that (part of) the data was sent. It might happen that not all the data could be sent in one shot so the application should returntrueif what was sent corresponds to a complete message -
app_stats_add_cb_t: should aggregate application specific statistics -
app_stats_print_cb_t: should print application specific statistics using the supplied printer
-
-
the
fooapplication can request the test engine to perform operations by sending the following notifications:-
TEST_NOTIF_APP_CLIENT/SERVER_SEND_START: notifies the test engine that the application would like to send data (when possible) on the current connection -
TEST_NOTIF_APP_CLIENT/SERVER_SEND_STOP: notifies the test engine that the application has finished sending data (for now) on the current connection -
TEST_NOTIF_APP_CLIENT/SERVER_CLOSE: notifies the test engine that the application would like to close the connection
-
- application
-
CLI: the
fooapplication can define it's own CLI commands using the DPDK cmdline infrastructure. These can be added to a localcli_ctxwhich can be registered with the main CLI through a call tocli_add_main_ctx. -
module initialization: the
fooapplication must implement two module init functions:-
foo_init: should initialize global data to be used by the application (e.g., CLI, statistics storage).foo_initshould be called directly from themainWARP17 function where all modules are initialized. -
foo_lcore_init: should initalize per core global data to be used by the application (e.g., per core pointers to the statistics corresponding to the current core).foo_lcore_initshould be called frompkt_receive_loopwhere all modules are initialized.
-
-
example config: ideally, applications should also provide some configuration examples which could go to the
examples/directory. -
.dot file: applications will most likely be implemented as state machines. A
.dotfile describing the state machine should be added to thedot/directory -
tests: any new application shouldn't break any existing tests and must have it's own tests:
-
a configuration and functionality test file in
ut/test_foo.pywhich should try to extensively cover all the code introduced by the application -
one or more scaling test entries (method) in
ut/test_perf.py(class TestPerf) which should define the desired performance/scalability values.
-
-
commit messages: please make sure that commit messages follow the
.git-commit.templateprovided in the repository. In order to enforce this template locally you can execute the following command:
git config commit.template ./.git-commit.template