trace: add trace mode configuration parameter
[dpdk.git] / lib / librte_eal / common / eal_common_options.c
index 8dcfeb9..7e3a7df 100644 (file)
@@ -6,19 +6,25 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
+#ifndef RTE_EXEC_ENV_WINDOWS
 #include <syslog.h>
+#endif
 #include <ctype.h>
 #include <limits.h>
 #include <errno.h>
 #include <getopt.h>
+#ifndef RTE_EXEC_ENV_WINDOWS
 #include <dlfcn.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <dirent.h>
 
+#include <rte_string_fns.h>
 #include <rte_eal.h>
 #include <rte_log.h>
 #include <rte_lcore.h>
+#include <rte_memory.h>
 #include <rte_tailq.h>
 #include <rte_version.h>
 #include <rte_devargs.h>
@@ -28,6 +34,7 @@
 #include "eal_options.h"
 #include "eal_filesystem.h"
 #include "eal_private.h"
+#include "eal_trace.h"
 
 #define BITS_PER_HEX 4
 #define LCORE_OPT_LST 1
@@ -61,6 +68,10 @@ eal_long_options[] = {
        {OPT_IOVA_MODE,         1, NULL, OPT_IOVA_MODE_NUM        },
        {OPT_LCORES,            1, NULL, OPT_LCORES_NUM           },
        {OPT_LOG_LEVEL,         1, NULL, OPT_LOG_LEVEL_NUM        },
+       {OPT_TRACE,             1, NULL, OPT_TRACE_NUM            },
+       {OPT_TRACE_DIR,         1, NULL, OPT_TRACE_DIR_NUM        },
+       {OPT_TRACE_BUF_SIZE,    1, NULL, OPT_TRACE_BUF_SIZE_NUM   },
+       {OPT_TRACE_MODE,        1, NULL, OPT_TRACE_MODE_NUM       },
        {OPT_MASTER_LCORE,      1, NULL, OPT_MASTER_LCORE_NUM     },
        {OPT_MBUF_POOL_OPS_NAME, 1, NULL, OPT_MBUF_POOL_OPS_NAME_NUM},
        {OPT_NO_HPET,           0, NULL, OPT_NO_HPET_NUM          },
@@ -105,7 +116,7 @@ static const char *default_solib_dir = RTE_EAL_PMD_PATH;
  * Note: PLEASE DO NOT ALTER THIS without making a corresponding
  * change to usertools/dpdk-pmdinfo.py
  */
-static const char dpdk_solib_path[] __attribute__((used)) =
+static const char dpdk_solib_path[] __rte_used =
 "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
 
 TAILQ_HEAD(device_option_list, device_option);
@@ -139,7 +150,7 @@ eal_option_device_add(enum rte_devtype type, const char *optarg)
        }
 
        devopt->type = type;
-       ret = snprintf(devopt->arg, optlen, "%s", optarg);
+       ret = strlcpy(devopt->arg, optarg, optlen);
        if (ret < 0) {
                RTE_LOG(ERR, EAL, "Unable to copy device option\n");
                free(devopt);
@@ -203,7 +214,9 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
        }
        internal_cfg->base_virtaddr = 0;
 
+#ifdef LOG_DAEMON
        internal_cfg->syslog_facility = LOG_DAEMON;
+#endif
 
        /* if set to NONE, interrupt mode is determined automatically */
        internal_cfg->vfio_intr_mode = RTE_INTR_MODE_NONE;
