+ }
+
+ rte_eth_macaddr_get(port, &vmdq_ports_eth_addr[port]);
+ printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
+ " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
+ (unsigned)port,
+ vmdq_ports_eth_addr[port].addr_bytes[0],
+ vmdq_ports_eth_addr[port].addr_bytes[1],
+ vmdq_ports_eth_addr[port].addr_bytes[2],
+ vmdq_ports_eth_addr[port].addr_bytes[3],
+ vmdq_ports_eth_addr[port].addr_bytes[4],
+ vmdq_ports_eth_addr[port].addr_bytes[5]);
+
+ /* Set mac for each pool.*/
+ for (q = 0; q < num_pools; q++) {
+ struct ether_addr mac;
+
+ mac = pool_addr_template;
+ mac.addr_bytes[4] = port;
+ mac.addr_bytes[5] = q;
+ printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n",
+ port, q,
+ mac.addr_bytes[0], mac.addr_bytes[1],
+ mac.addr_bytes[2], mac.addr_bytes[3],
+ mac.addr_bytes[4], mac.addr_bytes[5]);
+ retval = rte_eth_dev_mac_addr_add(port, &mac,
+ q + vmdq_pool_base);
+ if (retval) {
+ printf("mac addr add failed at pool %d\n", q);
+ return retval;
+ }
+ }
+
+ return 0;
+}
+
+/* Check num_pools parameter and set it if OK*/
+static int
+vmdq_parse_num_pools(const char *q_arg)
+{
+ char *end = NULL;
+ int n;
+
+ /* parse number string */
+ n = strtol(q_arg, &end, 10);
+ if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+ if (n != 16 && n != 32)
+ return -1;
+ if (n == 16)
+ num_pools = ETH_16_POOLS;
+ else
+ num_pools = ETH_32_POOLS;
+
+ return 0;
+}
+
+/* Check num_tcs parameter and set it if OK*/
+static int
+vmdq_parse_num_tcs(const char *q_arg)
+{
+ char *end = NULL;
+ int n;
+
+ /* parse number string */
+ n = strtol(q_arg, &end, 10);
+ if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (n != 4 && n != 8)
+ return -1;
+ if (n == 4)
+ num_tcs = ETH_4_TCS;
+ else
+ num_tcs = ETH_8_TCS;
+
+ return 0;
+}
+
+static int
+parse_portmask(const char *portmask)
+{
+ char *end = NULL;
+ unsigned long pm;
+
+ /* parse hexadecimal string */
+ pm = strtoul(portmask, &end, 16);
+ if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
+ return -1;
+
+ if (pm == 0)
+ return -1;
+
+ return pm;
+}
+
+/* Display usage */
+static void
+vmdq_usage(const char *prgname)
+{
+ printf("%s [EAL options] -- -p PORTMASK]\n"
+ " --nb-pools NP: number of pools (32 default, 16)\n"
+ " --nb-tcs NP: number of TCs (4 default, 8)\n"
+ " --enable-rss: enable RSS (disabled by default)\n",
+ prgname);
+}
+
+/* Parse the argument (num_pools) given in the command line of the application */
+static int
+vmdq_parse_args(int argc, char **argv)
+{
+ int opt;
+ int option_index;
+ unsigned i;
+ const char *prgname = argv[0];
+ static struct option long_option[] = {
+ {"nb-pools", required_argument, NULL, 0},
+ {"nb-tcs", required_argument, NULL, 0},
+ {"enable-rss", 0, NULL, 0},
+ {NULL, 0, 0, 0}
+ };
+
+ /* Parse command line */
+ while ((opt = getopt_long(argc, argv, "p:", long_option,
+ &option_index)) != EOF) {
+ switch (opt) {
+ /* portmask */
+ case 'p':
+ enabled_port_mask = parse_portmask(optarg);
+ if (enabled_port_mask == 0) {
+ printf("invalid portmask\n");
+ vmdq_usage(prgname);
+ return -1;
+ }
+ break;
+ case 0:
+ if (!strcmp(long_option[option_index].name, "nb-pools")) {
+ if (vmdq_parse_num_pools(optarg) == -1) {
+ printf("invalid number of pools\n");
+ return -1;
+ }
+ }
+
+ if (!strcmp(long_option[option_index].name, "nb-tcs")) {
+ if (vmdq_parse_num_tcs(optarg) == -1) {
+ printf("invalid number of tcs\n");
+ return -1;
+ }
+ }
+
+ if (!strcmp(long_option[option_index].name, "enable-rss"))
+ rss_enable = 1;
+ break;
+
+ default:
+ vmdq_usage(prgname);
+ return -1;
+ }
+ }
+
+ for (i = 0; i < RTE_MAX_ETHPORTS; i++) {
+ if (enabled_port_mask & (1 << i))
+ ports[num_ports++] = (uint8_t)i;
+ }
+
+ if (num_ports < 2 || num_ports % 2) {
+ printf("Current enabled port number is %u,"
+ " but it should be even and at least 2\n", num_ports);
+ return -1;
+ }