eal/arm64: fix poly64/128 compilation with GCC < 4.9
[dpdk.git] / lib / librte_eal / common / eal_common_options.c
index 6ca8af1..56c368c 100644 (file)
@@ -61,9 +61,11 @@ const char
 eal_short_options[] =
        "b:" /* pci-blacklist */
        "c:" /* coremask */
+       "s:" /* service coremask */
        "d:" /* driver */
        "h"  /* help */
        "l:" /* corelist */
+       "S:" /* service corelist */
        "m:" /* memory size */
        "n:" /* memory channels */
        "r:" /* memory ranks */
@@ -118,7 +120,7 @@ static const char *default_solib_dir = RTE_EAL_PMD_PATH;
 /*
  * Stringified version of solib path used by dpdk-pmdinfo.py
  * Note: PLEASE DO NOT ALTER THIS without making a corresponding
- * change to tools/dpdk-pmdinfo.py
+ * change to usertools/dpdk-pmdinfo.py
  */
 static const char dpdk_solib_path[] __attribute__((used)) =
 "DPDK_PLUGIN_PATH=" RTE_EAL_PMD_PATH;
@@ -126,6 +128,7 @@ static const char dpdk_solib_path[] __attribute__((used)) =
 
 static int master_lcore_parsed;
 static int mem_parsed;
+static int core_parsed;
 
 void
 eal_reset_internal_config(struct internal_config *internal_cfg)
@@ -147,12 +150,6 @@ eal_reset_internal_config(struct internal_config *internal_cfg)
        internal_cfg->base_virtaddr = 0;
 
        internal_cfg->syslog_facility = LOG_DAEMON;
-       /* default value from build option */
-#if RTE_LOG_LEVEL >= RTE_LOG_DEBUG
-       internal_cfg->log_level = RTE_LOG_INFO;
-#else
-       internal_cfg->log_level = RTE_LOG_LEVEL;
-#endif
 
        internal_cfg->xen_dom0_support = 0;
 
@@ -271,6 +268,77 @@ static int xdigit2val(unsigned char c)
        return val;
 }
 
+static int
+eal_parse_service_coremask(const char *coremask)
+{
+       struct rte_config *cfg = rte_eal_get_configuration();
+       int i, j, idx = 0;
+       unsigned int count = 0;
+       char c;
+       int val;
+
+       if (coremask == NULL)
+               return -1;
+       /* Remove all blank characters ahead and after .
+        * Remove 0x/0X if exists.
+        */
+       while (isblank(*coremask))
+               coremask++;
+       if (coremask[0] == '0' && ((coremask[1] == 'x')
+               || (coremask[1] == 'X')))
+               coremask += 2;
+       i = strlen(coremask);
+       while ((i > 0) && isblank(coremask[i - 1]))
+               i--;
+
+       if (i == 0)
+               return -1;
+
+       for (i = i - 1; i >= 0 && idx < RTE_MAX_LCORE; i--) {
+               c = coremask[i];
+               if (isxdigit(c) == 0) {
+                       /* invalid characters */
+                       return -1;
+               }
+               val = xdigit2val(c);
+               for (j = 0; j < BITS_PER_HEX && idx < RTE_MAX_LCORE;
+                               j++, idx++) {
+                       if ((1 << j) & val) {
+                               /* handle master lcore already parsed */
+                               uint32_t lcore = idx;
+                               if (master_lcore_parsed &&
+                                               cfg->master_lcore == lcore) {
+                                       RTE_LOG(ERR, EAL,
+                                               "Error: lcore %u is master lcore, cannot use as service core\n",
+                                               idx);
+                                       return -1;
+                               }
+
+                               if (!lcore_config[idx].detected) {
+                                       RTE_LOG(ERR, EAL,
+                                               "lcore %u unavailable\n", idx);
+                                       return -1;
+                               }
+                               lcore_config[idx].core_role = ROLE_SERVICE;
+                               count++;
+                       }
+               }
+       }
+
+       for (; i >= 0; i--)
+               if (coremask[i] != '0')
+                       return -1;
+
+       for (; idx < RTE_MAX_LCORE; idx++)
+               lcore_config[idx].core_index = -1;
+
+       if (count == 0)
+               return -1;
+
+       cfg->service_lcore_count = count;
+       return 0;
+}
+
 static int
 eal_parse_coremask(const char *coremask)
 {
@@ -334,6 +402,72 @@ eal_parse_coremask(const char *coremask)
        return 0;
 }
 