@@ -259,8 +272,7 @@ eal_plugindir_init(const char *path)
        while ((dent = readdir(d)) != NULL) {
                struct stat sb;
 
-               snprintf(sopath, PATH_MAX-1, "%s/%s", path, dent->d_name);
-               sopath[PATH_MAX-1] = 0;
+               snprintf(sopath, sizeof(sopath), "%s/%s", path, dent->d_name);
 
                if (!(stat(sopath, &sb) == 0 && S_ISREG(sb.st_mode)))
                        continue;
@@ -277,6 +289,7 @@ eal_plugindir_init(const char *path)
 int
 eal_plugins_init(void)
 {
+#ifndef RTE_EXEC_ENV_WINDOWS
        struct shared_driver *solib = NULL;
        struct stat sb;
 
@@ -305,6 +318,7 @@ eal_plugins_init(void)
 
        }
        return 0;
+#endif
 }
 
 /*
@@ -372,7 +386,7 @@ eal_parse_service_coremask(const char *coremask)
                                        return -1;
                                }
 
-                               if (!lcore_config[idx].detected) {
+                               if (eal_cpu_detected(idx) == 0) {
                                        RTE_LOG(ERR, EAL,
                                                "lcore %u unavailable\n", idx);
                                        return -1;
@@ -428,7 +442,7 @@ update_lcore_config(int *cores)
 
        for (i = 0; i < RTE_MAX_LCORE; i++) {
                if (cores[i] != -1) {
-                       if (!lcore_config[i].detected) {
+                       if (eal_cpu_detected(i) == 0) {
                                RTE_LOG(ERR, EAL, "lcore %u unavailable\n", i);
                                ret = -1;
                                continue;
@@ -657,14 +671,14 @@ eal_parse_master_lcore(const char *arg)
  *                       ',' used for a single number.
  */
 static int
-eal_parse_set(const char *input, uint16_t set[], unsigned num)
+eal_parse_set(const char *input, rte_cpuset_t *set)
 {
        unsigned idx;
        const char *str = input;
        char *end = NULL;
        unsigned min, max;
 
-       memset(set, 0, num * sizeof(uint16_t));
+       CPU_ZERO(set);
 
        while (isblank(*str))
                str++;
@@ -677,7 +691,7 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
        if (*str != '(') {
                errno = 0;
                idx = strtoul(str, &end, 10);
-               if (errno || end == NULL || idx >= num)
+               if (errno || end == NULL || idx >= CPU_SETSIZE)
                        return -1;
                else {
                        while (isblank(*end))
@@ -695,7 +709,7 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
 
                                errno = 0;
                                idx = strtoul(end, &end, 10);
-                               if (errno || end == NULL || idx >= num)
+                               if (errno || end == NULL || idx >= CPU_SETSIZE)
                                        return -1;
                                max = idx;
                                while (isblank(*end))
@@ -710,7 +724,7 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
 
                        for (idx = RTE_MIN(min, max);
                             idx <= RTE_MAX(min, max); idx++)
-                               set[idx] = 1;
+                               CPU_SET(idx, set);
 
                        return end - input;
                }
@@ -735,7 +749,7 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
                /* get the digit value */
                errno = 0;
                idx = strtoul(str, &end, 10);
-               if (errno || end == NULL || idx >= num)
+               if (errno || end == NULL || idx >= CPU_SETSIZE)
                        return -1;
 
                /* go ahead to separator '-',',' and ')' */
@@ -752,7 +766,7 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
                                min = idx;
                        for (idx = RTE_MIN(min, max);
                             idx <= RTE_MAX(min, max); idx++)
-                               set[idx] = 1;
+                               CPU_SET(idx, set);
 
                        min = RTE_MAX_LCORE;
                } else
@@ -771,28 +785,21 @@ eal_parse_set(const char *input, uint16_t set[], unsigned num)
        return str - input;
 }
 
-/* convert from set array to cpuset bitmap */
 static int
