#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 "fwd.h"
static struct fwd_info fwd_info;
struct fwd_info *fwd = &fwd_info;
#define foreach_thd_lport(_t, _lp) \
for (int _i = 0; _i < _t->lport_cnt && (_lp = _t->lports[_i]); _i++, _lp = _t->lports[_i])
static uint64_t dest_eth_addr[CNE_MAX_ETHPORTS];
xmm_t val_eth[CNE_MAX_ETHPORTS];
struct ipv4_l3fwd_lpm_route {
uint32_t ip;
uint8_t depth;
uint8_t if_out;
};
#define IPV4_L3FWD_LPM_NUM_ROUTES \
(sizeof(ipv4_l3fwd_lpm_route_array) / sizeof(ipv4_l3fwd_lpm_route_array[0]))
static struct ipv4_l3fwd_lpm_route ipv4_l3fwd_lpm_route_array[] = {
};
void
{
struct cne_graph_cluster_stats *stats = NULL;
const char *pattern = "worker_*";
if (pthread_barrier_wait(&fwd->barrier) > 0)
CNE_ERR("Failed to wait on barrier\n");
while (!fwd->timer_quit) {
sleep(1);
if (stats)
break;
}
if (!stats)
return;
vt_make_space(16 + (fwd->flags & FWD_DEBUG_STATS) ? 12 : 0);
while (!fwd->timer_quit) {
vt_save();
vt_restore();
sleep(1);
}
fflush(stdout);
}
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)
{
const char *patterns[] = {"ip4*", "pktdev_tx-*", "pkt_drop", NULL};
char name[128];
for (int i = 0; patterns[i]; i++)
if (add_graph_pattern(gi, patterns[i]))
goto err;
foreach_thd_lport (thd, lport) {
snprintf(name,
sizeof(name),
"pktdev_rx-%u", lport->
lpid);
if (add_graph_pattern(gi, name))
goto err;
}
snprintf(name,
sizeof(name),
"worker_%d",
cne_id());
CNE_INFO("Create Graph '%s'\n", name);
if (!gi->graph)
CNE_ERR_GOTO(err,
"cne_graph_lookup(): graph '%s' not found\n", name);
return 0;
err:
return -1;
}
static int
initialize_routes(void)
{
uint8_t rewrite_data[2 *
sizeof(
struct ether_addr)];
uint8_t rewrite_len;
memset(&rewrite_data, 0, sizeof(rewrite_data));
rewrite_len = sizeof(rewrite_data);
for (uint16_t i = 0; i < IPV4_L3FWD_LPM_NUM_ROUTES; i++) {
char route_str[INET6_ADDRSTRLEN * 4];
char abuf[INET6_ADDRSTRLEN];
struct in_addr in;
uint32_t dst_port;
dst_port = ipv4_l3fwd_lpm_route_array[i].if_out;
break;
in.s_addr = htonl(ipv4_l3fwd_lpm_route_array[i].ip);
snprintf(route_str, sizeof(route_str), "%s / %d (%d)",
inet_ntop(AF_INET, &in, abuf, sizeof(abuf)), ipv4_l3fwd_lpm_route_array[i].depth,
ipv4_l3fwd_lpm_route_array[i].if_out);
ipv4_l3fwd_lpm_route_array[i].depth, i,
CNE_ERR_RET(
"Unable to add ip4 route %s to graph\n", route_str);
memcpy(rewrite_data, val_eth + dst_port, rewrite_len);
CNE_ERR_RET(
"Unable to add next hop %u for route %s\n", i, route_str);
CNE_INFO("Added route %s, next_hop %u\n", route_str, i);
}
return 0;
}
void
thread_func(void *arg)
{
graph_info_t *gi;
int tid;
pthread_setaffinity_np(pthread_self(),
sizeof(cpu_set_t), &thd->
group->
lcore_bitmap);
if (pthread_barrier_wait(&fwd->barrier) > 0)
if (tid < 0)
if (tid >= cne_countof(fwd->graph_info))
CNE_ERR_GOTO(err,
"Number of threads cannot be >= %d\n", cne_countof(fwd->graph_info));
gi = &fwd->graph_info[tid];
if (initialize_graph(thd, gi))
if (initialize_routes())
CNE_INFO(
"Entering main loop on tid %d, graph %s\n",
cne_id(), gi->graph->name);
return;
err:
(void)pthread_barrier_wait(&fwd->barrier);
}
static int
{
CNE_DEBUG("No lports attached to thread '%s'\n", thd->name);
else {
foreach_thd_lport (thd, lport) {
cne_printf(
">>> [blue]lport [red]%d[] - '[cyan]%s[]'\n", lport->
lpid, lport->name);
CNE_ERR("pktdev_close() returned error\n");
}
}
return 0;
}
static void
my_quit(struct fwd_info *f)
{
if (f && !f->timer_quit) {
f->timer_quit = 1;
jcfg_thread_foreach(f->jinfo, _thread_quit, f);
if (pthread_barrier_destroy(&f->barrier))
CNE_ERR("Failed to destroy pthread barrier\n");
}
}
static void
__on_exit(int val, void *arg, int exit_type)
{
struct fwd_info *f = 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);
my_quit(f);
break;
default:
my_quit(f);
break;
}
break;
cne_printf_pos(99, 1,
"\n>>> [cyan]Terminating with status [green]%d[]\n", val);
my_quit(f);
break;
cne_printf_pos(99, 1,
"\n>>> [cyan]User called exit, with [red]%d[]\n", val);
my_quit(f);
break;
default:
cne_printf_pos(99, 1,
"\n>>> [cyan]Unknow Exit type %d[]\n", exit_type);
break;
}
fflush(stdout);
}
static int
initialize(void)
{
uint16_t nb_conf = 0;
CNE_INFO(
"pktmbuf_t size %ld, udata64 offset %ld\n",
sizeof(
pktmbuf_t),
*(uint64_t *)(val_eth + lportid) = dest_eth_addr[lportid];
pktdev_conf[nb_conf++].port_id = lportid;
CNE_ERR_RET(
"Unable to get MAC address from lport %d\n", lportid);
}
return 0;
}
int
main(int argc, char **argv)
{
int signals[] = {SIGINT, SIGTERM, SIGUSR1};
memset(&fwd_info, 0, sizeof(struct fwd_info));
if (
cne_on_exit(__on_exit, fwd, signals, cne_countof(signals)) < 0)
if (parse_args(argc, argv))
cne_printf(
"\n*** [yellow]l3fwd-graph[], [blue]PID[]: [green]%d[] [blue]lcore[]: [green]%d[]\n",
if (initialize())
if (pthread_barrier_wait(&fwd->barrier) > 0)
while (!fwd->timer_quit)
sleep(1);
if (pthread_barrier_destroy(&fwd->barrier))
return 0;
err:
if (fwd->barrier_inited && pthread_barrier_destroy(&fwd->barrier))
CNE_ERR("Failed to destroy barrier\n");
cne_printf(
"\n*** [cyan]l3fwd-graph Application[], [blue]PID[]: [green]%d[] failed\n",
getpid());
return -1;
}
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)
#define ETHER_LOCAL_ADMIN_ADDR
CNDP_API __cne_always_inline void ether_addr_copy(const struct ether_addr *ea_from, struct ether_addr *ea_to)
CNDP_API void cne_graph_cluster_stats_get(struct cne_graph_cluster_stats *stat, bool skip_cb)
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)
CNDP_API void cne_graph_cluster_stats_destroy(struct cne_graph_cluster_stats *stat)
#define CNE_GRAPH_ID_INVALID
CNDP_API struct cne_graph_cluster_stats * cne_graph_cluster_stats_create(const struct cne_graph_cluster_stats_param *prm)
static void cne_graph_walk(struct cne_graph *graph)
#define CNE_IPV4(a, b, c, d)
#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)
CNDP_API int metrics_destroy(void)
int cne_node_eth_config(struct cne_node_pktdev_config *cfg, uint16_t cnt)
int cne_node_ip4_rewrite_add(uint16_t next_hop, uint8_t *rewrite_data, uint8_t rewrite_len, uint16_t dst_port)
@ CNE_NODE_IP4_LOOKUP_NEXT_REWRITE
int cne_node_ip4_route_add(uint32_t ip, uint8_t depth, uint16_t next_hop, enum cne_node_ip4_lookup_next next_node)
CNDP_API int pktdev_macaddr_get(uint16_t lport_id, struct ether_addr *mac_addr)
CNDP_API int pktdev_close(uint16_t lport_id)
CNDP_API int pktdev_is_valid_port(uint16_t lport_id)
CNDP_API uint16_t pktdev_port_count(void)
const char ** graph_patterns
uint16_t nb_graph_patterns