From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id D6FD0A0613 for ; Tue, 27 Aug 2019 11:31:51 +0200 (CEST) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id CEC9B54AE; Tue, 27 Aug 2019 11:31:51 +0200 (CEST) Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by dpdk.org (Postfix) with ESMTP id A7E3E1BFFB for ; Tue, 27 Aug 2019 11:31:50 +0200 (CEST) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 25B9D3082E25; Tue, 27 Aug 2019 09:31:50 +0000 (UTC) Received: from rh.redhat.com (ovpn-117-48.ams2.redhat.com [10.36.117.48]) by smtp.corp.redhat.com (Postfix) with ESMTP id 158695C1D6; Tue, 27 Aug 2019 09:31:48 +0000 (UTC) From: Kevin Traynor To: Yangchao Zhou Cc: Ferruh Yigit , dpdk stable Date: Tue, 27 Aug 2019 10:30:23 +0100 Message-Id: <20190827093032.20423-46-ktraynor@redhat.com> In-Reply-To: <20190827093032.20423-1-ktraynor@redhat.com> References: <20190827093032.20423-1-ktraynor@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.46]); Tue, 27 Aug 2019 09:31:50 +0000 (UTC) Subject: [dpdk-stable] patch 'kni: fix kernel crash with multi-segments' has been queued to LTS release 18.11.3 X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" Hi, FYI, your patch has been queued to LTS release 18.11.3 Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet. It will be pushed if I get no objections before 09/03/19. So please shout if anyone has objections. Also note that after the patch there's a diff of the upstream commit vs the patch applied to the branch. This will indicate if there was any rebasing needed to apply to the stable branch. If there were code changes for rebasing (ie: not only metadata diffs), please double check that the rebase was correctly done. Queued patches are on a temporary branch at: https://github.com/kevintraynor/dpdk-stable-queue This queued commit can be viewed at: https://github.com/kevintraynor/dpdk-stable-queue/commit/97699e43ded7e4b3893c88686c23a46923da037d Thanks. Kevin Traynor --- >From 97699e43ded7e4b3893c88686c23a46923da037d Mon Sep 17 00:00:00 2001 From: Yangchao Zhou Date: Tue, 25 Jun 2019 23:04:14 +0800 Subject: [PATCH] kni: fix kernel crash with multi-segments [ upstream commit 5eb1708ec1db1f2d644f44a42468139df0b0ad6c ] va2pa depends on the physical address and virtual address offset of current mbuf. It may get the wrong physical address of next mbuf which allocated in another hugepage segment. In rte_mempool_populate_default(), trying to allocate whole block of contiguous memory could be failed. Then, it would reserve memory in several memzones that have different physical address and virtual address offsets. The rte_mempool_populate_default() is used by rte_pktmbuf_pool_create(). Fixes: 8451269e6d7b ("kni: remove continuous memory restriction") Signed-off-by: Yangchao Zhou Acked-by: Ferruh Yigit --- .../prog_guide/kernel_nic_interface.rst | 8 ++- kernel/linux/kni/kni_net.c | 51 ++++++++++++------- .../eal/include/exec-env/rte_kni_common.h | 2 +- lib/librte_kni/rte_kni.c | 16 +++++- lib/librte_kni/rte_kni_fifo.h | 11 ++++ 5 files changed, 66 insertions(+), 22 deletions(-) diff --git a/doc/guides/prog_guide/kernel_nic_interface.rst b/doc/guides/prog_guide/kernel_nic_interface.rst index 7b8a481a6..9c1483adc 100644 --- a/doc/guides/prog_guide/kernel_nic_interface.rst +++ b/doc/guides/prog_guide/kernel_nic_interface.rst @@ -267,10 +267,14 @@ Use Case: Ingress On the DPDK RX side, the mbuf is allocated by the PMD in the RX thread context. -This thread will enqueue the mbuf in the rx_q FIFO. +This thread will enqueue the mbuf in the rx_q FIFO, +and the next pointers in mbuf-chain will convert to physical address. The KNI thread will poll all KNI active devices for the rx_q. If an mbuf is dequeued, it will be converted to a sk_buff and sent to the net stack via netif_rx(). -The dequeued mbuf must be freed, so the same pointer is sent back in the free_q FIFO. +The dequeued mbuf must be freed, so the same pointer is sent back in the free_q FIFO, +and next pointers must convert back to virtual address if exists before put in the free_q FIFO. The RX thread, in the same main loop, polls this FIFO and frees the mbuf after dequeuing it. +The address conversion of the next pointer is to prevent the chained mbuf +in different hugepage segments from causing kernel crash. Use Case: Egress diff --git a/kernel/linux/kni/kni_net.c b/kernel/linux/kni/kni_net.c index 0be1517f0..96dc93949 100644 --- a/kernel/linux/kni/kni_net.c +++ b/kernel/linux/kni/kni_net.c @@ -62,16 +62,4 @@ kva2data_kva(struct rte_kni_mbuf *m) } -/* virtual address to physical address */ -static void * -va2pa(void *va, struct rte_kni_mbuf *m) -{ - void *pa; - - pa = (void *)((unsigned long)va - - ((unsigned long)m->buf_addr - - (unsigned long)m->buf_physaddr)); - return pa; -} - /* * It can be called to process the request. @@ -174,5 +162,8 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, { uint32_t ret, i, num_dst, num_rx; - void *kva; + struct rte_kni_mbuf *kva, *prev_kva; + int nb_segs; + int kva_nb_segs; + do { num_dst = kni_fifo_free_count(dst_va); @@ -189,4 +180,15 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, kva = pa2kva(kni->pa[i]); kni->va[i] = pa2va(kni->pa[i], kva); + + kva_nb_segs = kva->nb_segs; + for (nb_segs = 0; nb_segs < kva_nb_segs; nb_segs++) { + if (!kva->next) + break; + + prev_kva = kva; + kva = pa2kva(kva->next); + /* Convert physical address to virtual address */ + prev_kva->next = pa2va(prev_kva->next, kva); + } } @@ -314,5 +316,5 @@ kni_net_rx_normal(struct kni_dev *kni) uint32_t len; uint32_t i, num_rx, num_fq; - struct rte_kni_mbuf *kva; + struct rte_kni_mbuf *kva, *prev_kva; void *data_kva; struct sk_buff *skb; @@ -364,6 +366,9 @@ kni_net_rx_normal(struct kni_dev *kni) break; - kva = pa2kva(va2pa(kva->next, kva)); + prev_kva = kva; + kva = pa2kva(kva->next); data_kva = kva2data_kva(kva); + /* Convert physical address to virtual address */ + prev_kva->next = pa2va(prev_kva->next, kva); } } @@ -397,5 +402,5 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) uint32_t len; uint32_t i, num, num_rq, num_tq, num_aq, num_fq; - struct rte_kni_mbuf *kva; + struct rte_kni_mbuf *kva, *next_kva; void *data_kva; struct rte_kni_mbuf *alloc_kva; @@ -440,4 +445,11 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) kni->va[i] = pa2va(kni->pa[i], kva); + while (kva->next) { + next_kva = pa2kva(kva->next); + /* Convert physical address to virtual address */ + kva->next = pa2va(kva->next, next_kva); + kva = next_kva; + } + alloc_kva = pa2kva(kni->alloc_pa[i]); alloc_data_kva = kva2data_kva(alloc_kva); @@ -482,5 +494,5 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) uint32_t len; uint32_t i, num_rq, num_fq, num; - struct rte_kni_mbuf *kva; + struct rte_kni_mbuf *kva, *prev_kva; void *data_kva; struct sk_buff *skb; @@ -546,6 +558,9 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) break; - kva = pa2kva(va2pa(kva->next, kva)); + prev_kva = kva; + kva = pa2kva(kva->next); data_kva = kva2data_kva(kva); + /* Convert physical address to virtual address */ + prev_kva->next = pa2va(prev_kva->next, kva); } } diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h index 5db5a1333..eb7adf34a 100644 --- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h +++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h @@ -87,5 +87,5 @@ struct rte_kni_mbuf { char pad3[8] __attribute__((__aligned__(RTE_CACHE_LINE_MIN_SIZE))); void *pool; - void *next; + void *next; /**< Physical address of next mbuf in kernel. */ }; diff --git a/lib/librte_kni/rte_kni.c b/lib/librte_kni/rte_kni.c index 2721afdf8..941bec968 100644 --- a/lib/librte_kni/rte_kni.c +++ b/lib/librte_kni/rte_kni.c @@ -359,4 +359,17 @@ va2pa(struct rte_mbuf *m) } +static void * +va2pa_all(struct rte_mbuf *mbuf) +{ + void *phy_mbuf = va2pa(mbuf); + struct rte_mbuf *next = mbuf->next; + while (next) { + mbuf->next = va2pa(next); + mbuf = next; + next = mbuf->next; + } + return phy_mbuf; +} + static void obj_free(struct rte_mempool *mp __rte_unused, void *opaque, void *obj, @@ -551,4 +564,5 @@ unsigned rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num) { + num = RTE_MIN(kni_fifo_free_count(kni->rx_q), num); void *phy_mbufs[num]; unsigned int ret; @@ -556,5 +570,5 @@ rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num) for (i = 0; i < num; i++) - phy_mbufs[i] = va2pa(mbufs[i]); + phy_mbufs[i] = va2pa_all(mbufs[i]); ret = kni_fifo_put(kni->rx_q, phy_mbufs, num); diff --git a/lib/librte_kni/rte_kni_fifo.h b/lib/librte_kni/rte_kni_fifo.h index 287d7deb2..d2ec82fe8 100644 --- a/lib/librte_kni/rte_kni_fifo.h +++ b/lib/librte_kni/rte_kni_fifo.h @@ -105,2 +105,13 @@ kni_fifo_count(struct rte_kni_fifo *fifo) return (fifo->len + fifo_write - fifo_read) & (fifo->len - 1); } + +/** + * Get the num of available elements in the fifo + */ +static inline uint32_t +kni_fifo_free_count(struct rte_kni_fifo *fifo) +{ + uint32_t fifo_write = __KNI_LOAD_ACQUIRE(&fifo->write); + uint32_t fifo_read = __KNI_LOAD_ACQUIRE(&fifo->read); + return (fifo_read - fifo_write - 1) & (fifo->len - 1); +} -- 2.20.1 --- Diff of the applied patch vs upstream commit (please double-check if non-empty: --- --- - 2019-08-27 09:40:13.423545661 +0100 +++ 0046-kni-fix-kernel-crash-with-multi-segments.patch 2019-08-27 09:40:10.947143732 +0100 @@ -1 +1 @@ -From 5eb1708ec1db1f2d644f44a42468139df0b0ad6c Mon Sep 17 00:00:00 2001 +From 97699e43ded7e4b3893c88686c23a46923da037d Mon Sep 17 00:00:00 2001 @@ -5,0 +6,2 @@ +[ upstream commit 5eb1708ec1db1f2d644f44a42468139df0b0ad6c ] + @@ -17 +18,0 @@ -Cc: stable@dpdk.org @@ -24 +25 @@ - .../linux/eal/include/rte_kni_common.h | 2 +- + .../eal/include/exec-env/rte_kni_common.h | 2 +- @@ -30 +31 @@ -index 5afd05c0a..38369b30e 100644 +index 7b8a481a6..9c1483adc 100644 @@ -33 +34 @@ -@@ -269,10 +269,14 @@ Use Case: Ingress +@@ -267,10 +267,14 @@ Use Case: Ingress @@ -51 +52 @@ -index 319ee2dcb..a736407e6 100644 +index 0be1517f0..96dc93949 100644 @@ -54 +55 @@ -@@ -63,16 +63,4 @@ kva2data_kva(struct rte_kni_mbuf *m) +@@ -62,16 +62,4 @@ kva2data_kva(struct rte_kni_mbuf *m) @@ -71 +72 @@ -@@ -175,5 +163,8 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, +@@ -174,5 +162,8 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, @@ -81 +82 @@ -@@ -190,4 +181,15 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, +@@ -189,4 +180,15 @@ kni_fifo_trans_pa2va(struct kni_dev *kni, @@ -97 +98 @@ -@@ -315,5 +317,5 @@ kni_net_rx_normal(struct kni_dev *kni) +@@ -314,5 +316,5 @@ kni_net_rx_normal(struct kni_dev *kni) @@ -104 +105 @@ -@@ -362,6 +364,9 @@ kni_net_rx_normal(struct kni_dev *kni) +@@ -364,6 +366,9 @@ kni_net_rx_normal(struct kni_dev *kni) @@ -115 +116 @@ -@@ -394,5 +399,5 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) +@@ -397,5 +402,5 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) @@ -122 +123 @@ -@@ -438,4 +443,11 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) +@@ -440,4 +445,11 @@ kni_net_rx_lo_fifo(struct kni_dev *kni) @@ -134 +135 @@ -@@ -480,5 +492,5 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) +@@ -482,5 +494,5 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) @@ -141 +142 @@ -@@ -538,6 +550,9 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) +@@ -546,6 +558,9 @@ kni_net_rx_lo_fifo_skb(struct kni_dev *kni) @@ -152,4 +153,4 @@ -diff --git a/lib/librte_eal/linux/eal/include/rte_kni_common.h b/lib/librte_eal/linux/eal/include/rte_kni_common.h -index 91a1c1408..37d9ee8f0 100644 ---- a/lib/librte_eal/linux/eal/include/rte_kni_common.h -+++ b/lib/librte_eal/linux/eal/include/rte_kni_common.h +diff --git a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h +index 5db5a1333..eb7adf34a 100644 +--- a/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h ++++ b/lib/librte_eal/linuxapp/eal/include/exec-env/rte_kni_common.h @@ -164 +165 @@ -index 1de053deb..4b51fb4fe 100644 +index 2721afdf8..941bec968 100644 @@ -167 +168 @@ -@@ -350,4 +350,17 @@ va2pa(struct rte_mbuf *m) +@@ -359,4 +359,17 @@ va2pa(struct rte_mbuf *m) @@ -185 +186 @@ -@@ -542,4 +555,5 @@ unsigned +@@ -551,4 +564,5 @@ unsigned @@ -191 +192 @@ -@@ -547,5 +561,5 @@ rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num) +@@ -556,5 +570,5 @@ rte_kni_tx_burst(struct rte_kni *kni, struct rte_mbuf **mbufs, unsigned int num)