+static int
+eal_parse_service_corelist(const char *corelist)
+{
+       struct rte_config *cfg = rte_eal_get_configuration();
+       int i, idx = 0;
+       unsigned count = 0;
+       char *end = NULL;
+       int min, max;
+
+       if (corelist == NULL)
+               return -1;
+
+       /* Remove all blank characters ahead and after */
+       while (isblank(*corelist))
+               corelist++;
+       i = strlen(corelist);
+       while ((i > 0) && isblank(corelist[i - 1]))
+               i--;
+
+       /* Get list of cores */
+       min = RTE_MAX_LCORE;
+       do {
+               while (isblank(*corelist))
+                       corelist++;
+               if (*corelist == '\0')
+                       return -1;
+               errno = 0;
+               idx = strtoul(corelist, &end, 10);
+               if (errno || end == NULL)
+                       return -1;
+               while (isblank(*end))
+                       end++;
+               if (*end == '-') {
+                       min = idx;
+               } else if ((*end == ',') || (*end == '\0')) {
+                       max = idx;
+                       if (min == RTE_MAX_LCORE)
+                               min = idx;
+                       for (idx = min; idx <= max; idx++) {
+                               if (cfg->lcore_role[idx] != ROLE_SERVICE) {
+                                       /* handle master lcore already parsed */
+                                       uint32_t lcore = idx;
+                                       if (cfg->master_lcore == lcore &&
+                                                       master_lcore_parsed) {
+                                               RTE_LOG(ERR, EAL,
+                                                       "Error: lcore %u is master lcore, cannot use as service core\n",
+                                                       idx);
+                                               return -1;
+                                       }
+                                       lcore_config[idx].core_role =
+                                                       ROLE_SERVICE;
+                                       count++;
+                               }
+                       }
+                       min = RTE_MAX_LCORE;
+               } else
+                       return -1;
+               corelist = end + 1;
+       } while (*end != '\0');
+
+       if (count == 0)
+               return -1;
+
+       return 0;
+}
+
 static int
 eal_parse_corelist(const char *corelist)
 {
@@ -414,6 +548,13 @@ eal_parse_master_lcore(const char *arg)
        if (cfg->master_lcore >= RTE_MAX_LCORE)
                return -1;
        master_lcore_parsed = 1;
+
+       /* ensure master core is not used as service core */
+       if (lcore_config[cfg->master_lcore].core_role == ROLE_SERVICE) {
+               RTE_LOG(ERR, EAL, "Error: Master lcore is used as a service core.\n");
+               return -1;
+       }
+
        return 0;
 }
 
@@ -738,25 +879,49 @@ eal_parse_syslog(const char *facility, struct internal_config *conf)
 }
 
 static int
-eal_parse_log_level(const char *level, uint32_t *log_level)
+eal_parse_log_level(const char *arg)
 {
-       char *end;
+       char *end, *str, *type, *level;
        unsigned long tmp;
 
+       str = strdup(arg);
+       if (str == NULL)
+               return -1;
+
+       if (strchr(str, ',') == NULL) {
+               type = NULL;
+               level = str;
+       } else {
+               type = strsep(&str, ",");
+               level = strsep(&str, ",");
+       }
+
        errno = 0;
        tmp = strtoul(level, &end, 0);
 
        /* check for errors */
        if ((errno != 0) || (level[0] == '\0') ||
-           end == NULL || (*end != '\0'))
-               return -1;
+                   end == NULL || (*end != '\0'))
+               goto fail;
 
        /* log_level is a uint32_t */
        if (tmp >= UINT32_MAX)
-               return -1;
+               goto fail;
+
+       if (type == NULL) {
+               rte_log_set_global_level(tmp);
+       } else if (rte_log_set_level_regexp(type, tmp) < 0) {
+               printf("cannot set log level %s,%lu\n",
+                       type, tmp);
+               goto fail;
+       }
 
-       *log_level = tmp;
+       free(str);
        return 0;
+
+fail:
+       free(str);
+       return -1;
 }
 
 static enum rte_proc_type_t
@@ -797,6 +962,7 @@ eal_parse_common_option(int opt, const char *optarg,
                        RTE_LOG(ERR, EAL, "invalid coremask\n");
                        return -1;
                }
+               core_parsed = 1;
                break;
        /* corelist */
        case 'l':
