+/* 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;
+ }
+
+ return 0;
+}
+
+static void
+update_mac_address(struct rte_mbuf *m, unsigned dst_port)
+{
+ struct rte_ether_hdr *eth;
+ void *tmp;
+
+ eth = rte_pktmbuf_mtod(m, struct rte_ether_hdr *);
+
+ /* 02:00:00:00:00:xx */
+ tmp = ð->d_addr.addr_bytes[0];
+ *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);
+
+ /* src addr */
+ rte_ether_addr_copy(&vmdq_ports_eth_addr[dst_port], ð->s_addr);
+}
+