diff --git a/.gitignore b/.gitignore index 0855f4f4..cd28963a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,4 @@ app/nginx-1.16.0/objs/ app/nginx-1.16.0/Makefile dpdk/.ci/ dpdk/.travis.yml +.vscode/ diff --git a/lib/ff_config.c b/lib/ff_config.c index be4514b1..1741caa7 100644 --- a/lib/ff_config.c +++ b/lib/ff_config.c @@ -589,6 +589,8 @@ ini_parse_handler(void* user, const char* section, const char* name, pconfig->dpdk.pkt_tx_delay = atoi(value); } else if (MATCH("kni", "enable")) { pconfig->kni.enable= atoi(value); + } else if (MATCH("kni", "kni_action")) { + pconfig->kni.kni_action= strdup(value); } else if (MATCH("kni", "method")) { pconfig->kni.method= strdup(value); } else if (MATCH("kni", "tcp_port")) { @@ -804,6 +806,16 @@ ff_check_config(struct ff_config *cfg) } } + if(cfg->kni.kni_action) { + if (strcasecmp(cfg->kni.kni_action,"alltokni") && + strcasecmp(cfg->kni.kni_action,"alltoff") && + strcasecmp(cfg->kni.kni_action,"default")){ + fprintf(stderr, "conf kni.kni_action[alltokni|alltoff|default] is error(%s)\n", + cfg->kni.kni_action); + return -1; + } + } + #define CHECK_VALID(n) \ do { \ if (!pc->n) { \ diff --git a/lib/ff_config.h b/lib/ff_config.h index be04ab5d..f89654db 100644 --- a/lib/ff_config.h +++ b/lib/ff_config.h @@ -145,6 +145,7 @@ struct ff_config { struct { int enable; + char *kni_action; char *method; char *tcp_port; char *udp_port; diff --git a/lib/ff_dpdk_if.c b/lib/ff_dpdk_if.c index c7f0e7d9..1c788319 100644 --- a/lib/ff_dpdk_if.c +++ b/lib/ff_dpdk_if.c @@ -70,6 +70,7 @@ int enable_kni; static int kni_accept; +static int knictl_action = FF_KNICTL_ACTION_DEFAULT; #endif static int numa_on; @@ -476,6 +477,21 @@ init_msg_ring(void) } #ifdef FF_KNI + +static enum FF_KNICTL_CMD get_kni_action(const char *c){ + if (!c) + return FF_KNICTL_ACTION_DEFAULT; + if (0 == strcasecmp(c, "alltokni")){ + return FF_KNICTL_ACTION_ALL_TO_KNI; + } else if (0 == strcasecmp(c, "alltoff")){ + return FF_KNICTL_ACTION_ALL_TO_FF; + } else if (0 == strcasecmp(c, "default")){ + return FF_KNICTL_ACTION_DEFAULT; + } else { + return FF_KNICTL_ACTION_DEFAULT; + } +} + static int init_kni(void) { @@ -484,6 +500,8 @@ init_kni(void) if(strcasecmp(ff_global_cfg.kni.method, "accept") == 0) kni_accept = 1; + knictl_action = get_kni_action(ff_global_cfg.kni.kni_action); + ff_kni_init(nb_ports, ff_global_cfg.kni.tcp_port, ff_global_cfg.kni.udp_port); @@ -1109,10 +1127,22 @@ process_packets(uint16_t port_id, uint16_t queue_id, struct rte_mbuf **bufs, #endif ff_veth_input(ctx, rtem); #ifdef FF_KNI - } else if (enable_kni && - ((filter == FILTER_KNI && kni_accept) || - (filter == FILTER_UNKNOWN && !kni_accept)) ) { - ff_kni_enqueue(port_id, rtem); + } else if (enable_kni) { + if (knictl_action == FF_KNICTL_ACTION_ALL_TO_KNI){ + ff_kni_enqueue(port_id, rtem); + } else if (knictl_action == FF_KNICTL_ACTION_ALL_TO_FF){ + ff_veth_input(ctx, rtem); + } else if (knictl_action == FF_KNICTL_ACTION_DEFAULT){ + if (enable_kni && + ((filter == FILTER_KNI && kni_accept) || + (filter == FILTER_UNKNOWN && !kni_accept)) ) { + ff_kni_enqueue(port_id, rtem); + } else { + ff_veth_input(ctx, rtem); + } + } else { + ff_veth_input(ctx, rtem); + } #endif } else { ff_veth_input(ctx, rtem); @@ -1257,6 +1287,26 @@ handle_traffic_msg(struct ff_msg *msg) msg->result = 0; } +#ifdef FF_KNI +static inline void +handle_knictl_msg(struct ff_msg *msg) +{ + if (msg->knictl.kni_cmd == FF_KNICTL_CMD_SET){ + switch (msg->knictl.kni_action){ + case FF_KNICTL_ACTION_ALL_TO_FF: knictl_action = FF_KNICTL_ACTION_ALL_TO_FF; msg->result = 0; printf("new kni action: alltoff\n"); break; + case FF_KNICTL_ACTION_ALL_TO_KNI: knictl_action = FF_KNICTL_ACTION_ALL_TO_KNI; msg->result = 0; printf("new kni action: alltokni\n"); break; + case FF_KNICTL_ACTION_DEFAULT: knictl_action = FF_KNICTL_ACTION_DEFAULT; msg->result = 0; printf("new kni action: default\n"); break; + default: msg->result = -1; + } + } + else if (msg->knictl.kni_cmd == FF_KNICTL_CMD_GET){ + msg->knictl.kni_action = knictl_action; + } else { + msg->result = -2; + } +} +#endif + static inline void handle_default_msg(struct ff_msg *msg) { @@ -1295,6 +1345,11 @@ handle_msg(struct ff_msg *msg, uint16_t proc_id) case FF_TRAFFIC: handle_traffic_msg(msg); break; +#ifdef FF_KNI + case FF_KNICTL: + handle_knictl_msg(msg); + break; +#endif default: handle_default_msg(msg); break; diff --git a/lib/ff_msg.h b/lib/ff_msg.h index d9a7cfa7..be1b16a5 100644 --- a/lib/ff_msg.h +++ b/lib/ff_msg.h @@ -44,6 +44,7 @@ enum FF_MSG_TYPE { FF_NGCTL, FF_IPFW_CTL, FF_TRAFFIC, + FF_KNICTL, /* * to add other msg type before FF_MSG_NUM @@ -106,6 +107,25 @@ struct ff_traffic_args { uint64_t tx_bytes; }; +enum FF_KNICTL_CMD { + FF_KNICTL_CMD_GET, + FF_KNICTL_CMD_SET, + FF_KNICTL_CMD_UNKNOWN, +}; + +enum FF_KNICTL_ACTION { + FF_KNICTL_ACTION_DEFAULT, + FF_KNICTL_ACTION_ALL_TO_KNI, + FF_KNICTL_ACTION_ALL_TO_FF, + FF_KNICTL_ACTION_MAX +}; + +struct ff_knictl_args { + int kni_cmd; + int kni_action; +}; + + #define MAX_MSG_BUF_SIZE 10240 /* structure of ipc msg */ @@ -126,6 +146,7 @@ struct ff_msg { struct ff_ngctl_args ngctl; struct ff_ipfw_args ipfw; struct ff_traffic_args traffic; + struct ff_knictl_args knictl; }; } __attribute__((packed)) __rte_cache_aligned; diff --git a/tools/Makefile b/tools/Makefile index 9f7a2231..ae7b5942 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,4 +1,4 @@ -SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl ipfw arp traffic +SUBDIRS=compat libutil libmemstat libxo libnetgraph sysctl ifconfig route top netstat ngctl ipfw arp traffic knictl PREFIX_BIN=/usr/local/bin all: @@ -20,6 +20,7 @@ install: ln -sf ${PREFIX_BIN}/f-stack/sysctl ${PREFIX_BIN}/ff_sysctl ln -sf ${PREFIX_BIN}/f-stack/top ${PREFIX_BIN}/ff_top ln -sf ${PREFIX_BIN}/f-stack/traffic ${PREFIX_BIN}/ff_traffic + ln -sf ${PREFIX_BIN}/f-stack/knictl ${PREFIX_BIN}/knictl uninstall: rm -rf ${PREFIX_BIN}/f-stack diff --git a/tools/knictl/Makefile b/tools/knictl/Makefile new file mode 100644 index 00000000..2ba7b26f --- /dev/null +++ b/tools/knictl/Makefile @@ -0,0 +1,9 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 +# $FreeBSD$ + + +TOPDIR?=${CURDIR}/../.. + +PROG=knictl + +include ${TOPDIR}/tools/prog.mk diff --git a/tools/knictl/knictl.c b/tools/knictl/knictl.c new file mode 100644 index 00000000..f47bc4a6 --- /dev/null +++ b/tools/knictl/knictl.c @@ -0,0 +1,149 @@ +#include +#include +#include "ff_ipc.h" + +void +usage(void) +{ + printf("Usage:\n"); + printf(" knictl [-p ] [-P ] " + "[-a alltokni/alltoff/default][-n]\n use `-a` to set kni action\n use `-n` to show \n"); +} + +enum FF_KNICTL_CMD get_action(const char *c){ + if (!c) + return FF_KNICTL_ACTION_MAX; + if (0 == strcasecmp(c, "alltokni")){ + return FF_KNICTL_ACTION_ALL_TO_KNI; + } else if (0 == strcasecmp(c, "alltoff")){ + return FF_KNICTL_ACTION_ALL_TO_FF; + } else if (0 == strcasecmp(c, "default")){ + return FF_KNICTL_ACTION_DEFAULT; + } else { + return FF_KNICTL_ACTION_MAX; + } +} + +const char * get_action_str(enum FF_KNICTL_CMD cmd){ + switch (cmd) + { + case FF_KNICTL_ACTION_ALL_TO_KNI: + return "alltokni"; + break; + case FF_KNICTL_ACTION_ALL_TO_FF: + return "alltoff"; + break; + case FF_KNICTL_ACTION_DEFAULT: + return "default"; + break; + default: + return "unknown"; + break; + } + return "unknown"; +} + + +int knictl_status(struct ff_knictl_args *knictl){ + int ret; + struct ff_msg *msg, *retmsg = NULL; + + msg = ff_ipc_msg_alloc(); + if (msg == NULL) { + errno = ENOMEM; + return -1; + } + + msg->msg_type = FF_KNICTL; + msg->knictl = *knictl; + ret = ff_ipc_send(msg); + if (ret < 0) { + errno = EPIPE; + ff_ipc_msg_free(msg); + return -1; + } + + do { + if (retmsg != NULL) { + ff_ipc_msg_free(retmsg); + } + + ret = ff_ipc_recv(&retmsg, msg->msg_type); + if (ret < 0) { + errno = EPIPE; + ff_ipc_msg_free(msg); + return -1; + } + } while (msg != retmsg); + + *knictl = retmsg->knictl; + + ff_ipc_msg_free(msg); + + return 0; +} + +int main(int argc, char **argv) +{ + int ch, has_action = 0, i; + enum FF_KNICTL_CMD cmd; + struct ff_knictl_args knictl = {.kni_cmd = FF_KNICTL_CMD_GET}; + struct ff_knictl_args pknictl[RTE_MAX_LCORE]; + int proc_id = 0, max_proc_id = -1; + + ff_ipc_init(); + while ((ch = getopt(argc, argv, "hp:P:a:n")) != -1) { + switch(ch) { + case 'p': + proc_id = atoi(optarg); + ff_set_proc_id(proc_id); + break; + case 'P': + max_proc_id = atoi(optarg); + if (max_proc_id < 0 || max_proc_id >= RTE_MAX_LCORE) { + usage(); + return -1; + } + break; + case 'a': + if (has_action){ + usage(); + return -1; + } + has_action = 1; + cmd = knictl.kni_cmd = FF_KNICTL_CMD_SET; + knictl.kni_action = get_action(optarg); + if (knictl.kni_action < FF_KNICTL_ACTION_DEFAULT || knictl.kni_action >= FF_KNICTL_ACTION_MAX){ + usage(); + return -1; + } + break; + case 'n': + if (has_action){ + usage(); + return -1; + } + has_action = 1; + cmd = knictl.kni_cmd = FF_KNICTL_CMD_GET; + break; + case 'h': + default: + usage(); + return -1; + } + } + if (max_proc_id == -1){ + printf(" using default proc id\n"); + int ret = knictl_status(&knictl); + printf(" %s to %s knictl type: %s\n", ret ? "fail": "success", knictl.kni_cmd == FF_KNICTL_CMD_GET ? "get" : "set", get_action_str(knictl.kni_action)); + } + else { + int proc_id = 0; + for (; proc_id < max_proc_id; proc_id++){ + pknictl[proc_id] = knictl; + ff_set_proc_id(proc_id); + int ret = knictl_status(&pknictl[proc_id]); + printf(" %s to %s knictl type: %s, proc_id: %d\n", ret ? "fail": "success", pknictl[proc_id].kni_cmd == FF_KNICTL_CMD_GET ? "get" : "set", get_action_str(pknictl[proc_id].kni_action), proc_id); + } + } +} \ No newline at end of file