diff --git a/conf/dpvs.bond.conf.sample b/conf/dpvs.bond.conf.sample index a93679990..f6e554c8d 100644 --- a/conf/dpvs.bond.conf.sample +++ b/conf/dpvs.bond.conf.sample @@ -250,6 +250,7 @@ worker_defs { worker cpu8 { type slave cpu_id 8 + icmp_redirect_core port bond0 { rx_queue_ids 7 tx_queue_ids 7 diff --git a/conf/dpvs.conf.items b/conf/dpvs.conf.items index fee3fb379..df579f7ff 100644 --- a/conf/dpvs.conf.items +++ b/conf/dpvs.conf.items @@ -137,6 +137,7 @@ worker_defs { worker cpu5 { type kni cpu_id 5 + icmp_redirect_core port dpdk0 { tx_queue_ids 6 } diff --git a/conf/dpvs.conf.sample b/conf/dpvs.conf.sample index 28765edf3..f9baf3f7a 100644 --- a/conf/dpvs.conf.sample +++ b/conf/dpvs.conf.sample @@ -201,6 +201,7 @@ worker_defs { worker cpu8 { type slave cpu_id 8 + icmp_redirect_core port dpdk0 { rx_queue_ids 7 tx_queue_ids 7 diff --git a/conf/dpvs.conf.single-bond.sample b/conf/dpvs.conf.single-bond.sample index b7df4a427..aec33d3a8 100644 --- a/conf/dpvs.conf.single-bond.sample +++ b/conf/dpvs.conf.single-bond.sample @@ -158,6 +158,7 @@ worker_defs { worker cpu8 { type slave cpu_id 8 + icmp_redirect_core port bond0 { rx_queue_ids 7 tx_queue_ids 7 diff --git a/conf/dpvs.conf.single-nic.sample b/conf/dpvs.conf.single-nic.sample index 1e0b105ca..40a34dd99 100644 --- a/conf/dpvs.conf.single-nic.sample +++ b/conf/dpvs.conf.single-nic.sample @@ -130,6 +130,7 @@ worker_defs { worker cpu8 { type slave cpu_id 8 + icmp_redirect_core port dpdk0 { rx_queue_ids 7 tx_queue_ids 7 diff --git a/include/icmp.h b/include/icmp.h index b54d37448..8ff582434 100644 --- a/include/icmp.h +++ b/include/icmp.h @@ -26,4 +26,9 @@ void icmp_send(struct rte_mbuf *imbuf, int type, int code, uint32_t info); #define icmp4_id(icmph) (((icmph)->un).echo.id) +#ifdef CONFIG_ICMP_REDIRECT_CORE +int icmp_recv_proc(struct rte_mbuf *mbuf); +void icmp_redirect_proc(void *args); +extern lcoreid_t g_icmp_redirect_lcore_id; +#endif #endif /* __DPVS_ICMP_H__ */ diff --git a/include/ipv4.h b/include/ipv4.h index 059cc859b..ce3fb3b63 100644 --- a/include/ipv4.h +++ b/include/ipv4.h @@ -119,6 +119,7 @@ int ip4_defrag(struct rte_mbuf *mbuf, int user); uint32_t ip4_select_id(struct ipv4_hdr *iph); int ipv4_local_out(struct rte_mbuf *mbuf); +int ipv4_rcv_fin(struct rte_mbuf *mbuf); /* helper functions */ static inline struct ipv4_hdr *ip4_hdr(const struct rte_mbuf *mbuf) diff --git a/include/netif.h b/include/netif.h index 39c3e6463..cf6a4acc7 100644 --- a/include/netif.h +++ b/include/netif.h @@ -316,7 +316,7 @@ int netif_ctrl_term(void); /* netif ctrl plane cleanup */ void netif_cfgfile_init(void); void netif_keyword_value_init(void); void install_netif_keywords(void); - +void kni_ingress(struct rte_mbuf *mbuf, struct netif_port *dev); static inline void *netif_priv(struct netif_port *dev) { diff --git a/src/config.mk b/src/config.mk index a87430f11..c9871fc96 100644 --- a/src/config.mk +++ b/src/config.mk @@ -44,6 +44,7 @@ CFLAGS += -D DPVS_MAX_LCORE=64 #CFLAGS += -D CONFIG_NDISC_DEBUG #CFLAGS += -D CONFIG_MSG_DEBUG #CFLAGS += -D CONFIG_DPVS_MP_DEBUG +#CFLAGS += -D CONFIG_ICMP_REDIRECT_CORE ifeq ($(CONFIG_PDUMP), y) CFLAGS += -D CONFIG_DPVS_PDUMP diff --git a/src/icmp.c b/src/icmp.c index 00768fa6b..240311fc8 100644 --- a/src/icmp.c +++ b/src/icmp.c @@ -20,6 +20,11 @@ #include "icmp.h" #include "netinet/in.h" #include "netinet/ip_icmp.h" +#ifdef CONFIG_ICMP_REDIRECT_CORE +#include "netif.h" +#include "scheduler.h" +#include "global_data.h" +#endif #define ICMP #define RTE_LOGTYPE_ICMP RTE_LOGTYPE_USER1 @@ -318,10 +323,113 @@ static struct inet_protocol icmp_protocol = { .handler = icmp_rcv, }; +#ifdef CONFIG_ICMP_REDIRECT_CORE +static struct rte_ring *icmp_redirect_ring; +#define ICMP_RING_SIZE 2048 +lcoreid_t g_icmp_redirect_lcore_id = 0; + +static struct dpvs_lcore_job icmp_redirect = { + .name = "icmp_redirect_proc", + .type = LCORE_JOB_LOOP, + .func = icmp_redirect_proc, + .data = NULL, +}; + +static int icmp_redirect_init(void) +{ + int ret = 0; + int socket_id; + + socket_id = rte_socket_id(); + icmp_redirect_ring = rte_ring_create("icmp_redirect_ring", ICMP_RING_SIZE, socket_id, RING_F_SC_DEQ); + if (icmp_redirect_ring == NULL) { + rte_panic("create ring:icmp_redirect_ring failed!\n"); + return EDPVS_NOMEM; + } + + ret = dpvs_lcore_job_register(&icmp_redirect, LCORE_ROLE_FWD_WORKER); + if (ret < 0) { + rte_ring_free(icmp_redirect_ring); + return ret; + } + + return EDPVS_OK; +} + +int icmp_recv_proc(struct rte_mbuf *mbuf) +{ + int ret = 0; + ret = rte_ring_enqueue(icmp_redirect_ring, mbuf); + if (unlikely(-EDQUOT == ret)) { + RTE_LOG(WARNING, ICMP, "%s: icmp ring quota exceeded\n", __func__); + } + else if (ret < 0) { + RTE_LOG(WARNING, ICMP, "%s: icmp ring enqueue failed\n", __func__); + rte_pktmbuf_free(mbuf); + } + + return 0; +} + +void icmp_redirect_proc(void *args) +{ + int ret = 0; + int i = 0; + lcoreid_t cid; + struct rte_mbuf *mbufs[NETIF_MAX_PKT_BURST]; + uint16_t nb_rb = 0; + uint16_t data_off; + + cid = rte_lcore_id(); + if (cid != g_icmp_redirect_lcore_id) + return; + + nb_rb = rte_ring_dequeue_burst(icmp_redirect_ring, (void**)mbufs, NETIF_MAX_PKT_BURST, NULL); + if (nb_rb <= 0) { + return; + } + + for (i = 0; i < nb_rb; i++) { + struct rte_mbuf *mbuf = mbufs[i]; + struct netif_port *dev = netif_port_get(mbuf->port); + + /* Remove ether_hdr at the beginning of an mbuf */ + data_off = mbuf->data_off; + if (unlikely(NULL == rte_pktmbuf_adj(mbuf, sizeof(struct ether_hdr)))) { + rte_pktmbuf_free(mbuf); + return; + } + + ret = INET_HOOK(AF_INET, INET_HOOK_PRE_ROUTING, + mbuf, dev, NULL, ipv4_rcv_fin); + if (ret == EDPVS_KNICONTINUE) { + if (dev->flag & NETIF_PORT_FLAG_FORWARD2KNI) { + rte_pktmbuf_free(mbuf); + return; + } + if (likely(NULL != rte_pktmbuf_prepend(mbuf, + (mbuf->data_off - data_off)))) { + kni_ingress(mbuf, dev); + } else { + rte_pktmbuf_free(mbuf); + } + } + } + + return; +} +#endif + int icmp_init(void) { int err; +#ifdef CONFIG_ICMP_REDIRECT_CORE + err = icmp_redirect_init(); + if (err) + return err; +#endif + err = ipv4_register_protocol(&icmp_protocol, IPPROTO_ICMP); return err; diff --git a/src/ipv4.c b/src/ipv4.c index 2c054b3c7..978b8f770 100644 --- a/src/ipv4.c +++ b/src/ipv4.c @@ -326,7 +326,7 @@ static int ip4_rcv_options(struct rte_mbuf *mbuf) return EDPVS_OK; } -static int ipv4_rcv_fin(struct rte_mbuf *mbuf) +int ipv4_rcv_fin(struct rte_mbuf *mbuf) { int err; struct route_entry *rt = NULL; @@ -378,6 +378,9 @@ static int ipv4_rcv_fin(struct rte_mbuf *mbuf) static int ipv4_rcv(struct rte_mbuf *mbuf, struct netif_port *port) { +#ifdef CONFIG_ICMP_REDIRECT_CORE + struct icmphdr *ich, _icmph; +#endif struct ipv4_hdr *iph; uint16_t hlen, len; eth_type_t etype = mbuf->packet_type; /* FIXME: use other field ? */ @@ -430,6 +433,18 @@ static int ipv4_rcv(struct rte_mbuf *mbuf, struct netif_port *port) if (unlikely(iph->next_proto_id == IPPROTO_OSPF)) return EDPVS_KNICONTINUE; +#ifdef CONFIG_ICMP_REDIRECT_CORE + else if (unlikely(iph->next_proto_id == IPPROTO_ICMP)) { + ich = mbuf_header_pointer(mbuf, hlen, sizeof(_icmph), &_icmph); + if (unlikely(!ich)) + goto drop; + if (ich->type == ICMP_ECHOREPLY || ich->type == ICMP_ECHO) { + rte_pktmbuf_prepend(mbuf, (uint16_t)sizeof(struct ether_hdr)); + icmp_recv_proc(mbuf); + return EDPVS_OK; + } + } +#endif return INET_HOOK(AF_INET, INET_HOOK_PRE_ROUTING, mbuf, port, NULL, ipv4_rcv_fin); diff --git a/src/netif.c b/src/netif.c index 69b37ac9b..730d86a19 100644 --- a/src/netif.c +++ b/src/netif.c @@ -43,6 +43,9 @@ #include #include #include +#ifdef CONFIG_ICMP_REDIRECT_CORE +#include "icmp.h" +#endif #define NETIF_PKTPOOL_NB_MBUF_DEF 65535 #define NETIF_PKTPOOL_NB_MBUF_MIN 1023 @@ -145,7 +148,6 @@ static struct list_head port_ntab[NETIF_PORT_TABLE_BUCKETS]; /* hashed by name * #define NETIF_CTRL_BUFFER_LEN 4096 /* function declarations */ -static void kni_ingress(struct rte_mbuf *mbuf, struct netif_port *dev); static void kni_lcore_loop(void *dummy); @@ -734,6 +736,18 @@ static void cpu_id_handler(vector_t tokens) FREE_PTR(str); } +#ifdef CONFIG_ICMP_REDIRECT_CORE +static void cpu_icmp_redirect_handler(vector_t tokens) +{ + struct worker_conf_stream *current_worker = list_entry(worker_list.next, + struct worker_conf_stream, worker_list_node); + + RTE_LOG(INFO, NETIF, "%s(%d) used to redirect icmp packets\n", + current_worker->name, current_worker->cpu_id); + g_icmp_redirect_lcore_id = current_worker->cpu_id; +} +#endif + static void worker_port_handler(vector_t tokens) { assert(VECTOR_SIZE(tokens) >= 1); @@ -918,6 +932,9 @@ void install_netif_keywords(void) install_sublevel(); install_keyword("type", worker_type_handler, KW_TYPE_INIT); install_keyword("cpu_id", cpu_id_handler, KW_TYPE_INIT); +#ifdef CONFIG_ICMP_REDIRECT_CORE + install_keyword("icmp_redirect_core", cpu_icmp_redirect_handler, KW_TYPE_INIT); +#endif install_keyword("port", worker_port_handler, KW_TYPE_INIT); install_sublevel(); install_keyword("rx_queue_ids", rx_queue_ids_handler, KW_TYPE_INIT); @@ -2691,7 +2708,7 @@ static inline void free_mbufs(struct rte_mbuf **pkts, unsigned num) } } -static void kni_ingress(struct rte_mbuf *mbuf, struct netif_port *dev) +void kni_ingress(struct rte_mbuf *mbuf, struct netif_port *dev) { if (!kni_dev_exist(dev)) goto freepkt;