@@ -804,6 +970,21 @@ eal_parse_common_option(int opt, const char *optarg,
                        RTE_LOG(ERR, EAL, "invalid core list\n");
                        return -1;
                }
+               core_parsed = 1;
+               break;
+       /* service coremask */
+       case 's':
+               if (eal_parse_service_coremask(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid service coremask\n");
+                       return -1;
+               }
+               break;
+       /* service corelist */
+       case 'S':
+               if (eal_parse_service_corelist(optarg) < 0) {
+                       RTE_LOG(ERR, EAL, "invalid service core list\n");
+                       return -1;
+               }
                break;
        /* size of memory */
        case 'm':
@@ -895,15 +1076,12 @@ eal_parse_common_option(int opt, const char *optarg,
                break;
 
        case OPT_LOG_LEVEL_NUM: {
-               uint32_t log;
-
-               if (eal_parse_log_level(optarg, &log) < 0) {
+               if (eal_parse_log_level(optarg) < 0) {
                        RTE_LOG(ERR, EAL,
                                "invalid parameters for --"
                                OPT_LOG_LEVEL "\n");
                        return -1;
                }
-               conf->log_level = log;
                break;
        }
        case OPT_LCORES_NUM:
@@ -912,6 +1090,7 @@ eal_parse_common_option(int opt, const char *optarg,
                                OPT_LCORES "\n");
                        return -1;
                }
+               core_parsed = 1;
                break;
 
        /* don't know what to do, leave this to caller */
@@ -923,18 +1102,46 @@ eal_parse_common_option(int opt, const char *optarg,
        return 0;
 }
 
+static void
+eal_auto_detect_cores(struct rte_config *cfg)
+{
+       unsigned int lcore_id;
+       unsigned int removed = 0;
+       rte_cpuset_t affinity_set;
+       pthread_t tid = pthread_self();
+
+       if (pthread_getaffinity_np(tid, sizeof(rte_cpuset_t),
+                               &affinity_set) < 0)
+               CPU_ZERO(&affinity_set);
+
+       for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
+               if (cfg->lcore_role[lcore_id] == ROLE_RTE &&
+                   !CPU_ISSET(lcore_id, &affinity_set)) {
+                       cfg->lcore_role[lcore_id] = ROLE_OFF;
+                       removed++;
+               }
+       }
+
+       cfg->lcore_count -= removed;
+}
+
 int
 eal_adjust_config(struct internal_config *internal_cfg)
 {
        int i;
        struct rte_config *cfg = rte_eal_get_configuration();
 
+       if (!core_parsed)
+               eal_auto_detect_cores(cfg);
+
        if (internal_config.process_type == RTE_PROC_AUTO)
                internal_config.process_type = eal_proc_type_detect();
 
        /* default master lcore is the first one */
-       if (!master_lcore_parsed)
+       if (!master_lcore_parsed) {
                cfg->master_lcore = rte_get_next_lcore(-1, 0, 0);
+               lcore_config[cfg->master_lcore].core_role = ROLE_RTE;
+       }
 
        /* if no memory amounts were requested, this will result in 0 and
         * will be overridden later, right after eal_hugepage_info_init() */
@@ -1007,6 +1214,7 @@ eal_common_usage(void)
               "                      ',' is used for single number separator.\n"
               "                      '( )' can be omitted for single element group,\n"
               "                      '@' can be omitted if cpus and lcores have the same value\n"
+              "  -s SERVICE COREMASK Hexadecimal bitmask of cores to be used as service cores\n"
               "  --"OPT_MASTER_LCORE" ID   Core ID that is used as master\n"
               "  -n CHANNELS         Number of memory channels\n"
               "  -m MB               Memory to allocate (see also --"OPT_SOCKET_MEM")\n"
@@ -1027,7 +1235,9 @@ eal_common_usage(void)
               "  --"OPT_VMWARE_TSC_MAP"    Use VMware TSC map instead of native RDTSC\n"
               "  --"OPT_PROC_TYPE"         Type of this process (primary|secondary|auto)\n"
               "  --"OPT_SYSLOG"            Set syslog facility\n"
-              "  --"OPT_LOG_LEVEL"         Set default log level\n"
+              "  --"OPT_LOG_LEVEL"=<int>   Set global log level\n"
+              "  --"OPT_LOG_LEVEL"=<type-regexp>,<int>\n"
+              "                      Set specific log level\n"
               "  -v                  Display version information on startup\n"
               "  -h, --help          This help\n"
               "\nEAL options for DEBUG use only:\n"