X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=VNFs%2FDPPD-PROX%2Frx_pkt.c;h=e1756cb33d19b580d8230ca661d31145601bc965;hb=090efc9c81c8b1943d162249d965a3e40502d50e;hp=a6c1fd107f8f0094ccfe39ef14479eb31ad704c5;hpb=51759157a499326cfe69ec0eecb00b1c5879bf50;p=samplevnf.git diff --git a/VNFs/DPPD-PROX/rx_pkt.c b/VNFs/DPPD-PROX/rx_pkt.c index a6c1fd10..e1756cb3 100644 --- a/VNFs/DPPD-PROX/rx_pkt.c +++ b/VNFs/DPPD-PROX/rx_pkt.c @@ -1,5 +1,5 @@ /* -// Copyright (c) 2010-2017 Intel Corporation +// Copyright (c) 2010-2020 Intel Corporation // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -24,7 +24,14 @@ #include "stats.h" #include "log.h" #include "mbuf_utils.h" -#include "input.h" /* Needed for callback on dump */ +#include "prefetch.h" +#include "arp.h" +#include "tx_pkt.h" +#include "handle_master.h" +#include "input.h" +#include "prox_ipv6.h" /* Needed for callback on dump */ + +#define TCP_PORT_BGP rte_cpu_to_be_16(179) /* _param version of the rx_pkt_hw functions are used to create two instances of very similar variations of these functions. The @@ -38,7 +45,9 @@ packets are received if the dequeue step involves finding 32 packets. */ -#define MIN_PMD_RX 32 +#define MIN_PMD_RX 32 +#define PROX_L3 1 +#define PROX_NDP 2 static uint16_t rx_pkt_hw_port_queue(struct port_queue *pq, struct rte_mbuf **mbufs, int multi) { @@ -70,93 +79,298 @@ static void next_port_pow2(struct rx_params_hw *rx_params_hw) rx_params_hw->last_read_portid = (rx_params_hw->last_read_portid + 1) & rx_params_hw->rxport_mask; } -static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbufs, int multi, - void (*next)(struct rx_params_hw *rx_param_hw)) +static inline void dump_l3(struct task_base *tbase, struct rte_mbuf *mbuf) +{ + if (unlikely(tbase->aux->task_rt_dump.n_print_rx)) { + if ((tbase->aux->task_rt_dump.input == NULL) || (tbase->aux->task_rt_dump.input->reply == NULL)) { + plogdx_info(mbuf, "RX: "); + } else { + struct input *input = tbase->aux->task_rt_dump.input; + char tmp[128]; + int strlen; +#if RTE_VERSION >= RTE_VERSION_NUM(1,8,0,0) + int port_id = mbuf->port; +#else + int port_id = mbuf->pkt.in_port; +#endif + strlen = snprintf(tmp, sizeof(tmp), "pktdump,%d,%d\n", port_id, + rte_pktmbuf_pkt_len(mbuf)); + input->reply(input, tmp, strlen); + input->reply(input, rte_pktmbuf_mtod(mbuf, char *), rte_pktmbuf_pkt_len(mbuf)); + input->reply(input, "\n", 1); + } + tbase->aux->task_rt_dump.n_print_rx --; + if (0 == tbase->aux->task_rt_dump.n_print_rx) { + task_base_del_rx_pkt_function(tbase, rx_pkt_dump); + } + } + if (unlikely(tbase->aux->task_rt_dump.n_trace)) { + plogdx_info(mbuf, "RX: "); + tbase->aux->task_rt_dump.n_trace--; + } +} + +static inline void handle_ipv4(struct task_base *tbase, struct rte_mbuf **mbufs, int i, prox_rte_ipv4_hdr *pip, int *skip) +{ + prox_rte_tcp_hdr *tcp = (prox_rte_tcp_hdr *)(pip + 1); + if (pip->next_proto_id == IPPROTO_ICMP) { + dump_l3(tbase, mbufs[i]); + tx_ring(tbase, tbase->l3.ctrl_plane_ring, ICMP_TO_MASTER, mbufs[i]); + (*skip)++; + } else if ((tcp->src_port == TCP_PORT_BGP) || (tcp->dst_port == TCP_PORT_BGP)) { + dump_l3(tbase, mbufs[i]); + tx_ring(tbase, tbase->l3.ctrl_plane_ring, BGP_TO_MASTER, mbufs[i]); + (*skip)++; + } else if (unlikely(*skip)) { + mbufs[i - *skip] = mbufs[i]; + } +} +static inline int handle_l3(struct task_base *tbase, uint16_t nb_rx, struct rte_mbuf ***mbufs_ptr) +{ + struct rte_mbuf **mbufs = *mbufs_ptr; + int i; + struct ether_hdr_arp *hdr_arp[MAX_PKT_BURST]; + prox_rte_ether_hdr *hdr; + prox_rte_ipv4_hdr *pip; + prox_rte_vlan_hdr *vlan; + int skip = 0; + + for (i = 0; i < nb_rx; i++) { + PREFETCH0(mbufs[i]); + } + + for (i = 0; i < nb_rx; i++) { + hdr_arp[i] = rte_pktmbuf_mtod(mbufs[i], struct ether_hdr_arp *); + PREFETCH0(hdr_arp[i]); + } + for (i = 0; i < nb_rx; i++) { + if (likely(hdr_arp[i]->ether_hdr.ether_type == ETYPE_IPv4)) { + hdr = (prox_rte_ether_hdr *)hdr_arp[i]; + pip = (prox_rte_ipv4_hdr *)(hdr + 1); + handle_ipv4(tbase, mbufs, i, pip, &skip); + } else { + switch (hdr_arp[i]->ether_hdr.ether_type) { + case ETYPE_VLAN: + hdr = (prox_rte_ether_hdr *)hdr_arp[i]; + vlan = (prox_rte_vlan_hdr *)(hdr + 1); + if (vlan->eth_proto == ETYPE_IPv4) { + pip = (prox_rte_ipv4_hdr *)(vlan + 1); + handle_ipv4(tbase, mbufs, i, pip, &skip); + } else if (vlan->eth_proto == ETYPE_ARP) { + dump_l3(tbase, mbufs[i]); + tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_PKT_FROM_NET_TO_MASTER, mbufs[i]); + skip++; + } + break; + case ETYPE_ARP: + dump_l3(tbase, mbufs[i]); + tx_ring(tbase, tbase->l3.ctrl_plane_ring, ARP_PKT_FROM_NET_TO_MASTER, mbufs[i]); + skip++; + break; + default: + if (unlikely(skip)) { + mbufs[i - skip] = mbufs[i]; + } + } + } + } + return skip; +} + +static inline int handle_ndp(struct task_base *tbase, uint16_t nb_rx, struct rte_mbuf ***mbufs_ptr) +{ + struct rte_mbuf **mbufs = *mbufs_ptr; + prox_rte_ipv6_hdr *ipv6_hdr; + int i; + prox_rte_ether_hdr *hdr[MAX_PKT_BURST]; + int skip = 0; + uint16_t vlan = 0; + + for (i = 0; i < nb_rx; i++) { + PREFETCH0(mbufs[i]); + } + for (i = 0; i < nb_rx; i++) { + hdr[i] = rte_pktmbuf_mtod(mbufs[i], prox_rte_ether_hdr *); + PREFETCH0(hdr[i]); + } + for (i = 0; i < nb_rx; i++) { + ipv6_hdr = prox_get_ipv6_hdr(hdr[i], rte_pktmbuf_pkt_len(mbufs[i]), &vlan); + if (unlikely((ipv6_hdr) && (ipv6_hdr->proto == ICMPv6))) { + dump_l3(tbase, mbufs[i]); + tx_ring(tbase, tbase->l3.ctrl_plane_ring, NDP_PKT_FROM_NET_TO_MASTER, mbufs[i]); + skip++; + } else if (unlikely(skip)) { + mbufs[i - skip] = mbufs[i]; + } + } + return skip; +} + +static uint16_t rx_pkt_hw_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi, + void (*next)(struct rx_params_hw *rx_param_hw), int l3_ndp) { uint8_t last_read_portid; - uint16_t nb_rx; + uint16_t nb_rx, ret; + int skip = 0; START_EMPTY_MEASSURE(); - *mbufs = tbase->ws_mbuf->mbuf[0] + + *mbufs_ptr = tbase->ws_mbuf->mbuf[0] + (RTE_ALIGN_CEIL(tbase->ws_mbuf->idx[0].prod, 2) & WS_MBUF_MASK); last_read_portid = tbase->rx_params_hw.last_read_portid; struct port_queue *pq = &tbase->rx_params_hw.rx_pq[last_read_portid]; - nb_rx = rx_pkt_hw_port_queue(pq, *mbufs, multi); + nb_rx = rx_pkt_hw_port_queue(pq, *mbufs_ptr, multi); next(&tbase->rx_params_hw); + if (l3_ndp == PROX_L3) + skip = handle_l3(tbase, nb_rx, mbufs_ptr); + else if (l3_ndp == PROX_NDP) + skip = handle_ndp(tbase, nb_rx, mbufs_ptr); + + if (skip) + TASK_STATS_ADD_RX_NON_DP(&tbase->aux->stats, skip); if (likely(nb_rx > 0)) { TASK_STATS_ADD_RX(&tbase->aux->stats, nb_rx); - return nb_rx; + return nb_rx - skip; } TASK_STATS_ADD_IDLE(&tbase->aux->stats, rte_rdtsc() - cur_tsc); return 0; } -static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs, int multi) +static inline uint16_t rx_pkt_hw1_param(struct task_base *tbase, struct rte_mbuf ***mbufs_ptr, int multi, int l3_ndp) { uint16_t nb_rx, n; + int skip = 0; START_EMPTY_MEASSURE(); - *mbufs = tbase->ws_mbuf->mbuf[0] + + *mbufs_ptr = tbase->ws_mbuf->mbuf[0] + (RTE_ALIGN_CEIL(tbase->ws_mbuf->idx[0].prod, 2) & WS_MBUF_MASK); nb_rx = rte_eth_rx_burst(tbase->rx_params_hw1.rx_pq.port, tbase->rx_params_hw1.rx_pq.queue, - *mbufs, MAX_PKT_BURST); + *mbufs_ptr, MAX_PKT_BURST); if (multi) { n = nb_rx; while ((n != 0) && (MAX_PKT_BURST - nb_rx >= MIN_PMD_RX)) { n = rte_eth_rx_burst(tbase->rx_params_hw1.rx_pq.port, tbase->rx_params_hw1.rx_pq.queue, - *mbufs + nb_rx, MIN_PMD_RX); + *mbufs_ptr + nb_rx, MIN_PMD_RX); nb_rx += n; PROX_PANIC(nb_rx > 64, "Received %d packets while expecting maximum %d\n", n, MIN_PMD_RX); } } - if (likely(nb_rx > 0)) { - TASK_STATS_ADD_RX(&tbase->aux->stats, nb_rx); - return nb_rx; + if (unlikely(nb_rx == 0)) { + TASK_STATS_ADD_IDLE(&tbase->aux->stats, rte_rdtsc() - cur_tsc); + return 0; } - TASK_STATS_ADD_IDLE(&tbase->aux->stats, rte_rdtsc() - cur_tsc); - return 0; + + if (l3_ndp == PROX_L3) + skip = handle_l3(tbase, nb_rx, mbufs_ptr); + else if (l3_ndp == PROX_NDP) + skip = handle_ndp(tbase, nb_rx, mbufs_ptr); + + if (skip) + TASK_STATS_ADD_RX_NON_DP(&tbase->aux->stats, skip); + + TASK_STATS_ADD_RX(&tbase->aux->stats, nb_rx); + return nb_rx - skip; } uint16_t rx_pkt_hw(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw_param(tbase, mbufs, 0, next_port); + return rx_pkt_hw_param(tbase, mbufs, 0, next_port, 0); } uint16_t rx_pkt_hw_pow2(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2); + return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, 0); } uint16_t rx_pkt_hw1(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw1_param(tbase, mbufs, 0); + return rx_pkt_hw1_param(tbase, mbufs, 0, 0); } uint16_t rx_pkt_hw_multi(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw_param(tbase, mbufs, 1, next_port); + return rx_pkt_hw_param(tbase, mbufs, 1, next_port, 0); } uint16_t rx_pkt_hw_pow2_multi(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2); + return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, 0); } uint16_t rx_pkt_hw1_multi(struct task_base *tbase, struct rte_mbuf ***mbufs) { - return rx_pkt_hw1_param(tbase, mbufs, 1); + return rx_pkt_hw1_param(tbase, mbufs, 1, 0); +} + +uint16_t rx_pkt_hw_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 0, next_port, PROX_L3); +} + +uint16_t rx_pkt_hw_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 0, next_port, PROX_NDP); +} + +uint16_t rx_pkt_hw_pow2_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, PROX_L3); +} + +uint16_t rx_pkt_hw_pow2_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 0, next_port_pow2, PROX_NDP); +} + +uint16_t rx_pkt_hw1_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw1_param(tbase, mbufs, 0, PROX_L3); +} + +uint16_t rx_pkt_hw1_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw1_param(tbase, mbufs, 0, PROX_NDP); +} + +uint16_t rx_pkt_hw_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 1, next_port, PROX_L3); +} + +uint16_t rx_pkt_hw_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 1, next_port, PROX_NDP); +} + +uint16_t rx_pkt_hw_pow2_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, PROX_L3); +} + +uint16_t rx_pkt_hw_pow2_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw_param(tbase, mbufs, 1, next_port_pow2, PROX_NDP); +} + +uint16_t rx_pkt_hw1_multi_l3(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw1_param(tbase, mbufs, 1, PROX_L3); +} + +uint16_t rx_pkt_hw1_multi_ndp(struct task_base *tbase, struct rte_mbuf ***mbufs) +{ + return rx_pkt_hw1_param(tbase, mbufs, 1, PROX_NDP); } /* The following functions implement ring access */ -static uint16_t ring_deq(struct rte_ring *r, struct rte_mbuf **mbufs) +uint16_t ring_deq(struct rte_ring *r, struct rte_mbuf **mbufs) { void **v_mbufs = (void **)mbufs; #ifdef BRAS_RX_BULK @@ -273,13 +487,9 @@ static uint16_t call_prev_rx_pkt(struct task_base *tbase, struct rte_mbuf ***mbu { uint16_t ret; - if (tbase->aux->rx_prev_idx + 1 == tbase->aux->rx_prev_count) { - ret = tbase->aux->rx_pkt_prev[tbase->aux->rx_prev_idx](tbase, mbufs); - } else { - tbase->aux->rx_prev_idx++; - ret = tbase->aux->rx_pkt_prev[tbase->aux->rx_prev_idx](tbase, mbufs); - tbase->aux->rx_prev_idx--; - } + tbase->aux->rx_prev_idx++; + ret = tbase->aux->rx_pkt_prev[tbase->aux->rx_prev_idx - 1](tbase, mbufs); + tbase->aux->rx_prev_idx--; return ret; } @@ -297,9 +507,9 @@ uint16_t rx_pkt_dump(struct task_base *tbase, struct rte_mbuf ***mbufs) uint32_t n_dump = tbase->aux->task_rt_dump.n_print_rx; n_dump = ret < n_dump? ret : n_dump; - if (tbase->aux->task_rt_dump.input->reply == NULL) { + if ((tbase->aux->task_rt_dump.input == NULL) || (tbase->aux->task_rt_dump.input->reply == NULL)) { for (uint32_t i = 0; i < n_dump; ++i) { - plogd_info((*mbufs)[i], "RX: "); + plogdx_info((*mbufs)[i], "RX: "); } } else { @@ -336,12 +546,13 @@ uint16_t rx_pkt_dump(struct task_base *tbase, struct rte_mbuf ***mbufs) uint16_t rx_pkt_trace(struct task_base *tbase, struct rte_mbuf ***mbufs) { + tbase->aux->task_rt_dump.cur_trace = 0; uint16_t ret = call_prev_rx_pkt(tbase, mbufs); if (ret) { uint32_t n_trace = tbase->aux->task_rt_dump.n_trace; n_trace = ret < n_trace? ret : n_trace; - tbase->aux->task_rt_dump.cur_trace = n_trace; + n_trace = n_trace <= MAX_RING_BURST ? n_trace : MAX_RING_BURST; for (uint32_t i = 0; i < n_trace; ++i) { uint8_t *pkt = rte_pktmbuf_mtod((*mbufs)[i], uint8_t *); @@ -349,6 +560,7 @@ uint16_t rx_pkt_trace(struct task_base *tbase, struct rte_mbuf ***mbufs) tbase->aux->task_rt_dump.pkt_cpy_len[i] = rte_pktmbuf_pkt_len((*mbufs)[i]); tbase->aux->task_rt_dump.pkt_mbuf_addr[i] = (*mbufs)[i]; } + tbase->aux->task_rt_dump.cur_trace += n_trace; tbase->aux->task_rt_dump.n_trace -= n_trace; /* Unset by TX when n_trace = 0 */ @@ -363,7 +575,10 @@ uint16_t rx_pkt_distr(struct task_base *tbase, struct rte_mbuf ***mbufs) { uint16_t ret = call_prev_rx_pkt(tbase, mbufs); - tbase->aux->rx_bucket[ret]++; + if (likely(ret < RX_BUCKET_SIZE)) + tbase->aux->rx_bucket[ret]++; + else + tbase->aux->rx_bucket[RX_BUCKET_SIZE - 1]++; return ret; } @@ -392,36 +607,3 @@ uint16_t rx_pkt_tsc(struct task_base *tbase, struct rte_mbuf ***mbufs) return ret; } - -uint16_t rx_pkt_all(struct task_base *tbase, struct rte_mbuf ***mbufs) -{ - uint16_t tot = 0; - uint16_t ret = 0; - struct rte_mbuf **new_mbufs; - struct rte_mbuf **dst = tbase->aux->all_mbufs; - - /* In case we receive less than MAX_PKT_BURST packets in one - iteration, do no perform any copying of mbuf pointers. Use - the buffer itself instead. */ - ret = call_prev_rx_pkt(tbase, &new_mbufs); - if (ret < MAX_PKT_BURST/2) { - *mbufs = new_mbufs; - return ret; - } - - memcpy(dst + tot, new_mbufs, ret * sizeof(*dst)); - tot += ret; - *mbufs = dst; - - do { - ret = call_prev_rx_pkt(tbase, &new_mbufs); - memcpy(dst + tot, new_mbufs, ret * sizeof(*dst)); - tot += ret; - } while (ret == MAX_PKT_BURST/2 && tot < MAX_RX_PKT_ALL - MAX_PKT_BURST); - - if (tot >= MAX_RX_PKT_ALL - MAX_PKT_BURST) { - plog_err("Could not receive all packets - buffer full\n"); - } - - return tot; -}