#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700 
#endif
 
 
#include <pthread.h>             
#include <sched.h>               
#include <stdio.h>               
#include <stdlib.h>              
#include <getopt.h>              
#include <bsd/string.h>          
#include <pmd_af_xdp.h>          
#include <stdint.h>              
#include <strings.h>             
#include <string.h>              
 
#include <openssl/pem.h>
#include "picotls.h"
#include "picotls/openssl.h"
#include "quicly.h"
#include "quicly/defaults.h"
#include "quicly/streambuf.h"
 
 
#include "cnet-quic.h"         
 
 
static int
process_callback(
jcfg_info_t *j, 
void *_obj, 
void *arg, 
int idx)
 
{
    struct cnet_info *ci = arg;
    uint32_t cache_sz;
    char *umem_addr;
 
    if (!_obj)
        return -1;
 
 
    switch (obj.
hdr->cbtype) {
 
        break;
 
        break;
 
        if (!strcmp(obj.
opt->name, NO_METRICS_TAG)) {
 
        } 
else if (!strcmp(obj.
opt->name, NO_RESTAPI_TAG)) {
 
        } 
else if (!strcmp(obj.
opt->name, ENABLE_CLI_TAG)) {
 
        }
        break;
 
        
            CNE_ERR_RET(
"**** Failed to allocate mmap memory %ld\n",
 
 
            cache_sz = MEMPOOL_CACHE_MAX_SIZE;
 
 
        
 
            
            ri->addr = umem_addr;
 
            
            if (!pi) {
                CNE_ERR_RET(
"pktmbuf_pool_init() failed for region %d\n", i);
 
            }
            snprintf(name, 
sizeof(name), 
"%s-%d", obj.
umem->name, i);
 
            ri->pool = pi;
        }
        break;
 
        do {
            struct fwd_port *pd;
            struct lport_cfg pcfg = {0};
 
 
            pd = calloc(1, sizeof(struct fwd_port));
            if (!pd)
                CNE_ERR_RET(
"Unable to allocate fwd_port structure\n");
 
            lport->priv_ = pd;
 
            pcfg.bufsz        = umem->
bufsz;
 
            pcfg.rx_nb_desc   = umem->
rxdesc;
 
            pcfg.tx_nb_desc   = umem->
txdesc;
 
            pcfg.flags        = lport->
flags;
 
 
            if (!pcfg.addr) {
                free(pd);
                CNE_ERR_RET(
"lport %s region index %d >= %d or not configured correctly\n",
 
            }
 
            
            strlcpy(pcfg.pmd_name, lport->
pmd_name, 
sizeof(pcfg.pmd_name));
 
            strlcpy(pcfg.ifname, lport->
netdev, 
sizeof(pcfg.ifname));
 
            strlcpy(pcfg.name, lport->name, sizeof(pcfg.name));
 
            if (pd->lport < 0) {
                free(pd);
                CNE_ERR_RET(
"Unable to setup port %s, pktdev_port_setup() failed\n", lport->name);
 
            }
                free(pd);
                CNE_ERR_RET(
"Failed to register netif for %s\n", lport->name);
 
            }
        } while ((0));
        break;
 
        break;
 
            pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t),
                CNE_ERR_RET(
"Unable to create thread %d (%s) or type %s\n", idx, obj.
thd->name,
 
        } else
            CNE_WARN("[yellow]*** [cyan]Unknown thread type[] '[orange]%s[]'\n",
        break;
 
        break;
 
    default:
        return -1;
    }
 
    return 0;
}
 
static void
print_usage(char *prog_name)
{
    cne_printf(
"Usage: %s [-h] [-c json_file] <mode>\n" 
               "  <mode>         Mode types drop, tx-only, or [lb | loopback]\n"
               "  -c <json-file> The JSON configuration file\n"
               "  -s <cmd-file>  File containing cli commands for setup\n"
               "  -C             Wait on unix domain socket for JSON or JSON-C file\n"
               "  -d             More debug stats are displayed\n"
               "  -D             JCFG debug decoding\n"
               "  -V             JCFG information verbose\n"
               "  -P             JCFG debug parsing\n"
               "  -U             Disable UDP checksum (default enabled)\n"
               "  -L [level]     Enable a logging level\n"
               "  -h             Display the help information\n",
               prog_name);
}
 
