From e77fec694936ce067153c5a6596c6bc818baaa5c Mon Sep 17 00:00:00 2001 From: Yangchao Zhou Date: Thu, 19 Apr 2018 11:12:20 +0800 Subject: [PATCH] kni: fix possible mbuf leaks and speed up port release rx_q fifo can only be released by kernel thread. There may be mbuf leaks in rx_q because kernel threads are randomly stopped. When the kni is released and netdev is unregisterd, convert the physical address mbufs in rx_q to the virtual address in free_q. By the way, alloc_q can be processed together to speed up the release rate in userspace. In my test, it is improved from 300-500ms with a mempool that has 131072 mbufs to 10ms(regardless of the specifications). Suggested-by: Ferruh Yigit Signed-off-by: Yangchao Zhou Acked-by: Ferruh Yigit --- kernel/linux/kni/kni_dev.h | 1 + kernel/linux/kni/kni_misc.c | 2 ++ kernel/linux/kni/kni_net.c | 40 +++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/kernel/linux/kni/kni_dev.h b/kernel/linux/kni/kni_dev.h index c9393d8919..6275ef27f4 100644 --- a/kernel/linux/kni/kni_dev.h +++ b/kernel/linux/kni/kni_dev.h @@ -92,6 +92,7 @@ struct kni_dev { void *alloc_va[MBUF_BURST_SZ]; }; +void kni_net_release_fifo_phy(struct kni_dev *kni); void kni_net_rx(struct kni_dev *kni); void kni_net_init(struct net_device *dev); void kni_net_config_lo_mode(char *lo_str); diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c index 01574ecf74..fa69f8e638 100644 --- a/kernel/linux/kni/kni_misc.c +++ b/kernel/linux/kni/kni_misc.c @@ -192,6 +192,8 @@ kni_dev_remove(struct kni_dev *dev) free_netdev(dev->net_dev); } + kni_net_release_fifo_phy(dev); + return 0; } diff --git a/kernel/linux/kni/kni_net.c b/kernel/linux/kni/kni_net.c index 9f9b798c57..7fcfa106cb 100644 --- a/kernel/linux/kni/kni_net.c +++ b/kernel/linux/kni/kni_net.c @@ -163,6 +163,46 @@ kni_net_release(struct net_device *dev) return (ret == 0) ? req.result : ret; } +static void +kni_fifo_trans_pa2va(struct kni_dev *kni, + struct rte_kni_fifo *src_pa, struct rte_kni_fifo *dst_va) +{ + uint32_t ret, i, num_dst, num_rx; + void *kva; + do { + num_dst = kni_fifo_free_count(dst_va); + if (num_dst == 0) + return; + + num_rx = min_t(uint32_t, num_dst, MBUF_BURST_SZ); + + num_rx = kni_fifo_get(src_pa, kni->pa, num_rx); + if (num_rx == 0) + return; + + for (i = 0; i < num_rx; i++) { + kva = pa2kva(kni->pa[i]); + kni->va[i] = pa2va(kni->pa[i], kva); + } + + ret = kni_fifo_put(dst_va, kni->va, num_rx); + if (ret != num_rx) { + /* Failing should not happen */ + pr_err("Fail to enqueue entries into dst_va\n"); + return; + } + } while (1); +} + +/* Try to release mbufs when kni release */ +void kni_net_release_fifo_phy(struct kni_dev *kni) +{ + /* release rx_q first, because it can't release in userspace */ + kni_fifo_trans_pa2va(kni, kni->rx_q, kni->free_q); + /* release alloc_q for speeding up kni release in userspace */ + kni_fifo_trans_pa2va(kni, kni->alloc_q, kni->free_q); +} + /* * Configuration changes (passed on by ifconfig) */ -- 2.20.1