27 #include <flow_common.h>
34 #include <rte_lcore.h>
35 #include <rte_malloc.h>
36 #include <rte_ethdev.h>
37 #include <rte_ip_frag.h>
38 #include <rte_cycles.h>
39 #include <rte_mempool.h>
43 #define IP_FRAG_MAX_PKT_BURST 32
44 #define IP_FRAG_BURST_PREFETCH (IP_FRAG_MAX_PKT_BURST / 8)
45 #define IP_FRAG_FLUSH_THRESHOLD 16
47 #define IP_FRAG_TBL_BUCKET_SIZE 4
83 rte_pktmbuf_free(pkt);
98 uint8_t *data_beg = rte_pktmbuf_mtod(pkt, uint8_t *);
99 uint8_t *data_end = data_beg + rte_pktmbuf_data_len(pkt);
107 return unknown_parse(data_beg, data_end, parse_ctx, pkt_type);
124 pkt->l2_len = l2_len;
125 pkt->l3_len = l3_len;
126 pkt->ol_flags |= flags;
136 hdr->hdr_checksum = 0;
137 hdr->hdr_checksum = rte_ipv4_cksum(hdr);
161 struct rte_mbuf *pkt,
167 pkt->l2_len = l2_len;
168 pkt->l3_len = l3_len;
169 pkt->ol_flags |= RTE_MBUF_F_TX_IPV4 | RTE_MBUF_F_TX_IP_CKSUM;
184 struct rte_mbuf *pkt,
203 struct rte_mbuf *pkt,
210 transport_ctx->
udp_hdr->dgram_cksum = 0;
213 pkt->l2_len = link_ctx->
len;
214 pkt->l3_len = network_ctx->
len;
215 transport_ctx->
udp_hdr->dgram_cksum = rte_ipv6_phdr_cksum(network_ctx->
ipv6.hdr, pkt->ol_flags);
216 pkt->ol_flags |= RTE_MBUF_F_TX_IPV6 | RTE_MBUF_F_TX_UDP_CKSUM;
219 transport_ctx->
udp_hdr->dgram_cksum = 0;
235 struct rte_mbuf *pkt,
246 rte_cpu_to_be_16(rte_pktmbuf_pkt_len(pkt) -
258 rte_cpu_to_be_16(rte_pktmbuf_pkt_len(pkt) - parse_ctx->
link_ctx.
len);
266 rte_cpu_to_be_16(rte_pktmbuf_pkt_len(pkt) - parse_ctx->
link_ctx.
len -
298 uint16_t tail_size = rte_pktmbuf_pkt_len(pkt) - rte_pktmbuf_data_len(pkt);
299 struct rte_mbuf *tail = pkt->next;
300 struct rte_mbuf *tmp;
304 if (tail_size > rte_pktmbuf_tailroom(pkt)) {
305 DOCA_LOG_DBG(
"Resulting packet size %u doesn't fit into tailroom size %u",
307 rte_pktmbuf_tailroom(pkt));
313 pkt->pkt_len = pkt->data_len;
316 seg_len = rte_pktmbuf_data_len(tail);
317 dst = rte_pktmbuf_append(pkt, seg_len);
319 memcpy(dst, rte_pktmbuf_mtod(tail,
void *), seg_len);
322 rte_pktmbuf_free_seg(tail);
339 struct rte_mbuf *pkt,
349 rte_ipv4_frag_reassemble_packet(wt_data->
frag_tbl,
354 rte_ipv6_frag_reassemble_packet(wt_data->
frag_tbl,
374 struct rte_mbuf *pkt,
388 rte_ipv4_frag_reassemble_packet(wt_data->
frag_tbl,
393 rte_ipv6_frag_reassemble_packet(wt_data->
frag_tbl,
415 struct rte_mbuf *pkt,
418 struct rte_mbuf **whole_pkt)
420 struct rte_mbuf *res;
435 if (!wt_data->
cfg->
mbuf_chain && !rte_pktmbuf_is_contiguous(res)) {
461 struct rte_mbuf *pkt,
473 inferred_pkt_type = pkt_type;
474 memset(&parse_ctx, 0,
sizeof(parse_ctx));
524 struct rte_mbuf *pkts[],
531 rte_prefetch0(rte_pktmbuf_mtod(pkts[i],
void *));
538 for (; i < pkts_cnt; i++)
563 rte_ip_frag_table_del_expired_entries(wt_data->
frag_tbl, &wt_data->
death_row, rte_rdtsc());
570 struct rte_mbuf *pkt_in,
571 struct rte_mbuf **pkts_out,
572 uint16_t pkts_out_max,
574 struct rte_mempool *direct_pool,
579 rte_ipv4_fragment_packet(pkt_in, pkts_out, pkts_out_max, mtu, direct_pool,
indirect_pool) :
580 rte_ipv4_fragment_copy_nonseg_packet(pkt_in, pkts_out, pkts_out_max, mtu, direct_pool);
582 return wt_data->
cfg->
mbuf_chain ? rte_ipv6_fragment_packet(pkt_in,
602 struct rte_mbuf *pkt)
605 uint8_t eth_hdr_copy[RTE_PKTMBUF_HEADROOM];
613 memset(&parse_ctx, 0,
sizeof(parse_ctx));
616 ret =
plain_parse(rte_pktmbuf_mtod(pkt, uint8_t *),
617 rte_pktmbuf_mtod(pkt, uint8_t *) + rte_pktmbuf_data_len(pkt),
625 if (rte_pktmbuf_pkt_len(pkt) <= wt_data->
cfg->
mtu) {
633 if (
sizeof(eth_hdr_copy) < eth_hdr_len) {
635 DOCA_LOG_ERR(
"Ethernet header size %lu too big", eth_hdr_len);
638 memcpy(eth_hdr_copy, parse_ctx.
link_ctx.
eth, eth_hdr_len);
639 rte_pktmbuf_adj(pkt, eth_hdr_len);
646 wt_data->
cfg->
mtu - eth_hdr_len,
651 DOCA_LOG_ERR(
"RTE fragmentation failed with code: %d", -num_frags);
654 rte_pktmbuf_free(pkt);
662 rte_ipv4_hdr_len(rte_pktmbuf_mtod(pkt,
struct rte_ipv4_hdr *)),
663 rte_pktmbuf_mtod(pkt,
struct rte_ipv4_hdr *));
665 eth_hdr_new = rte_pktmbuf_prepend(pkt, eth_hdr_len);
667 memcpy(eth_hdr_new, eth_hdr_copy, eth_hdr_len);
687 struct rte_mbuf *pkts[],
694 rte_prefetch0(rte_pktmbuf_mtod(pkts[i],
void *));
703 for (; i < pkts_cnt; i++) {
776 static const struct rte_mbuf_dynflag flag_outer_desc = {
777 .name =
"ip_frag outer",
779 static const struct rte_mbuf_dynflag flag_inner_desc = {
780 .name =
"ip_frag inner",
785 flag_outer = rte_mbuf_dynflag_register(&flag_outer_desc);
786 if (flag_outer < 0) {
787 DOCA_LOG_ERR(
"Failed to register mbuf outer fragmentation flag with code: %d", -flag_outer);
791 flag_inner = rte_mbuf_dynflag_register(&flag_inner_desc);
792 if (flag_inner < 0) {
793 DOCA_LOG_ERR(
"Failed to register mbuf inner fragmentation flag with code: %d", -flag_inner);
811 char mempool_name[RTE_MEMPOOL_NAMESIZE];
815 RTE_LCORE_FOREACH_WORKER(lcore)
817 socket = rte_lcore_to_socket_id(lcore);
819 if (!indirect_pools[socket]) {
820 snprintf(mempool_name,
sizeof(mempool_name),
"Indirect mempool %u", socket);
821 indirect_pools[socket] = rte_pktmbuf_pool_create(mempool_name,
827 if (!indirect_pools[socket]) {
828 DOCA_LOG_ERR(
"Failed to allocate indirect mempool for socket %u", socket);
832 DOCA_LOG_DBG(
"Indirect mempool for socket %u initialized", socket);
849 RTE_LCORE_FOREACH_WORKER(lcore)
851 wt_data = &wt_data_arr[lcore];
854 rte_ip_frag_table_destroy(wt_data->
frag_tbl);
858 rte_free(wt_data_arr);
870 struct rte_mempool *indirect_pools[],
879 wt_data_arr = rte_calloc(
"Worker data", RTE_MAX_LCORE,
sizeof(*wt_data_arr), _Alignof(typeof(*wt_data_arr)));
881 DOCA_LOG_ERR(
"Failed to allocate worker thread data array");
885 RTE_LCORE_FOREACH(lcore)
887 wt_data = &wt_data_arr[lcore];
889 wt_data->
indirect_pool = indirect_pools[rte_lcore_to_socket_id(lcore)];
892 wt_data->
tx_buffer = rte_zmalloc_socket(
"TX buffer",
895 rte_lcore_to_socket_id(lcore));
897 DOCA_LOG_ERR(
"Failed to allocate worker thread tx buffer");
902 rte_eth_tx_buffer_set_err_callback(wt_data->
tx_buffer,
903 rte_eth_tx_buffer_count_callback,
911 rte_lcore_to_socket_id(lcore));
913 DOCA_LOG_ERR(
"Failed to allocate worker thread fragmentation table");
918 DOCA_LOG_DBG(
"Worker thread %u data initialized", lcore);
921 *wt_data_arr_out = wt_data_arr;
944 DOCA_LOG_INFO(
"//////////////////// SW COUNTERS ////////////////////");
946 for (port_id = 0; port_id <
ctx->
num_ports; port_id++) {
948 memset(&sw_sum_port, 0,
sizeof(sw_sum_port));
950 RTE_LCORE_FOREACH(lcore)
952 wt_data = &wt_data_arr[lcore];
956 "Core sw %3u frags_rx=%-8lu whole=%-8lu mtu_fits_rx=%-8lu mtu_exceed_rx=%-8lu frags_gen=%-8lu err=%-8lu",
974 "TOTAL sw port %d frags_rx=%-8lu whole=%-8lu mtu_fits_rx=%-8lu mtu_exceed_rx=%-8lu frags_gen=%-8lu err=%-8lu",
988 sw_sum.
err += sw_sum_port.
err;
993 "TOTAL sw frags_rx=%-8lu whole=%-8lu mtu_fits_rx=%-8lu mtu_exceed_rx=%-8lu frags_gen=%-8lu err=%-8lu",
1013 DOCA_LOG_INFO(
"//////////////////// TX BUFFER ERROR ////////////////////");
1015 RTE_LCORE_FOREACH(lcore)
1017 wt_data = &wt_data_arr[lcore];
1037 DOCA_LOG_INFO(
"//////////////////// FRAG TABLE STATS ////////////////////");
1039 RTE_LCORE_FOREACH(lcore)
1041 wt_data = &wt_data_arr[lcore];
1044 rte_ip_frag_table_statistics_dump(stdout, wt_data->
frag_tbl);
1056 rte_mbuf_dyn_dump(stdout);
1075 struct doca_flow_pipe_cfg *
cfg;
1138 struct doca_flow_pipe *pipe_miss,
1139 struct doca_flow_pipe **pipe_out)
1146 const int num_of_entries = 1;
1151 .rss.outer_flags = flags};
1158 .num_entries = num_of_entries,
1159 .match = &match_pipe,
1160 .match_mask = &match_pipe,
1163 struct doca_flow_pipe *pipe;
1195 DOCA_LOG_ERR(
"Failed to process port %u entries", port_id);
1214 for (port_id = 0; port_id <
ctx->
num_ports; port_id++) {
1245 struct rte_mempool *indirect_pools[RTE_MAX_NUMA_NODES] = {
NULL};
1264 goto cleanup_doca_flow;
1268 goto cleanup_doca_flow;
1272 goto cleanup_doca_flow;
1277 goto cleanup_wt_data;
1286 DOCA_LOG_INFO(
"Initialization finished, starting data path");
1291 rte_eal_mp_wait_lcore();
struct doca_flow_port * init_doca_flow(uint16_t port_id, uint8_t rxq_num)
static void cleanup(struct cache_invalidate_sample_state *state)
static doca_error_t destroy_pipe_cfg(struct doca_flow_pipe_cfg *cfg)
static struct doca_flow_fwd fwd_miss
static uint16_t * rss_queues
static struct doca_flow_fwd fwd
#define DEFAULT_TIMEOUT_US
enum doca_error doca_error_t
DOCA API return codes.
DOCA_STABLE const char * doca_error_get_descr(doca_error_t error)
Returns the description string of an error code.
@ DOCA_ERROR_INVALID_VALUE
#define DOCA_FLOW_PROTO_IPV4
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_destroy(struct doca_flow_pipe_cfg *cfg)
Destroy DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_create(struct doca_flow_pipe_cfg **cfg, struct doca_flow_port *port)
Create DOCA Flow pipe configuration struct.
DOCA_STABLE doca_error_t doca_flow_entries_process(struct doca_flow_port *port, uint16_t pipe_queue, uint64_t timeout, uint32_t max_processed_entries)
Process entries in queue.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_cfg_set_match(struct doca_flow_pipe_cfg *cfg, const struct doca_flow_match *match, const struct doca_flow_match *match_mask)
Set pipe's match and match mask.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_create(const struct doca_flow_pipe_cfg *cfg, const struct doca_flow_fwd *fwd, const struct doca_flow_fwd *fwd_miss, struct doca_flow_pipe **pipe)
Create one new pipe.
DOCA_EXPERIMENTAL doca_error_t doca_flow_pipe_add_entry(uint16_t pipe_queue, struct doca_flow_pipe *pipe, const struct doca_flow_match *match, const struct doca_flow_actions *actions, const struct doca_flow_monitor *monitor, const struct doca_flow_fwd *fwd, uint32_t flags, void *usr_ctx, struct doca_flow_pipe_entry **entry)
Add one new entry to a pipe.
DOCA_STABLE void doca_flow_destroy(void)
Destroy the doca flow.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_nr_entries(struct doca_flow_pipe_cfg *cfg, uint32_t nr_entries)
Set pipe's maximum number of flow rules.
DOCA_STABLE doca_error_t doca_flow_pipe_cfg_set_domain(struct doca_flow_pipe_cfg *cfg, enum doca_flow_pipe_domain domain)
Set pipe's domain.
@ DOCA_FLOW_RESOURCE_TYPE_NON_SHARED
@ DOCA_FLOW_PIPE_DOMAIN_DEFAULT
#define DOCA_LOG_ERR(format,...)
Generates an ERROR application log message.
#define DOCA_LOG_INFO(format,...)
Generates an INFO application log message.
#define DOCA_LOG_DBG(format,...)
Generates a DEBUG application log message.
static void ip_frag_ipv4_hdr_cksum(struct rte_ipv4_hdr *hdr)
static void ip_frag_pkt_fragment(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id, struct rte_mbuf *pkt)
static doca_error_t ip_frag_pkt_parse(enum parser_pkt_type *pkt_type, struct rte_mbuf *pkt, struct tun_parser_ctx *parse_ctx)
static doca_error_t ip_frag_wt_data_init(const struct ip_frag_config *cfg, struct rte_mempool *indirect_pools[], struct ip_frag_wt_data **wt_data_arr_out)
DOCA_LOG_REGISTER(IP_FRAG::DP)
#define IP_FRAG_MAX_PKT_BURST
static void ip_frag_debug_counters_print(struct ip_frag_ctx *ctx, struct ip_frag_wt_data *wt_data_arr)
#define IP_FRAG_BURST_PREFETCH
static doca_error_t ip_frag_pipe_create(struct ip_frag_pipe_cfg *pipe_cfg, struct doca_flow_pipe **pipe)
static void ip_frag_network_cksum_handle(struct ip_frag_wt_data *wt_data, struct rte_mbuf *pkt, struct link_parser_ctx *link_ctx, struct network_parser_ctx *network_ctx)
static void ip_frag_ipv4_cksum_handle(struct ip_frag_wt_data *wt_data, struct rte_mbuf *pkt, uint64_t l2_len, uint64_t l3_len, struct rte_ipv4_hdr *ipv4_hdr)
static void ip_frag_pkt_fixup(struct ip_frag_wt_data *wt_data, enum parser_pkt_type pkt_type, struct rte_mbuf *pkt, struct tun_parser_ctx *parse_ctx)
static void ip_frag_pkt_err_drop(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, struct rte_mbuf *pkt)
static doca_error_t ip_frag_rss_pipes_create(struct ip_frag_ctx *ctx)
static void ip_frag_wt_reassemble(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id, enum parser_pkt_type pkt_type)
static void ip_frag_wt_data_cleanup(struct ip_frag_wt_data *wt_data_arr)
static int32_t ip_frag_mbuf_fragment(struct ip_frag_wt_data *wt_data, struct conn_parser_ctx *parse_ctx, struct rte_mbuf *pkt_in, struct rte_mbuf **pkts_out, uint16_t pkts_out_max, uint16_t mtu, struct rte_mempool *direct_pool, struct rte_mempool *indirect_pool)
static void ip_frag_wt_fragment(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id)
struct rte_eth_dev_tx_buffer * tx_buffer
static doca_error_t ip_frag_pkt_flatten(struct rte_mbuf *pkt)
static struct rte_mbuf * ip_frag_pkt_reassemble_push_inner(struct ip_frag_wt_data *wt_data, enum parser_pkt_type pkt_type, struct rte_mbuf *pkt, struct tun_parser_ctx *parse_ctx, uint64_t rx_ts)
struct ip_frag_wt_data __rte_aligned(RTE_CACHE_LINE_SIZE)
static void ip_frag_network_cksum(struct network_parser_ctx *ctx)
struct rte_mempool * indirect_pool
doca_error_t ip_frag(struct ip_frag_config *cfg, struct application_dpdk_config *dpdk_cfg)
static struct rte_mbuf * ip_frag_pkt_reassemble_push_outer(struct ip_frag_wt_data *wt_data, struct rte_mbuf *pkt, struct tun_parser_ctx *parse_ctx, uint64_t rx_ts)
static void ip_frag_tx_buffer_error_print(struct ip_frag_wt_data *wt_data_arr)
static void ip_frag_tbl_stats_print(struct ip_frag_wt_data *wt_data_arr)
static void ip_frag_sw_counters_print(struct ip_frag_ctx *ctx, struct ip_frag_wt_data *wt_data_arr)
static doca_error_t ip_frag_rss_pipe_create(struct ip_frag_ctx *ctx, uint16_t port_id, char *pipe_name, bool is_root, uint32_t flags, struct doca_flow_pipe *pipe_miss, struct doca_flow_pipe **pipe_out)
const struct ip_frag_config * cfg
static void ip_frag_pkts_fragment(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id, struct rte_mbuf *pkts[], int pkts_cnt)
static int ip_frag_wt_thread_main(void *param)
#define IP_FRAG_TBL_BUCKET_SIZE
static doca_error_t ip_frag_pkt_reassemble_push(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, enum parser_pkt_type pkt_type, struct rte_mbuf *pkt, struct tun_parser_ctx *parse_ctx, uint64_t rx_ts, struct rte_mbuf **whole_pkt)
static doca_error_t ip_frag_mbuf_flags_init(struct ip_frag_config *cfg)
static void ip_frag_udp_cksum_handle(struct ip_frag_wt_data *wt_data, struct rte_mbuf *pkt, struct link_parser_ctx *link_ctx, struct network_parser_ctx *network_ctx, struct transport_parser_ctx *transport_ctx)
static void ip_frag_pkts_reassemble(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id, enum parser_pkt_type pkt_type, struct rte_mbuf *pkts[], int pkts_cnt, uint64_t rx_ts)
static void ip_frag_pkt_reassemble(struct ip_frag_wt_data *wt_data, uint16_t rx_port_id, uint16_t tx_port_id, enum parser_pkt_type pkt_type, struct rte_mbuf *pkt, uint64_t rx_ts)
#define IP_FRAG_FLUSH_THRESHOLD
static void ip_frag_pkt_reassemble_prepare(struct rte_mbuf *pkt, size_t l2_len, size_t l3_len, uint64_t flags)
static doca_error_t ip_frag_indirect_pool_init(uint16_t nb_queues, struct rte_mempool *indirect_pools[])
struct ip_frag_sw_counters sw_counters[IP_FRAG_PORT_NUM]
@ IP_FRAG_PORT_FRAGMENT_1
@ IP_FRAG_PORT_REASSEMBLE_0
@ IP_FRAG_PORT_REASSEMBLE_1
@ IP_FRAG_PORT_FRAGMENT_0
doca_error_t unknown_parse(uint8_t *data, uint8_t *data_end, struct tun_parser_ctx *ctx, enum parser_pkt_type *parser_pkt_type)
doca_error_t tunnel_parse(uint8_t *data, uint8_t *data_end, struct tun_parser_ctx *ctx)
doca_error_t plain_parse(uint8_t *data, uint8_t *data_end, struct conn_parser_ctx *ctx)
@ PARSER_PKT_TYPE_TUNNELED
@ PARSER_PKT_TYPE_UNKNOWN
doca_error_t stop_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[])
doca_error_t init_doca_flow_ports(int nb_ports, struct doca_flow_port *ports[], bool is_hairpin, struct doca_dev *dev_arr[], uint32_t actions_mem_size[])
doca_error_t set_flow_pipe_cfg(struct doca_flow_pipe_cfg *cfg, const char *name, enum doca_flow_pipe_type type, bool is_root)
#define SHARED_RESOURCE_NUM_VALUES
struct application_port_config port_config
struct link_parser_ctx link_ctx
struct network_parser_ctx network_ctx
struct doca_flow_pipe * next_pipe
enum doca_flow_fwd_type type
doca flow matcher information
struct doca_flow_parser_meta parser_meta
user context struct that will be used in entries process callback
struct rte_gtp_hdr * gtp_hdr
uint64_t mbuf_flag_inner_modified
uint32_t frag_tbl_timeout
uint64_t mbuf_flag_outer_modified
struct doca_flow_match * match_mask
struct doca_flow_fwd * fwd_miss
struct doca_flow_match * match
struct doca_flow_port * port
enum doca_flow_pipe_domain domain
struct doca_flow_fwd * fwd
struct rte_ip_frag_death_row death_row
struct rte_eth_dev_tx_buffer * tx_buffer
struct rte_ip_frag_tbl * frag_tbl
const struct ip_frag_config * cfg
struct ip_frag_sw_counters sw_counters[IP_FRAG_PORT_NUM]
struct rte_mempool * indirect_pool
struct rte_ether_hdr * eth
struct network_parser_ctx::@2::@4 ipv6
struct rte_ipv4_hdr * ipv4_hdr
struct rte_udp_hdr * udp_hdr
struct link_parser_ctx link_ctx
struct transport_parser_ctx transport_ctx
struct conn_parser_ctx inner
struct network_parser_ctx network_ctx
struct gtp_parser_ctx gtp_ctx
struct doca_flow_pipe * pipes[UPF_ACCEL_PORTS_MAX][UPF_ACCEL_PIPE_NUM]
struct doca_flow_port * ports[UPF_ACCEL_PORTS_MAX]
struct doca_dev * dev_arr[UPF_ACCEL_PORTS_MAX]
static uint32_t actions_mem_size[FLOW_SWITCH_PORTS_MAX]
struct upf_accel_ctx * ctx