#include <arpa/inet.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <net/ethernet.h>
#include <netinet/in.h>
#include <sched.h>
#include <stddef.h>
#include "cnet-graph.h"
static struct cnet_info cnet_info;
struct cnet_info *cinfo = &cnet_info;
typedef int (*cb_types_t)(int cd);
#define foreach_thd_lport(_t, _lp) \
for (int _i = 0; _i < _t->lport_cnt && (_lp = _t->lports[_i]); _i++, _lp = _t->lports[_i])
static inline int
add_graph_pattern(graph_info_t *gi, const char *pattern)
{
if ((gi->cnt + 1) > gi->nb_patterns) {
gi->cnt++;
gi->patterns = realloc(gi->patterns, ((gi->cnt + 1) * sizeof(char *)));
if (!gi->patterns)
}
gi->patterns[gi->nb_patterns++] = strdup(pattern);
gi->patterns[gi->nb_patterns] = NULL;
return 0;
}
static int
initialize_graph(
jcfg_thd_t *thd, graph_info_t *gi)
{
int ret;
snprintf(graph_name,
sizeof(graph_name),
"cnet_%d",
cne_id());
if (cinfo->flags & FWD_DEBUG_STATS)
cne_printf(
"[magenta]Graph Name[]: '[orange]%s[]', [magenta]Thread name [orange]%s[]\n",
graph_name, thd->name);
if (ret < 0)
CNE_ERR_GOTO(err,
"Unable to find %s option name\n", thd->name);
CNE_ERR_GOTO(err,
"Thread %s does not have any graph patterns\n", thd->name);
if (cinfo->flags & FWD_DEBUG_STATS)
for (
int i = 0; i < pattern_array->
array_sz; i++) {
char *pat = pattern_array->
arr[i]->
str;
if ((CNET_ENABLE_TCP == 0) && !strncasecmp("tcp*", pat, 4))
continue;
if (cinfo->flags & FWD_DEBUG_STATS)
if (add_graph_pattern(gi, pat))
goto err;
}
if (cinfo->flags & FWD_DEBUG_STATS)
foreach_thd_lport (thd, lport) {
snprintf(node_name,
sizeof(node_name),
"eth_rx-%u", lport->
lpid);
if (add_graph_pattern(gi, node_name))
goto err;
}
CNE_ERR_GOTO(err,
"cne_graph_create(): graph_id '%s' for uid %u\n", graph_name,
cne_id());
if (!gi->graph)
CNE_ERR_GOTO(err,
"cne_graph_lookup(): graph '%s' not found\n", graph_name);
this_stk->graph = gi->graph;
free(gi->patterns);
return 0;
err:
free(gi->patterns);
return -1;
}
#define RECV_NB_MBUFS 128
static int
udp_recv(int cd)
{
ssize_t nb_mbufs;
switch (cinfo->test) {
case DROP_TEST:
nb_mbufs =
chnl_recv(cd, mbufs, RECV_NB_MBUFS);
if (nb_mbufs > 0)
else if (nb_mbufs < 0)
CNE_ERR("Receive packets failed\n");
break;
case LOOPBACK_TEST:
nb_mbufs =
chnl_recv(cd, mbufs, RECV_NB_MBUFS);
if (nb_mbufs > 0) {
CNE_ERR("Unable to send packets\n");
}
} else if (nb_mbufs < 0)
CNE_ERR("Receive packets failed\n");
break;
case TXONLY_TEST:
break;
default:
break;
}
return 0;
}
static int
udp_close(int cd)
{
CNE_DEBUG("Close channel %d\n", cd);
return 0;
}
static int
tcp_accept(int cd)
{
int ncd;
struct sockaddr addr = {0};
socklen_t addr_len;
addr_len = sizeof(struct sockaddr_in);
if (ncd < 0)
CNE_ERR_RET(
"Accept returned an error from %d descriptor\n", cd);
CNE_DEBUG("Accept new chnl %d\n", ncd);
return 0;
}
static int
tcp_recv(int cd)
{
int nb_mbufs;
switch (cinfo->test) {
case DROP_TEST:
nb_mbufs =
chnl_recv(cd, mbufs, RECV_NB_MBUFS);
if (nb_mbufs <= 0) {
if (nb_mbufs < 0 && errno != ENOTCONN)
CNE_ERR("Receive packets failed: %d %s\n", errno, strerror(errno));
break;
}
for (int i = 0; i < nb_mbufs; i++) {
}
}
break;
case LOOPBACK_TEST:
nb_mbufs =
chnl_recv(cd, mbufs, RECV_NB_MBUFS);
if (nb_mbufs <= 0) {
if (nb_mbufs < 0)
CNE_ERR("Receive packets failed %d: %s\n", errno, strerror(errno));
break;
}
CNE_DEBUG("Loopback Received %d\n", nb_mbufs);
CNE_ERR("Unable to send packets\n");
}
break;
case TXONLY_TEST:
break;
default:
break;
}
return 0;
}
static int
{
CNE_DEBUG("Close channel %d\n", cd);
CNE_ERR_RET(
"unable to close connection on %d channel\n", cd);
return 0;
}
static int
proto_callback(int ctype, int cd)
{
udp_recv, udp_close, tcp_accept, tcp_recv, tcp_close,
};
return funcs[ctype](cd);
return -1;
}
void
thread_func(void *arg)
{
graph_info_t *gi;
pthread_t pid = pthread_self();
int tid;
CNE_RET(
"pthread_setaffinity_np('%s') failed\n", thd->name);
}
if (pthread_barrier_wait(&cinfo->barrier) > 0)
CNE_RET(
"cnet_stk_initialize('%s') failed\n", thd->name);
if (tid >= cne_countof(cinfo->graph_info))
CNE_ERR_GOTO(err,
"Number of threads cannot be >= %d\n", cne_countof(cinfo->graph_info));
gi = &cinfo->graph_info[tid];
if (initialize_graph(thd, gi))
snprintf(chnl_name, sizeof(chnl_name), "%s-chnl", thd->name);
CNE_ERR_GOTO(skip,
"Unable to find %s option name\n", thd->name);
CNE_ERR_GOTO(skip,
"Thread %s does not have any graph patterns\n", thd->name);
if (cinfo->flags & FWD_DEBUG_STATS)
cne_printf(
" [magenta]Channels[]: [cyan]%s[]\n%-12s", chnl_name,
"");
for (
int i = 0; i < chnl_array->
array_sz; i++) {
char *s = chnl_array->arr[i]->
str;
if (!s || (s[0] == '\0'))
if (cinfo->flags & FWD_DEBUG_STATS)
proto_callback) < 0)
break;
if (cinfo->flags & FWD_DEBUG_STATS)
}
if (cinfo->flags & FWD_DEBUG_STATS)
skip:
return;
err:
if (pthread_barrier_wait(&cinfo->barrier))
CNE_ERR("Barrier wait failed: %s\n", strerror(errno));
}
void
thread_timer_func(void *arg)
{
pthread_t pid = pthread_self();
CNE_RET(
"pthread_setaffinity_np('%s') failed\n", thd->name);
}
if (pthread_barrier_wait(&cinfo->barrier) > 0)
CNE_RET(
"Failed to wait for barrier\n");
CNE_DEBUG(
"Timer assigned to lcore %d, terminating\n",
cne_lcore_id());
}
static int
{
foreach_thd_lport (thd, lport) {
cne_printf(
" [orange]Close[] [magenta]lport [red]%d[] - '[cyan]%s[]'\n", lport->
lpid,
lport->name);
CNE_ERR("pktdev_close() returned error\n");
}
}
return 0;
}
static void
my_quit(struct cnet_info *ci)
{
if (ci) {
jcfg_thread_foreach(ci->jinfo, _thread_quit, ci);
}
}
static void
__on_exit(int val, void *arg, int exit_type)
{
struct cnet_info *ci = arg;
switch (exit_type) {
switch (val) {
case SIGUSR1:
break;
case SIGINT:
cne_printf_pos(99, 1,
"\n>>> [cyan]Terminating with signal [green]%d[]\n", val);
break;
default:
cne_printf_pos(99, 1,
"\n>>> [cyan]Terminating with signal [red]%d[]\n", val);
break;
}
break;
cne_printf_pos(99, 1,
"\n>>> [cyan]Terminating with status [green]%d[]\n", val);
break;
cne_printf_pos(99, 1,
"\n>>> [cyan]User called exit, with [red]%d[]\n", val);
break;
default:
cne_printf_pos(99, 1,
"\n>>> [cyan]Unknow Exit type %d[]\n", exit_type);
break;
}
my_quit(ci);
}
static int
initialize(void)
{
uint16_t nb_conf = 0;
CNE_DEBUG(
"pktmbuf_t size %ld, udata64 offset %ld\n",
sizeof(
pktmbuf_t),
pkt_conf[nb_conf++].port_id = lportid;
return 0;
}
static int
cli_tree(void)
{
}
int
main(int argc, char **argv)
{
const char *tests[] = {"Unknown", "Drop", "Loopback", "Tx Only", NULL};
int signals[] = {SIGINT, SIGTERM, SIGUSR1};
memset(&cnet_info, 0, sizeof(struct cnet_info));
if (
cne_init() < 0 || parse_args(argc, argv))
if (
cne_on_exit(__on_exit, cinfo, signals, cne_countof(signals)) < 0)
cne_printf(
"\n[yellow]*** [cyan:-:italic]CNET-GRAPH Application[], "
"[green]Mode[]: [magenta:-:italic]%s[], "
"[green]Burst Size[]: [magenta]%d[] \n",
tests[cinfo->test], cinfo->burst);
cne_printf(
"\n*** [yellow]cnet-graph[], [blue]PID[]: [green]%d[] [blue]lcore[]: [green]%d[]\n",
if (!cinfo->cnet)
usleep(1000);
if (initialize())
if (pthread_barrier_wait(&cinfo->barrier) > 0)
if (pthread_barrier_destroy(&cinfo->barrier))
usleep(500000);
cne_printf(
">>> [cyan]CNET-Graph Application Exiting[]: [green]Bye![]\n");
return 0;
err:
if (pthread_barrier_destroy(&cinfo->barrier))
CNE_ERR("Failed to destroy barrier\n");
leave:
cne_printf(
"\n*** [cyan]cnet-graph Application[], [blue]PID[]: [green]%d[] failed\n", getpid());
return -1;
}
CNDP_API void cli_start(const char *msg)
CNDP_API int cli_setup_with_tree(cli_tree_t tree)
CNDP_API void cli_destroy(void)
CNDP_API int cli_create(struct cli_cfg *cfg)
CNDP_API int cli_create_with_defaults(struct cli_cfg *cfg)
CNDP_API int cne_id(void)
CNDP_API int cne_init(void)
CNDP_API int cne_on_exit(on_exit_fn_t exit_fn, void *arg, int *signals, int nb_signals)
#define offsetof(TYPE, MEMBER)
CNDP_API int cne_graph_destroy(cne_graph_t id)
CNDP_API cne_graph_t cne_graph_create(const char *name, const char **patterns)
CNDP_API struct cne_graph * cne_graph_lookup(const char *name)
#define CNE_GRAPH_ID_INVALID
#define CNE_GRAPH_NAMESIZE
static void cne_graph_walk(struct cne_graph *graph)
CNDP_API uint32_t cne_log_get_level(void)
#define CNE_ERR_GOTO(lbl,...)
CNDP_API int cne_printf_pos(int16_t r, int16_t c, const char *fmt,...)
CNDP_API int cne_printf(const char *fmt,...)
CNDP_API int cne_lcore_id(void)
void cne_timer_subsystem_init(void)
void cne_timer_manage(void)
CNDP_API struct cnet * cnet_create(void)
Create cnet structure and use default value, will call cnet_config_create().
CNDP_API int cnet_add_cli_cmds(void)
Called to initialize the CLI commands for the CNET structure.
CNDP_API void cnet_stop(void)
Stop and free resources of the cnet structure.
CNDP_API int chnl_open(const char *str, int flags, chnl_cb_t fn)
CNDP_API int chnl_recv(int cd, pktmbuf_t **mbufs, size_t len)
#define CHNL_ENABLE_UDP_CHECKSUM
CNDP_API int chnl_accept(int cd, struct sockaddr *sa, socklen_t *addrlen)
Accept on a channel similar to 'accept()'.
CNDP_API int chnl_send(int cd, pktmbuf_t **mbufs, uint16_t nb_mbufs)
CNDP_API int chnl_close(int cd)
CNDP_API int cnet_stk_initialize(struct cnet *cnet)
Initialize the stack instance.
CNDP_API int cnet_eth_node_config(struct pkt_eth_node_config *cfg, uint16_t cnt)
CNDP_API int jcfg_option_array_get(jcfg_info_t *jinfo, const char *name, obj_value_t **val_arr)
CNDP_API int metrics_destroy(void)
CNDP_API int pktdev_close(uint16_t lport_id)
CNDP_API uint16_t pktdev_port_count(void)
#define pktmbuf_data_len(m)
#define pktmbuf_mtod(m, t)
static void pktmbuf_free_bulk(pktmbuf_t **mbufs, unsigned int count)