aboutsummaryrefslogtreecommitdiffstats
path: root/tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c')
-rw-r--r--tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c b/tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c
new file mode 100644
index 00000000..7803a971
--- /dev/null
+++ b/tools/docker/test-containers/dpdk-forwarding-pods/l2l3fwd/dpdk-args.c
@@ -0,0 +1,446 @@
+// SPDX-License-Identifier: Apache-2.0
+// Copyright(c) 2021 Red Hat, Inc.
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libnetutil_api.h"
+#include "dpdk-args.h"
+#include "c_util.h"
+
+bool debugArgs = true;
+
+#define DPDK_ARGS_MAX_ARGS (30)
+#define DPDK_ARGS_MAX_ARG_STRLEN (100)
+char myArgsArray[DPDK_ARGS_MAX_ARGS][DPDK_ARGS_MAX_ARG_STRLEN];
+char* myArgv[DPDK_ARGS_MAX_ARGS];
+
+//#define DPDK_ARGS_MAX_NUM_DIR (30)
+//static const char DEFAULT_DIR[] = "/var/lib/cni/";
+
+static char STR_MASTER[] = "master";
+static char STR_SLAVE[] = "slave";
+static char STR_ETHERNET[] = "ethernet";
+
+/* Large enough to hold: ",mac=aa:bb:cc:dd:ee:ff" */
+#define DPDK_ARGS_MAX_MAC_STRLEN (25)
+#define DPDK_ARGS_MAX_CONTAINERNAME_STRLEN (80)
+
+
+static int getInterfaces(int argc, int *pPortCnt, int *pPortMask) {
+ int i = 0;
+ int vhostCnt = 0;
+ int memifCnt = 1;
+ int sriovCnt = 0;
+ int err;
+ struct InterfaceResponse ifaceRsp;
+ char macStr[DPDK_ARGS_MAX_MAC_STRLEN];
+#if 0
+ // Refactor code later to find JSON file. Needs work so commented out for now.
+ DIR *d;
+ struct dirent *dir;
+ int currIndex = 0;
+ int freeIndex = 0;
+ char* dirList[DPDK_ARGS_MAX_NUM_DIR];
+ char* fileExt;
+
+ memset(dirList, 0, sizeof(char*)*DPDK_ARGS_MAX_NUM_DIR);
+
+ dirList[freeIndex] = malloc(sizeof(char) * (strlen(DEFAULT_DIR)+1));
+ strcpy(dirList[freeIndex++], DEFAULT_DIR);
+
+ while (dirList[currIndex] != NULL) {
+ printf(" Directory:%s\n", dirList[currIndex]);
+ d = opendir(dirList[currIndex]);
+ if (d)
+ {
+ while ((dir = readdir(d)) != NULL)
+ {
+ if ((dir->d_name) &&
+ (strcmp(dir->d_name, ".") != 0) &&
+ (strcmp(dir->d_name, "..") != 0))
+ {
+ printf(" Name:%s %d\n", dir->d_name, dir->d_type);
+ if (dir->d_type == DT_DIR) {
+ printf(" Add to Dir List:%s\n", dir->d_name);
+ dirList[freeIndex] = malloc(sizeof(char) * (strlen(DEFAULT_DIR)+strlen(dir->d_name)+1));
+ sprintf(dirList[freeIndex++], "%s%s/", DEFAULT_DIR, dir->d_name);
+ }
+ else
+ {
+ if (strstr(dir->d_name, "net") != NULL)
+ {
+ fileExt = strrchr(dir->d_name, '.');
+ if ((fileExt == NULL) || (strcmp(fileExt, ".json") != 0)) {
+ printf(" Adding to vdev list:%s\n", dir->d_name);
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "--vdev=virtio_user%d,path=%s%s", i, dirList[currIndex], dir->d_name);
+ i++;
+ }
+ else {
+ printf(" Invalid FileExt\n");
+ }
+ }
+ }
+ }
+ }
+ closedir(d);
+ }
+ free(dirList[currIndex]);
+ currIndex++;
+ }
+#endif
+
+ ifaceRsp.numIfaceAllocated = NETUTIL_NUM_NETWORKINTERFACE;
+ ifaceRsp.numIfacePopulated = 0;
+ ifaceRsp.pIface = malloc(ifaceRsp.numIfaceAllocated * sizeof(struct InterfaceData));
+ if (ifaceRsp.pIface) {
+ memset(ifaceRsp.pIface, 0, (ifaceRsp.numIfaceAllocated * sizeof(struct InterfaceData)));
+ err = GetInterfaces(&ifaceRsp);
+ if ((err == NETUTIL_ERRNO_SUCCESS) || (err == NETUTIL_ERRNO_SIZE_ERROR)) {
+
+ if (debugArgs) {
+ dumpInterfaces(&ifaceRsp);
+ }
+
+ for (i = 0; i < ifaceRsp.numIfacePopulated; i++) {
+ switch (ifaceRsp.pIface[i].DeviceType) {
+ case NETUTIL_TYPE_SRIOV:
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Pci.PciAddress) {
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "-w %s", ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Pci.PciAddress);
+ sriovCnt++;
+
+ *pPortMask = *pPortMask | 1 << *pPortCnt;
+ *pPortCnt = *pPortCnt + 1;
+ } else {
+ printf("ERROR: PCI Address not found. Type=%d\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Type);
+ }
+ break;
+ case NETUTIL_TYPE_VHOST:
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Path) {
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Mode == NETUTIL_VHOST_MODE_SERVER) {
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "--vdev=virtio_user%d,path=%s,server=1",
+ vhostCnt, ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Path);
+
+ vhostCnt++;
+ *pPortMask = *pPortMask | 1 << *pPortCnt;
+ *pPortCnt = *pPortCnt + 1;
+ }
+ else if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Mode == NETUTIL_VHOST_MODE_CLIENT) {
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "--vdev=virtio_user%d,path=%s,queues=1",
+ vhostCnt, ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Path);
+
+ vhostCnt++;
+ *pPortMask = *pPortMask | 1 << *pPortCnt;
+ *pPortCnt = *pPortCnt + 1;
+ } else {
+ printf("ERROR: Unknown vHost Mode=%d\n", ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.VhostUser.Mode);
+ }
+ } else {
+ printf("ERROR: vHost Path not found. Type=%d\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Type);
+ }
+ break;
+ case NETUTIL_TYPE_MEMIF:
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Path) {
+ char *pRole = NULL;
+ char *pMode = NULL;
+
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Role == NETUTIL_MEMIF_ROLE_MASTER) {
+ pRole = STR_MASTER;
+ }
+ else if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Role == NETUTIL_MEMIF_ROLE_SLAVE) {
+ pRole = STR_SLAVE;
+ }
+ else {
+ printf("ERROR: Unknown memif Role=%d\n", ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Role);
+ }
+
+ if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode == NETUTIL_MEMIF_MODE_ETHERNET) {
+ pMode = STR_ETHERNET;
+ }
+ else if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode == NETUTIL_MEMIF_MODE_IP) {
+ //pMode = "ip";
+ printf("ERROR: memif Mode=%d - Not Supported in DPDK!\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode);
+ }
+ else if (ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode == NETUTIL_MEMIF_MODE_INJECT_PUNT) {
+ //pMode = "inject-punt"";
+ printf("ERROR: memif Mode=%d - Not Supported in DPDK!\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode);
+ }
+ else {
+ printf("ERROR: Unknown memif Mode=%d\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Mode);
+ }
+
+ if ((ifaceRsp.pIface[i].NetworkStatus.Mac) &&
+ (strcmp(ifaceRsp.pIface[i].NetworkStatus.Mac,"") != 0)) {
+ snprintf(&macStr[0], DPDK_ARGS_MAX_MAC_STRLEN-1,
+ ",mac=%s", ifaceRsp.pIface[i].NetworkStatus.Mac);
+ }
+ else {
+ macStr[0] = '\0';
+ }
+
+ if ((pRole) && (pMode)) {
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "--vdev=net_memif%d,socket=%s,role=%s%s", memifCnt,
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Memif.Path, pRole, &macStr[0]);
+
+ memifCnt++;
+ *pPortMask = *pPortMask | 1 << *pPortCnt;
+ *pPortCnt = *pPortCnt + 1;
+ }
+ } else {
+ printf("ERROR: Memif Path not found. Type=%d\n",
+ ifaceRsp.pIface[i].NetworkStatus.DeviceInfo.Type);
+ }
+ break;
+ }
+ } /* END of FOR EACH Interface */
+
+ if (sriovCnt == 0) {
+ strncpy(&myArgsArray[argc++][0], "--no-pci", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ }
+
+ freeInterfaces(&ifaceRsp);
+ }
+ else {
+ printf("Couldn't get network interface, err code: %d\n", err);
+ }
+ }
+
+ return(argc);
+}
+
+static int getHugepages(int argc) {
+ int i = 0;
+ int err;
+ int containerIndex = 0;
+ int64_t reqMemory = 0;
+ int64_t hugepageMemory = 1024;
+ struct HugepagesResponse hugepagesRsp;
+
+ memset(&hugepagesRsp, 0, sizeof(struct HugepagesResponse));
+ hugepagesRsp.numStructAllocated = NETUTIL_NUM_HUGEPAGES_DATA;
+ hugepagesRsp.pHugepages = malloc(hugepagesRsp.numStructAllocated * sizeof(struct HugepagesData));
+ if (hugepagesRsp.pHugepages) {
+ memset(hugepagesRsp.pHugepages, 0, (hugepagesRsp.numStructAllocated * sizeof(struct HugepagesData)));
+ err = GetHugepages(&hugepagesRsp);
+ if ((err == NETUTIL_ERRNO_SUCCESS) || (err == NETUTIL_ERRNO_SIZE_ERROR)) {
+
+ if (debugArgs) {
+ dumpHugepages(&hugepagesRsp);
+ }
+
+ /* Loop through the list of containers to match container name from env. */
+ if (hugepagesRsp.MyContainerName) {
+ for (i = 0; i < hugepagesRsp.numStructPopulated; i++) {
+ if (hugepagesRsp.pHugepages[i].ContainerName) {
+ if (strcmp(hugepagesRsp.MyContainerName, hugepagesRsp.pHugepages[i].ContainerName) == 0) {
+ containerIndex = i;
+ printf(" MATCH: ContainerName=%s, Index=%d\n", hugepagesRsp.pHugepages[i].ContainerName, containerIndex);
+ break;
+ }
+ }
+ }
+ }
+
+ /* Limit can never be less than Request. So use Limit if non-zero. */
+ /* However, for hugepages, Limit and Request should be the same, so */
+ /* either value should be fine. */
+ reqMemory =
+ (hugepagesRsp.pHugepages[containerIndex].Limit1G != 0) ? hugepagesRsp.pHugepages[containerIndex].Limit1G :
+ (hugepagesRsp.pHugepages[containerIndex].Limit2M != 0) ? hugepagesRsp.pHugepages[containerIndex].Limit2M :
+ (hugepagesRsp.pHugepages[containerIndex].Limit != 0) ? hugepagesRsp.pHugepages[containerIndex].Limit :
+ (hugepagesRsp.pHugepages[containerIndex].Request1G != 0) ? hugepagesRsp.pHugepages[containerIndex].Request1G :
+ (hugepagesRsp.pHugepages[containerIndex].Request2M != 0) ? hugepagesRsp.pHugepages[containerIndex].Request2M :
+ hugepagesRsp.pHugepages[containerIndex].Request;
+
+ if (reqMemory != 0) {
+ /* Assuming 2 NUMA sockets, only use what container has access too. */
+ /* TBD: Manage NUMA properly. */
+ hugepageMemory = reqMemory / 2;
+ }
+
+ freeHugepages(&hugepagesRsp);
+
+ } else {
+ printf(" Couldn't get Hugepage info, defaulting to %ld, err code: %d\n", hugepageMemory, err);
+ }
+ }
+
+ /* Build up memory portion of DPDK Args. */
+ strncpy(&myArgsArray[argc++][0], "-m", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "%ld", hugepageMemory);
+
+ strncpy(&myArgsArray[argc++][0], "-n", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "4", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ return(argc);
+}
+
+char** GetArgs(int *pArgc, eDpdkAppType appType)
+{
+ int argc = 0;
+ int i;
+ struct CPUResponse cpuRsp;
+ int err;
+ int portMask = 0;
+ int portCnt = 0;
+ int lcoreBase = 0;
+ int port;
+ int length = 0;
+
+ sleep(2);
+
+ memset(&cpuRsp, 0, sizeof(cpuRsp));
+ err = GetCPUInfo(&cpuRsp);
+ if (err) {
+ printf("Couldn't get CPU info, err code: %d\n", err);
+ }
+ if (cpuRsp.CPUSet) {
+ printf(" cpuRsp.CPUSet = %s\n", cpuRsp.CPUSet);
+
+ // Free the string
+ free(cpuRsp.CPUSet);
+ }
+
+
+ memset(&myArgsArray[0][0], 0, sizeof(char)*DPDK_ARGS_MAX_ARG_STRLEN*DPDK_ARGS_MAX_ARGS);
+ memset(&myArgv[0], 0, sizeof(char)*DPDK_ARGS_MAX_ARGS);
+
+ if (pArgc) {
+ /*
+ * Initialize EAL Options
+ */
+ strncpy(&myArgsArray[argc++][0], "dpdk-app", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ argc = getHugepages(argc);
+
+ //strncpy(&myArgsArray[argc++][0], "--file-prefix=dpdk-app_", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ if (appType == DPDK_APP_TESTPMD) {
+ strncpy(&myArgsArray[argc++][0], "-l", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "1-3", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ strncpy(&myArgsArray[argc++][0], "--master-lcore", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "1", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ argc = getInterfaces(argc, &portCnt, &portMask);
+
+ /*
+ * Initialize APP Specific Options
+ */
+ strncpy(&myArgsArray[argc++][0], "--", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ strncpy(&myArgsArray[argc++][0], "--auto-start", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "--tx-first", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "--no-lsc-interrupt", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ /* testpmd exits if there is not user enteraction, so print stats */
+ /* every so often to keep program running. */
+ strncpy(&myArgsArray[argc++][0], "--stats-period", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "60", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ }
+ else if (appType == DPDK_APP_L3FWD) {
+ /* NOTE: The l3fwd app requires a TX Queue per lcore. So seeting lcore to 1 */
+ /* until additional queues are added to underlying interface. */
+ strncpy(&myArgsArray[argc++][0], "-l", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "1", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ strncpy(&myArgsArray[argc++][0], "--master-lcore", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "1", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ lcoreBase = 1;
+
+ argc = getInterfaces(argc, &portCnt, &portMask);
+
+ /*
+ * Initialize APP Specific Options
+ */
+ strncpy(&myArgsArray[argc++][0], "--", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ /* Set the PortMask, Hexadecimal bitmask of ports used by app. */
+ strncpy(&myArgsArray[argc++][0], "-p", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "0x%x", portMask);
+
+ /* Set all ports to promiscuous mode so that packets are accepted */
+ /* regardless of the packet’s Ethernet MAC destination address. */
+ strncpy(&myArgsArray[argc++][0], "-P", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ /* Determines which queues from which ports are mapped to which cores. */
+ /* Usage: --config="(port,queue,lcore)[,(port,queue,lcore)]" */
+ length = 0;
+ for (port = 0; port < portCnt; port++) {
+ /* If the first port, add '--config="' to string. */
+ if (port == 0) {
+ length += snprintf(&myArgsArray[argc][length], DPDK_ARGS_MAX_ARG_STRLEN-length,
+ "--config=\"");
+ }
+ /* If not the first port, add a ',' to string. */
+ else {
+ length += snprintf(&myArgsArray[argc][length], DPDK_ARGS_MAX_ARG_STRLEN-length, ",");
+ }
+
+ /* Add each port data */
+ length += snprintf(&myArgsArray[argc][length], DPDK_ARGS_MAX_ARG_STRLEN-length,
+ "(%d,%d,%d)", port, 0 /* queue */, lcoreBase /*+port*/);
+
+ /* If the last port, add a trailing " to string. */
+ if (port == portCnt-1) {
+ length += snprintf(&myArgsArray[argc][length], DPDK_ARGS_MAX_ARG_STRLEN-length, "\"");
+ }
+ }
+ argc++;
+
+ /* Set to use software to analyze packet type. Without this option, */
+ /* hardware will check the packet type. Not sure if vHost supports. */
+ strncpy(&myArgsArray[argc++][0], "--parse-ptype", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ }
+ else if (appType == DPDK_APP_L2FWD) {
+ strncpy(&myArgsArray[argc++][0], "-l", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "1-3", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ argc = getInterfaces(argc, &portCnt, &portMask);
+
+ /*
+ * Initialize APP Specific Options
+ */
+ strncpy(&myArgsArray[argc++][0], "--", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ /* Set the PortMask, Hexadecimal bitmask of ports used by app. */
+ strncpy(&myArgsArray[argc++][0], "-p", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ snprintf(&myArgsArray[argc++][0], DPDK_ARGS_MAX_ARG_STRLEN-1,
+ "0x%x", portMask);
+
+ /* Set the PERIOD, statistics will be refreshed each PERIOD seconds. */
+ strncpy(&myArgsArray[argc++][0], "-T", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ strncpy(&myArgsArray[argc++][0], "120", DPDK_ARGS_MAX_ARG_STRLEN-1);
+
+ /* Set to no-mac-updating. When enabled: */
+ /* - source MAC address is replaced by the TX port MAC address */
+ /* - The destination MAC address is replaced by 02:00:00:00:00:TX_PORT_ID */
+ strncpy(&myArgsArray[argc++][0], "--no-mac-updating", DPDK_ARGS_MAX_ARG_STRLEN-1);
+ }
+
+ for (i = 0; i < argc; i++) {
+ myArgv[i] = &myArgsArray[i][0];
+ }
+ *pArgc = argc;
+ }
+
+ return(myArgv);
+}