-convert_to_cpuset(rte_cpuset_t *cpusetp,
-             uint16_t *set, unsigned num)
+check_cpuset(rte_cpuset_t *set)
 {
-       unsigned idx;
+       unsigned int idx;
 
-       CPU_ZERO(cpusetp);
-
-       for (idx = 0; idx < num; idx++) {
-               if (!set[idx])
+       for (idx = 0; idx < CPU_SETSIZE; idx++) {
+               if (!CPU_ISSET(idx, set))
                        continue;
 
-               if (!lcore_config[idx].detected) {
+               if (eal_cpu_detected(idx) == 0) {
                        RTE_LOG(ERR, EAL, "core %u "
                                "unavailable\n", idx);
                        return -1;
                }
-
-               CPU_SET(idx, cpusetp);
        }
-
        return 0;
 }
 
@@ -814,7 +821,8 @@ static int
 eal_parse_lcores(const char *lcores)
 {
        struct rte_config *cfg = rte_eal_get_configuration();
-       static uint16_t set[RTE_MAX_LCORE];
+       rte_cpuset_t lcore_set;
+       unsigned int set_count;
        unsigned idx = 0;
        unsigned count = 0;
        const char *lcore_start = NULL;
@@ -863,18 +871,13 @@ eal_parse_lcores(const char *lcores)
                lcores += strcspn(lcores, "@,");
 
                if (*lcores == '@') {
-                       /* explicit assign cpu_set */
-                       offset = eal_parse_set(lcores + 1, set, RTE_DIM(set));
+                       /* explicit assign cpuset and update the end cursor */
+                       offset = eal_parse_set(lcores + 1, &cpuset);
                        if (offset < 0)
                                goto err;
-
-                       /* prepare cpu_set and update the end cursor */
-                       if (0 > convert_to_cpuset(&cpuset,
-                                                 set, RTE_DIM(set)))
-                               goto err;
                        end = lcores + 1 + offset;
                } else { /* ',' or '\0' */
-                       /* haven't given cpu_set, current loop done */
+                       /* haven't given cpuset, current loop done */
                        end = lcores;
 
                        /* go back to check <number>-<number> */
@@ -888,18 +891,19 @@ eal_parse_lcores(const char *lcores)
                        goto err;
 
                /* parse lcore_set from start point */
-               if (0 > eal_parse_set(lcore_start, set, RTE_DIM(set)))
+               if (eal_parse_set(lcore_start, &lcore_set) < 0)
                        goto err;
 
-               /* without '@', by default using lcore_set as cpu_set */
-               if (*lcores != '@' &&
-                   0 > convert_to_cpuset(&cpuset, set, RTE_DIM(set)))
-                       goto err;
+               /* without '@', by default using lcore_set as cpuset */
+               if (*lcores != '@')
+                       rte_memcpy(&cpuset, &lcore_set, sizeof(cpuset));
 
+               set_count = CPU_COUNT(&lcore_set);
                /* start to update lcore_set */
                for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
-                       if (!set[idx])
+                       if (!CPU_ISSET(idx, &lcore_set))
                                continue;
+                       set_count--;
 
                        if (cfg->lcore_role[idx] != ROLE_RTE) {
                                lcore_config[idx].core_index = count;
@@ -911,10 +915,17 @@ eal_parse_lcores(const char *lcores)
                                CPU_ZERO(&cpuset);
                                CPU_SET(idx, &cpuset);
                        }
+
+                       if (check_cpuset(&cpuset) < 0)
+                               goto err;
                        rte_memcpy(&lcore_config[idx].cpuset, &cpuset,
                                   sizeof(rte_cpuset_t));
                }
 
+               /* some cores from the lcore_set can't be handled by EAL */
+               if (set_count != 0)
+                       goto err;
+
                lcores = end + 1;
        } while (*end != '\0');
 
@@ -929,6 +940,7 @@ err:
        return ret;
 }
 
+#ifndef RTE_EXEC_ENV_WINDOWS
 static int
 eal_parse_syslog(const char *facility, struct internal_config *conf)
 {
@@ -967,6 +979,7 @@ eal_parse_syslog(const char *facility, struct internal_config *conf)
        }
        return -1;
 }
+#endif
 
 static int
 eal_parse_log_priority(const char *level)
@@ -1038,7 +1051,7 @@ eal_parse_log_level(const char *arg)
        if (regex) {
                if (rte_log_set_level_regexp(regex, priority) < 0) {
                        fprintf(stderr, "cannot set log level %s,%d\n",
-                               pattern, priority);
+                               regex, priority);
                        goto fail;
                }
                if (rte_log_save_regexp(regex, priority) < 0)
@@ -1095,6 +1108,36 @@ eal_parse_iova_mode(const char *name)
        return 0;
 }
 
