* [PATCH v8 bpf-next 07/10] bpf: Make redirect_info accessible from modules
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
We are going to add kern_flags field in redirect_info for kernel
internal use.
In order to avoid function call to access the flags, make redirect_info
accessible from modules. Also as it is now non-static, add prefix bpf_
to redirect_info.
v6:
- Fix sparse warning around EXPORT_SYMBOL.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
include/linux/filter.h | 10 ++++++++++
net/core/filter.c | 29 +++++++++++------------------
2 files changed, 21 insertions(+), 18 deletions(-)
diff --git a/include/linux/filter.h b/include/linux/filter.h
index c73dd73..4717af8 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -537,6 +537,16 @@ struct sk_msg_buff {
struct list_head list;
};
+struct bpf_redirect_info {
+ u32 ifindex;
+ u32 flags;
+ struct bpf_map *map;
+ struct bpf_map *map_to_flush;
+ unsigned long map_owner;
+};
+
+DECLARE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
+
/* Compute the linear packet data range [data, data_end) which
* will be accessed by various program types (cls_bpf, act_bpf,
* lwt, ...). Subsystems allowing direct data access must (!)
diff --git a/net/core/filter.c b/net/core/filter.c
index 7509bb7..4754089 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2082,19 +2082,12 @@ static int __bpf_redirect(struct sk_buff *skb, struct net_device *dev,
.arg3_type = ARG_ANYTHING,
};
-struct redirect_info {
- u32 ifindex;
- u32 flags;
- struct bpf_map *map;
- struct bpf_map *map_to_flush;
- unsigned long map_owner;
-};
-
-static DEFINE_PER_CPU(struct redirect_info, redirect_info);
+DEFINE_PER_CPU(struct bpf_redirect_info, bpf_redirect_info);
+EXPORT_PER_CPU_SYMBOL_GPL(bpf_redirect_info);
BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
if (unlikely(flags & ~(BPF_F_INGRESS)))
return TC_ACT_SHOT;
@@ -2107,7 +2100,7 @@ struct redirect_info {
int skb_do_redirect(struct sk_buff *skb)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
struct net_device *dev;
dev = dev_get_by_index_rcu(dev_net(skb->dev), ri->ifindex);
@@ -3200,7 +3193,7 @@ static int __bpf_tx_xdp_map(struct net_device *dev_rx, void *fwd,
void xdp_do_flush_map(void)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
struct bpf_map *map = ri->map_to_flush;
ri->map_to_flush = NULL;
@@ -3245,7 +3238,7 @@ static inline bool xdp_map_invalid(const struct bpf_prog *xdp_prog,
static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
struct bpf_prog *xdp_prog)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
unsigned long map_owner = ri->map_owner;
struct bpf_map *map = ri->map;
u32 index = ri->ifindex;
@@ -3285,7 +3278,7 @@ static int xdp_do_redirect_map(struct net_device *dev, struct xdp_buff *xdp,
int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
struct bpf_prog *xdp_prog)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
struct net_device *fwd;
u32 index = ri->ifindex;
int err;
@@ -3317,7 +3310,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
struct xdp_buff *xdp,
struct bpf_prog *xdp_prog)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
unsigned long map_owner = ri->map_owner;
struct bpf_map *map = ri->map;
u32 index = ri->ifindex;
@@ -3368,7 +3361,7 @@ static int xdp_do_generic_redirect_map(struct net_device *dev,
int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
u32 index = ri->ifindex;
struct net_device *fwd;
int err = 0;
@@ -3399,7 +3392,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
BPF_CALL_2(bpf_xdp_redirect, u32, ifindex, u64, flags)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
if (unlikely(flags))
return XDP_ABORTED;
@@ -3423,7 +3416,7 @@ int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
BPF_CALL_4(bpf_xdp_redirect_map, struct bpf_map *, map, u32, ifindex, u64, flags,
unsigned long, map_owner)
{
- struct redirect_info *ri = this_cpu_ptr(&redirect_info);
+ struct bpf_redirect_info *ri = this_cpu_ptr(&bpf_redirect_info);
if (unlikely(flags))
return XDP_ABORTED;
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 06/10] veth: Add ndo_xdp_xmit
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
This allows NIC's XDP to redirect packets to veth. The destination veth
device enqueues redirected packets to the napi ring of its peer, then
they are processed by XDP on its peer veth device.
This can be thought as calling another XDP program by XDP program using
REDIRECT, when the peer enables driver XDP.
Note that when the peer veth device does not set driver xdp, redirected
packets will be dropped because the peer is not ready for NAPI.
v4:
- Don't use xdp_ok_fwd_dev() because checking IFF_UP is not necessary.
Add comments about it and check only MTU.
v2:
- Drop the part converting xdp_frame into skb when XDP is not enabled.
- Implement bulk interface of ndo_xdp_xmit.
- Implement XDP_XMIT_FLUSH bit and drop ndo_xdp_flush.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Acked-by: John Fastabend <john.fastabend@gmail.com>
---
drivers/net/veth.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 89f3059..dbb693a 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -17,6 +17,7 @@
#include <net/rtnetlink.h>
#include <net/dst.h>
#include <net/xfrm.h>
+#include <net/xdp.h>
#include <linux/veth.h>
#include <linux/module.h>
#include <linux/bpf.h>
@@ -125,6 +126,11 @@ static void *veth_ptr_to_xdp(void *ptr)
return (void *)((unsigned long)ptr & ~VETH_XDP_FLAG);
}
+static void *veth_xdp_to_ptr(void *ptr)
+{
+ return (void *)((unsigned long)ptr | VETH_XDP_FLAG);
+}
+
static void veth_ptr_free(void *ptr)
{
if (veth_is_xdp_frame(ptr))
@@ -267,6 +273,50 @@ static struct sk_buff *veth_build_skb(void *head, int headroom, int len,
return skb;
}
+static int veth_xdp_xmit(struct net_device *dev, int n,
+ struct xdp_frame **frames, u32 flags)
+{
+ struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
+ struct net_device *rcv;
+ unsigned int max_len;
+ int i, drops = 0;
+
+ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+ return -EINVAL;
+
+ rcv = rcu_dereference(priv->peer);
+ if (unlikely(!rcv))
+ return -ENXIO;
+
+ rcv_priv = netdev_priv(rcv);
+ /* Non-NULL xdp_prog ensures that xdp_ring is initialized on receive
+ * side. This means an XDP program is loaded on the peer and the peer
+ * device is up.
+ */
+ if (!rcu_access_pointer(rcv_priv->xdp_prog))
+ return -ENXIO;
+
+ max_len = rcv->mtu + rcv->hard_header_len + VLAN_HLEN;
+
+ spin_lock(&rcv_priv->xdp_ring.producer_lock);
+ for (i = 0; i < n; i++) {
+ struct xdp_frame *frame = frames[i];
+ void *ptr = veth_xdp_to_ptr(frame);
+
+ if (unlikely(frame->len > max_len ||
+ __ptr_ring_produce(&rcv_priv->xdp_ring, ptr))) {
+ xdp_return_frame_rx_napi(frame);
+ drops++;
+ }
+ }
+ spin_unlock(&rcv_priv->xdp_ring.producer_lock);
+
+ if (flags & XDP_XMIT_FLUSH)
+ __veth_xdp_flush(rcv_priv);
+
+ return n - drops;
+}
+
static struct sk_buff *veth_xdp_rcv_one(struct veth_priv *priv,
struct xdp_frame *frame)
{
@@ -769,6 +819,7 @@ static int veth_xdp(struct net_device *dev, struct netdev_bpf *xdp)
.ndo_features_check = passthru_features_check,
.ndo_set_rx_headroom = veth_set_rx_headroom,
.ndo_bpf = veth_xdp,
+ .ndo_xdp_xmit = veth_xdp_xmit,
};
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 05/10] veth: Handle xdp_frames in xdp napi ring
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
This is preparation for XDP TX and ndo_xdp_xmit.
This allows napi handler to handle xdp_frames through xdp ring as well
as sk_buff.
v8:
- Don't use xdp_frame pointer address to calculate skb->head and
headroom.
v7:
- Use xdp_scrub_frame() instead of memset().
v3:
- Revert v2 change around rings and use a flag to differentiate skb and
xdp_frame, since bulk skb xmit makes little performance difference
for now.
v2:
- Use another ring instead of using flag to differentiate skb and
xdp_frame. This approach makes bulk skb transmit possible in
veth_xmit later.
- Clear xdp_frame feilds in skb->head.
- Implement adjust_tail.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Acked-by: John Fastabend <john.fastabend@gmail.com>
---
drivers/net/veth.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 84 insertions(+), 5 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 9edf104..89f3059 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -22,12 +22,12 @@
#include <linux/bpf.h>
#include <linux/filter.h>
#include <linux/ptr_ring.h>
-#include <linux/skb_array.h>
#include <linux/bpf_trace.h>
#define DRV_NAME "veth"
#define DRV_VERSION "1.0"
+#define VETH_XDP_FLAG BIT(0)
#define VETH_RING_SIZE 256
#define VETH_XDP_HEADROOM (XDP_PACKET_HEADROOM + NET_IP_ALIGN)
@@ -115,6 +115,24 @@ static void veth_get_ethtool_stats(struct net_device *dev,
/* general routines */
+static bool veth_is_xdp_frame(void *ptr)
+{
+ return (unsigned long)ptr & VETH_XDP_FLAG;
+}
+
+static void *veth_ptr_to_xdp(void *ptr)
+{
+ return (void *)((unsigned long)ptr & ~VETH_XDP_FLAG);
+}
+
+static void veth_ptr_free(void *ptr)
+{
+ if (veth_is_xdp_frame(ptr))
+ xdp_return_frame(veth_ptr_to_xdp(ptr));
+ else
+ kfree_skb(ptr);
+}
+
static void __veth_xdp_flush(struct veth_priv *priv)
{
/* Write ptr_ring before reading rx_notify_masked */
@@ -249,6 +267,63 @@ static struct sk_buff *veth_build_skb(void *head, int headroom, int len,
return skb;
}
+static struct sk_buff *veth_xdp_rcv_one(struct veth_priv *priv,
+ struct xdp_frame *frame)
+{
+ void *hard_start = frame->data - frame->headroom;
+ void *head = hard_start - sizeof(struct xdp_frame);
+ int len = frame->len, delta = 0;
+ struct bpf_prog *xdp_prog;
+ unsigned int headroom;
+ struct sk_buff *skb;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(priv->xdp_prog);
+ if (likely(xdp_prog)) {
+ struct xdp_buff xdp;
+ u32 act;
+
+ xdp.data_hard_start = hard_start;
+ xdp.data = frame->data;
+ xdp.data_end = frame->data + frame->len;
+ xdp.data_meta = frame->data - frame->metasize;
+ xdp.rxq = &priv->xdp_rxq;
+
+ act = bpf_prog_run_xdp(xdp_prog, &xdp);
+
+ switch (act) {
+ case XDP_PASS:
+ delta = frame->data - xdp.data;
+ len = xdp.data_end - xdp.data;
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ case XDP_ABORTED:
+ trace_xdp_exception(priv->dev, xdp_prog, act);
+ case XDP_DROP:
+ goto err_xdp;
+ }
+ }
+ rcu_read_unlock();
+
+ headroom = sizeof(struct xdp_frame) + frame->headroom - delta;
+ skb = veth_build_skb(head, headroom, len, 0);
+ if (!skb) {
+ xdp_return_frame(frame);
+ goto err;
+ }
+
+ xdp_scrub_frame(frame);
+ skb->protocol = eth_type_trans(skb, priv->dev);
+err:
+ return skb;
+err_xdp:
+ rcu_read_unlock();
+ xdp_return_frame(frame);
+
+ return NULL;
+}
+
static struct sk_buff *veth_xdp_rcv_skb(struct veth_priv *priv,
struct sk_buff *skb)
{
@@ -359,12 +434,16 @@ static int veth_xdp_rcv(struct veth_priv *priv, int budget)
int i, done = 0;
for (i = 0; i < budget; i++) {
- struct sk_buff *skb = __ptr_ring_consume(&priv->xdp_ring);
+ void *ptr = __ptr_ring_consume(&priv->xdp_ring);
+ struct sk_buff *skb;
- if (!skb)
+ if (!ptr)
break;
- skb = veth_xdp_rcv_skb(priv, skb);
+ if (veth_is_xdp_frame(ptr))
+ skb = veth_xdp_rcv_one(priv, veth_ptr_to_xdp(ptr));
+ else
+ skb = veth_xdp_rcv_skb(priv, ptr);
if (skb)
napi_gro_receive(&priv->xdp_napi, skb);
@@ -417,7 +496,7 @@ static void veth_napi_del(struct net_device *dev)
napi_disable(&priv->xdp_napi);
netif_napi_del(&priv->xdp_napi);
priv->rx_notify_masked = false;
- ptr_ring_cleanup(&priv->xdp_ring, __skb_array_destroy_skb);
+ ptr_ring_cleanup(&priv->xdp_ring, veth_ptr_free);
}
static int veth_enable_xdp(struct net_device *dev)
--
1.8.3.1
^ permalink raw reply related
* [PATCH net-next 2/2] net: hns3: Refine the MSIX allocation for PF
From: Salil Mehta @ 2018-08-03 9:56 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
linux-kernel, linuxarm, Jian Shen
In-Reply-To: <20180803095631.798-1-salil.mehta@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
The offset of msix number for roce is different between different
revision id. We should get it from firmware, instead of a fix value.
This patch refines the msix allocation, make it compatible.
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h | 2 ++
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 8 ++++++--
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h | 3 +--
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
index 5cd22f9..cd0a4f2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
@@ -358,6 +358,8 @@ struct hclge_pf_res_cmd {
__le16 buf_size;
__le16 msixcap_localid_ba_nic;
__le16 msixcap_localid_ba_rocee;
+#define HCLGE_MSIX_OFT_ROCEE_S 0
+#define HCLGE_MSIX_OFT_ROCEE_M GENMASK(15, 0)
#define HCLGE_PF_VEC_NUM_S 0
#define HCLGE_PF_VEC_NUM_M GENMASK(7, 0)
__le16 pf_intr_vector_number;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index a9b888f..fc813b7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -932,6 +932,9 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev)
hdev->pkt_buf_size = __le16_to_cpu(req->buf_size) << HCLGE_BUF_UNIT_S;
if (hnae3_dev_roce_supported(hdev)) {
+ hdev->roce_base_msix_offset =
+ hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee),
+ HCLGE_MSIX_OFT_ROCEE_M, HCLGE_MSIX_OFT_ROCEE_S);
hdev->num_roce_msi =
hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number),
HCLGE_PF_VEC_NUM_M, HCLGE_PF_VEC_NUM_S);
@@ -939,7 +942,8 @@ static int hclge_query_pf_resource(struct hclge_dev *hdev)
/* PF should have NIC vectors and Roce vectors,
* NIC vectors are queued before Roce vectors.
*/
- hdev->num_msi = hdev->num_roce_msi + HCLGE_ROCE_VECTOR_OFFSET;
+ hdev->num_msi = hdev->num_roce_msi +
+ hdev->roce_base_msix_offset;
} else {
hdev->num_msi =
hnae3_get_field(__le16_to_cpu(req->pf_intr_vector_number),
@@ -2037,7 +2041,7 @@ static int hclge_init_msi(struct hclge_dev *hdev)
hdev->num_msi_left = vectors;
hdev->base_msi_vector = pdev->irq;
hdev->roce_base_vector = hdev->base_msi_vector +
- HCLGE_ROCE_VECTOR_OFFSET;
+ hdev->roce_base_msix_offset;
hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
sizeof(u16), GFP_KERNEL);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
index dfa5c94..1528fb3 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
@@ -16,8 +16,6 @@
#define HCLGE_INVALID_VPORT 0xffff
-#define HCLGE_ROCE_VECTOR_OFFSET 96
-
#define HCLGE_PF_CFG_BLOCK_SIZE 32
#define HCLGE_PF_CFG_DESC_NUM \
(HCLGE_PF_CFG_BLOCK_SIZE / HCLGE_CFG_RD_LEN_BYTES)
@@ -509,6 +507,7 @@ struct hclge_dev {
u16 num_msi;
u16 num_msi_left;
u16 num_msi_used;
+ u16 roce_base_msix_offset;
u32 base_msi_vector;
u16 *vector_status;
int *vector_irq;
--
2.7.4
^ permalink raw reply related
* [PATCH net-next 1/2] net: hns3: Fix MSIX allocation issue for VF
From: Salil Mehta @ 2018-08-03 9:56 UTC (permalink / raw)
To: davem
Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
linux-kernel, linuxarm, Jian Shen
In-Reply-To: <20180803095631.798-1-salil.mehta@huawei.com>
From: Jian Shen <shenjian15@huawei.com>
The msix number for vf is different, depends on the max vf number.
Futherly if the vf supports roce, the offset of msix is not fixed.
It's incorrect to fix the msix number to 33. This patch fixes it by
querying the msix number from firmware, and adjusting it with roce
support.
Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support")
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
---
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +-
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h | 14 ++++
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 80 ++++++++++++++++++----
.../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h | 4 +-
4 files changed, 85 insertions(+), 16 deletions(-)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 6c9e5d6..bd031af 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -50,7 +50,8 @@ static const struct pci_device_id hns3_pci_tbl[] = {
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_MACSEC),
HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_VF), 0},
- {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF), 0},
+ {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_100G_RDMA_DCB_PFC_VF),
+ HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
/* required last entry */
{0, }
};
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
index 621c6cb..19b3286 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
@@ -82,6 +82,7 @@ struct hclgevf_cmq {
enum hclgevf_opcode_type {
/* Generic command */
HCLGEVF_OPC_QUERY_FW_VER = 0x0001,
+ HCLGEVF_OPC_QUERY_VF_RSRC = 0x0024,
/* TQP command */
HCLGEVF_OPC_QUERY_TX_STATUS = 0x0B03,
HCLGEVF_OPC_QUERY_RX_STATUS = 0x0B13,
@@ -134,6 +135,19 @@ struct hclgevf_query_version_cmd {
__le32 firmware_rsv[5];
};
+#define HCLGEVF_MSIX_OFT_ROCEE_S 0
+#define HCLGEVF_MSIX_OFT_ROCEE_M (0xffff << HCLGEVF_MSIX_OFT_ROCEE_S)
+#define HCLGEVF_VEC_NUM_S 0
+#define HCLGEVF_VEC_NUM_M (0xff << HCLGEVF_VEC_NUM_S)
+struct hclgevf_query_res_cmd {
+ __le16 tqp_num;
+ __le16 reserved;
+ __le16 msixcap_localid_ba_nic;
+ __le16 msixcap_localid_ba_rocee;
+ __le16 vf_intr_vector_number;
+ __le16 rsv[7];
+};
+
#define HCLGEVF_RSS_HASH_KEY_OFFSET 4
#define HCLGEVF_RSS_HASH_KEY_NUM 16
struct hclgevf_rss_config_cmd {
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index d1f16f0..9c0091f 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -1370,14 +1370,13 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
struct hnae3_handle *roce = &hdev->roce;
struct hnae3_handle *nic = &hdev->nic;
- roce->rinfo.num_vectors = HCLGEVF_ROCEE_VECTOR_NUM;
+ roce->rinfo.num_vectors = hdev->num_roce_msix;
if (hdev->num_msi_left < roce->rinfo.num_vectors ||
hdev->num_msi_left == 0)
return -EINVAL;
- roce->rinfo.base_vector =
- hdev->vector_status[hdev->num_msi_used];
+ roce->rinfo.base_vector = hdev->roce_base_vector;
roce->rinfo.netdev = nic->kinfo.netdev;
roce->rinfo.roce_io_base = hdev->hw.io_base;
@@ -1520,10 +1519,15 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev)
if (hclgevf_dev_ongoing_reset(hdev))
return 0;
- hdev->num_msi = HCLGEVF_MAX_VF_VECTOR_NUM;
+ if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B))
+ vectors = pci_alloc_irq_vectors(pdev,
+ hdev->roce_base_msix_offset + 1,
+ hdev->num_msi,
+ PCI_IRQ_MSIX);
+ else
+ vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi,
+ PCI_IRQ_MSI | PCI_IRQ_MSIX);
- vectors = pci_alloc_irq_vectors(pdev, 1, hdev->num_msi,
- PCI_IRQ_MSI | PCI_IRQ_MSIX);
if (vectors < 0) {
dev_err(&pdev->dev,
"failed(%d) to allocate MSI/MSI-X vectors\n",
@@ -1538,6 +1542,7 @@ static int hclgevf_init_msi(struct hclgevf_dev *hdev)
hdev->num_msi = vectors;
hdev->num_msi_left = vectors;
hdev->base_msi_vector = pdev->irq;
+ hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset;
hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
sizeof(u16), GFP_KERNEL);
@@ -1733,6 +1738,45 @@ static void hclgevf_pci_uninit(struct hclgevf_dev *hdev)
pci_disable_device(pdev);
}
+static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev)
+{
+ struct hclgevf_query_res_cmd *req;
+ struct hclgevf_desc desc;
+ int ret;
+
+ hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_QUERY_VF_RSRC, true);
+ ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "query vf resource failed, ret = %d.\n", ret);
+ return ret;
+ }
+
+ req = (struct hclgevf_query_res_cmd *)desc.data;
+
+ if (hnae3_get_bit(hdev->ae_dev->flag, HNAE3_DEV_SUPPORT_ROCE_B)) {
+ hdev->roce_base_msix_offset =
+ hnae3_get_field(__le16_to_cpu(req->msixcap_localid_ba_rocee),
+ HCLGEVF_MSIX_OFT_ROCEE_M,
+ HCLGEVF_MSIX_OFT_ROCEE_S);
+ hdev->num_roce_msix =
+ hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number),
+ HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
+
+ /* VF should have NIC vectors and Roce vectors, NIC vectors
+ * are queued before Roce vectors. The offset is fixed to 64.
+ */
+ hdev->num_msi = hdev->num_roce_msix +
+ hdev->roce_base_msix_offset;
+ } else {
+ hdev->num_msi =
+ hnae3_get_field(__le16_to_cpu(req->vf_intr_vector_number),
+ HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
+ }
+
+ return 0;
+}
+
static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
{
struct pci_dev *pdev = hdev->pdev;
@@ -1750,18 +1794,26 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
return ret;
}
+ ret = hclgevf_cmd_init(hdev);
+ if (ret)
+ goto err_cmd_init;
+
+ /* Get vf resource */
+ ret = hclgevf_query_vf_resource(hdev);
+ if (ret) {
+ dev_err(&hdev->pdev->dev,
+ "Query vf status error, ret = %d.\n", ret);
+ goto err_query_vf;
+ }
+
ret = hclgevf_init_msi(hdev);
if (ret) {
dev_err(&pdev->dev, "failed(%d) to init MSI/MSI-X\n", ret);
- goto err_irq_init;
+ goto err_query_vf;
}
hclgevf_state_init(hdev);
- ret = hclgevf_cmd_init(hdev);
- if (ret)
- goto err_cmd_init;
-
ret = hclgevf_misc_irq_init(hdev);
if (ret) {
dev_err(&pdev->dev, "failed(%d) to init Misc IRQ(vector0)\n",
@@ -1817,11 +1869,11 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
err_config:
hclgevf_misc_irq_uninit(hdev);
err_misc_irq_init:
- hclgevf_cmd_uninit(hdev);
-err_cmd_init:
hclgevf_state_uninit(hdev);
hclgevf_uninit_msi(hdev);
-err_irq_init:
+err_query_vf:
+ hclgevf_cmd_uninit(hdev);
+err_cmd_init:
hclgevf_pci_uninit(hdev);
return ret;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
index 0656e8e..b23ba17 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
@@ -12,7 +12,6 @@
#define HCLGEVF_MOD_VERSION "1.0"
#define HCLGEVF_DRIVER_NAME "hclgevf"
-#define HCLGEVF_ROCEE_VECTOR_NUM 0
#define HCLGEVF_MISC_VECTOR_NUM 0
#define HCLGEVF_INVALID_VPORT 0xffff
@@ -150,6 +149,9 @@ struct hclgevf_dev {
u16 num_msi;
u16 num_msi_left;
u16 num_msi_used;
+ u16 num_roce_msix; /* Num of roce vectors for this VF */
+ u16 roce_base_msix_offset;
+ int roce_base_vector;
u32 base_msi_vector;
u16 *vector_status;
int *vector_irq;
--
2.7.4
^ permalink raw reply related
* [PATCH v8 bpf-next 04/10] xdp: Helper function to clear kernel pointers in xdp_frame
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
xdp_frame has kernel pointers which should not be readable from bpf
programs. When we want to reuse xdp_frame region but it may be read by
bpf programs later, we can use this helper to clear kernel pointers.
This is more efficient than calling memset() for the entire struct.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
include/net/xdp.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/net/xdp.h b/include/net/xdp.h
index fcb033f..76b9525 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -84,6 +84,13 @@ struct xdp_frame {
struct net_device *dev_rx; /* used by cpumap */
};
+/* Clear kernel pointers in xdp_frame */
+static inline void xdp_scrub_frame(struct xdp_frame *frame)
+{
+ frame->data = NULL;
+ frame->dev_rx = NULL;
+}
+
/* Convert xdp_buff to xdp_frame */
static inline
struct xdp_frame *convert_to_xdp_frame(struct xdp_buff *xdp)
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 03/10] veth: Avoid drops by oversized packets when XDP is enabled
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
Oversized packets including GSO packets can be dropped if XDP is
enabled on receiver side, so don't send such packets from peer.
Drop TSO and SCTP fragmentation features so that veth devices themselves
segment packets with XDP enabled. Also cap MTU accordingly.
v4:
- Don't auto-adjust MTU but cap max MTU.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
drivers/net/veth.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index d3b9f10..9edf104 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -543,6 +543,23 @@ static int veth_get_iflink(const struct net_device *dev)
return iflink;
}
+static netdev_features_t veth_fix_features(struct net_device *dev,
+ netdev_features_t features)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ struct net_device *peer;
+
+ peer = rtnl_dereference(priv->peer);
+ if (peer) {
+ struct veth_priv *peer_priv = netdev_priv(peer);
+
+ if (peer_priv->_xdp_prog)
+ features &= ~NETIF_F_GSO_SOFTWARE;
+ }
+
+ return features;
+}
+
static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
{
struct veth_priv *peer_priv, *priv = netdev_priv(dev);
@@ -572,6 +589,7 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
struct veth_priv *priv = netdev_priv(dev);
struct bpf_prog *old_prog;
struct net_device *peer;
+ unsigned int max_mtu;
int err;
old_prog = priv->_xdp_prog;
@@ -585,6 +603,15 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
goto err;
}
+ max_mtu = PAGE_SIZE - VETH_XDP_HEADROOM -
+ peer->hard_header_len -
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ if (peer->mtu > max_mtu) {
+ NL_SET_ERR_MSG_MOD(extack, "Peer MTU is too large to set XDP");
+ err = -ERANGE;
+ goto err;
+ }
+
if (dev->flags & IFF_UP) {
err = veth_enable_xdp(dev);
if (err) {
@@ -592,14 +619,29 @@ static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
goto err;
}
}
+
+ if (!old_prog) {
+ peer->hw_features &= ~NETIF_F_GSO_SOFTWARE;
+ peer->max_mtu = max_mtu;
+ }
}
if (old_prog) {
- if (!prog && dev->flags & IFF_UP)
- veth_disable_xdp(dev);
+ if (!prog) {
+ if (dev->flags & IFF_UP)
+ veth_disable_xdp(dev);
+
+ if (peer) {
+ peer->hw_features |= NETIF_F_GSO_SOFTWARE;
+ peer->max_mtu = ETH_MAX_MTU;
+ }
+ }
bpf_prog_put(old_prog);
}
+ if ((!!old_prog ^ !!prog) && peer)
+ netdev_update_features(peer);
+
return 0;
err:
priv->_xdp_prog = old_prog;
@@ -644,6 +686,7 @@ static int veth_xdp(struct net_device *dev, struct netdev_bpf *xdp)
.ndo_poll_controller = veth_poll_controller,
#endif
.ndo_get_iflink = veth_get_iflink,
+ .ndo_fix_features = veth_fix_features,
.ndo_features_check = passthru_features_check,
.ndo_set_rx_headroom = veth_set_rx_headroom,
.ndo_bpf = veth_xdp,
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 02/10] veth: Add driver XDP
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
This is the basic implementation of veth driver XDP.
Incoming packets are sent from the peer veth device in the form of skb,
so this is generally doing the same thing as generic XDP.
This itself is not so useful, but a starting point to implement other
useful veth XDP features like TX and REDIRECT.
This introduces NAPI when XDP is enabled, because XDP is now heavily
relies on NAPI context. Use ptr_ring to emulate NIC ring. Tx function
enqueues packets to the ring and peer NAPI handler drains the ring.
Currently only one ring is allocated for each veth device, so it does
not scale on multiqueue env. This can be resolved by allocating rings
on the per-queue basis later.
Note that NAPI is not used but netif_rx is used when XDP is not loaded,
so this does not change the default behaviour.
v6:
- Check skb->len only when allocation is needed.
- Add __GFP_NOWARN to alloc_page() as it can be triggered by external
events.
v3:
- Fix race on closing the device.
- Add extack messages in ndo_bpf.
v2:
- Squashed with the patch adding NAPI.
- Implement adjust_tail.
- Don't acquire consumer lock because it is guarded by NAPI.
- Make poll_controller noop since it is unnecessary.
- Register rxq_info on enabling XDP rather than on opening the device.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
drivers/net/veth.c | 374 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 367 insertions(+), 7 deletions(-)
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index a69ad39..d3b9f10 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -19,10 +19,18 @@
#include <net/xfrm.h>
#include <linux/veth.h>
#include <linux/module.h>
+#include <linux/bpf.h>
+#include <linux/filter.h>
+#include <linux/ptr_ring.h>
+#include <linux/skb_array.h>
+#include <linux/bpf_trace.h>
#define DRV_NAME "veth"
#define DRV_VERSION "1.0"
+#define VETH_RING_SIZE 256
+#define VETH_XDP_HEADROOM (XDP_PACKET_HEADROOM + NET_IP_ALIGN)
+
struct pcpu_vstats {
u64 packets;
u64 bytes;
@@ -30,9 +38,16 @@ struct pcpu_vstats {
};
struct veth_priv {
+ struct napi_struct xdp_napi;
+ struct net_device *dev;
+ struct bpf_prog __rcu *xdp_prog;
+ struct bpf_prog *_xdp_prog;
struct net_device __rcu *peer;
atomic64_t dropped;
unsigned requested_headroom;
+ bool rx_notify_masked;
+ struct ptr_ring xdp_ring;
+ struct xdp_rxq_info xdp_rxq;
};
/*
@@ -98,11 +113,43 @@ static void veth_get_ethtool_stats(struct net_device *dev,
.get_link_ksettings = veth_get_link_ksettings,
};
-static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
+/* general routines */
+
+static void __veth_xdp_flush(struct veth_priv *priv)
+{
+ /* Write ptr_ring before reading rx_notify_masked */
+ smp_mb();
+ if (!priv->rx_notify_masked) {
+ priv->rx_notify_masked = true;
+ napi_schedule(&priv->xdp_napi);
+ }
+}
+
+static int veth_xdp_rx(struct veth_priv *priv, struct sk_buff *skb)
+{
+ if (unlikely(ptr_ring_produce(&priv->xdp_ring, skb))) {
+ dev_kfree_skb_any(skb);
+ return NET_RX_DROP;
+ }
+
+ return NET_RX_SUCCESS;
+}
+
+static int veth_forward_skb(struct net_device *dev, struct sk_buff *skb, bool xdp)
{
struct veth_priv *priv = netdev_priv(dev);
+
+ return __dev_forward_skb(dev, skb) ?: xdp ?
+ veth_xdp_rx(priv, skb) :
+ netif_rx(skb);
+}
+
+static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct veth_priv *rcv_priv, *priv = netdev_priv(dev);
struct net_device *rcv;
int length = skb->len;
+ bool rcv_xdp = false;
rcu_read_lock();
rcv = rcu_dereference(priv->peer);
@@ -111,7 +158,10 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
goto drop;
}
- if (likely(dev_forward_skb(rcv, skb) == NET_RX_SUCCESS)) {
+ rcv_priv = netdev_priv(rcv);
+ rcv_xdp = rcu_access_pointer(rcv_priv->xdp_prog);
+
+ if (likely(veth_forward_skb(rcv, skb, rcv_xdp) == NET_RX_SUCCESS)) {
struct pcpu_vstats *stats = this_cpu_ptr(dev->vstats);
u64_stats_update_begin(&stats->syncp);
@@ -122,14 +172,15 @@ static netdev_tx_t veth_xmit(struct sk_buff *skb, struct net_device *dev)
drop:
atomic64_inc(&priv->dropped);
}
+
+ if (rcv_xdp)
+ __veth_xdp_flush(rcv_priv);
+
rcu_read_unlock();
+
return NETDEV_TX_OK;
}
-/*
- * general routines
- */
-
static u64 veth_stats_one(struct pcpu_vstats *result, struct net_device *dev)
{
struct veth_priv *priv = netdev_priv(dev);
@@ -179,18 +230,254 @@ static void veth_set_multicast_list(struct net_device *dev)
{
}
+static struct sk_buff *veth_build_skb(void *head, int headroom, int len,
+ int buflen)
+{
+ struct sk_buff *skb;
+
+ if (!buflen) {
+ buflen = SKB_DATA_ALIGN(headroom + len) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ }
+ skb = build_skb(head, buflen);
+ if (!skb)
+ return NULL;
+
+ skb_reserve(skb, headroom);
+ skb_put(skb, len);
+
+ return skb;
+}
+
+static struct sk_buff *veth_xdp_rcv_skb(struct veth_priv *priv,
+ struct sk_buff *skb)
+{
+ u32 pktlen, headroom, act, metalen;
+ void *orig_data, *orig_data_end;
+ struct bpf_prog *xdp_prog;
+ int mac_len, delta, off;
+ struct xdp_buff xdp;
+
+ rcu_read_lock();
+ xdp_prog = rcu_dereference(priv->xdp_prog);
+ if (unlikely(!xdp_prog)) {
+ rcu_read_unlock();
+ goto out;
+ }
+
+ mac_len = skb->data - skb_mac_header(skb);
+ pktlen = skb->len + mac_len;
+ headroom = skb_headroom(skb) - mac_len;
+
+ if (skb_shared(skb) || skb_head_is_locked(skb) ||
+ skb_is_nonlinear(skb) || headroom < XDP_PACKET_HEADROOM) {
+ struct sk_buff *nskb;
+ int size, head_off;
+ void *head, *start;
+ struct page *page;
+
+ size = SKB_DATA_ALIGN(VETH_XDP_HEADROOM + pktlen) +
+ SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+ if (size > PAGE_SIZE)
+ goto drop;
+
+ page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
+ if (!page)
+ goto drop;
+
+ head = page_address(page);
+ start = head + VETH_XDP_HEADROOM;
+ if (skb_copy_bits(skb, -mac_len, start, pktlen)) {
+ page_frag_free(head);
+ goto drop;
+ }
+
+ nskb = veth_build_skb(head,
+ VETH_XDP_HEADROOM + mac_len, skb->len,
+ PAGE_SIZE);
+ if (!nskb) {
+ page_frag_free(head);
+ goto drop;
+ }
+
+ skb_copy_header(nskb, skb);
+ head_off = skb_headroom(nskb) - skb_headroom(skb);
+ skb_headers_offset_update(nskb, head_off);
+ if (skb->sk)
+ skb_set_owner_w(nskb, skb->sk);
+ consume_skb(skb);
+ skb = nskb;
+ }
+
+ xdp.data_hard_start = skb->head;
+ xdp.data = skb_mac_header(skb);
+ xdp.data_end = xdp.data + pktlen;
+ xdp.data_meta = xdp.data;
+ xdp.rxq = &priv->xdp_rxq;
+ orig_data = xdp.data;
+ orig_data_end = xdp.data_end;
+
+ act = bpf_prog_run_xdp(xdp_prog, &xdp);
+
+ switch (act) {
+ case XDP_PASS:
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(act);
+ case XDP_ABORTED:
+ trace_xdp_exception(priv->dev, xdp_prog, act);
+ case XDP_DROP:
+ goto drop;
+ }
+ rcu_read_unlock();
+
+ delta = orig_data - xdp.data;
+ off = mac_len + delta;
+ if (off > 0)
+ __skb_push(skb, off);
+ else if (off < 0)
+ __skb_pull(skb, -off);
+ skb->mac_header -= delta;
+ off = xdp.data_end - orig_data_end;
+ if (off != 0)
+ __skb_put(skb, off);
+ skb->protocol = eth_type_trans(skb, priv->dev);
+
+ metalen = xdp.data - xdp.data_meta;
+ if (metalen)
+ skb_metadata_set(skb, metalen);
+out:
+ return skb;
+drop:
+ rcu_read_unlock();
+ kfree_skb(skb);
+ return NULL;
+}
+
+static int veth_xdp_rcv(struct veth_priv *priv, int budget)
+{
+ int i, done = 0;
+
+ for (i = 0; i < budget; i++) {
+ struct sk_buff *skb = __ptr_ring_consume(&priv->xdp_ring);
+
+ if (!skb)
+ break;
+
+ skb = veth_xdp_rcv_skb(priv, skb);
+
+ if (skb)
+ napi_gro_receive(&priv->xdp_napi, skb);
+
+ done++;
+ }
+
+ return done;
+}
+
+static int veth_poll(struct napi_struct *napi, int budget)
+{
+ struct veth_priv *priv =
+ container_of(napi, struct veth_priv, xdp_napi);
+ int done;
+
+ done = veth_xdp_rcv(priv, budget);
+
+ if (done < budget && napi_complete_done(napi, done)) {
+ /* Write rx_notify_masked before reading ptr_ring */
+ smp_store_mb(priv->rx_notify_masked, false);
+ if (unlikely(!__ptr_ring_empty(&priv->xdp_ring))) {
+ priv->rx_notify_masked = true;
+ napi_schedule(&priv->xdp_napi);
+ }
+ }
+
+ return done;
+}
+
+static int veth_napi_add(struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ int err;
+
+ err = ptr_ring_init(&priv->xdp_ring, VETH_RING_SIZE, GFP_KERNEL);
+ if (err)
+ return err;
+
+ netif_napi_add(dev, &priv->xdp_napi, veth_poll, NAPI_POLL_WEIGHT);
+ napi_enable(&priv->xdp_napi);
+
+ return 0;
+}
+
+static void veth_napi_del(struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+
+ napi_disable(&priv->xdp_napi);
+ netif_napi_del(&priv->xdp_napi);
+ priv->rx_notify_masked = false;
+ ptr_ring_cleanup(&priv->xdp_ring, __skb_array_destroy_skb);
+}
+
+static int veth_enable_xdp(struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ int err;
+
+ if (!xdp_rxq_info_is_reg(&priv->xdp_rxq)) {
+ err = xdp_rxq_info_reg(&priv->xdp_rxq, dev, 0);
+ if (err < 0)
+ return err;
+
+ err = xdp_rxq_info_reg_mem_model(&priv->xdp_rxq,
+ MEM_TYPE_PAGE_SHARED, NULL);
+ if (err < 0)
+ goto err;
+
+ err = veth_napi_add(dev);
+ if (err)
+ goto err;
+ }
+
+ rcu_assign_pointer(priv->xdp_prog, priv->_xdp_prog);
+
+ return 0;
+err:
+ xdp_rxq_info_unreg(&priv->xdp_rxq);
+
+ return err;
+}
+
+static void veth_disable_xdp(struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+
+ rcu_assign_pointer(priv->xdp_prog, NULL);
+ veth_napi_del(dev);
+ xdp_rxq_info_unreg(&priv->xdp_rxq);
+}
+
static int veth_open(struct net_device *dev)
{
struct veth_priv *priv = netdev_priv(dev);
struct net_device *peer = rtnl_dereference(priv->peer);
+ int err;
if (!peer)
return -ENOTCONN;
+ if (priv->_xdp_prog) {
+ err = veth_enable_xdp(dev);
+ if (err)
+ return err;
+ }
+
if (peer->flags & IFF_UP) {
netif_carrier_on(dev);
netif_carrier_on(peer);
}
+
return 0;
}
@@ -203,6 +490,9 @@ static int veth_close(struct net_device *dev)
if (peer)
netif_carrier_off(peer);
+ if (priv->_xdp_prog)
+ veth_disable_xdp(dev);
+
return 0;
}
@@ -228,7 +518,7 @@ static void veth_dev_free(struct net_device *dev)
static void veth_poll_controller(struct net_device *dev)
{
/* veth only receives frames when its peer sends one
- * Since it's a synchronous operation, we are guaranteed
+ * Since it has nothing to do with disabling irqs, we are guaranteed
* never to have pending data when we poll for it so
* there is nothing to do here.
*
@@ -276,6 +566,72 @@ static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
rcu_read_unlock();
}
+static int veth_xdp_set(struct net_device *dev, struct bpf_prog *prog,
+ struct netlink_ext_ack *extack)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ struct bpf_prog *old_prog;
+ struct net_device *peer;
+ int err;
+
+ old_prog = priv->_xdp_prog;
+ priv->_xdp_prog = prog;
+ peer = rtnl_dereference(priv->peer);
+
+ if (prog) {
+ if (!peer) {
+ NL_SET_ERR_MSG_MOD(extack, "Cannot set XDP when peer is detached");
+ err = -ENOTCONN;
+ goto err;
+ }
+
+ if (dev->flags & IFF_UP) {
+ err = veth_enable_xdp(dev);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Setup for XDP failed");
+ goto err;
+ }
+ }
+ }
+
+ if (old_prog) {
+ if (!prog && dev->flags & IFF_UP)
+ veth_disable_xdp(dev);
+ bpf_prog_put(old_prog);
+ }
+
+ return 0;
+err:
+ priv->_xdp_prog = old_prog;
+
+ return err;
+}
+
+static u32 veth_xdp_query(struct net_device *dev)
+{
+ struct veth_priv *priv = netdev_priv(dev);
+ const struct bpf_prog *xdp_prog;
+
+ xdp_prog = priv->_xdp_prog;
+ if (xdp_prog)
+ return xdp_prog->aux->id;
+
+ return 0;
+}
+
+static int veth_xdp(struct net_device *dev, struct netdev_bpf *xdp)
+{
+ switch (xdp->command) {
+ case XDP_SETUP_PROG:
+ return veth_xdp_set(dev, xdp->prog, xdp->extack);
+ case XDP_QUERY_PROG:
+ xdp->prog_id = veth_xdp_query(dev);
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
static const struct net_device_ops veth_netdev_ops = {
.ndo_init = veth_dev_init,
.ndo_open = veth_open,
@@ -290,6 +646,7 @@ static void veth_set_rx_headroom(struct net_device *dev, int new_hr)
.ndo_get_iflink = veth_get_iflink,
.ndo_features_check = passthru_features_check,
.ndo_set_rx_headroom = veth_set_rx_headroom,
+ .ndo_bpf = veth_xdp,
};
#define VETH_FEATURES (NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HW_CSUM | \
@@ -451,10 +808,13 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
*/
priv = netdev_priv(dev);
+ priv->dev = dev;
rcu_assign_pointer(priv->peer, peer);
priv = netdev_priv(peer);
+ priv->dev = peer;
rcu_assign_pointer(priv->peer, dev);
+
return 0;
err_register_dev:
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 01/10] net: Export skb_headers_offset_update
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
In-Reply-To: <1533283098-2397-1-git-send-email-makita.toshiaki@lab.ntt.co.jp>
This is needed for veth XDP which does skb_copy_expand()-like operation.
v2:
- Drop skb_copy_header part because it has already been exported now.
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
---
include/linux/skbuff.h | 1 +
net/core/skbuff.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index fd3cb1b..f692968 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1035,6 +1035,7 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
}
struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
+void skb_headers_offset_update(struct sk_buff *skb, int off);
int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask);
struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t priority);
void skb_copy_header(struct sk_buff *new, const struct sk_buff *old);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 51b0a912..4acd464 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1291,7 +1291,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
}
EXPORT_SYMBOL(skb_clone);
-static void skb_headers_offset_update(struct sk_buff *skb, int off)
+void skb_headers_offset_update(struct sk_buff *skb, int off)
{
/* Only adjust this if it actually is csum_start rather than csum */
if (skb->ip_summed == CHECKSUM_PARTIAL)
@@ -1305,6 +1305,7 @@ static void skb_headers_offset_update(struct sk_buff *skb, int off)
skb->inner_network_header += off;
skb->inner_mac_header += off;
}
+EXPORT_SYMBOL(skb_headers_offset_update);
void skb_copy_header(struct sk_buff *new, const struct sk_buff *old)
{
--
1.8.3.1
^ permalink raw reply related
* [PATCH v8 bpf-next 00/10] veth: Driver XDP
From: Toshiaki Makita @ 2018-08-03 7:58 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann
Cc: Toshiaki Makita, netdev, Jesper Dangaard Brouer, Jakub Kicinski,
John Fastabend
This patch set introduces driver XDP for veth.
Basically this is used in conjunction with redirect action of another XDP
program.
NIC -----------> veth===veth
(XDP) (redirect) (XDP)
In this case xdp_frame can be forwarded to the peer veth without
modification, so we can expect far better performance than generic XDP.
Envisioned use-cases
--------------------
* Container managed XDP program
Container host redirects frames to containers by XDP redirect action, and
privileged containers can deploy their own XDP programs.
* XDP program cascading
Two or more XDP programs can be called for each packet by redirecting
xdp frames to veth.
* Internal interface for an XDP bridge
When using XDP redirection to create a virtual bridge, veth can be used
to create an internal interface for the bridge.
Implementation
--------------
This changeset is making use of NAPI to implement ndo_xdp_xmit and
XDP_TX/REDIRECT. This is mainly because XDP heavily relies on NAPI
context.
- patch 1: Export a function needed for veth XDP.
- patch 2-3: Basic implementation of veth XDP.
- patch 4-6: Add ndo_xdp_xmit.
- patch 7-9: Add XDP_TX and XDP_REDIRECT.
- patch 10: Performance optimization for multi-queue env.
Tests and performance numbers
-----------------------------
Tested with a simple XDP program which only redirects packets between
NIC and veth. I used i40e 25G NIC (XXV710) for the physical NIC. The
server has 20 of Xeon Silver 2.20 GHz cores.
pktgen --(wire)--> XXV710 (i40e) <--(XDP redirect)--> veth===veth (XDP)
The rightmost veth loads XDP progs and just does DROP or TX. The number
of packets is measured in the XDP progs. The leftmost pktgen sends
packets at 37.1 Mpps (almost 25G wire speed).
veth XDP action Flows Mpps
================================
DROP 1 10.6
DROP 2 21.2
DROP 100 36.0
TX 1 5.0
TX 2 10.0
TX 100 31.0
I also measured netperf TCP_STREAM but was not so great performance due
to lack of tx/rx checksum offload and TSO, etc.
netperf <--(wire)--> XXV710 (i40e) <--(XDP redirect)--> veth===veth (XDP PASS)
Direction Flows Gbps
==============================
external->veth 1 20.8
external->veth 2 23.5
external->veth 100 23.6
veth->external 1 9.0
veth->external 2 17.8
veth->external 100 22.9
Also tested doing ifup/down or load/unload a XDP program repeatedly
during processing XDP packets in order to check if enabling/disabling
NAPI is working as expected, and found no problems.
v8:
- Don't use xdp_frame pointer address to calculate skb->head, headroom,
and xdp_buff.data_hard_start.
v7:
- Introduce xdp_scrub_frame() to clear kernel pointers in xdp_frame and
use it instead of memset().
v6:
- Check skb->len only if reallocation is needed.
- Add __GFP_NOWARN to alloc_page() since it can be triggered by external
events.
- Fix sparse warning around EXPORT_SYMBOL.
v5:
- Fix broken SOBs.
v4:
- Don't adjust MTU automatically.
- Skip peer IFF_UP check on .ndo_xdp_xmit() because it is unnecessary.
Add comments to explain that.
- Use redirect_info instead of xdp_mem_info for storing no_direct flag
to avoid per packet copy cost.
v3:
- Drop skb bulk xmit patch since it makes little performance
difference. The hotspot in TCP skb xmit at this point is checksum
computation in skb_segment and packet copy on XDP_REDIRECT due to
cloned/nonlinear skb.
- Fix race on closing device.
- Add extack messages in ndo_bpf.
v2:
- Squash NAPI patch with "Add driver XDP" patch.
- Remove conversion from xdp_frame to skb when NAPI is not enabled.
- Introduce per-queue XDP ring (patch 8).
- Introduce bulk skb xmit when XDP is enabled on the peer (patch 9).
Signed-off-by: Toshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Toshiaki Makita (10):
net: Export skb_headers_offset_update
veth: Add driver XDP
veth: Avoid drops by oversized packets when XDP is enabled
xdp: Helper function to clear kernel pointers in xdp_frame
veth: Handle xdp_frames in xdp napi ring
veth: Add ndo_xdp_xmit
bpf: Make redirect_info accessible from modules
xdp: Helpers for disabling napi_direct of xdp_return_frame
veth: Add XDP TX and REDIRECT
veth: Support per queue XDP ring
drivers/net/veth.c | 750 ++++++++++++++++++++++++++++++++++++++++++++++++-
include/linux/filter.h | 35 +++
include/linux/skbuff.h | 1 +
include/net/xdp.h | 7 +
net/core/filter.c | 29 +-
net/core/skbuff.c | 3 +-
net/core/xdp.c | 6 +-
7 files changed, 801 insertions(+), 30 deletions(-)
--
1.8.3.1
^ permalink raw reply
* Re: [PATCH net-next] vhost: switch to use new message format
From: Michael S. Tsirkin @ 2018-08-03 7:59 UTC (permalink / raw)
To: Jason Wang; +Cc: kvm, virtualization, netdev, linux-kernel
In-Reply-To: <1533279891-12249-1-git-send-email-jasowang@redhat.com>
On Fri, Aug 03, 2018 at 03:04:51PM +0800, Jason Wang wrote:
> We use to have message like:
>
> struct vhost_msg {
> int type;
> union {
> struct vhost_iotlb_msg iotlb;
> __u8 padding[64];
> };
> };
>
> Unfortunately, there will be a hole of 32bit in 64bit machine because
> of the alignment. This leads a different formats between 32bit API and
> 64bit API. What's more it will break 32bit program running on 64bit
> machine.
>
> So fixing this by introducing a new message type with an explicit
> 32bit reserved field after type like:
>
> struct vhost_msg_v2 {
> int type;
> __u32 reserved;
> union {
> struct vhost_iotlb_msg iotlb;
> __u8 padding[64];
> };
> };
>
> We will have a consistent ABI after switching to use this. To enable
> this capability, introduce a new ioctl (VHOST_SET_BAKCEND_FEATURE) for
> userspace to enable this feature (VHOST_BACKEND_F_IOTLB_V2).
>
> Fixes: 6b1e6cc7855b ("vhost: new device IOTLB API")
> Signed-off-by: Jason Wang <jasowang@redhat.com>
> ---
> drivers/vhost/net.c | 30 ++++++++++++++++++++
> drivers/vhost/vhost.c | 71 ++++++++++++++++++++++++++++++++++------------
> drivers/vhost/vhost.h | 11 ++++++-
> include/uapi/linux/vhost.h | 18 ++++++++++++
> 4 files changed, 111 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
> index 367d802..4e656f8 100644
> --- a/drivers/vhost/net.c
> +++ b/drivers/vhost/net.c
> @@ -78,6 +78,10 @@ enum {
> };
>
> enum {
> + VHOST_NET_BACKEND_FEATURES = (1ULL << VHOST_BACKEND_F_IOTLB_MSG_V2)
> +};
> +
> +enum {
> VHOST_NET_VQ_RX = 0,
> VHOST_NET_VQ_TX = 1,
> VHOST_NET_VQ_MAX = 2,
> @@ -1399,6 +1403,21 @@ static long vhost_net_reset_owner(struct vhost_net *n)
> return err;
> }
>
> +static int vhost_net_set_backend_features(struct vhost_net *n, u64 features)
> +{
> + int i;
> +
> + mutex_lock(&n->dev.mutex);
> + for (i = 0; i < VHOST_NET_VQ_MAX; ++i) {
> + mutex_lock(&n->vqs[i].vq.mutex);
> + n->vqs[i].vq.acked_backend_features = features;
> + mutex_unlock(&n->vqs[i].vq.mutex);
> + }
> + mutex_unlock(&n->dev.mutex);
> +
> + return 0;
> +}
> +
> static int vhost_net_set_features(struct vhost_net *n, u64 features)
> {
> size_t vhost_hlen, sock_hlen, hdr_len;
> @@ -1489,6 +1508,17 @@ static long vhost_net_ioctl(struct file *f, unsigned int ioctl,
> if (features & ~VHOST_NET_FEATURES)
> return -EOPNOTSUPP;
> return vhost_net_set_features(n, features);
> + case VHOST_GET_BACKEND_FEATURES:
> + features = VHOST_NET_BACKEND_FEATURES;
> + if (copy_to_user(featurep, &features, sizeof(features)))
> + return -EFAULT;
> + return 0;
> + case VHOST_SET_BACKEND_FEATURES:
> + if (copy_from_user(&features, featurep, sizeof(features)))
> + return -EFAULT;
> + if (features & ~VHOST_NET_BACKEND_FEATURES)
> + return -EOPNOTSUPP;
> + return vhost_net_set_backend_features(n, features);
> case VHOST_RESET_OWNER:
> return vhost_net_reset_owner(n);
> case VHOST_SET_OWNER:
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index a502f1a..6f6c42d 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -315,6 +315,7 @@ static void vhost_vq_reset(struct vhost_dev *dev,
> vq->log_addr = -1ull;
> vq->private_data = NULL;
> vq->acked_features = 0;
> + vq->acked_backend_features = 0;
> vq->log_base = NULL;
> vq->error_ctx = NULL;
> vq->kick = NULL;
> @@ -1027,28 +1028,40 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev,
> ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
> struct iov_iter *from)
> {
> - struct vhost_msg_node node;
> - unsigned size = sizeof(struct vhost_msg);
> - size_t ret;
> - int err;
> + struct vhost_iotlb_msg msg;
> + size_t offset;
> + int type, ret;
>
> - if (iov_iter_count(from) < size)
> - return 0;
> - ret = copy_from_iter(&node.msg, size, from);
> - if (ret != size)
> + ret = copy_from_iter(&type, sizeof(type), from);
> + if (ret != sizeof(type))
> goto done;
>
> - switch (node.msg.type) {
> + switch (type) {
> case VHOST_IOTLB_MSG:
> - err = vhost_process_iotlb_msg(dev, &node.msg.iotlb);
> - if (err)
> - ret = err;
> + /* There maybe a hole after type for V1 message type,
> + * so skip it here.
> + */
> + offset = offsetof(struct vhost_msg, iotlb) - sizeof(int);
> + break;
> + case VHOST_IOTLB_MSG_V2:
> + offset = sizeof(__u32);
> break;
> default:
> ret = -EINVAL;
> - break;
> + goto done;
> + }
> +
> + iov_iter_advance(from, offset);
> + ret = copy_from_iter(&msg, sizeof(msg), from);
> + if (ret != sizeof(msg))
> + goto done;
> + if (vhost_process_iotlb_msg(dev, &msg)) {
> + ret = -EFAULT;
> + goto done;
> }
>
> + ret = (type == VHOST_IOTLB_MSG) ? sizeof(struct vhost_msg) :
> + sizeof(struct vhost_msg_v2);
> done:
> return ret;
> }
We can actually fix 32 bit apps too, checking the mode for v1.
But that can wait for another patch.
> @@ -1107,13 +1120,28 @@ ssize_t vhost_chr_read_iter(struct vhost_dev *dev, struct iov_iter *to,
> finish_wait(&dev->wait, &wait);
>
> if (node) {
> - ret = copy_to_iter(&node->msg, size, to);
> + struct vhost_iotlb_msg *msg;
> + void *start = &node->msg;
> +
> + switch (node->msg.type) {
> + case VHOST_IOTLB_MSG:
> + size = sizeof(node->msg);
> + msg = &node->msg.iotlb;
> + break;
> + case VHOST_IOTLB_MSG_V2:
> + size = sizeof(node->msg_v2);
> + msg = &node->msg_v2.iotlb;
> + break;
> + default:
> + BUG();
> + break;
> + }
>
> - if (ret != size || node->msg.type != VHOST_IOTLB_MISS) {
> + ret = copy_to_iter(start, size, to);
> + if (ret != size || msg->type != VHOST_IOTLB_MISS) {
> kfree(node);
> return ret;
> }
> -
> vhost_enqueue_msg(dev, &dev->pending_list, node);
> }
>
> @@ -1126,12 +1154,19 @@ static int vhost_iotlb_miss(struct vhost_virtqueue *vq, u64 iova, int access)
> struct vhost_dev *dev = vq->dev;
> struct vhost_msg_node *node;
> struct vhost_iotlb_msg *msg;
> + bool v2 = vhost_backend_has_feature(vq, VHOST_BACKEND_F_IOTLB_MSG_V2);
>
> - node = vhost_new_msg(vq, VHOST_IOTLB_MISS);
> + node = vhost_new_msg(vq, v2 ? VHOST_IOTLB_MSG_V2 : VHOST_IOTLB_MSG);
> if (!node)
> return -ENOMEM;
>
> - msg = &node->msg.iotlb;
> + if (v2) {
> + node->msg_v2.type = VHOST_IOTLB_MSG_V2;
> + msg = &node->msg_v2.iotlb;
> + } else {
> + msg = &node->msg.iotlb;
> + }
> +
> msg->type = VHOST_IOTLB_MISS;
> msg->iova = iova;
> msg->perm = access;
> diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h
> index 6c844b9..466ef75 100644
> --- a/drivers/vhost/vhost.h
> +++ b/drivers/vhost/vhost.h
> @@ -132,6 +132,7 @@ struct vhost_virtqueue {
> struct vhost_umem *iotlb;
> void *private_data;
> u64 acked_features;
> + u64 acked_backend_features;
> /* Log write descriptors */
> void __user *log_base;
> struct vhost_log *log;
> @@ -147,7 +148,10 @@ struct vhost_virtqueue {
> };
>
> struct vhost_msg_node {
> - struct vhost_msg msg;
> + union {
> + struct vhost_msg msg;
> + struct vhost_msg_v2 msg_v2;
> + };
> struct vhost_virtqueue *vq;
> struct list_head node;
> };
> @@ -238,6 +242,11 @@ static inline bool vhost_has_feature(struct vhost_virtqueue *vq, int bit)
> return vq->acked_features & (1ULL << bit);
> }
>
> +static inline bool vhost_backend_has_feature(struct vhost_virtqueue *vq, int bit)
> +{
> + return vq->acked_backend_features & (1ULL << bit);
> +}
> +
> #ifdef CONFIG_VHOST_CROSS_ENDIAN_LEGACY
> static inline bool vhost_is_little_endian(struct vhost_virtqueue *vq)
> {
> diff --git a/include/uapi/linux/vhost.h b/include/uapi/linux/vhost.h
> index c51f8e5..c176e9d 100644
> --- a/include/uapi/linux/vhost.h
> +++ b/include/uapi/linux/vhost.h
> @@ -65,6 +65,7 @@ struct vhost_iotlb_msg {
> };
>
> #define VHOST_IOTLB_MSG 0x1
> +#define VHOST_IOTLB_MSG_V2 0x2
>
> struct vhost_msg {
> int type;
> @@ -74,6 +75,15 @@ struct vhost_msg {
> };
> };
>
> +struct vhost_msg_v2 {
> + int type;
> + __u32 reserved;
> + union {
> + struct vhost_iotlb_msg iotlb;
> + __u8 padding[64];
> + };
> +};
> +
> struct vhost_memory_region {
> __u64 guest_phys_addr;
> __u64 memory_size; /* bytes */
> @@ -160,6 +170,14 @@ struct vhost_memory {
> #define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, \
> struct vhost_vring_state)
>
> +/* Set or get vhost backend capability */
> +
> +/* Use message type V2 */
> +#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1
> +
> +#define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64)
> +#define VHOST_GET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x26, __u64)
> +
> /* VHOST_NET specific defines */
>
> /* Attach virtio net ring to a raw socket, or tap device.
Acked-by: Michael S. Tsirkin <mst@redhat.com>
> --
> 2.7.4
^ permalink raw reply
* [PATCH][net-next] tun: not use hardcoded mask value
From: Li RongQing @ 2018-08-03 7:50 UTC (permalink / raw)
To: netdev
0x3ff in tun_hashfn is mask of TUN_NUM_FLOW_ENTRIES, instead
of hardcode, define a macro to setup the relationship with
TUN_NUM_FLOW_ENTRIES
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
drivers/net/tun.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 0a3134712652..2bbefe828670 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -200,6 +200,7 @@ struct tun_flow_entry {
};
#define TUN_NUM_FLOW_ENTRIES 1024
+#define TUN_MASK_FLOW_ENTRIES (TUN_NUM_FLOW_ENTRIES - 1)
struct tun_prog {
struct rcu_head rcu;
@@ -406,7 +407,7 @@ static inline __virtio16 cpu_to_tun16(struct tun_struct *tun, u16 val)
static inline u32 tun_hashfn(u32 rxhash)
{
- return rxhash & 0x3ff;
+ return rxhash & TUN_MASK_FLOW_ENTRIES;
}
static struct tun_flow_entry *tun_flow_find(struct hlist_head *head, u32 rxhash)
--
2.16.2
^ permalink raw reply related
* [PATCH][net-next] net: check extack._msg before print
From: Li RongQing @ 2018-08-03 7:45 UTC (permalink / raw)
To: netdev
dev_set_mtu_ext is able to fail with a valid mtu value, at that
condition, extack._msg is not set and random since it is in stack,
then kernel will crash when print it.
Fixes: 7a4c53bee3324a ("net: report invalid mtu value via netlink extack")
Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
net/core/dev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/core/dev.c b/net/core/dev.c
index 36e994519488..f68122f0ab02 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7583,8 +7583,9 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
struct netlink_ext_ack extack;
int err;
+ memset(&extack, 0, sizeof(extack));
err = dev_set_mtu_ext(dev, new_mtu, &extack);
- if (err)
+ if (err && extack._msg)
net_err_ratelimited("%s: %s\n", dev->name, extack._msg);
return err;
}
--
2.16.2
^ permalink raw reply related
* ERP Business Solution
From: Janine Ben @ 2018-08-03 7:15 UTC (permalink / raw)
To: janine
[-- Attachment #1: Type: text/plain, Size: 1229 bytes --]
Hi Sir/Ma'am,
Hope you are doing great.
This is Janine Ben(Business Consultant).We provide ERP Software for industries and also We create Apps, Websites, and Innovative Marketing Strategies to help brands excel in digital culture.
We Offer ERP Software for industrial management as per their needs and requirements.
The following are types of ERP Software which we are providing for all the industry:
* Enterprise resource planning software (ERP)
* Customer Relationship Management System(CRM)
* Feedback & complaint management system (FCMS)
* Inventory Management system (IMS)
* Attendance Management Software (AMS)
* Human Resource Management Software (HRM)
We Offer Website Development on CMS Platform like Word press/Joomla/ Drupal/ Magentowith One time Development cost and No Recurring cost involved in it
We also provide hosting, supports and maintenance services.
Please let me know If you are Interested, I can send you more details on the Company Information/packages/Portfolio/Past work details.
P.S: Please share your Skype or Contact number for Real-time Communication.
Best Regards,
Janine Ben| Business Consultant
If you did not wish to receive this, please reply with "Leave Out" in the subject line.
[-- Attachment #2: Type: text/html, Size: 1821 bytes --]
^ permalink raw reply
* [PATCH net-next] rxrpc: Reuse SKCIPHER_REQUEST_ON_STACK buffer
From: David Howells @ 2018-08-03 9:15 UTC (permalink / raw)
To: netdev; +Cc: Kees Cook, Arnd Bergmann, dhowells, linux-afs, linux-kernel
From: Kees Cook <keescook@chromium.org>
The use of SKCIPHER_REQUEST_ON_STACK() will trigger FRAME_WARN warnings
(when less than 2048) once the VLA is no longer hidden from the check:
net/rxrpc/rxkad.c:398:1: warning: the frame size of 1152 bytes is larger than 1024 bytes [-Wframe-larger-than=]
net/rxrpc/rxkad.c:242:1: warning: the frame size of 1152 bytes is larger than 1024 bytes [-Wframe-larger-than=]
This passes the initial SKCIPHER_REQUEST_ON_STACK allocation to the leaf
functions for reuse. Two requests allocated on the stack is not needed
when only one is used at a time.
Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David Howells <dhowells@redhat.com>
---
net/rxrpc/rxkad.c | 25 +++++++++++++------------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 6988073ae842..eaf8f4f446b0 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -146,10 +146,10 @@ static int rxkad_prime_packet_security(struct rxrpc_connection *conn)
static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
struct sk_buff *skb,
u32 data_size,
- void *sechdr)
+ void *sechdr,
+ struct skcipher_request *req)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxkad_level1_hdr hdr;
struct rxrpc_crypt iv;
struct scatterlist sg;
@@ -183,12 +183,12 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
struct sk_buff *skb,
u32 data_size,
- void *sechdr)
+ void *sechdr,
+ struct skcipher_request *req)
{
const struct rxrpc_key_token *token;
struct rxkad_level2_hdr rxkhdr;
struct rxrpc_skb_priv *sp;
- SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_crypt iv;
struct scatterlist sg[16];
struct sk_buff *trailer;
@@ -296,11 +296,12 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
ret = 0;
break;
case RXRPC_SECURITY_AUTH:
- ret = rxkad_secure_packet_auth(call, skb, data_size, sechdr);
+ ret = rxkad_secure_packet_auth(call, skb, data_size, sechdr,
+ req);
break;
case RXRPC_SECURITY_ENCRYPT:
ret = rxkad_secure_packet_encrypt(call, skb, data_size,
- sechdr);
+ sechdr, req);
break;
default:
ret = -EPERM;
@@ -316,10 +317,10 @@ static int rxkad_secure_packet(struct rxrpc_call *call,
*/
static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
unsigned int offset, unsigned int len,
- rxrpc_seq_t seq)
+ rxrpc_seq_t seq,
+ struct skcipher_request *req)
{
struct rxkad_level1_hdr sechdr;
- SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_crypt iv;
struct scatterlist sg[16];
struct sk_buff *trailer;
@@ -402,11 +403,11 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb,
*/
static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb,
unsigned int offset, unsigned int len,
- rxrpc_seq_t seq)
+ rxrpc_seq_t seq,
+ struct skcipher_request *req)
{
const struct rxrpc_key_token *token;
struct rxkad_level2_hdr sechdr;
- SKCIPHER_REQUEST_ON_STACK(req, call->conn->cipher);
struct rxrpc_crypt iv;
struct scatterlist _sg[4], *sg;
struct sk_buff *trailer;
@@ -549,9 +550,9 @@ static int rxkad_verify_packet(struct rxrpc_call *call, struct sk_buff *skb,
case RXRPC_SECURITY_PLAIN:
return 0;
case RXRPC_SECURITY_AUTH:
- return rxkad_verify_packet_1(call, skb, offset, len, seq);
+ return rxkad_verify_packet_1(call, skb, offset, len, seq, req);
case RXRPC_SECURITY_ENCRYPT:
- return rxkad_verify_packet_2(call, skb, offset, len, seq);
+ return rxkad_verify_packet_2(call, skb, offset, len, seq, req);
default:
return -ENOANO;
}
^ permalink raw reply related
* [PATCH 2/2] include/net/bond_3ad: Simplify the code by using the ARRAY_SIZE
From: zhong jiang @ 2018-08-03 6:53 UTC (permalink / raw)
To: woojung.huh, davem, UNGLinuxDriver; +Cc: netdev, linux-kernel
In-Reply-To: <1533279195-50245-1-git-send-email-zhongjiang@huawei.com>
We prefer to ARRAY_SIZE rather than the open code to calculate size.
Signed-off-by: zhong jiang <zhongjiang@huawei.com>
---
include/net/bond_3ad.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/net/bond_3ad.h b/include/net/bond_3ad.h
index f358ad5..fc31115 100644
--- a/include/net/bond_3ad.h
+++ b/include/net/bond_3ad.h
@@ -283,7 +283,7 @@ static inline const char *bond_3ad_churn_desc(churn_state_t state)
"none",
"unknown"
};
- int max_size = sizeof(churn_description) / sizeof(churn_description[0]);
+ int max_size = ARRAY_SIZE(churn_description);
if (state >= max_size)
state = max_size - 1;
--
1.7.12.4
^ permalink raw reply related
* [PATCH v2 net-next] bnxt_en: combine 'else if' and 'else' into single branch
From: YueHaibing @ 2018-08-03 8:48 UTC (permalink / raw)
To: davem, michael.chan; +Cc: linux-kernel, netdev, vasundhara-v.volam, YueHaibing
The else-if branch and else branch set mac_ok to true similarly,
so combine the two into single else branch.
Also add comments to explain the two conditions, which
from Michael Chan and Vasundhara Volam.
Signed-off-by: YueHaibing <yuehaibing@huawei.com>
Acked-by: Michael Chan <michael.chan@broadcom.com>
---
v2: fix typos: 'branche'--> 'branch' , 'Aslo'-->'Also'
---
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
index a649108..f560845 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
@@ -956,9 +956,13 @@ static int bnxt_vf_validate_set_mac(struct bnxt *bp, struct bnxt_vf_info *vf)
} else if (is_valid_ether_addr(vf->vf_mac_addr)) {
if (ether_addr_equal((const u8 *)req->l2_addr, vf->vf_mac_addr))
mac_ok = true;
- } else if (bp->hwrm_spec_code < 0x10202) {
- mac_ok = true;
} else {
+ /* There are two cases:
+ * 1.If firmware spec < 0x10202,VF MAC address is not forwarded
+ * to the PF and so it doesn't have to match
+ * 2.Allow VF to modify it's own MAC when PF has not assigned a
+ * valid MAC address and firmware spec >= 0x10202
+ */
mac_ok = true;
}
if (mac_ok)
--
2.7.0
^ permalink raw reply related
* Re: KASAN: use-after-free Read in bpf_cgroup_storage_release
From: Daniel Borkmann @ 2018-08-03 8:48 UTC (permalink / raw)
To: syzbot, ast, linux-kernel, netdev, syzkaller-bugs
In-Reply-To: <000000000000f3b1570572779079@google.com>
On 08/02/2018 07:59 PM, syzbot wrote:
> Hello,
>
> syzbot found the following crash on:
>
> HEAD commit: fc2a3b5dd618 Merge branch 'bpf-cgroup-local-storage'
> git tree: bpf-next
> console output: https://syzkaller.appspot.com/x/log.txt?x=17a6a1c8400000
> kernel config: https://syzkaller.appspot.com/x/.config?x=3bfcc1651962483
> dashboard link: https://syzkaller.appspot.com/bug?extid=25554ab865a12b51c66f
> compiler: gcc (GCC) 8.0.1 20180413 (experimental)
> syzkaller repro:https://syzkaller.appspot.com/x/repro.syz?x=12c4b9b4400000
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13e9d6f0400000
>
> IMPORTANT: if you fix the bug, please add the following tag to the commit:
> Reported-by: syzbot+25554ab865a12b51c66f@syzkaller.appspotmail.com
#syz fix: 82c018d734a7 Merge branch 'bpf-cgroup-local-storage'
^ permalink raw reply
* Re: [PATCH bpf-next 05/13] docs: net: Fix indentation issues for code snippets
From: Daniel Borkmann @ 2018-08-03 8:44 UTC (permalink / raw)
To: Tobin C. Harding, Alexei Starovoitov
Cc: Jonathan Corbet, David S. Miller, linux-doc, netdev, linux-kernel
In-Reply-To: <20180801050908.29970-6-me@tobin.cc>
On 08/01/2018 07:09 AM, Tobin C. Harding wrote:
[...]
> -Starting bpf_dbg is trivial and just requires issuing:
> +Starting bpf_dbg is trivial and just requires issuing::
>
> -# ./bpf_dbg
> + # ./bpf_dbg
>
> In case input and output do not equal stdin/stdout, bpf_dbg takes an
> alternative stdin source as a first argument, and an alternative stdout
> @@ -381,86 +384,87 @@ file "~/.bpf_dbg_init" and the command history is stored in the file
> Interaction in bpf_dbg happens through a shell that also has auto-completion
> support (follow-up example commands starting with '>' denote bpf_dbg shell).
> The usual workflow would be to ...
> -
> -> load bpf 6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0
> - Loads a BPF filter from standard output of bpf_asm, or transformed via
> - e.g. `tcpdump -iem1 -ddd port 22 | tr '\n' ','`. Note that for JIT
> - debugging (next section), this command creates a temporary socket and
> - loads the BPF code into the kernel. Thus, this will also be useful for
> - JIT developers.
> -
> -> load pcap foo.pcap
> - Loads standard tcpdump pcap file.
> -
> -> run [<n>]
> -bpf passes:1 fails:9
> - Runs through all packets from a pcap to account how many passes and fails
> - the filter will generate. A limit of packets to traverse can be given.
> -
> -> disassemble
> -l0: ldh [12]
> -l1: jeq #0x800, l2, l5
> -l2: ldb [23]
> -l3: jeq #0x1, l4, l5
> -l4: ret #0xffff
> -l5: ret #0
> - Prints out BPF code disassembly.
> -
> -> dump
> -/* { op, jt, jf, k }, */
> -{ 0x28, 0, 0, 0x0000000c },
> -{ 0x15, 0, 3, 0x00000800 },
> -{ 0x30, 0, 0, 0x00000017 },
> -{ 0x15, 0, 1, 0x00000001 },
> -{ 0x06, 0, 0, 0x0000ffff },
> -{ 0x06, 0, 0, 0000000000 },
> - Prints out C-style BPF code dump.
> -
> -> breakpoint 0
> -breakpoint at: l0: ldh [12]
> -> breakpoint 1
> -breakpoint at: l1: jeq #0x800, l2, l5
> - ...
> - Sets breakpoints at particular BPF instructions. Issuing a `run` command
> - will walk through the pcap file continuing from the current packet and
> - break when a breakpoint is being hit (another `run` will continue from
> - the currently active breakpoint executing next instructions):
> -
> - > run
> - -- register dump --
> - pc: [0] <-- program counter
> - code: [40] jt[0] jf[0] k[12] <-- plain BPF code of current instruction
> - curr: l0: ldh [12] <-- disassembly of current instruction
> - A: [00000000][0] <-- content of A (hex, decimal)
> - X: [00000000][0] <-- content of X (hex, decimal)
> - M[0,15]: [00000000][0] <-- folded content of M (hex, decimal)
> - -- packet dump -- <-- Current packet from pcap (hex)
> - len: 42
> - 0: 00 19 cb 55 55 a4 00 14 a4 43 78 69 08 06 00 01
> - 16: 08 00 06 04 00 01 00 14 a4 43 78 69 0a 3b 01 26
> - 32: 00 00 00 00 00 00 0a 3b 01 01
> - (breakpoint)
> - >
> -
> -> breakpoint
> -breakpoints: 0 1
> - Prints currently set breakpoints.
> -
> -> step [-<n>, +<n>]
> - Performs single stepping through the BPF program from the current pc
> - offset. Thus, on each step invocation, above register dump is issued.
> - This can go forwards and backwards in time, a plain `step` will break
> - on the next BPF instruction, thus +1. (No `run` needs to be issued here.)
> -
> -> select <n>
> - Selects a given packet from the pcap file to continue from. Thus, on
> - the next `run` or `step`, the BPF program is being evaluated against
> - the user pre-selected packet. Numbering starts just as in Wireshark
> - with index 1.
> -
> -> quit
> -#
> - Exits bpf_dbg.
> +::
> +
> + > load bpf 6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0
> + Loads a BPF filter from standard output of bpf_asm, or transformed via
> + e.g. `tcpdump -iem1 -ddd port 22 | tr '\n' ','`. Note that for JIT
> + debugging (next section), this command creates a temporary socket and
> + loads the BPF code into the kernel. Thus, this will also be useful for
> + JIT developers.
Here for the bpf_dbg howto, it would be good to separate explanation from
the cmdline code snippets. This would more easily clarify the commands
themselves if we already go the rst route, so I'd prefer splitting this up.
> + > load pcap foo.pcap
> + Loads standard tcpdump pcap file.
> +
> + > run [<n>]
> + bpf passes:1 fails:9
> + Runs through all packets from a pcap to account how many passes and fails
> + the filter will generate. A limit of packets to traverse can be given.
> +
> + > disassemble
> + l0: ldh [12]
> + l1: jeq #0x800, l2, l5
> + l2: ldb [23]
> + l3: jeq #0x1, l4, l5
> + l4: ret #0xffff
> + l5: ret #0
> + Prints out BPF code disassembly.
> +
> + > dump
> + /* { op, jt, jf, k }, */
> + { 0x28, 0, 0, 0x0000000c },
> + { 0x15, 0, 3, 0x00000800 },
> + { 0x30, 0, 0, 0x00000017 },
> + { 0x15, 0, 1, 0x00000001 },
> + { 0x06, 0, 0, 0x0000ffff },
> + { 0x06, 0, 0, 0000000000 },
> + Prints out C-style BPF code dump.
> +
> + > breakpoint 0
> + breakpoint at: l0: ldh [12]
> + > breakpoint 1
> + breakpoint at: l1: jeq #0x800, l2, l5
> + ...
> + Sets breakpoints at particular BPF instructions. Issuing a `run` command
> + will walk through the pcap file continuing from the current packet and
> + break when a breakpoint is being hit (another `run` will continue from
> + the currently active breakpoint executing next instructions):
> +
> + > run
> + -- register dump --
> + pc: [0] <-- program counter
> + code: [40] jt[0] jf[0] k[12] <-- plain BPF code of current instruction
> + curr: l0:ldh [12] <-- disassembly of current instruction
> + A: [00000000][0] <-- content of A (hex, decimal)
> + X: [00000000][0] <-- content of X (hex, decimal)
> + M[0,15]: [00000000][0] <-- folded content of M (hex, decimal)
> + -- packet dump -- <-- Current packet from pcap (hex)
> + len: 42
> + 0: 00 19 cb 55 55 a4 00 14 a4 43 78 69 08 06 00 01
> + 16: 08 00 06 04 00 01 00 14 a4 43 78 69 0a 3b 01 26
> + 32: 00 00 00 00 00 00 0a 3b 01 01
> + (breakpoint)
> + >
> +
> + > breakpoint
> + breakpoints: 0 1
> + Prints currently set breakpoints.
> +
> + > step [-<n>, +<n>]
> + Performs single stepping through the BPF program from the current pc
> + offset. Thus, on each step invocation, above register dump is issued.
> + This can go forwards and backwards in time, a plain `step` will break
> + on the next BPF instruction, thus +1. (No `run` needs to be issued here.)
> +
> + > select <n>
> + Selects a given packet from the pcap file to continue from. Thus, on
> + the next `run` or `step`, the BPF program is being evaluated against
> + the user pre-selected packet. Numbering starts just as in Wireshark
> + with index 1.
> +
> + > quit
> + #
> + Exits bpf_dbg.
>
^ permalink raw reply
* Re: [PATCH bpf-next 12/13] docs: net: Fix various minor typos
From: Daniel Borkmann @ 2018-08-03 8:41 UTC (permalink / raw)
To: Tobin C. Harding, Alexei Starovoitov
Cc: Jonathan Corbet, David S. Miller, linux-doc, netdev, linux-kernel
In-Reply-To: <20180801050908.29970-13-me@tobin.cc>
On 08/01/2018 07:09 AM, Tobin C. Harding wrote:
> There are a few minor typos and grammatical issues. We should however
> try to keep the current flavour of the document.
>
> Fix typos and grammar if glaringly required.
>
> Signed-off-by: Tobin C. Harding <me@tobin.cc>
Overall looks good, just some minor nits:
> Documentation/networking/filter.rst | 65 +++++++++++++++--------------
> 1 file changed, 33 insertions(+), 32 deletions(-)
>
> diff --git a/Documentation/networking/filter.rst b/Documentation/networking/filter.rst
> index 99dfa74fc4f7..b989a6c882b8 100644
> --- a/Documentation/networking/filter.rst
> +++ b/Documentation/networking/filter.rst
> @@ -32,10 +32,10 @@ removing the old one and placing your new one in its place, assuming your
> filter has passed the checks, otherwise if it fails the old filter will
> remain on that socket.
>
> -SO_LOCK_FILTER option allows to lock the filter attached to a socket. Once
> -set, a filter cannot be removed or changed. This allows one process to
> +SO_LOCK_FILTER option allows locking of the filter attached to a socket.
> +Once set, a filter cannot be removed or changed. This allows one process to
> setup a socket, attach a filter, lock it then drop privileges and be
> -assured that the filter will be kept until the socket is closed.
> +assured that the filter will be kept until the socket is closed.
^-- looks like extra whitespace slipped in?
> The biggest user of this construct might be libpcap. Issuing a high-level
> filter command like ``tcpdump -i em1 port 22`` passes through the libpcap
> @@ -470,7 +470,7 @@ JIT compiler
> ============
>
> The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC,
> -ARM, ARM64, MIPS and s390 and can be enabled through CONFIG_BPF_JIT. The JIT
> +ARM, ARM64, MIPS and s390 which can be enabled through CONFIG_BPF_JIT. The JIT
> compiler is transparently invoked for each attached filter from user space
> or for internal kernel users if it has been previously enabled by root::
>
> @@ -580,7 +580,7 @@ Internally, for the kernel interpreter, a different instruction set
> format with similar underlying principles from BPF described in previous
> paragraphs is being used. However, the instruction set format is modelled
> closer to the underlying architecture to mimic native instruction sets, so
> -that a better performance can be achieved (more details later). This new
> +that better performance can be achieved (more details later). This new
> ISA is called 'eBPF' or 'internal BPF' interchangeably. (Note: eBPF which
> originates from [e]xtended BPF is not the same as BPF extensions! While
> eBPF is an ISA, BPF extensions date back to classic BPF's 'overloading'
> @@ -655,12 +655,12 @@ Some core changes of the new internal format:
>
> 32-bit architectures run 64-bit internal BPF programs via interpreter.
> Their JITs may convert BPF programs that only use 32-bit subregisters into
> - native instruction set and let the rest being interpreted.
> + native instruction set and let the rest be interpreted.
>
> - Operation is 64-bit, because on 64-bit architectures, pointers are also
> - 64-bit wide, and we want to pass 64-bit values in/out of kernel functions,
> - so 32-bit eBPF registers would otherwise require to define register-pair
> - ABI, thus, there won't be able to use a direct eBPF register to HW register
> + Operation is 64-bit since on 64-bit architectures pointers are also
> + 64-bit wide and we want to pass 64-bit values in/out of kernel functions.
> + 32-bit eBPF registers would otherwise require us to define a register-pair
> + ABI, thus we would not be able to use a direct eBPF register to HW register
> mapping and JIT would need to do combine/split/move operations for every
> register in and out of the function, which is complex, bug prone and slow.
> Another reason is the use of atomic 64-bit counters.
> @@ -694,7 +694,7 @@ Some core changes of the new internal format:
> situations without performance penalty.
>
> After an in-kernel function call, R1 - R5 are reset to unreadable and R0 has
> - a return value of the function. Since R6 - R9 are callee saved, their state
> + the return value of the function. Since R6 - R9 are callee saved, their state
> is preserved across the call.
>
> For example, consider three C functions::
> @@ -732,7 +732,7 @@ Some core changes of the new internal format:
> are currently not supported, but these restrictions can be lifted if necessary
> in the future.
>
> - On 64-bit architectures all register map to HW registers one to one. For
> + On 64-bit architectures all registers map to HW registers one to one. For
> example, x86_64 JIT compiler can map them as ... ::
>
> R0 - rax
> @@ -831,9 +831,10 @@ A program, that is translated internally consists of the following elements::
>
> op:16, jt:8, jf:8, k:32 ==> op:8, dst_reg:4, src_reg:4, off:16, imm:32
>
> -So far 87 internal BPF instructions were implemented. 8-bit ``op`` opcode field
> -has room for new instructions. Some of them may use 16/24/32 byte encoding. New
> -instructions must be multiple of 8 bytes to preserve backward compatibility.
> +So far 87 internal BPF instructions have been implemented. 8-bit ``op``
> +opcode field has room for new instructions. Some of them may use 16/24/32
> +byte encoding. New instructions must be a multiple of 8 bytes to preserve
> +backward compatibility.
>
> Internal BPF is a general purpose RISC instruction set. Not every register and
> every instruction are used during translation from original BPF to new format.
> @@ -844,11 +845,11 @@ out of registers and would have to resort to spill/fill to stack.
>
> Internal BPF can used as generic assembler for last step performance
> optimizations, socket filters and seccomp are using it as assembler. Tracing
> -filters may use it as assembler to generate code from kernel. In kernel usage
> +filters may use it as assembler to generate code from kernel. In-kernel usage
^-- ditto
> may not be bounded by security considerations, since generated internal BPF code
> -may be optimizing internal code path and not being exposed to the user space.
> -Safety of internal BPF can come from a verifier (TBD). In such use cases as
> -described, it may be used as safe instruction set.
> +may use an optimised internal code path and may not be being exposed to user
> +space. Safety of internal BPF can come from a verifier (TBD). In such use cases
> +as described, it may be used as safe as the instruction set.
>
> Just like the original BPF, the new format runs within a controlled environment,
> is deterministic and the kernel can easily prove that. The safety of the program
> @@ -945,7 +946,7 @@ Classic BPF is using BPF_MISC class to represent A = X and X = A moves.
> eBPF is using BPF_MOV | BPF_X | BPF_ALU code instead. Since there are no
> BPF_MISC operations in eBPF, the class 7 is used as BPF_ALU64 to mean
> exactly the same operations as BPF_ALU, but with 64-bit wide operands
> -instead. So BPF_ADD | BPF_X | BPF_ALU64 means 64-bit addition, i.e.:
> +instead. So BPF_ADD | BPF_X | BPF_ALU64 means 64-bit addition i.e.
> dst_reg = dst_reg + src_reg
>
> Classic BPF wastes the whole BPF_RET class to represent a single 'ret'
> @@ -1024,8 +1025,8 @@ Where size is one of: BPF_B or BPF_H or BPF_W or BPF_DW. Note that 1 and
> 2 byte atomic increments are not supported.
>
> eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM which consists
> -of two consecutive ``struct bpf_insn`` 8-byte blocks and interpreted as single
> -instruction that loads 64-bit immediate value into a dst_reg.
> +of two consecutive ``struct bpf_insn`` 8-byte blocks and is interpreted as
> +a single instruction that loads 64-bit immediate value into a dst_reg.
> Classic BPF has similar instruction: BPF_LD | BPF_W | BPF_IMM which loads
> 32-bit immediate value into a register.
>
> @@ -1035,8 +1036,8 @@ eBPF verifier
> The safety of the eBPF program is determined in two steps.
>
> First step does DAG check to disallow loops and other CFG validation.
> -In particular it will detect programs that have unreachable instructions.
> -(though classic BPF checker allows them)
> +In particular it will detect programs that have unreachable instructions
> +(though classic BPF checker allows them).
>
> Second step starts from the first insn and descends all possible paths.
> It simulates execution of every insn and observes the state change of
> @@ -1107,7 +1108,7 @@ For example::
> bpf_ld R0 = *(u32 *)(R10 - 4)
> bpf_exit
>
> -is invalid program.
> +is an invalid program.
> Though R10 is correct read-only register and has type PTR_TO_STACK
> and R10 - 4 is within stack bounds, there were no stores into that location.
>
> @@ -1118,13 +1119,13 @@ Allowed function calls are customized with bpf_verifier_ops->get_func_proto()
> The eBPF verifier will check that registers match argument constraints.
> After the call register R0 will be set to return type of the function.
>
> -Function calls is a main mechanism to extend functionality of eBPF programs.
> -Socket filters may let programs to call one set of functions, whereas tracing
> -filters may allow completely different set.
> +Function calls is an important mechanism to extend functionality of eBPF
> +programs. Socket filters may let programs call one set of functions,
^-- ditto
> +whereas tracing filters may allow a completely different set.
>
> -If a function made accessible to eBPF program, it needs to be thought through
> -from safety point of view. The verifier will guarantee that the function is
> -called with valid arguments.
> +If a function is made accessible to eBPF program, it needs to be thought
> +through from a safety point of view. The verifier will guarantee that the
> +function is called with valid arguments.
>
> seccomp vs socket filters have different security restrictions for classic BPF.
> Seccomp solves this by two stage verifier: classic BPF verifier is followed
> @@ -1202,7 +1203,7 @@ checked and found to be non-NULL, all copies can become PTR_TO_MAP_VALUEs.
> As well as range-checking, the tracked information is also used for enforcing
> alignment of pointer accesses. For instance, on most systems the packet pointer
> is 2 bytes after a 4-byte alignment. If a program adds 14 bytes to that to jump
> -over the Ethernet header, then reads IHL and addes (IHL * 4), the resulting
> +over the Ethernet header, then reads IHL and adds (IHL * 4), the resulting
> pointer will have a variable offset known to be 4n+2 for some n, so adding the 2
> bytes (NET_IP_ALIGN) gives a 4-byte alignment and so word-sized accesses through
> that pointer are safe.
>
^ permalink raw reply
* [PATCH net 1/1] net/smc: no cursor update send in state SMC_INIT
From: Ursula Braun @ 2018-08-03 8:38 UTC (permalink / raw)
To: davem; +Cc: netdev, linux-s390, schwidefsky, heiko.carstens, raspl,
linux-kernel
If a writer blocked condition is received without data, the current
consumer cursor is immediately sent. Servers could already receive this
condition in state SMC_INIT without finished tx-setup. This patch
avoids sending a consumer cursor update in this case.
Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
---
net/smc/smc_cdc.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c
index a7e8d63fc8ae..9bde1e4ca288 100644
--- a/net/smc/smc_cdc.c
+++ b/net/smc/smc_cdc.c
@@ -233,7 +233,8 @@ static void smc_cdc_msg_recv_action(struct smc_sock *smc,
/* force immediate tx of current consumer cursor, but
* under send_lock to guarantee arrival in seqno-order
*/
- smc_tx_sndbuf_nonempty(conn);
+ if (smc->sk.sk_state != SMC_INIT)
+ smc_tx_sndbuf_nonempty(conn);
}
}
--
2.16.4
^ permalink raw reply related
* Re: [V9fs-developer] [PATCH] net/9p: avoid request size exceed to the virtqueue number in the zero copy
From: Dominique Martinet @ 2018-08-03 8:27 UTC (permalink / raw)
To: jiangyiwen
Cc: Eric Van Hensbergen, Ron Minnich, Latchesar Ionkov,
Linux Kernel Mailing List, v9fs-developer, netdev
In-Reply-To: <5B640FCC.3000704@huawei.com>
jiangyiwen wrote on Fri, Aug 03, 2018:
> On 2018/8/3 15:32, Dominique Martinet wrote:
> > jiangyiwen wrote on Fri, Aug 03, 2018:
> >> Unfortunately, when the address(input and response headers) are not
> >> at page boundary, it will need two extra entry in the zero copy, or
> >> else it will cause sg array out of bounds.
> >>
> >> To avoid the problem, we should subtract two pages for maxsize.
> >
> > Good catch, that must have been painful to figure.
> >
> > Given we know how big the headers are (something like 11 or 23 bytes
> > depending on the op/direction, it's capped by P9_IOHDRSZ at 24),
> > couldn't we just cheat and not use the start of the buffer if we detect
> > it's overlapping?
>
> Actually, generally the P9_IOHDRSZ will not cause the problem, because
> 24 bytes is too small, but P9_ZC_HDR_SZ(4096 bytes) often cause two pages.
>
> So I have a question about why we need to use P9_ZC_HDR_SZ, actually we
> may use P9_IOHDRSZ instead.
The reason is historical (for non-dotl versions of 9P), but the reply if
error could be longer than P9_IOHDRSZ in this case - see the code in
p9_check_zc_errors that copies the end of the string back from the zc
buffer to the 4k buffer
I don't see much other reason, though... But I don't understand how that
is a problem - we don't actually put the full P9_ZC_HDR_SZ in chan->sg
for headers, but these:
out = pack_sg_list(chan->sg, 0,
VIRTQUEUE_NUM, req->tc.sdata, req->tc.size);
in = pack_sg_list(chan->sg, out,
VIRTQUEUE_NUM, req->rc.sdata, in_hdr_len);
req->tc.size is the size of the header up till that point and in_hdr_len
is the size expected from the header.
That's why I suggested that if these are on a page boundary, we could
just memcpy that data further within the P9_ZC_HDR_SZ-sized buffer and
use that for the header (then move it back to the start of the buffer
for the reply header)
--
Dominique
^ permalink raw reply
* AW: AW: AW: PROBLEM: Kernel Oops in UDP stack
From: Marcel Hellwig @ 2018-08-03 8:24 UTC (permalink / raw)
To: 'Eric Dumazet', David Laight,
'davem@davemloft.net', 'kuznet@ms2.inr.ac.ru',
'yoshfuji@linux-ipv6.org', 'andrew@lunn.ch'
Cc: 'netdev@vger.kernel.org',
'linux-kernel@vger.kernel.org', Matthias Wystrik
In-Reply-To: <b297c600-1600-3560-7f2e-6d504529e0db@gmail.com>
>
>Well, this driver does not use NET_IP_ALIGN reservation, meaning IP header is not 4-byte aligned.
>
>No idea why mis-alignments are okay in IP layer, but not in UDP
>
>You could try to patch it to use netdev_alloc_skb_ip_align() instead of dev_alloc_skb()
Looks very promising! CPU runs for 3 hours and no panic so far. Let's hope it survives the weekend! *fingers crossed*
The strange thing I don't understand is, why does the 3.5.7 kernel does not crash (or 4.17.12, yes I managed to run a recent kernel on our machine! \o/ )? It does not use netdev_alloc_skb_ip_align either[0][1], but one thing, that I noticed it, that there is a difference in /proc/iomem
3.4.113
# cat /proc/iomem
08000000-0801ffff : lpc-eth.0
31060000-31060fff : lpc-eth.0
40088000-4008801f : serial
[...]
3.5.7
# cat /proc/iomem
20084000-20084fff : /ahb/apb/ssp@20084000
2008c000-2008cfff : /ahb/apb/ssp@2008c000
31000000-31000fff : /ahb/dma@31000000
40088000-4008801f : serial
[...]
As you notice lpc-eth.0 (or 31060000.ethernet as it's called nowadays) is not listed, so my guess it is served by DMA?
May that the reason why it does not crash (Notice: 3.5.7 runs via device tree file)?
So just my thought: If I would disable dma (somehow) would the error still occur in today's kernel?
[0]: https://elixir.bootlin.com/linux/v3.5.7/source/drivers/net/ethernet/nxp/lpc_eth.c#L1003
[1]: https://elixir.bootlin.com/linux/v4.17.12/source/drivers/net/ethernet/nxp/lpc_eth.c#L957
Mit freundlichen Grüßen / With kind regards
Marcel Hellwig
B. Sc. Informatik
Entwickler
m-u-t GmbH
Am Marienhof 2
22880 Wedel
Germany
Phone: +49 4103 9308 - 474
Fax: +49 4103 9308 - 99
mhellwig@mut-group.com
www.mut-group.com
Geschäftsführer (Managing Director): Fabian Peters
Amtsgericht Pinneberg (Commercial Register No.): HRB 10304 PI
USt-IdNr. (VAT-No.): DE228275390
WEEE-Reg-Nr.: DE 72271808
^ permalink raw reply
* Re: [V9fs-developer] [PATCH] net/9p: avoid request size exceed to the virtqueue number in the zero copy
From: jiangyiwen @ 2018-08-03 8:18 UTC (permalink / raw)
To: Dominique Martinet
Cc: Eric Van Hensbergen, Ron Minnich, Latchesar Ionkov,
Linux Kernel Mailing List, v9fs-developer, netdev
In-Reply-To: <20180803073240.GA26848@nautica>
On 2018/8/3 15:32, Dominique Martinet wrote:
> jiangyiwen wrote on Fri, Aug 03, 2018:
>> Unfortunately, when the address(input and response headers) are not
>> at page boundary, it will need two extra entry in the zero copy, or
>> else it will cause sg array out of bounds.
>>
>> To avoid the problem, we should subtract two pages for maxsize.
>
> Good catch, that must have been painful to figure.
>
> Given we know how big the headers are (something like 11 or 23 bytes
> depending on the op/direction, it's capped by P9_IOHDRSZ at 24),
> couldn't we just cheat and not use the start of the buffer if we detect
> it's overlapping?
>
Actually, generally the P9_IOHDRSZ will not cause the problem, because
24 bytes is too small, but P9_ZC_HDR_SZ(4096 bytes) often cause two pages.
So I have a question about why we need to use P9_ZC_HDR_SZ, actually we
may use P9_IOHDRSZ instead.
> It's probably faster to memcpy a few bytes than to use two pages for the
> sg list...
> It's definitely ugly though, just taking more margin here is probably
> just as good.
>
>
>
> I'm going to be picky about English again, sorry, please bear with me.
>
>> Subject: net/9p: avoid request size exceed to the virtqueue number in
>> the zero copy
>
> This is >72 characters so a little bit too long, if possible to shorten
> it.
> I'm also not sure 'exceed' is a noun so I probably wouldn't have
> understood this sentence without the rest of the message...
>
> The balance is difficult but it doesn't need to contain too much details
> either something like "9p/virtio: reduce transport maxsize" is simple
> but probably enough as it describes what is done: someone can look at
> the rest of the message for the justification.
>
Thanks, I will resend the patch later.
>
>
>> Signed-off-by: Yiwen Jiang <jiangyiwen@huawei.com>
>> ---
>> net/9p/trans_virtio.c | 9 +++++----
>> 1 file changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
>> index 6265d1d..63591b2 100644
>> --- a/net/9p/trans_virtio.c
>> +++ b/net/9p/trans_virtio.c
>> @@ -754,11 +754,12 @@ static void p9_virtio_remove(struct virtio_device *vdev)
>> .cancel = p9_virtio_cancel,
>> /*
>> * We leave one entry for input and one entry for response
>> - * headers. We also skip one more entry to accomodate, address
>> - * that are not at page boundary, that can result in an extra
>> - * page in zero copy.
>> + * headers. We also skip three more entrys to accomodate
>
> "entry"'s plural is "entries", this word is in checkpatch's dictionary
> as a common typo
Thanks, I will modify it.
>
>> + * (input + response headers + data pages), address
>> + * that are not at page boundary, that can result in
>> + * an extra page in zero copy.
>> */
>> - .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3),
>> + .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 5),
>> .def = 1,
>> .owner = THIS_MODULE,
>> };
>
> Thanks,
>
^ permalink raw reply
* Re: [PATCH bpf-next] selftests/bpf: fix a typo in map in map test
From: Daniel Borkmann @ 2018-08-03 8:17 UTC (permalink / raw)
To: Roman Gushchin, netdev
Cc: linux-kernel, kernel-team, Martin KaFai Lau, Arthur Fabre,
Alexei Starovoitov
In-Reply-To: <20180802224710.29662-1-guro@fb.com>
On 08/03/2018 12:47 AM, Roman Gushchin wrote:
> Commit fbeb1603bf4e ("bpf: verifier: MOV64 don't mark dst reg unbounded")
> revealed a typo in commit fb30d4b71214 ("bpf: Add tests for map-in-map"):
> BPF_MOV64_REG(BPF_REG_0, 0) was used instead of
> BPF_MOV64_IMM(BPF_REG_0, 0).
>
> I've noticed the problem by running bpf kselftests.
>
> Fixes: fb30d4b71214 ("bpf: Add tests for map-in-map")
> Signed-off-by: Roman Gushchin <guro@fb.com>
> Cc: Martin KaFai Lau <kafai@fb.com>
> Cc: Arthur Fabre <afabre@cloudflare.com>
> Cc: Daniel Borkmann <daniel@iogearbox.net>
> Cc: Alexei Starovoitov <ast@kernel.org>
Applied to bpf-next, thanks Roman!
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox