From patchwork Thu May 18 08:51:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bogdan Pricope X-Patchwork-Id: 100057 Delivered-To: patch@linaro.org Received: by 10.140.96.100 with SMTP id j91csp616947qge; Thu, 18 May 2017 01:52:50 -0700 (PDT) X-Received: by 10.55.59.139 with SMTP id i133mr2534441qka.248.1495097570628; Thu, 18 May 2017 01:52:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1495097570; cv=none; d=google.com; s=arc-20160816; b=fAzoffG26QjSga1dRqfepSnRV/U3TmwwnYoN8jOMk5Z28Izf+rpd8mk63Ft+NmnSNZ woPVpp4YLR0ACjsuEx+WuQZMJ7GTrvR6+iulI+T0SxXYPfHAAyqGyxZpUEYK1jWhTmaO HC0cw+O+C7Gz/RHyLtT8L0+cIjobXGsRKigMTYFDIk4eeuKdtG/tR6itI3J7aztghddt chS75pP9FwezYKh0OXA5PZLzTgF6g1HwyoceJ/8EPIJ6e32LP1NowAo4Fg3dvCrJxpzh QgSK722UBGkea9mYwDwHtPebUTOYZ+1l8N7a8xTd4X3V8MriAO0zyNbTmyhXl1/QvuXm qHnQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:subject:references:in-reply-to :message-id:date:to:from:delivered-to:arc-authentication-results; bh=U8j47QQGlYGC1a3M/voai8u9x5qOrYewSJfRhYkRNA0=; b=V+FoLe9ZbuXGbYvzRncbPBFW+3g09VnA1d4SNJahSFFgLquBuihNQQehPr0+6A8Mzs 7OOhZk+IiX/khqQSLXXqtu+UpGFONQPT8ZC56ru81rkmByfbFpO4/rV7pbg2HEcsemsY W+km9TZ5Oi78e2b3f5a045ZOzXaHumX8QsDzdhysM4s8eiAqTIo8q5Ekf09RF8l6JU8F OaC3bg0ie1g12fvX1iPdObcpHN2kLILb1c3s4k/Fow4mEjj+bw0RGdc3yFx0bRUYx3oZ fBEYMxozVcXMXvsZtsZMXwolyX6CtMVI2VwGzlrIRicocvbV3nCYCCWauz1rTOi501S8 WYkw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from lists.linaro.org (lists.linaro.org. [54.225.227.206]) by mx.google.com with ESMTP id b190si4871982qke.275.2017.05.18.01.52.50; Thu, 18 May 2017 01:52:50 -0700 (PDT) Received-SPF: pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) client-ip=54.225.227.206; Authentication-Results: mx.google.com; spf=pass (google.com: domain of lng-odp-bounces@lists.linaro.org designates 54.225.227.206 as permitted sender) smtp.mailfrom=lng-odp-bounces@lists.linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 4E5C460CF7; Thu, 18 May 2017 08:52:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on ip-10-142-244-252 X-Spam-Level: X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, RCVD_IN_SORBS_SPAM, URIBL_BLOCKED autolearn=disabled version=3.4.0 Received: from [127.0.0.1] (localhost [127.0.0.1]) by lists.linaro.org (Postfix) with ESMTP id 3173160CCF; Thu, 18 May 2017 08:52:40 +0000 (UTC) X-Original-To: lng-odp@lists.linaro.org Delivered-To: lng-odp@lists.linaro.org Received: by lists.linaro.org (Postfix, from userid 109) id 1F1AC60CD2; Thu, 18 May 2017 08:52:37 +0000 (UTC) Received: from mail-wr0-f170.google.com (mail-wr0-f170.google.com [209.85.128.170]) by lists.linaro.org (Postfix) with ESMTPS id 6D18560CFC for ; Thu, 18 May 2017 08:52:22 +0000 (UTC) Received: by mail-wr0-f170.google.com with SMTP id l9so28429959wre.1 for ; Thu, 18 May 2017 01:52:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=U8j47QQGlYGC1a3M/voai8u9x5qOrYewSJfRhYkRNA0=; b=VuvEWVsJB5nkV1aZ8jw//f+d5fabPRd3F9xbyPIAQXLMzOmbFKEq8sThPJ/9ALu/AN GwI4WxjB6g6mwMF4Ayd0cOQcRSQUGI5k/SYbE9Gxjz302mm7W9a7hTwEGLOUNZg1ZsT4 A9qkU/yrnFfqYYwuR2enUjl2Gw1CgzHQSaJpVRokr5UVtKuPUK7nqacYPp1fijoUripn wly4YuQSOit9WxHLWFpLzHtrijYkDFpn9GdsZrErJMHY3Jy4n/G8fdKeLq1Lz/9+a/sD OnNsULA9MxJviY/DJ41ur37XNhe1dJye48YZh1yKauf6P1Td+baDj9LwFxkiBw1XWiAn vzkA== X-Gm-Message-State: AODbwcCy3FgGMJbmzskxZ1OSPJLZ6CpY23aViy2SY6TtARyT2C1Kd0fh HXTCwdOgxlLJYQJcjBI= X-Received: by 10.223.136.71 with SMTP id e7mr1752494wre.73.1495097540658; Thu, 18 May 2017 01:52:20 -0700 (PDT) Received: from netbricks-team.enea.se ([193.202.22.66]) by smtp.gmail.com with ESMTPSA id c37sm5104112wra.16.2017.05.18.01.52.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 18 May 2017 01:52:19 -0700 (PDT) From: Bogdan Pricope To: lng-odp@lists.linaro.org Date: Thu, 18 May 2017 11:51:55 +0300 Message-Id: <1495097515-10181-2-git-send-email-bogdan.pricope@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1495097515-10181-1-git-send-email-bogdan.pricope@linaro.org> References: <1495097515-10181-1-git-send-email-bogdan.pricope@linaro.org> Subject: [lng-odp] [RFCv3] dpdk: enable hardware checksum support X-BeenThere: lng-odp@lists.linaro.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: "The OpenDataPlane \(ODP\) List" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: lng-odp-bounces@lists.linaro.org Sender: "lng-odp" Signed-off-by: Bogdan Pricope --- example/generator/odp_generator.c | 102 +++++++++++++++++++--- platform/linux-generic/odp_packet_io.c | 2 + platform/linux-generic/pktio/dpdk.c | 150 +++++++++++++++++++++++++++++++-- 3 files changed, 235 insertions(+), 19 deletions(-) -- 1.9.1 diff --git a/example/generator/odp_generator.c b/example/generator/odp_generator.c index ede1cdf..59f7f02 100644 --- a/example/generator/odp_generator.c +++ b/example/generator/odp_generator.c @@ -46,6 +46,7 @@ typedef struct { odp_pktio_t pktio; + odp_pktio_config_t config; odp_pktout_queue_t pktout[MAX_WORKERS]; unsigned pktout_count; } interface_t; @@ -90,6 +91,7 @@ static struct { */ typedef struct { odp_pktout_queue_t pktout; /**< Packet output queue to use*/ + odp_pktout_config_opt_t *pktout_cfg; /**< Packet output offload config*/ odp_pool_t pool; /**< Pool for packet IO */ odp_timer_pool_t tp; /**< Timer pool handle */ odp_queue_t tq; /**< Queue for timeouts */ @@ -114,6 +116,9 @@ static args_t *args; /** Barrier to sync threads execution */ static odp_barrier_t barrier; +/** List of interfaces */ +static interface_t *ifs; + /* helper funcs */ static void parse_args(int argc, char *argv[], appl_args_t *appl_args); static void print_info(char *progname, appl_args_t *appl_args); @@ -192,7 +197,8 @@ static int scan_ip(char *buf, unsigned int *paddr) * @return Handle of created packet * @retval ODP_PACKET_INVALID Packet could not be created */ -static odp_packet_t setup_udp_pkt_ref(odp_pool_t pool) +static odp_packet_t setup_udp_pkt_ref(odp_pool_t pool, + odp_pktout_config_opt_t *pktout_cfg) { odp_packet_t pkt; char *buf; @@ -237,7 +243,8 @@ static odp_packet_t setup_udp_pkt_ref(odp_pool_t pool) udp->dst_port = 0; udp->length = odp_cpu_to_be_16(args->appl.payload + ODPH_UDPHDR_LEN); udp->chksum = 0; - udp->chksum = odph_ipv4_udp_chksum(pkt); + if (!pktout_cfg->bit.udp_chksum) + udp->chksum = odph_ipv4_udp_chksum(pkt); return pkt; } @@ -251,7 +258,8 @@ static odp_packet_t setup_udp_pkt_ref(odp_pool_t pool) * @return Handle of created packet * @retval ODP_PACKET_INVALID Packet could not be created */ -static odp_packet_t pack_udp_pkt(odp_pool_t pool, odp_packet_t pkt_ref) +static odp_packet_t pack_udp_pkt(odp_pool_t pool, odp_packet_t pkt_ref, + odp_pktout_config_opt_t *pktout_cfg) { odp_packet_t pkt; char *buf; @@ -273,7 +281,17 @@ static odp_packet_t pack_udp_pkt(odp_pool_t pool, odp_packet_t pkt_ref) ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); seq = odp_atomic_fetch_add_u64(&counters.seq, 1) % 0xFFFF; ip->id = odp_cpu_to_be_16(seq); - ip->chksum = odph_chksum(ip, ODPH_IPV4HDR_LEN); + ip->chksum = 0; + if (!pktout_cfg->bit.ipv4_chksum) + ip->chksum = odph_chksum(ip, ODPH_IPV4HDR_LEN); + + if (pktout_cfg->bit.ipv4_chksum || pktout_cfg->bit.udp_chksum) { + odp_packet_l2_offset_set(pkt, 0); + odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); + odp_packet_has_ipv4_set(pkt, 1); + odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + odp_packet_has_udp_set(pkt, 1); + } return pkt; } @@ -342,7 +360,8 @@ static odp_packet_t setup_icmp_pkt_ref(odp_pool_t pool) * @return Handle of created packet * @retval ODP_PACKET_INVALID Packet could not be created */ -static odp_packet_t pack_icmp_pkt(odp_pool_t pool, odp_packet_t pkt_ref) +static odp_packet_t pack_icmp_pkt(odp_pool_t pool, odp_packet_t pkt_ref, + odp_pktout_config_opt_t *pktout_cfg) { odp_packet_t pkt; char *buf; @@ -367,7 +386,9 @@ static odp_packet_t pack_icmp_pkt(odp_pool_t pool, odp_packet_t pkt_ref) ip = (odph_ipv4hdr_t *)(buf + ODPH_ETHHDR_LEN); seq = odp_atomic_fetch_add_u64(&counters.seq, 1) % 0xffff; ip->id = odp_cpu_to_be_16(seq); - ip->chksum = odph_chksum(ip, ODPH_IPV4HDR_LEN); + ip->chksum = 0; + if (!pktout_cfg->bit.ipv4_chksum) + ip->chksum = odph_chksum(ip, ODPH_IPV4HDR_LEN); /* icmp */ icmp = (odph_icmphdr_t *)(buf + ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); @@ -381,6 +402,13 @@ static odp_packet_t pack_icmp_pkt(odp_pool_t pool, odp_packet_t pkt_ref) icmp->chksum = 0; icmp->chksum = odph_chksum(icmp, args->appl.payload + ODPH_ICMPHDR_LEN); + if (pktout_cfg->bit.ipv4_chksum) { + odp_packet_l2_offset_set(pkt, 0); + odp_packet_l3_offset_set(pkt, ODPH_ETHHDR_LEN); + odp_packet_has_ipv4_set(pkt, 1); + odp_packet_l4_offset_set(pkt, ODPH_ETHHDR_LEN + ODPH_IPV4HDR_LEN); + } + return pkt; } @@ -421,6 +449,22 @@ static int create_pktio(const char *dev, odp_pool_t pool, dev); return -1; } + + odp_pktio_config_init(&itf->config); + itf->config.pktin.bit.ipv4_chksum = capa.config.pktin.bit.ipv4_chksum; + itf->config.pktin.bit.udp_chksum = capa.config.pktin.bit.udp_chksum; + itf->config.pktin.bit.drop_ipv4_err = capa.config.pktin.bit.drop_ipv4_err; + itf->config.pktin.bit.drop_udp_err = capa.config.pktin.bit.drop_udp_err; + + itf->config.pktout.bit.ipv4_chksum = capa.config.pktout.bit.ipv4_chksum; + itf->config.pktout.bit.udp_chksum = capa.config.pktout.bit.udp_chksum; + + if (odp_pktio_config(itf->pktio, &itf->config)) { + EXAMPLE_ERR("Error: Failed to set interface configuration %s\n", + dev); + return -1; + } + if (num_rx_queues > capa.max_input_queues) num_rx_queues = capa.max_input_queues; @@ -481,6 +525,7 @@ static int gen_send_thread(void *arg) int ret, i; thread_args_t *thr_args; odp_pktout_queue_t pktout; + odp_pktout_config_opt_t *pktout_cfg; odp_packet_t pkt_array[MAX_UDP_TX_BURST]; int pkt_array_size; int burst_start, burst_size; @@ -490,9 +535,10 @@ static int gen_send_thread(void *arg) thr_args = arg; pktout = thr_args->pktout; + pktout_cfg = thr_args->pktout_cfg; if (args->appl.mode == APPL_MODE_UDP) { - pkt_ref = setup_udp_pkt_ref(thr_args->pool); + pkt_ref = setup_udp_pkt_ref(thr_args->pool, pktout_cfg); pkt_array_size = args->appl.udp_tx_burst; } else if (args->appl.mode == APPL_MODE_PING) { pkt_ref = setup_icmp_pkt_ref(thr_args->pool); @@ -521,7 +567,7 @@ static int gen_send_thread(void *arg) if (args->appl.mode == APPL_MODE_UDP) { for (i = 0; i < pkt_array_size; i++) { pkt_array[i] = pack_udp_pkt(thr_args->pool, - pkt_ref); + pkt_ref, pktout_cfg); if (!odp_packet_is_valid(pkt_array[i])) break; } @@ -532,7 +578,7 @@ static int gen_send_thread(void *arg) break; } } else if (args->appl.mode == APPL_MODE_PING) { - pkt_array[0] = pack_icmp_pkt(thr_args->pool, pkt_ref); + pkt_array[0] = pack_icmp_pkt(thr_args->pool, pkt_ref, pktout_cfg); if (!odp_packet_is_valid(pkt_array[0])) { EXAMPLE_ERR(" [%2i] alloc_single failed\n", thr); @@ -671,6 +717,7 @@ static int gen_recv_thread(void *arg) odp_packet_t pkts[MAX_RX_BURST], pkt; odp_event_t events[MAX_RX_BURST]; int pkt_cnt, ev_cnt, i; + interface_t *itf; thr = odp_thread_id(); (void)arg; @@ -692,6 +739,27 @@ static int gen_recv_thread(void *arg) continue; for (i = 0, pkt_cnt = 0; i < ev_cnt; i++) { pkt = odp_packet_from_event(events[i]); + itf = &ifs[odp_pktio_index(odp_packet_input(pkt))]; + + if (odp_packet_has_ipv4(pkt)) { + if (itf->config.pktin.bit.ipv4_chksum) { /* HW validation */ + if (odp_packet_has_l3_error(pkt)) + printf("HW detected L3 error\n"); + } /* else SW validation */ + } + + if (odp_packet_has_udp(pkt)) { + if (itf->config.pktin.bit.udp_chksum) { /* HW validation*/ + if (odp_packet_has_l4_error(pkt)) + printf("HW detected L4 error\n"); + } /* else SW validation */ + } + if (odp_packet_has_tcp(pkt)) { + if (itf->config.pktin.bit.tcp_chksum) { /* HW validation */ + if (odp_packet_has_l4_error(pkt)) + printf("HW detected L4 error\n"); + } /*else SW validation */ + } /* Drop packets with errors */ if (odp_unlikely(odp_packet_has_error(pkt))) { @@ -701,9 +769,11 @@ static int gen_recv_thread(void *arg) pkts[pkt_cnt++] = pkt; } - print_pkts(thr, pkts, pkt_cnt); + if (pkt_cnt) { + print_pkts(thr, pkts, pkt_cnt); - odp_packet_free_multi(pkts, pkt_cnt); + odp_packet_free_multi(pkts, pkt_cnt); + } } return 0; @@ -797,7 +867,6 @@ int main(int argc, char *argv[]) odp_pool_t tmop; odp_queue_t tq; odp_event_t ev; - interface_t *ifs; odp_instance_t instance; odph_odpthread_params_t thr_params; @@ -959,6 +1028,7 @@ int main(int argc, char *argv[]) abort(); } (void)args->thread[1].pktout; /* Not used*/ + (void)args->thread[1].pktout_cfg; /* Not used*/ args->thread[1].pool = pool; args->thread[1].tp = tp; args->thread[1].tq = tq; @@ -988,6 +1058,7 @@ int main(int argc, char *argv[]) abort(); } args->thread[0].pktout = ifs[0].pktout[0]; + args->thread[0].pktout_cfg = &ifs[0].config.pktout; args->thread[0].pool = pool; args->thread[0].tp = tp; args->thread[0].tq = tq; @@ -1019,15 +1090,18 @@ int main(int argc, char *argv[]) int (*thr_run_func)(void *); int if_idx, pktout_idx; - if (args->appl.mode == APPL_MODE_RCV) + if (args->appl.mode == APPL_MODE_RCV) { (void)args->thread[i].pktout; /*not used*/ - else { + (void)args->thread[i].pktout_cfg; /*not used*/ + } else { if_idx = i % args->appl.if_count; pktout_idx = (i / args->appl.if_count) % ifs[if_idx].pktout_count; args->thread[i].pktout = ifs[if_idx].pktout[pktout_idx]; + args->thread[i].pktout_cfg = + &ifs[if_idx].config.pktout; } tq = odp_queue_create("", NULL); if (tq == ODP_QUEUE_INVALID) { diff --git a/platform/linux-generic/odp_packet_io.c b/platform/linux-generic/odp_packet_io.c index 98460a5..6c00b10 100644 --- a/platform/linux-generic/odp_packet_io.c +++ b/platform/linux-generic/odp_packet_io.c @@ -150,6 +150,8 @@ static void init_pktio_entry(pktio_entry_t *entry) init_out_queues(entry); pktio_classifier_init(entry); + + odp_pktio_config_init(&entry->s.config); } static odp_pktio_t alloc_lock_pktio_entry(void) diff --git a/platform/linux-generic/pktio/dpdk.c b/platform/linux-generic/pktio/dpdk.c index 6ac89bd..5f07c13 100644 --- a/platform/linux-generic/pktio/dpdk.c +++ b/platform/linux-generic/pktio/dpdk.c @@ -27,6 +27,9 @@ #include #include #include +#include +#include +#include #include static int disable_pktio; /** !0 this pktio disabled, 0 enabled */ @@ -189,6 +192,7 @@ static int dpdk_setup_port(pktio_entry_t *pktio_entry) int ret; pkt_dpdk_t *pkt_dpdk = &pktio_entry->s.pkt_dpdk; struct rte_eth_rss_conf rss_conf; + uint16_t hw_ip_checksum = 0; /* Always set some hash functions to enable DPDK RSS hash calculation */ if (pkt_dpdk->hash.all_bits == 0) { @@ -198,13 +202,18 @@ static int dpdk_setup_port(pktio_entry_t *pktio_entry) rss_conf_to_hash_proto(&rss_conf, &pkt_dpdk->hash); } + if (pktio_entry->s.config.pktin.bit.ipv4_chksum || + pktio_entry->s.config.pktin.bit.udp_chksum || + pktio_entry->s.config.pktin.bit.tcp_chksum) + hw_ip_checksum = 1; + struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = pkt_dpdk->data_room, .split_hdr_size = 0, .header_split = 0, - .hw_ip_checksum = 0, + .hw_ip_checksum = hw_ip_checksum, .hw_vlan_filter = 0, .jumbo_frame = 1, .hw_strip_crc = 0, @@ -420,6 +429,11 @@ static void dpdk_init_capability(pktio_entry_t *pktio_entry, { pkt_dpdk_t *pkt_dpdk = &pktio_entry->s.pkt_dpdk; odp_pktio_capability_t *capa = &pkt_dpdk->capa; + int ptype_cnt; + int ptype_l3_ipv4 = 0; + int ptype_l4_tcp = 0; + int ptype_l4_udp = 0; + uint32_t ptype_mask = RTE_PTYPE_L3_MASK | RTE_PTYPE_L4_MASK; memset(dev_info, 0, sizeof(struct rte_eth_dev_info)); memset(capa, 0, sizeof(odp_pktio_capability_t)); @@ -431,9 +445,53 @@ static void dpdk_init_capability(pktio_entry_t *pktio_entry, PKTIO_MAX_QUEUES); capa->set_op.op.promisc_mode = 1; + ptype_cnt = rte_eth_dev_get_supported_ptypes(pkt_dpdk->port_id, + ptype_mask, NULL, 0); + if (ptype_cnt > 0) { + uint32_t ptypes[ptype_cnt]; + int i; + + ptype_cnt = rte_eth_dev_get_supported_ptypes(pkt_dpdk->port_id, + ptype_mask, ptypes, ptype_cnt); + for (i = 0; i < ptype_cnt; i++) + switch (ptypes[i]) { + case RTE_PTYPE_L3_IPV4: + ptype_l3_ipv4 = 1; + break; + case RTE_PTYPE_L4_TCP: + ptype_l4_tcp = 1; + break; + case RTE_PTYPE_L4_UDP: + ptype_l4_udp = 1; + break; + } + } + odp_pktio_config_init(&capa->config); capa->config.pktin.bit.ts_all = 1; capa->config.pktin.bit.ts_ptp = 1; + + capa->config.pktin.bit.ipv4_chksum = ptype_l3_ipv4 && + (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_IPV4_CKSUM)? 1:0; + if (capa->config.pktin.bit.ipv4_chksum) + capa->config.pktin.bit.drop_ipv4_err = 1; + + capa->config.pktin.bit.udp_chksum = ptype_l4_udp && + (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_UDP_CKSUM)? 1:0; + if (capa->config.pktin.bit.udp_chksum) + capa->config.pktin.bit.drop_udp_err = 1; + + capa->config.pktin.bit.tcp_chksum = ptype_l4_tcp && + (dev_info->rx_offload_capa & DEV_RX_OFFLOAD_TCP_CKSUM)? 1:0; + if (capa->config.pktin.bit.tcp_chksum) + capa->config.pktin.bit.drop_tcp_err = 1; + + capa->config.pktout.bit.ipv4_chksum = + (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_IPV4_CKSUM)? 1:0; + capa->config.pktout.bit.udp_chksum = + (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_UDP_CKSUM)? 1:0; + capa->config.pktout.bit.tcp_chksum = + (dev_info->tx_offload_capa & DEV_TX_OFFLOAD_TCP_CKSUM)? 1:0; } static int dpdk_open(odp_pktio_t id ODP_UNUSED, @@ -605,9 +663,11 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, int nb_pkts = 0; int alloc_len, num; odp_pool_t pool = pktio_entry->s.pkt_dpdk.pool; + odp_pktin_config_opt_t *pktin_cfg; /* Allocate maximum sized packets */ alloc_len = pktio_entry->s.pkt_dpdk.data_room; + pktin_cfg = &pktio_entry->s.config.pktin; num = packet_alloc_multi(pool, alloc_len, pkt_table, mbuf_num); if (num != mbuf_num) { @@ -658,6 +718,34 @@ static inline int mbuf_to_pkt(pktio_entry_t *pktio_entry, if (mbuf->ol_flags & PKT_RX_RSS_HASH) odp_packet_flow_hash_set(pkt, mbuf->hash.rss); + if (mbuf->packet_type & RTE_PTYPE_L3_IPV4 && + pktin_cfg->bit.ipv4_chksum && + mbuf->ol_flags & PKT_RX_IP_CKSUM_BAD) { + if (pktin_cfg->bit.drop_ipv4_err) { + odp_packet_free(pkt); + continue; + } else + pkt_hdr->p.error_flags.ip_err = 1; + } + + if (mbuf->packet_type & RTE_PTYPE_L4_UDP && + pktin_cfg->bit.udp_chksum && + mbuf->ol_flags & PKT_RX_L4_CKSUM_BAD) { + if (pktin_cfg->bit.drop_udp_err) { + odp_packet_free(pkt); + continue; + } else + pkt_hdr->p.error_flags.udp_err = 1; + } else if (mbuf->packet_type & RTE_PTYPE_L4_TCP && + pktin_cfg->bit.tcp_chksum && + mbuf->ol_flags & PKT_RX_L4_CKSUM_BAD) { + if (pktin_cfg->bit.drop_tcp_err) { + odp_packet_free(pkt); + continue; + } else + pkt_hdr->p.error_flags.tcp_err = 1; + } + packet_set_ts(pkt_hdr, ts); pkt_table[nb_pkts++] = pkt; @@ -675,7 +763,15 @@ fail: return (i > 0 ? i : -1); } - +static inline uint16_t phdr_csum(int ipv4, + void *l3_hdr, + uint64_t ol_flags) +{ + if (ipv4) + return rte_ipv4_phdr_cksum(l3_hdr, ol_flags); + else /*ipv6*/ + return rte_ipv6_phdr_cksum(l3_hdr, ol_flags); +} static inline int pkt_to_mbuf(pktio_entry_t *pktio_entry, struct rte_mbuf *mbuf_table[], const odp_packet_t pkt_table[], uint16_t num) @@ -684,14 +780,26 @@ static inline int pkt_to_mbuf(pktio_entry_t *pktio_entry, int i, j; char *data; uint16_t pkt_len; + odp_bool_t ipv4_chksum_cfg, udp_chksum_cfg, tcp_chksum_cfg; + odp_bool_t ipv4_chksum_pkt, udp_chksum_pkt, tcp_chksum_pkt; + odp_packet_t pkt; + odp_packet_hdr_t *pkt_hdr; + struct rte_mbuf *mbuf; if (odp_unlikely((rte_pktmbuf_alloc_bulk(pkt_dpdk->pkt_pool, mbuf_table, num)))) { ODP_ERR("Failed to alloc mbuf\n"); return 0; } + ipv4_chksum_cfg = pktio_entry->s.config.pktout.bit.ipv4_chksum; + udp_chksum_cfg = pktio_entry->s.config.pktout.bit.udp_chksum; + tcp_chksum_cfg = pktio_entry->s.config.pktout.bit.tcp_chksum; + for (i = 0; i < num; i++) { - pkt_len = _odp_packet_len(pkt_table[i]); + pkt = pkt_table[i]; + mbuf = mbuf_table[i]; + pkt_len = _odp_packet_len(pkt); + pkt_hdr = odp_packet_hdr(pkt); if (pkt_len > pkt_dpdk->mtu) { if (i == 0) @@ -700,9 +808,41 @@ static inline int pkt_to_mbuf(pktio_entry_t *pktio_entry, } /* Packet always fits in mbuf */ - data = rte_pktmbuf_append(mbuf_table[i], pkt_len); + data = rte_pktmbuf_append(mbuf, pkt_len); + + odp_packet_copy_to_mem(pkt, 0, pkt_len, data); + + ipv4_chksum_pkt = pkt_hdr->p.input_flags.ipv4 && ipv4_chksum_cfg; + udp_chksum_pkt = pkt_hdr->p.input_flags.udp && udp_chksum_cfg; + tcp_chksum_pkt = pkt_hdr->p.input_flags.tcp && tcp_chksum_cfg; + + if (ipv4_chksum_pkt || udp_chksum_pkt || tcp_chksum_pkt) { + mbuf->l2_len = pkt_hdr->p.l3_offset - pkt_hdr->p.l2_offset; + mbuf->l3_len = pkt_hdr->p.l4_offset - pkt_hdr->p.l3_offset; + mbuf->ol_flags = 0; - odp_packet_copy_to_mem(pkt_table[i], 0, pkt_len, data); + if (ipv4_chksum_pkt) /* ip->hdr_checksum = zero, l2_len and l3_len set */ + mbuf->ol_flags |= PKT_TX_IPV4 | PKT_TX_IP_CKSUM; + + if (udp_chksum_pkt) { /* l2_len and l3_len set */ + struct udp_hdr *udp = (struct udp_hdr *)(data + mbuf->l2_len + + mbuf->l3_len); + + udp->dgram_cksum = phdr_csum(pkt_hdr->p.input_flags.ipv4, + (void *)(data + mbuf->l2_len), + mbuf->ol_flags); + + mbuf->ol_flags |= PKT_TX_UDP_CKSUM; + } else if (tcp_chksum_pkt) { /* l2_len and l3_len set */ + struct tcp_hdr *tcp = (struct tcp_hdr *)(data + mbuf->l2_len + + mbuf->l3_len); + + tcp->cksum = phdr_csum(pkt_hdr->p.input_flags.ipv4, + (void *)(data + mbuf->l2_len), + mbuf->ol_flags); + mbuf->ol_flags |= PKT_TX_TCP_CKSUM; + } + } } return i;