+static int
+eal_parse_base_virtaddr(const char *arg)
+{
+       char *end;
+       uint64_t addr;
+
+       errno = 0;
+       addr = strtoull(arg, &end, 16);
+
+       /* check for errors */
+       if ((errno != 0) || (arg[0] == '\0') || end == NULL || (*end != '\0'))
+               return -1;
+
+       /* make sure we don't exceed 32-bit boundary on 32-bit target */
+#ifndef RTE_ARCH_64
+       if (addr >= UINTPTR_MAX)
+               return -1;
+#endif
+
+       /* align the addr on 16M boundary, 16MB is the minimum huge page
+        * size on IBM Power architecture. If the addr is aligned to 16MB,
+        * it can align to 2MB for x86. So this alignment can also be used
+        * on x86 and other architectures.
+        */
+       internal_config.base_virtaddr =
+               RTE_PTR_ALIGN_CEIL((uintptr_t)addr, (size_t)RTE_PGSIZE_16M);
+
+       return 0;
+}
+
 /* caller is responsible for freeing the returned string */
 static char *
 available_cores(void)
@@ -1107,7 +1150,7 @@ available_cores(void)
 
        /* find the first available cpu */
        for (idx = 0; idx < RTE_MAX_LCORE; idx++) {
-               if (!lcore_config[idx].detected)
+               if (eal_cpu_detected(idx) == 0)
                        continue;
                break;
        }