int
parse_args(int argc, char **argv)
{
    
    struct option lgopts[] = {
        {"cert", required_argument, 0, 'R'},
        {"key", required_argument, 0, 'Y'},
        {NULL, 0, 0, 0}
    };
    
    int opt, ret, option_index, flags = 0;
    char json_file[1024] = {0};
    char *prgname        = argv[0];
    char **argvopt;
    const int old_optind   = optind;
    const int old_optopt   = optopt;
    char *const old_optarg = optarg;
    char log_level[16]     = {0};
 
    cinfo->flags = FWD_ENABLE_UDP_CKSUM;
 
    argvopt = argv;
    optind  = 1;
 
    
    for (;;) {
        opt = getopt_long(argc, argvopt, "hc:s:dCDPVUuL:", lgopts, &option_index);
        if (opt == EOF)
            break;
 
        switch (opt) {
        case 'h':
            print_usage(argv[0]);
            return -1;
 
        case 'c':
            strlcpy(json_file, optarg, sizeof(json_file));
            break;
 
        case 's':
            break;
 
        case 'U':
            cinfo->flags &= ~FWD_ENABLE_UDP_CKSUM;
            break;
 
        case 'd':
            cinfo->flags |= FWD_DEBUG_STATS;
            break;
 
        case 'C':
            break;
 
        case 'D':
            break;
 
        case 'P':
            break;
 
        case 'V':
            break;
 
        case 'L':
            strlcpy(log_level, optarg, sizeof(log_level));
                CNE_ERR("Invalid command option\n");
                print_usage(argv[0]);
                return -1;
            }
            break;
 
        default:
            CNE_ERR("Invalid command option\n");
            print_usage(argv[0]);
            return -1;
        }
    }
 
    ret          = -1;
    cinfo->jinfo = 
jcfg_parser(flags, (
const char *)json_file);
 
    if (cinfo->jinfo == NULL)
        CNE_ERR_GOTO(out, 
"*** Did not find any configuration to use ***\n");
 
 
    
    CNE_DEBUG("Setup barrier for %d threads\n", jcfg_num_threads(cinfo->jinfo));
 
    if (pthread_barrier_init(&cinfo->barrier, NULL, jcfg_num_threads(cinfo->jinfo)))
    cinfo->barrier_inited = true;
 
    if (
jcfg_process(cinfo->jinfo, flags, process_callback, cinfo))
 
 
    if (!cinfo->opts.no_metrics && enable_metrics())
 
    if (optind >= 0)
        argv[optind - 1] = prgname;
    ret = optind - 1;
 
out:
    
    optind = old_optind;
    optopt = old_optopt;
    optarg = old_optarg;
 
    return ret;
}
static int cli_add_cmdfile(const char *filename)
 
CNDP_API int cne_log_set_level_str(char *log_level)
 
#define CNE_ERR_GOTO(lbl,...)
 
#define LPORT_SHARED_UMEM
 
CNDP_API void * mmap_addr(mmap_t *mm)
 
CNDP_API int mmap_free(mmap_t *mmap)
 
CNDP_API mmap_t * mmap_alloc(uint32_t bufcnt, uint32_t bufsz, mmap_type_t hugepage)
 
CNDP_API size_t mmap_size(mmap_t *mm, uint32_t *bufcnt, uint32_t *bufsz)
 
CNDP_API int cne_printf(const char *fmt,...)
 
CNDP_API int thread_create(const char *name, thd_func_t func, void *arg)
 
CNDP_API int cnet_netif_register(uint16_t lpid, char *ifname, char *netdev)
Register lport, ifname and netdev to create a netif structure.
 
CNDP_API jcfg_info_t * jcfg_parser(int flags, const char *s)
 
static int jcfg_default_get_u32(jcfg_info_t *jinfo, const char *name, uint32_t *v)
 
CNDP_API char * jcfg_lport_region(jcfg_lport_t *lport, uint32_t *objcnt)
 
CNDP_API int jcfg_process(jcfg_info_t *jinfo, int flags, jcfg_parse_cb_t *cb, void *cb_arg)
 
CNDP_API int pktdev_port_setup(lport_cfg_t *c)
 
static void pktmbuf_info_name_set(pktmbuf_info_t *pi, const char *str)
 
CNDP_API pktmbuf_info_t * pktmbuf_pool_create(char *addr, uint32_t bufcnt, uint32_t bufsz, uint32_t cache_sz, mbuf_ops_t *ops)