#include <stdio.h>
#include <stdlib.h>
#include "ethapp.h"
#define MAX_PORTS RTE_MAX_ETHPORTS
#define MAX_BURST_LENGTH 32
#define PORT_RX_QUEUE_SIZE 1024
#define PORT_TX_QUEUE_SIZE 1024
#define PKTPOOL_EXTRA_SIZE 512
#define PKTPOOL_CACHE 32
struct txq_port {
    uint16_t cnt_unsent;
    struct rte_mbuf *buf_frames[MAX_BURST_LENGTH];
 
};
struct app_port {
    struct txq_port txq;
    int port_active;
    int port_dirty;
    int idx_port;
};
struct app_config {
    struct app_port ports[MAX_PORTS];
    int cnt_ports;
    int exit_now;
};
struct app_config app_cfg;
void lock_port(int idx_port)
{
    struct app_port *ptr_port = &app_cfg.ports[idx_port];
}
void unlock_port(int idx_port)
{
    struct app_port *ptr_port = &app_cfg.ports[idx_port];
}
void mark_port_active(int idx_port)
{
    struct app_port *ptr_port = &app_cfg.ports[idx_port];
    ptr_port->port_active = 1;
}
void mark_port_inactive(int idx_port)
{
    struct app_port *ptr_port = &app_cfg.ports[idx_port];
    ptr_port->port_active = 0;
}
void mark_port_newmac(int idx_port)
{
    struct app_port *ptr_port = &app_cfg.ports[idx_port];
    ptr_port->port_dirty = 1;
}
static void setup_ports(struct app_config *app_cfg, int cnt_ports)
{
    int idx_port;
    int size_pktpool;
    char str_name[16];
    uint16_t nb_rxd = PORT_RX_QUEUE_SIZE;
    uint16_t nb_txd = PORT_TX_QUEUE_SIZE;
    memset(&cfg_port, 0, sizeof(cfg_port));
    for (idx_port = 0; idx_port < cnt_ports; idx_port++) {
        struct app_port *ptr_port = &app_cfg->ports[idx_port];
        size_pktpool = dev_info.rx_desc_lim.nb_max +
            dev_info.tx_desc_lim.nb_max + PKTPOOL_EXTRA_SIZE;
        snprintf(str_name, 16, "pkt_pool%i", idx_port);
            str_name,
            size_pktpool, PKTPOOL_CACHE,
            0,
            RTE_MBUF_DEFAULT_BUF_SIZE,
            );
        if (ptr_port->pkt_pool == NULL)
                "rte_pktmbuf_pool_create failed"
                );
        printf("Init port %i..\n", idx_port);
        ptr_port->port_active = 1;
        ptr_port->port_dirty = 0;
        ptr_port->idx_port = idx_port;
                 "rte_eth_dev_configure failed");
                             &nb_txd) < 0)
                 "rte_eth_dev_adjust_nb_rx_tx_desc failed");
                idx_port, 0, nb_rxd,
                ptr_port->pkt_pool) < 0)
                 "rte_eth_rx_queue_setup failed"
                );
        txconf = dev_info.default_txconf;
                idx_port, 0, nb_txd,
                 "rte_eth_tx_queue_setup failed"
                );
                 "%s:%i: rte_eth_dev_start failed",
                 __FILE__, __LINE__
                );
    }
}
static void process_frame(struct app_port *ptr_port,
{
}
static int slave_main(__attribute__((unused)) void *ptr_data)
{
    struct app_port *ptr_port;
    struct txq_port *txq;
    uint16_t cnt_recv_frames;
    uint16_t idx_frame;
    uint16_t cnt_sent;
    uint16_t idx_port;
    uint16_t lock_result;
    while (app_cfg.exit_now == 0) {
        for (idx_port = 0; idx_port < app_cfg.cnt_ports; idx_port++) {
            
            ptr_port = &app_cfg.ports[idx_port];
            if (lock_result == 0)
                continue;
            if (ptr_port->port_active == 0) {
                continue;
            }
            txq = &ptr_port->txq;
            
            if (ptr_port->port_dirty == 1) {
                    &ptr_port->mac_addr);
                ptr_port->port_dirty = 0;
            }
            
                ptr_port->idx_port, 0,
                &txq->buf_frames[txq->cnt_unsent],
                RTE_DIM(txq->buf_frames) - txq->cnt_unsent
 
                );
            if (cnt_recv_frames > 0) {
                for (idx_frame = 0;
                    idx_frame < cnt_recv_frames;
                    idx_frame++) {
                    ptr_frame = txq->buf_frames[
                        idx_frame + txq->cnt_unsent];
                    process_frame(ptr_port, ptr_frame);
                }
                txq->cnt_unsent += cnt_recv_frames;
            }
            
            if (txq->cnt_unsent > 0) {
                    ptr_port->idx_port, 0,
                    txq->buf_frames,
                    txq->cnt_unsent
                    );
                
                for (idx_frame = cnt_sent;
                    idx_frame < txq->cnt_unsent;
                    idx_frame++)
                    txq->buf_frames[idx_frame - cnt_sent] =
                        txq->buf_frames[idx_frame];
                txq->cnt_unsent -= cnt_sent;
            }
        } 
    } 
    return 0;
}
int main(int argc, char **argv)
{
    int cnt_args_parsed;
    uint32_t id_core;
    uint32_t cnt_ports;
    
    if (cnt_args_parsed < 0)
        rte_exit(EXIT_FAILURE, 
"rte_eal_init(): Failed");
 
    printf("Number of NICs: %i\n", cnt_ports);
    if (cnt_ports == 0)
        rte_exit(EXIT_FAILURE, 
"No available NIC ports!\n");
 
    if (cnt_ports > MAX_PORTS) {
        printf("Info: Using only %i of %i ports\n",
            cnt_ports, MAX_PORTS
            );
        cnt_ports = MAX_PORTS;
    }
    setup_ports(&app_cfg, cnt_ports);
    app_cfg.exit_now = 0;
    app_cfg.cnt_ports = cnt_ports;
        rte_exit(EXIT_FAILURE, 
"No available slave core!\n");
 
    
    ethapp_main();
    app_cfg.exit_now = 1;
            return -1;
    }
    return 0;
}