#include <stdint.h>
#include <sys/queue.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <inttypes.h>
#include <getopt.h>
#define MAX_QUEUES 1024
#define NUM_MBUFS_PER_PORT (MAX_QUEUES * RTE_MAX(RTE_TEST_RX_DESC_DEFAULT, \
                        RTE_TEST_TX_DESC_DEFAULT))
#define MBUF_CACHE_SIZE 64
#define MAX_PKT_BURST 32
#define RTE_TEST_RX_DESC_DEFAULT 1024
#define RTE_TEST_TX_DESC_DEFAULT 1024
#define INVALID_PORT_ID 0xFF
static uint32_t enabled_port_mask;
static uint16_t ports[RTE_MAX_ETHPORTS];
static unsigned num_ports;
static uint16_t num_queues, num_vmdq_queues;
static uint16_t vmdq_pool_base, vmdq_queue_base;
static uint8_t rss_enable;
        .split_hdr_size = 0,
    },
    .txmode = {
    },
    
    .rx_adv_conf = {
        .vmdq_dcb_conf = {
            .enable_default_pool = 0,
            .default_pool = 0,
            .nb_pool_maps = 0,
            .pool_map = {{0, 0},},
            .dcb_tc = {0},
        },
        .dcb_rx_conf = {
                .dcb_tc = {0},
        },
        .vmdq_rx_conf = {
            .enable_default_pool = 0,
            .default_pool = 0,
            .nb_pool_maps = 0,
            .pool_map = {{0, 0},},
        },
    },
    .tx_adv_conf = {
        .vmdq_dcb_tx_conf = {
            .dcb_tc = {0},
        },
    },
};
volatile unsigned long rxPackets[MAX_QUEUES] = {0};
const uint16_t vlan_tags[] = {
    0,  1,  2,  3,  4,  5,  6,  7,
    8,  9, 10, 11,  12, 13, 14, 15,
    16, 17, 18, 19, 20, 21, 22, 23,
    24, 25, 26, 27, 28, 29, 30, 31
};
const uint16_t num_vlans = 
RTE_DIM(vlan_tags);
     .
addr_bytes = {0x52, 0x54, 0x00, 0x12, 0x00, 0x00}
};
static inline int
{
    struct rte_eth_dcb_rx_conf   dcb_conf;
    struct rte_eth_vmdq_dcb_tx_conf tx_conf;
    uint8_t i;
    conf.nb_pool_maps = num_pools;
    vmdq_conf.nb_pool_maps = num_pools;
    conf.enable_default_pool = 0;
    vmdq_conf.enable_default_pool = 0;
    conf.default_pool = 0; 
    vmdq_conf.default_pool = 0;
    for (i = 0; i < conf.nb_pool_maps; i++) {
        conf.pool_map[i].vlan_id = vlan_tags[i];
        vmdq_conf.pool_map[i].vlan_id = vlan_tags[i];
        conf.pool_map[i].pools = 1UL << i;
        vmdq_conf.pool_map[i].pools = 1UL << i;
    }
        conf.dcb_tc[i] = i % num_tcs;
        dcb_conf.dcb_tc[i] = i % num_tcs;
        tx_conf.dcb_tc[i] = i % num_tcs;
    }
    (void)(
rte_memcpy(eth_conf, &vmdq_dcb_conf_default, 
sizeof(*eth_conf)));
              sizeof(conf)));
              sizeof(dcb_conf)));
              sizeof(vmdq_conf)));
              sizeof(tx_conf)));
    if (rss_enable) {
                            ETH_RSS_UDP |
                            ETH_RSS_TCP |
                            ETH_RSS_SCTP;
    }
    return 0;
}
static inline int
{
    uint16_t rxRingSize = RTE_TEST_RX_DESC_DEFAULT;
    uint16_t txRingSize = RTE_TEST_TX_DESC_DEFAULT;
    int retval;
    uint16_t q;
    uint16_t queues_per_pool;
    uint32_t max_nb_pools;
    uint64_t rss_hf_tmp;
    
    max_nb_pools = (uint32_t)dev_info.max_vmdq_pools;
    
    if (num_pools > max_nb_pools) {
        printf("num_pools %d >max_nb_pools %d\n",
            num_pools, max_nb_pools);
        return -1;
    }
    
    vmdq_queue_base = dev_info.vmdq_queue_base;
    vmdq_pool_base  = dev_info.vmdq_pool_base;
    printf("vmdq queue base: %d pool base %d\n",
        vmdq_queue_base, vmdq_pool_base);
    if (vmdq_pool_base == 0) {
        num_vmdq_queues = dev_info.max_rx_queues;
        num_queues = dev_info.max_rx_queues;
        if (num_tcs != num_vmdq_queues / num_pools) {
            printf("nb_tcs %d is invalid considering with"
                " nb_pools %d, nb_tcs * nb_pools should = %d\n",
                num_tcs, num_pools, num_vmdq_queues);
            return -1;
        }
    } else {
        queues_per_pool = dev_info.vmdq_queue_num /
                  dev_info.max_vmdq_pools;
        if (num_tcs > queues_per_pool) {
            printf("num_tcs %d > num of queues per pool %d\n",
                num_tcs, queues_per_pool);
            return -1;
        }
        num_vmdq_queues = num_pools * queues_per_pool;
        num_queues = vmdq_queue_base + num_vmdq_queues;
        printf("Configured vmdq pool num: %u,"
            " each vmdq pool has %u queues\n",
            num_pools, queues_per_pool);
    }
        return -1;
    retval = get_eth_conf(&port_conf);
    if (retval < 0)
        return retval;
        dev_info.flow_type_rss_offloads;
        printf("Port %u modified RSS hash function based on hardware support,"
            "requested:%#"PRIx64" configured:%#"PRIx64"\n",
            rss_hf_tmp,
    }
    
    if (retval != 0)
        return retval;
                &txRingSize);
    if (retval != 0)
        return retval;
    if (
RTE_MAX(rxRingSize, txRingSize) >
         RTE_MAX(RTE_TEST_RX_DESC_DEFAULT, RTE_TEST_TX_DESC_DEFAULT)) {
         printf("Mbuf pool has an insufficient size for port %u.\n",
        return -1;
    }
    for (q = 0; q < num_queues; q++) {
                    NULL,
                    mbuf_pool);
        if (retval < 0) {
            printf("initialize rx queue %d failed\n", q);
            return retval;
        }
    }
    txq_conf = dev_info.default_txconf;
    for (q = 0; q < num_queues; q++) {
                    &txq_conf);
        if (retval < 0) {
            printf("initialize tx queue %d failed\n", q);
            return retval;
        }
    }
    if (retval < 0) {
        printf(
"port %d start failed\n", 
port);
        return retval;
    }
    printf("Port %u MAC: %02"PRIx8" %02"PRIx8" %02"PRIx8
            " %02"PRIx8" %02"PRIx8" %02"PRIx8"\n",
            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]);
    
    for (q = 0; q < num_pools; q++) {
        mac = pool_addr_template;
        mac.addr_bytes[5] = q;
        printf("Port %u vmdq pool %u set mac %02x:%02x:%02x:%02x:%02x:%02x\n",
            mac.addr_bytes[0], mac.addr_bytes[1],
            mac.addr_bytes[2], mac.addr_bytes[3],
            mac.addr_bytes[4], mac.addr_bytes[5]);
                q + vmdq_pool_base);
        if (retval) {
            printf("mac addr add failed at pool %d\n", q);
            return retval;
        }
    }
    return 0;
}
static int
vmdq_parse_num_pools(const char *q_arg)
{
    char *end = NULL;
    int n;
    
    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)
    else
    return 0;
}
static int
vmdq_parse_num_tcs(const char *q_arg)
{
    char *end = NULL;
    int n;
    
    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)
    else
    return 0;
}
static int
parse_portmask(const char *portmask)
{
    char *end = NULL;
    unsigned long pm;
    
    pm = strtoul(portmask, &end, 16);
    if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0'))
        return -1;
    if (pm == 0)
        return -1;
    return pm;
}
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);
}
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}
    };
    
    while ((opt = getopt_long(argc, argv, "p:", long_option,
        &option_index)) != EOF) {
        switch (opt) {
        
        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)
{
    void *tmp;
    
    *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40);
    
}
static void
sighup_handler(int signum)
{
    unsigned q = vmdq_queue_base;
    for (; q < num_queues; q++) {
        if (q % (num_vmdq_queues / num_pools) == 0)
            printf("\nPool %u: ", (q - vmdq_queue_base) /
                          (num_vmdq_queues / num_pools));
        printf("%lu ", rxPackets[q]);
    }
    printf("\nFinished handling signal %d\n", signum);
}
static int
lcore_main(void *arg)
{
    const uintptr_t core_num = (uintptr_t)arg;
    uint16_t startQueue, endQueue;
    uint16_t q, i, p;
    const uint16_t quot = (uint16_t)(num_vmdq_queues / num_cores);
    const uint16_t remainder = (uint16_t)(num_vmdq_queues % num_cores);
    if (remainder) {
        if (core_num < remainder) {
            startQueue = (uint16_t)(core_num * (quot + 1));
            endQueue = (uint16_t)(startQueue + quot + 1);
        } else {
            startQueue = (uint16_t)(core_num * quot + remainder);
            endQueue = (uint16_t)(startQueue + quot);
        }
    } else {
        startQueue = (uint16_t)(core_num * quot);
        endQueue = (uint16_t)(startQueue + quot);
    }
    
    startQueue += vmdq_queue_base;
    endQueue   += vmdq_queue_base;
    printf("Core %u(lcore %u) reading queues %i-%i\n", (unsigned)core_num,
    if (startQueue == endQueue) {
        printf("lcore %u has nothing to do\n", (unsigned)core_num);
        return 0;
    }
    for (;;) {
        const uint16_t buf_size = sizeof(buf) / sizeof(buf[0]);
        for (p = 0; p < num_ports; p++) {
            const uint8_t src = ports[p];
            const uint8_t dst = ports[p ^ 1]; 
            if ((src == INVALID_PORT_ID) || (dst == INVALID_PORT_ID))
                continue;
            for (q = startQueue; q < endQueue; q++) {
                    q, buf, buf_size);
                    continue;
                rxPackets[q] += rxCount;
                for (i = 0; i < rxCount; i++)
                    update_mac_address(buf[i], dst);
                    q, buf, rxCount);
                if (txCount != rxCount) {
                    for (i = txCount; i < rxCount; i++)
                }
            }
        }
    }
}
static unsigned check_ports_num(unsigned nb_ports)
{
    unsigned valid_num_ports = num_ports;
    unsigned portid;
    if (num_ports > nb_ports) {
        printf("\nSpecified port number(%u) exceeds total system port number(%u)\n",
            num_ports, nb_ports);
        num_ports = nb_ports;
    }
    for (portid = 0; portid < num_ports; portid++) {
            printf("\nSpecified port ID(%u) is not valid\n",
                ports[portid]);
            ports[portid] = INVALID_PORT_ID;
            valid_num_ports--;
        }
    }
    return valid_num_ports;
}
int
main(int argc, char *argv[])
{
    unsigned cores;
    unsigned lcore_id;
    uintptr_t i;
    int ret;
    unsigned nb_ports, valid_num_ports;
    uint16_t portid;
    signal(SIGHUP, sighup_handler);
    
    if (ret < 0)
        rte_exit(EXIT_FAILURE, 
"Error with EAL initialization\n");
     argc -= ret;
    argv += ret;
    
    ret = vmdq_parse_args(argc, argv);
    if (ret < 0)
        rte_exit(EXIT_FAILURE, 
"Invalid VMDQ argument\n");
     if ((cores & (cores - 1)) != 0 || cores > RTE_MAX_LCORE) {
        rte_exit(EXIT_FAILURE,
"This program can only run on an even"                 " number of cores(1-%d)\n\n", RTE_MAX_LCORE);
    }
    
    valid_num_ports = check_ports_num(nb_ports);
    if (valid_num_ports < 2 || valid_num_ports % 2) {
        printf("Current valid ports number is %u\n", valid_num_ports);
        rte_exit(EXIT_FAILURE, 
"Error with valid ports number is not even or less than 2\n");
     }
        NUM_MBUFS_PER_PORT * nb_ports, MBUF_CACHE_SIZE,
    if (mbuf_pool == NULL)
        rte_exit(EXIT_FAILURE, 
"Cannot create mbuf pool\n");
     
        
        if ((enabled_port_mask & (1 << portid)) == 0) {
            printf("\nSkipping disabled port %d\n", portid);
            continue;
        }
        if (port_init(portid, mbuf_pool) != 0)
            rte_exit(EXIT_FAILURE, 
"Cannot initialize network ports\n");
     }
    
    i = 0;
    }
    
    (void) lcore_main((void*)i);
    return 0;
}