@@ -1121,7 +1164,7 @@ available_cores(void)
        sequence = 0;
 
        for (idx++ ; idx < RTE_MAX_LCORE; idx++) {
-               if (!lcore_config[idx].detected)
+               if (eal_cpu_detected(idx) == 0)
                        continue;
 
                if (idx == previous + 1) {
@@ -1361,6 +1404,7 @@ eal_parse_common_option(int opt, const char *optarg,
                }
                break;
 
+#ifndef RTE_EXEC_ENV_WINDOWS
        case OPT_SYSLOG_NUM:
                if (eal_parse_syslog(optarg, conf) < 0) {
                        RTE_LOG(ERR, EAL, "invalid parameters for --"
@@ -1368,6 +1412,7 @@ eal_parse_common_option(int opt, const char *optarg,
                        return -1;
                }
                break;
+#endif
 
        case OPT_LOG_LEVEL_NUM: {
                if (eal_parse_log_level(optarg) < 0) {
@@ -1378,6 +1423,43 @@ eal_parse_common_option(int opt, const char *optarg,
                }
                break;
        }
+
+       case OPT_TRACE_NUM: {
+               if (eal_trace_args_save(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid parameters for --"
+                               OPT_TRACE "\n");
+                       return -1;
+               }
+               break;
+       }
+
+       case OPT_TRACE_DIR_NUM: {
+               if (eal_trace_dir_args_save(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid parameters for --"
+                               OPT_TRACE_DIR "\n");
+                       return -1;
+               }
+               break;
+       }
+
+       case OPT_TRACE_BUF_SIZE_NUM: {
+               if (eal_trace_bufsz_args_save(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid parameters for --"
+                               OPT_TRACE_BUF_SIZE "\n");
+                       return -1;
+               }
+               break;
+       }
+
+       case OPT_TRACE_MODE_NUM: {
+               if (eal_trace_mode_args_save(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid parameters for --"
+                               OPT_TRACE_MODE "\n");
+                       return -1;
+               }
+               break;
+       }
+
        case OPT_LCORES_NUM:
                if (eal_parse_lcores(optarg) < 0) {
                        RTE_LOG(ERR, EAL, "invalid parameter for --"
@@ -1408,6 +1490,13 @@ eal_parse_common_option(int opt, const char *optarg,
                        return -1;
                }
                break;
+       case OPT_BASE_VIRTADDR_NUM:
+               if (eal_parse_base_virtaddr(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid parameter for --"
+                                       OPT_BASE_VIRTADDR "\n");
+                       return -1;
+               }
+               break;
 
        /* don't know what to do, leave this to caller */
        default:
@@ -1452,11 +1541,11 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
        unsigned int lcore_id;
 
        for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
-               if (eal_cpu_detected(lcore_id) &&
-                               rte_lcore_has_role(lcore_id, ROLE_OFF)) {
-                       CPU_SET(lcore_id, cpuset);
-               }
+               if (rte_lcore_has_role(lcore_id, ROLE_OFF))
+                       continue;
+               RTE_CPU_OR(cpuset, cpuset, &lcore_config[lcore_id].cpuset);
        }
+       RTE_CPU_NOT(cpuset, cpuset);
 
        if (pthread_getaffinity_np(pthread_self(), sizeof(rte_cpuset_t),
                                &default_set))
@@ -1464,9 +1553,11 @@ compute_ctrl_threads_cpuset(struct internal_config *internal_cfg)
 
        RTE_CPU_AND(cpuset, cpuset, &default_set);
 
-       /* if no detected CPU is off, use master core */
-       if (!CPU_COUNT(cpuset))
-               CPU_SET(rte_get_master_lcore(), cpuset);
+       /* if no remaining cpu, use master lcore cpu affinity */
+       if (!CPU_COUNT(cpuset)) {
+               memcpy(cpuset, &lcore_config[rte_get_master_lcore()].cpuset,
+                       sizeof(*cpuset));
+       }
 }
 
 int
@@ -1589,6 +1680,11 @@ eal_check_common_options(struct internal_config *internal_cfg)
                                "with --"OPT_MATCH_ALLOCATIONS"\n");
                return -1;
        }
+       if (internal_cfg->legacy_mem && internal_cfg->memory == 0) {
+               RTE_LOG(NOTICE, EAL, "Static memory layout is selected, "
+                       "amount of reserved memory can be adjusted with "
+                       "-m or --"OPT_SOCKET_MEM"\n");
+       }
 
        return 0;
 }
@@ -1633,14 +1729,40 @@ eal_common_usage(void)
               "                      (can be used multiple times)\n"
               "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
               "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
+#ifndef RTE_EXEC_ENV_WINDOWS
               "  --"OPT_SYSLOG"            Set syslog facility\n"
+#endif
               "  --"OPT_LOG_LEVEL"=<int>   Set global log level\n"
               "  --"OPT_LOG_LEVEL"=<type-match>:<int>\n"
               "                      Set specific log level\n"
+              "  --"OPT_TRACE"=<regex-match>\n"
+              "                      Enable trace based on regular expression trace name.\n"
+              "                      By default, the trace is disabled.\n"
+              "                      User must specify this option to enable trace.\n"
+              "  --"OPT_TRACE_DIR"=<directory path>\n"
+              "                      Specify trace directory for trace output.\n"
+              "                      By default, trace output will created at\n"
+              "                      $HOME directory and parameter must be\n"
+              "                      specified once only.\n"
+              "  --"OPT_TRACE_BUF_SIZE"=<int>\n"
+              "                      Specify maximum size of allocated memory\n"
+              "                      for trace output for each thread. Valid\n"
+              "                      unit can be either 'B|K|M' for 'Bytes',\n"
+              "                      'KBytes' and 'MBytes' respectively.\n"
+              "                      Default is 1MB and parameter must be\n"
+              "                      specified once only.\n"
+              "  --"OPT_TRACE_MODE"=<o[verwrite] | d[iscard]>\n"
+              "                      Specify the mode of update of trace\n"
+              "                      output file. Either update on a file can\n"
+              "                      be wrapped or discarded when file size\n"
+              "                      reaches its maximum limit.\n"
+              "                      Default mode is 'overwrite' and parameter\n"
+              "                      must be specified once only.\n"
               "  -v                  Display version information on startup\n"
               "  -h, --help          This help\n"
               "  --"OPT_IN_MEMORY"   Operate entirely in memory. This will\n"
               "                      disable secondary process support\n"
+              "  --"OPT_BASE_VIRTADDR"     Base virtual address\n"
               "\nEAL options for DEBUG use only:\n"
               "  --"OPT_HUGE_UNLINK"       Unlink hugepage files after init\n"
               "  --"OPT_NO_HUGE"           Use malloc instead of hugetlbfs\n"