Netdev List
 help / color / mirror / Atom feed
* [PATCH iproute2-next 01/11] libnetlink: Convert GETADDR dumps to use rtnl_addrdump_req
From: David Ahern @ 2018-09-29 17:59 UTC (permalink / raw)
  To: netdev; +Cc: stephen, christian, David Ahern
In-Reply-To: <20180929175931.18448-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add rtnl_addrdump_req for address dumps using the proper ifaddrmsg
as the header. Convert existing RTM_GETADDR dumps to use it.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/libnetlink.h |  4 ++++
 ip/ipaddress.c       |  6 +++---
 lib/libnetlink.c     | 16 ++++++++++++++++
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index 9d9249e634dc..2d9f6190230c 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -46,6 +46,10 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned int subscriptions,
 	__attribute__((warn_unused_result));
 
 void rtnl_close(struct rtnl_handle *rth);
+
+int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
+	__attribute__((warn_unused_result));
+
 int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type)
 	__attribute__((warn_unused_result));
 int rtnl_wilddump_req_filter(struct rtnl_handle *rth, int fam, int type,
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index 8dc6c32fd6d9..f29480ce51d4 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -1698,7 +1698,7 @@ static int ipaddr_flush(void)
 	filter.flushe = sizeof(flushb);
 
 	while ((max_flush_loops == 0) || (round < max_flush_loops)) {
-		if (rtnl_wilddump_request(&rth, filter.family, RTM_GETADDR) < 0) {
+		if (rtnl_addrdump_req(&rth, filter.family) < 0) {
 			perror("Cannot send dump request");
 			exit(1);
 		}
@@ -1790,7 +1790,7 @@ int ip_linkaddr_list(int family, req_filter_fn_t filter_fn,
 	}
 
 	if (ainfo) {
-		if (rtnl_wilddump_request(&rth, family, RTM_GETADDR) < 0) {
+		if (rtnl_addrdump_req(&rth, family) < 0) {
 			perror("Cannot send dump request");
 			return 1;
 		}
@@ -1915,7 +1915,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
 		if (ipadd_save_prep())
 			exit(1);
 
-		if (rtnl_wilddump_request(&rth, preferred_family, RTM_GETADDR) < 0) {
+		if (rtnl_addrdump_req(&rth, preferred_family) < 0) {
 			perror("Cannot send dump request");
 			exit(1);
 		}
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index f18dceac2b5e..749cf4fbb88e 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -199,6 +199,22 @@ int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions)
 	return rtnl_open_byproto(rth, subscriptions, NETLINK_ROUTE);
 }
 
+int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct ifaddrmsg ifm;
+	} req = {
+		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_type = RTM_GETADDR,
+		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+		.ifm.ifa_family = family,
+	};
+
+	return send(rth->fd, &req, sizeof(req), 0);
+}
+
 int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
 {
 	return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2-next 04/11] libnetlink: Convert GETMDB dumps to use rtnl_mdbdump_req
From: David Ahern @ 2018-09-29 17:59 UTC (permalink / raw)
  To: netdev; +Cc: stephen, christian, David Ahern
In-Reply-To: <20180929175931.18448-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add rtnl_mdbdump_req for mdb dumps using the proper br_port_msg as
the header. Convert existing RTM_GETMDB dumps to use it.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 bridge/mdb.c         |  2 +-
 include/libnetlink.h |  2 ++
 lib/libnetlink.c     | 17 +++++++++++++++++
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/bridge/mdb.c b/bridge/mdb.c
index 841a36123050..03fcc91f0219 100644
--- a/bridge/mdb.c
+++ b/bridge/mdb.c
@@ -293,7 +293,7 @@ static int mdb_show(int argc, char **argv)
 	new_json_obj(json);
 
 	/* get mdb entries*/
-	if (rtnl_wilddump_request(&rth, PF_BRIDGE, RTM_GETMDB) < 0) {
+	if (rtnl_mdbdump_req(&rth, PF_BRIDGE) < 0) {
 		perror("Cannot send dump request");
 		return -1;
 	}
diff --git a/include/libnetlink.h b/include/libnetlink.h
index bacaec8216f7..8f2b2935074a 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -53,6 +53,8 @@ int rtnl_addrlbldump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
 int rtnl_routedump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
+int rtnl_mdbdump_req(struct rtnl_handle *rth, int family)
+	__attribute__((warn_unused_result));
 
 int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type)
 	__attribute__((warn_unused_result));
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index fb5f1714c2d8..51ea457cd31a 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -23,6 +23,7 @@
 #include <time.h>
 #include <sys/uio.h>
 #include <linux/if_addrlabel.h>
+#include <linux/if_bridge.h>
 
 #include "libnetlink.h"
 
@@ -248,6 +249,22 @@ int rtnl_routedump_req(struct rtnl_handle *rth, int family)
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
+int rtnl_mdbdump_req(struct rtnl_handle *rth, int family)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct br_port_msg bpm;
+	} req = {
+		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_type = RTM_GETMDB,
+		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+		.bpm.family = family,
+	};
+
+	return send(rth->fd, &req, sizeof(req), 0);
+}
+
 int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
 {
 	return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2-next 02/11] libnetlink: Convert GETROUTE dumps to use rtnl_routedump_req
From: David Ahern @ 2018-09-29 17:59 UTC (permalink / raw)
  To: netdev; +Cc: stephen, christian, David Ahern
In-Reply-To: <20180929175931.18448-1-dsahern@kernel.org>

From: David Ahern <dsahern@gmail.com>

Add rtnl_routedump_req for route dumps using the proper rtmsg
as the header. Convert existing RTM_GETROUTE dumps to use it.

Signed-off-by: David Ahern <dsahern@gmail.com>
---
 include/libnetlink.h |  2 ++
 ip/ipmroute.c        |  2 +-
 ip/iproute.c         |  4 ++--
 lib/libnetlink.c     | 16 ++++++++++++++++
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/include/libnetlink.h b/include/libnetlink.h
index 2d9f6190230c..a60af316b505 100644
--- a/include/libnetlink.h
+++ b/include/libnetlink.h
@@ -49,6 +49,8 @@ void rtnl_close(struct rtnl_handle *rth);
 
 int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
 	__attribute__((warn_unused_result));
+int rtnl_routedump_req(struct rtnl_handle *rth, int family)
+	__attribute__((warn_unused_result));
 
 int rtnl_wilddump_request(struct rtnl_handle *rth, int fam, int type)
 	__attribute__((warn_unused_result));
diff --git a/ip/ipmroute.c b/ip/ipmroute.c
index bc23cfea7e8b..c5dfa9cb1538 100644
--- a/ip/ipmroute.c
+++ b/ip/ipmroute.c
@@ -283,7 +283,7 @@ static int mroute_list(int argc, char **argv)
 		filter.iif = idx;
 	}
 
-	if (rtnl_wilddump_request(&rth, filter.af, RTM_GETROUTE) < 0) {
+	if (rtnl_routedump_req(&rth, filter.af) < 0) {
 		perror("Cannot send dump request");
 		return 1;
 	}
diff --git a/ip/iproute.c b/ip/iproute.c
index 398322fd1f4f..699635923764 100644
--- a/ip/iproute.c
+++ b/ip/iproute.c
@@ -1645,7 +1645,7 @@ static int iproute_flush(int do_ipv6, rtnl_filter_t filter_fn)
 	filter.flushe = sizeof(flushb);
 
 	for (;;) {
-		if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
+		if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
 			perror("Cannot send dump request");
 			return -2;
 		}
@@ -1891,7 +1891,7 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
 		return iproute_flush(do_ipv6, filter_fn);
 
 	if (!filter.cloned) {
-		if (rtnl_wilddump_request(&rth, do_ipv6, RTM_GETROUTE) < 0) {
+		if (rtnl_routedump_req(&rth, do_ipv6) < 0) {
 			perror("Cannot send dump request");
 			return -2;
 		}
diff --git a/lib/libnetlink.c b/lib/libnetlink.c
index 749cf4fbb88e..fda5309ce44d 100644
--- a/lib/libnetlink.c
+++ b/lib/libnetlink.c
@@ -215,6 +215,22 @@ int rtnl_addrdump_req(struct rtnl_handle *rth, int family)
 	return send(rth->fd, &req, sizeof(req), 0);
 }
 
+int rtnl_routedump_req(struct rtnl_handle *rth, int family)
+{
+	struct {
+		struct nlmsghdr nlh;
+		struct rtmsg rtm;
+	} req = {
+		.nlh.nlmsg_len = sizeof(req),
+		.nlh.nlmsg_type = RTM_GETROUTE,
+		.nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+		.nlh.nlmsg_seq = rth->dump = ++rth->seq,
+		.rtm.rtm_family = family,
+	};
+
+	return send(rth->fd, &req, sizeof(req), 0);
+}
+
 int rtnl_wilddump_request(struct rtnl_handle *rth, int family, int type)
 {
 	return rtnl_wilddump_req_filter(rth, family, type, RTEXT_FILTER_VF);
-- 
2.11.0

^ permalink raw reply related

* [PATCH iproute2-next 00/11] Fix dump requests to use proper header for type
From: David Ahern @ 2018-09-29 17:59 UTC (permalink / raw)
  To: netdev; +Cc: stephen, christian, David Ahern

From: David Ahern <dsahern@gmail.com>

iproute2 currently uses ifinfomsg as the header for all dumps using the
wilddump headers. This is wrong as each message type actually has its own
header type. While the kernel has traditionally let it go as it for the
most part only uses the family entry, the use of kernel side filters is
increasing to alter what is returned on a request. The kernel side filters
really need to use the proper header type.

To that end, fix iproute2 to use the proper header struct for the GET type.

David Ahern (11):
  libnetlink: Convert GETADDR dumps to use rtnl_addrdump_req
  libnetlink: Convert GETROUTE dumps to use rtnl_routedump_req
  libnetlink: Convert GETADDRLABEL dumps to use rtnl_addrlbldump_req
  libnetlink: Convert GETMDB dumps to use rtnl_mdbdump_req
  libnetlink: Convert GETNETCONF dumps to use rtnl_netconfdump_req
  libnetlink: Convert GETRULE dumps to use rtnl_ruledump_req
  libnetlink: Convert GETNEIGH dumps to use rtnl_neighdump_req
  libnetlink: Convert GETNEIGHTBL dumps to use rtnl_neightbldump_req
  libnetlink: Convert GETNSID dumps to use rtnl_nsiddump_req
  libnetlink: Rename rtnl_wilddump_* to rtnl_linkdump_*
  libnetlink: Rename rtnl_wilddump_stats_req_filter to
    rtnl_statsdump_req_filter

 bridge/link.c        |   4 +-
 bridge/mdb.c         |   2 +-
 bridge/vlan.c        |  10 +---
 include/libnetlink.h |  30 ++++++++--
 ip/ipaddress.c       |  10 ++--
 ip/ipaddrlabel.c     |   4 +-
 ip/iplink.c          |   4 +-
 ip/iplink_xstats.c   |   4 +-
 ip/ipmroute.c        |   2 +-
 ip/ipnetconf.c       |   3 +-
 ip/ipnetns.c         |   2 +-
 ip/ipntable.c        |   2 +-
 ip/iproute.c         |   4 +-
 ip/iprule.c          |   2 +-
 ip/iptoken.c         |   2 +-
 ip/iptuntap.c        |   2 +-
 ip/rtmon.c           |   2 +-
 ip/tunnel.c          |   2 +-
 lib/libnetlink.c     | 164 ++++++++++++++++++++++++++++++++++++++++++++++++---
 lib/ll_map.c         |   2 +-
 misc/arpd.c          |   2 +-
 misc/ifstat.c        |   6 +-
 22 files changed, 210 insertions(+), 55 deletions(-)

-- 
2.11.0

^ permalink raw reply

* __nf_register_net_hook jump label splat
From: Borislav Petkov @ 2018-09-29 23:04 UTC (permalink / raw)
  To: netdev
  Cc: Pablo Neira Ayuso, Jozsef Kadlecsik, Florian Westphal,
	David S. Miller, netfilter-devel, coreteam, linux-kernel

Hi people,

this is something new I'm triggering with rc5 + tip/master while rc4 +
tip/master is fine. Any ideas?

If I had to guess, it looks like this thing:

#ifdef HAVE_JUMP_LABEL
        static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]);
#endif



[   24.472503] bridge: filtering via arp/ip/ip6tables is no longer available by default. Update your scripts to load br_netfilter if you need this.
[   24.497078] Bridge firewalling registered
[   24.507989] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000
[   24.517700] PGD 80284ff51067 P4D 80284ff51067 PUD 80284ff52067 PMD 0 
[   24.525895] Oops: 0000 [#1] PREEMPT SMP NOPTI
[   24.531949] CPU: 121 PID: 4848 Comm: wickedd Not tainted 4.19.0-rc5+ #1
[   24.549787] RIP: 0010:jump_label_update+0xa4/0xd0
[   24.556049] Code: 73 08 48 85 f6 74 31 48 8b 43 10 48 c7 c2 60 01 f0 81 48 85 c0 74 11 8b 90 b8 02 00 00 48 c1 e2 04 48 03 90 b0 02 00 00 31 c9 <83> 38 01 48 89 ef 0f 94 c1 e8 8e fd ff ff 48 8b 1b 48 85 db 75 be
[   24.578102] RSP: 0018:ffffc9000f783c70 EFLAGS: 00010246
[   24.584946] RAX: 0000000000000000 RBX: ffff884045145880 RCX: 0000000000000000
[   24.593679] RDX: ffffffff81f00160 RSI: ffffffff81efff00 RDI: ffffffff8204e220
[   24.601575] usb 3-2.2: device not accepting address 8, error -71
[   24.602418] RBP: ffffffff827ef800 R08: 0000000000000002 R09: 0000000000000000
[   24.602424] R10: ffff88407ea62f48 R11: 0000000000000000 R12: ffff884033dfcdc0
[   24.610307] usb 3-2-port2: unable to enumerate USB device
[   24.619267] R13: ffffffff821078d0 R14: 0000000000000000 R15: 0000000000000000
[   24.619271] FS:  00007f30357a4700(0000) GS:ffff88407ea40000(0000) knlGS:0000000000000000
[   24.619274] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   24.619276] CR2: 0000000000000000 CR3: 0000802853e20000 CR4: 00000000003406e0
[   24.619277] Call Trace:
[   24.619289]  static_key_slow_inc_cpuslocked+0x73/0xa0
[   24.682426]  static_key_slow_inc+0x16/0x20
[   24.682435]  __nf_register_net_hook+0x98/0x100
[   24.682440]  nf_register_net_hook+0x23/0x80
[   24.682445]  nf_register_net_hooks+0x3c/0x90
[   24.682452]  brnf_device_event+0x68/0xb0 [br_netfilter]
[   24.682461]  notifier_call_chain+0x47/0x70
[   24.682470]  register_netdevice+0x352/0x4c0
[   24.682475]  register_netdev+0x1f/0x30
[   24.682485]  br_add_bridge+0x4b/0x70 [bridge]
[   24.682500]  br_ioctl_deviceless_stub+0x112/0x250 [bridge]
[   24.705565] usb 3-2.3: new high-speed USB device number 9 using xhci_hcd
[   24.707752]  sock_ioctl+0x250/0x320
[   24.761176]  do_vfs_ioctl+0x92/0x5e0
[   24.761182]  ? __sys_recvmsg+0x45/0x80
[   24.761186]  ksys_ioctl+0x60/0x90
[   24.761191]  __x64_sys_ioctl+0x16/0x20
[   24.761198]  do_syscall_64+0x4f/0xe0
[   24.761206]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[   24.761212] RIP: 0033:0x7f3034f62417
[   24.761216] Code: 00 00 00 48 8b 05 71 8a 2b 00 64 c7 00 26 00 00 00 48 c7 c0 ff ff ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 b8 10 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 41 8a 2b 00 f7 d8 64 89 01 48
[   24.761224] RSP: 002b:00007ffecdc9ca08 EFLAGS: 00000246
[   24.793641] usb 3-2.3: device descriptor read/64, error -71
[   24.796390]  ORIG_RAX: 0000000000000010
[   24.796397] RAX: ffffffffffffffda RBX: 0000000001236ff0 RCX: 00007f3034f62417
[   24.854147] RDX: 0000000001236ff0 RSI: 00000000000089a0 RDI: 0000000000000008
[   24.854149] RBP: 00007ffecdc9ca48 R08: 0000000000000000 R09: 0000000001297650
[   24.854150] R10: 000000006829aa3c R11: 0000000000000246 R12: 00000000012385f0
[   24.854152] R13: 000000000129a840 R14: 0000000001205700 R15: 0000000001208fc0
[   24.854156] Modules linked in: br_netfilter bridge stp llc iscsi_ibft iscsi_boot_sysfs msr ipmi_ssif nls_iso8859_1 nls_cp437 joydev amd64_edac_mod vfat edac_mce_amd fat kvm_amd hid_generic usbhid kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel pcbc e1000e aesni_intel aes_x86_64 crypto_simd cryptd ptp glue_helper pps_core sp5100_tco pcspkr ipmi_si ccp ipmi_devintf i2c_piix4 k10temp ipmi_msghandler pcc_cpufreq pinctrl_amd acpi_cpufreq button btrfs libcrc32c xor zstd_decompress zstd_compress xxhash ast i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops xhci_pci ttm xhci_hcd raid6_pq crc32c_intel drm usbcore dm_mirror dm_region_hash dm_log sg dm_multipath dm_mod scsi_dh_rdac scsi_dh_emc scsi_dh_alua efivarfs
[   24.890644] CR2: 0000000000000000
[   24.973524] ---[ end trace e5c10bd51bf12555 ]---
[   24.973529] RIP: 0010:jump_label_update+0xa4/0xd0
[   24.973532] Code: 73 08 48 85 f6 74 31 48 8b 43 10 48 c7 c2 60 01 f0 81 48 85 c0 74 11 8b 90 b8 02 00 00 48 c1 e2 04 48 03 90 b0 02 00 00 31 c9 <83> 38 01 48 89 ef 0f 94 c1 e8 8e fd ff ff 48 8b 1b 48 85 db 75 be
[   24.973534] RSP: 0018:ffffc9000f783c70 EFLAGS: 00010246
[   24.973536] RAX: 0000000000000000 RBX: ffff884045145880 RCX: 0000000000000000
[   24.973538] RDX: ffffffff81f00160 RSI: ffffffff81efff00 RDI: ffffffff8204e220
[   24.973539] RBP: ffffffff827ef800 R08: 0000000000000002 R09: 0000000000000000
[   24.973541] R10: ffff88407ea62f48 R11: 0000000000000000 R12: ffff884033dfcdc0
[   24.973542] R13: ffffffff821078d0 R14: 0000000000000000 R15: 0000000000000000
[   24.973545] FS:  00007f30357a4700(0000) GS:ffff88407ea40000(0000) knlGS:0000000000000000
[   24.973546] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   24.973548] CR2: 0000000000000000 CR3: 0000802853e20000 CR4: 00000000003406e0

-- 
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

^ permalink raw reply

* [PATCH] net/packet: fix packet drop as of virtio gso
From: Jianfeng Tan @ 2018-09-29 15:41 UTC (permalink / raw)
  To: netdev; +Cc: davem, jasowang, mst

When we use raw socket as the vhost backend, a packet from virito with
gso offloading information, cannot be sent out in later validaton at
xmit path, as we did not set correct skb->protocol which is further used
for looking up the gso function.

To fix this, we set this field according to virito hdr information.

Fixes: e858fae2b0b8f4 ("virtio_net: use common code for virtio_net_hdr and skb GSO conversion")

Cc: stable@vger.kernel.org
Signed-off-by: Jianfeng Tan <jianfeng.tan@linux.alibaba.com>
---
 include/linux/virtio_net.h | 18 ++++++++++++++++++
 net/packet/af_packet.c     | 11 +++++++----
 2 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
index 9397628a1967..cb462f9ab7dd 100644
--- a/include/linux/virtio_net.h
+++ b/include/linux/virtio_net.h
@@ -5,6 +5,24 @@
 #include <linux/if_vlan.h>
 #include <uapi/linux/virtio_net.h>
 
+static inline int virtio_net_hdr_set_proto(struct sk_buff *skb,
+					   const struct virtio_net_hdr *hdr)
+{
+	switch (hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+	case VIRTIO_NET_HDR_GSO_TCPV4:
+	case VIRTIO_NET_HDR_GSO_UDP:
+		skb->protocol = cpu_to_be16(ETH_P_IP);
+		break;
+	case VIRTIO_NET_HDR_GSO_TCPV6:
+		skb->protocol = cpu_to_be16(ETH_P_IPV6);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 					const struct virtio_net_hdr *hdr,
 					bool little_endian)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 75c92a87e7b2..d6e94dc7e290 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2715,10 +2715,12 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
 			}
 		}
 
-		if (po->has_vnet_hdr && virtio_net_hdr_to_skb(skb, vnet_hdr,
-							      vio_le())) {
-			tp_len = -EINVAL;
-			goto tpacket_error;
+		if (po->has_vnet_hdr) {
+			if (virtio_net_hdr_to_skb(skb, vnet_hdr, vio_le())) {
+				tp_len = -EINVAL;
+				goto tpacket_error;
+			}
+			virtio_net_hdr_set_proto(skb, vnet_hdr);
 		}
 
 		skb->destructor = tpacket_destruct_skb;
@@ -2915,6 +2917,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 		if (err)
 			goto out_free;
 		len += sizeof(vnet_hdr);
+		virtio_net_hdr_set_proto(skb, &vnet_hdr);
 	}
 
 	skb_probe_transport_header(skb, reserve);
-- 
2.17.1

^ permalink raw reply related

* [PATCHv2 net-next] geneve: allow to clear ttl inherit
From: Hangbin Liu @ 2018-09-29 15:06 UTC (permalink / raw)
  To: netdev; +Cc: David Miller, Phil Sutter, Hangbin Liu, Michal Kubecek
In-Reply-To: <1538096998-20937-1-git-send-email-liuhangbin@gmail.com>

As Michal remaind, we should allow to clear ttl inherit. Then we will
have three states:

1. set the flag, and do ttl inherit.
2. do not set the flag, use configured ttl value, or default ttl (0) if
   not set.
3. disable ttl inherit, use previous configured ttl value, or default ttl (0).

Fixes: 52d0d404d39dd ("geneve: add ttl inherit support")
CC: Michal Kubecek <mkubecek@suse.cz>
Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
---
 drivers/net/geneve.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 6625fab..82eccc9 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -1325,11 +1325,15 @@ static int geneve_nl2info(struct nlattr *tb[], struct nlattr *data[],
 		info->key.tun_id = tunid;
 	}
 
-	if (data[IFLA_GENEVE_TTL])
+	if (data[IFLA_GENEVE_TTL_INHERIT]) {
+		if (nla_get_u8(data[IFLA_GENEVE_TTL_INHERIT]))
+			*ttl_inherit = true;
+		else
+			*ttl_inherit = false;
+	} else if (data[IFLA_GENEVE_TTL]) {
 		info->key.ttl = nla_get_u8(data[IFLA_GENEVE_TTL]);
-
-	if (data[IFLA_GENEVE_TTL_INHERIT])
-		*ttl_inherit = true;
+		*ttl_inherit = false;
+	}
 
 	if (data[IFLA_GENEVE_TOS])
 		info->key.tos = nla_get_u8(data[IFLA_GENEVE_TOS]);
-- 
2.5.5

^ permalink raw reply related

* Re: [PATCH net-next] geneve: fix ttl inherit type
From: Hangbin Liu @ 2018-09-29 15:03 UTC (permalink / raw)
  To: Michal Kubecek
  Cc: netdev, David Miller, Stephen Hemminger, David Ahern, Phil Sutter
In-Reply-To: <20180928234619.GA17323@unicorn.suse.cz>

On Sat, Sep 29, 2018 at 01:46:19AM +0200, Michal Kubecek wrote:
> Is it desirable to switch to a flag? If I read geneve_changelink() and
> geneve_nl2info() correctly, it allows you to set the ttl_inherit flag
> for an existing device but doesn't allow you to clear it. With NLA_U8,
> you could distinguish three cases: set the flag (non-zero value), clear
> the flag (zero value) and preserve current state (attribute not
> present).
> 
> The same problem exists for vxlan but vxlan code intentionally disallows
> changing the flag value for an existing device (I'm not sure if it's
> because it's really impossible or just due to limits of the interface).
> Unfortunately it has been already released with NLA_FLAG in 4.18,
> AFAICS, so we have to live with it. But it's not too late for geneve.
> 
> Michal Kubecek

Hi michal,

I thought about the vxlan issue and agree with you. TTL inherit is a way
to define the ttl number we should use. It also should be able to be changed
as the normal ttl. How about enabling clear ttl inherit flag like:

--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -3303,13 +3303,11 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
        if (data[IFLA_VXLAN_TOS])
                conf->tos  = nla_get_u8(data[IFLA_VXLAN_TOS]);

-       if (data[IFLA_VXLAN_TTL])
-               conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
-
        if (data[IFLA_VXLAN_TTL_INHERIT]) {
-               if (changelink)
-                       return -EOPNOTSUPP;
                conf->flags |= VXLAN_F_TTL_INHERIT;
+       } else if (data[IFLA_VXLAN_TTL]) {
+               conf->flags &= ~VXLAN_F_TTL_INHERIT;
+               conf->ttl = nla_get_u8(data[IFLA_VXLAN_TTL]);
        }


Before this fix, we disabled changing it after creating vxlan. And with this fix
we can set/unset it. I think this should not be a usage break. What do you think?

Thanks
Hangbin

^ permalink raw reply

* Re: [PATCH iproute2 net-next] ipneigh: support setting of NTF_ROUTER on neigh entries
From: Roopa Prabhu @ 2018-09-29 15:02 UTC (permalink / raw)
  To: David Ahern; +Cc: netdev
In-Reply-To: <e0455cc6-54b2-45ab-10dd-b162d9e76b3d@gmail.com>

On Fri, Sep 28, 2018 at 9:57 AM David Ahern <dsahern@gmail.com> wrote:
>
> On 9/25/18 3:15 PM, Roopa Prabhu wrote:
> > From: Roopa Prabhu <roopa@cumulusnetworks.com>
> >
> > Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
> > ---
> >  ip/ipneigh.c | 2 ++
> >  1 file changed, 2 insertions(+)
> >
>
> applied to iproute2-next.
>
> And then I noticed you did not update the help or the man page. Please
> send a follow up.

Oops, looks like i missed including it in this patch before sending.
will post it today.

^ permalink raw reply

* [PATCH V2 net-next 08/10] net: hns3: Change return type of hclge_tm_schd_info_update()
From: Salil Mehta @ 2018-09-29 14:56 UTC (permalink / raw)
  To: davem
  Cc: salil.mehta, yisen.zhuang, lipeng321, mehta.salil, netdev,
	linux-kernel, linuxarm, Huazhong Tan, Yunsheng Lin
In-Reply-To: <20180929145622.5448-1-salil.mehta@huawei.com>

From: Huazhong Tan <tanhuazhong@huawei.com>

hclge_tm_schd_info_update should return an error when num_tc is greater
than alloc_tqps.

This patch changes the return type of hnae3_register_ae_algo from void
to int.

Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: Yunsheng Lin <linyunsheng@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_dcb.c | 8 ++++++--
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c  | 9 ++++++++-
 drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h  | 2 +-
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
index 92f19384e258..e72f724123d7 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
@@ -184,7 +184,9 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
 	if (ret)
 		return ret;
 
-	hclge_tm_schd_info_update(hdev, num_tc);
+	ret = hclge_tm_schd_info_update(hdev, num_tc);
+	if (ret)
+		return ret;
 
 	ret = hclge_ieee_ets_to_tm_info(hdev, ets);
 	if (ret)
@@ -310,7 +312,9 @@ static int hclge_setup_tc(struct hnae3_handle *h, u8 tc, u8 *prio_tc)
 		return -EINVAL;
 	}
 
-	hclge_tm_schd_info_update(hdev, tc);
+	ret = hclge_tm_schd_info_update(hdev, tc);
+	if (ret)
+		return ret;
 
 	ret = hclge_tm_prio_tc_info_update(hdev, prio_tc);
 	if (ret)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
index ab7280d7f79c..aa5cb9834d73 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
@@ -1280,10 +1280,15 @@ int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc)
 	return 0;
 }
 
-void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
+int hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
 {
 	u8 i, bit_map = 0;
 
+	for (i = 0; i < hdev->num_alloc_vport; i++) {
+		if (num_tc > hdev->vport[i].alloc_tqps)
+			return -EINVAL;
+	}
+
 	hdev->tm_info.num_tc = num_tc;
 
 	for (i = 0; i < hdev->tm_info.num_tc; i++)
@@ -1297,6 +1302,8 @@ void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc)
 	hdev->hw_tc_map = bit_map;
 
 	hclge_tm_schd_info_init(hdev);
+
+	return 0;
 }
 
 int hclge_tm_init_hw(struct hclge_dev *hdev)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
index e1568b826aac..25eef13a3e14 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
@@ -132,7 +132,7 @@ int hclge_tm_schd_init(struct hclge_dev *hdev);
 int hclge_pause_setup_hw(struct hclge_dev *hdev);
 int hclge_tm_schd_mode_hw(struct hclge_dev *hdev);
 int hclge_tm_prio_tc_info_update(struct hclge_dev *hdev, u8 *prio_tc);
-void hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
+int hclge_tm_schd_info_update(struct hclge_dev *hdev, u8 num_tc);
 int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
 int hclge_tm_map_cfg(struct hclge_dev *hdev);
 int hclge_tm_init_hw(struct hclge_dev *hdev);
-- 
2.11.0

^ permalink raw reply related

* Re: [PATCH v3] PCI: Reprogram bridge prefetch registers on resume
From: Thomas Martitz @ 2018-09-29 21:06 UTC (permalink / raw)
  To: Bjorn Helgaas, Daniel Drake
  Cc: bhelgaas, linux-pci, linux, nouveau, linux-pm, peter, kherbst,
	andy.shevchenko, rafael.j.wysocki, keith.busch, jonathan.derrick,
	davem, hkallweit1, netdev, nic_swsd, rchang, linux-kernel
In-Reply-To: <20180927205247.GA18434@bhelgaas-glaptop.roam.corp.google.com>

Am 27.09.18 um 22:52 schrieb Bjorn Helgaas:
> [+cc LKML]
> 
> On Tue, Sep 18, 2018 at 04:32:44PM -0500, Bjorn Helgaas wrote:
>> On Thu, Sep 13, 2018 at 11:37:45AM +0800, Daniel Drake wrote:
>>> On 38+ Intel-based Asus products, the nvidia GPU becomes unusable
>>> after S3 suspend/resume. The affected products include multiple
>>> generations of nvidia GPUs and Intel SoCs. After resume, nouveau logs
>>> many errors such as:
>>>
>>>      fifo: fault 00 [READ] at 0000005555555000 engine 00 [GR] client 04
>>>            [HUB/FE] reason 4a [] on channel -1 [007fa91000 unknown]
>>>      DRM: failed to idle channel 0 [DRM]
>>>
>>> Similarly, the nvidia proprietary driver also fails after resume
>>> (black screen, 100% CPU usage in Xorg process). We shipped a sample
>>> to Nvidia for diagnosis, and their response indicated that it's a
>>> problem with the parent PCI bridge (on the Intel SoC), not the GPU.
>>>
>>> Runtime suspend/resume works fine, only S3 suspend is affected.
>>>
>>> We found a workaround: on resume, rewrite the Intel PCI bridge
>>> 'Prefetchable Base Upper 32 Bits' register (PCI_PREF_BASE_UPPER32). In
>>> the cases that I checked, this register has value 0 and we just have to
>>> rewrite that value.
>>>
>>> Linux already saves and restores PCI config space during suspend/resume,
>>> but this register was being skipped because upon resume, it already
>>> has value 0 (the correct, pre-suspend value).
>>>
>>> Intel appear to have previously acknowledged this behaviour and the
>>> requirement to rewrite this register.
>>> https://bugzilla.kernel.org/show_bug.cgi?id=116851#c23
>>>
>>> Based on that, rewrite the prefetch register values even when that
>>> appears unnecessary.
>>>
>>> We have confirmed this solution on all the affected models we have
>>> in-hands (X542UQ, UX533FD, X530UN, V272UN).
>>>
>>> Additionally, this solves an issue where r8169 MSI-X interrupts were
>>> broken after S3 suspend/resume on Asus X441UAR. This issue was recently
>>> worked around in commit 7bb05b85bc2d ("r8169: don't use MSI-X on
>>> RTL8106e"). It also fixes the same issue on RTL6186evl/8111evl on an
>>> Aimfor-tech laptop that we had not yet patched. I suspect it will also
>>> fix the issue that was worked around in commit 7c53a722459c ("r8169:
>>> don't use MSI-X on RTL8168g").
>>>
>>> Thomas Martitz reports that this change also solves an issue where
>>> the AMD Radeon Polaris 10 GPU on the HP Zbook 14u G5 is unresponsive
>>> after S3 suspend/resume.
>>>
>>> Link: https://bugzilla.kernel.org/show_bug.cgi?id=201069
>>> Signed-off-by: Daniel Drake <drake@endlessm.com>
>>
>> Applied with Rafael's and Peter's reviewed-by to pci/enumeration for v4.20.
>> Thanks for the the huge investigative effort!
> 
> Since this looks low-risk and fixes several painful issues, I think
> this merits a stable tag and being included in v4.19 (instead of
> waiting for v4.20).
> 
> I moved it to for-linus for v4.19.  Let me know if you object.


The latest iteration does not work on my HP system. The GPU fails to 
power up just like the unpatched kernel.

[  516.833580] amdgpu 0000:01:00.0: Refused to change power state, 
currently in D3
[  516.912885] amdgpu 0000:01:00.0: Refused to change power state, 
currently in D3
[  516.929175] amdgpu 0000:01:00.0: Refused to change power state, 
currently in D3
[  521.932435] [drm:atom_op_jump] *ERROR* atombios stuck in loop for 
more than 5secs aborting
[  521.932440] [drm:amdgpu_atom_execute_table_locked] *ERROR* atombios 
stuck executing C392 (len 62, WS 0, PS 0) @ 0xC3AE
[  521.932442] [drm:amdgpu_atom_execute_table_locked] *ERROR* atombios 
stuck executing ADB8 (len 140, WS 0, PS 8) @ 0xADD3
[  521.932444] [drm:amdgpu_device_resume] *ERROR* amdgpu asic init failed
[  522.883309] amdgpu 0000:01:00.0: Wait for MC idle timedout !
[  523.831676] amdgpu 0000:01:00.0: Wait for MC idle timedout !
[  523.832931] [drm] PCIE GART of 256M enabled (table at 
0x000000F400000000).
[  523.836807] amdgpu: [powerplay] Failed to send Message.
[  523.836862] amdgpu: [powerplay] SMC address must be 4 byte aligned.
[  523.836863] amdgpu: [powerplay] [AVFS][Polaris10_SetupGfxLvlStruct] 
Problems copying VRConfig value over to SMC
[  523.836864] amdgpu: [powerplay] [AVFS][Polaris10_AVFSEventMgr] Could 
not Copy Graphics Level table over to SMU
[  523.836908] amdgpu: [powerplay]
                 last message was failed ret is 65535
[  523.836924] amdgpu: [powerplay]
                 failed to send message 252 ret is 65535
[  523.836949] amdgpu: [powerplay]
                 last message was failed ret is 65535
[  523.836965] amdgpu: [powerplay]
                 failed to send message 253 ret is 65535
[  523.836989] amdgpu: [powerplay]
                 last message was failed ret is 65535
[  523.837006] amdgpu: [powerplay]
                 failed to send message 250 ret is 65535
[  523.837029] amdgpu: [powerplay]
                 last message was failed ret is 65535
[  523.837045] amdgpu: [powerplay]



> 
>>> ---
>>>   drivers/pci/pci.c | 25 +++++++++++++++++--------
>>>   1 file changed, 17 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
>>> index 29ff9619b5fa..5d58220b6997 100644
>>> --- a/drivers/pci/pci.c
>>> +++ b/drivers/pci/pci.c
>>> @@ -1289,12 +1289,12 @@ int pci_save_state(struct pci_dev *dev)
>>>   EXPORT_SYMBOL(pci_save_state);
>>>   
>>>   static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
>>> -				     u32 saved_val, int retry)
>>> +				     u32 saved_val, int retry, bool force)
>>>   {
>>>   	u32 val;
>>>   
>>>   	pci_read_config_dword(pdev, offset, &val);
>>> -	if (val == saved_val)
>>> +	if (!force && val == saved_val)
>>>   		return;
>>>   
>>>   	for (;;) {
>>> @@ -1313,25 +1313,34 @@ static void pci_restore_config_dword(struct pci_dev *pdev, int offset,
>>>   }
>>>   
>>>   static void pci_restore_config_space_range(struct pci_dev *pdev,
>>> -					   int start, int end, int retry)
>>> +					   int start, int end, int retry,
>>> +					   bool force)
>>>   {
>>>   	int index;
>>>   
>>>   	for (index = end; index >= start; index--)
>>>   		pci_restore_config_dword(pdev, 4 * index,
>>>   					 pdev->saved_config_space[index],
>>> -					 retry);
>>> +					 retry, force);
>>>   }
>>>   
>>>   static void pci_restore_config_space(struct pci_dev *pdev)
>>>   {
>>>   	if (pdev->hdr_type == PCI_HEADER_TYPE_NORMAL) {
>>> -		pci_restore_config_space_range(pdev, 10, 15, 0);
>>> +		pci_restore_config_space_range(pdev, 10, 15, 0, false);
>>>   		/* Restore BARs before the command register. */
>>> -		pci_restore_config_space_range(pdev, 4, 9, 10);
>>> -		pci_restore_config_space_range(pdev, 0, 3, 0);
>>> +		pci_restore_config_space_range(pdev, 4, 9, 10, false);
>>> +		pci_restore_config_space_range(pdev, 0, 3, 0, false);
>>> +	} else if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
>>> +		pci_restore_config_space_range(pdev, 12, 15, 0, false);
>>> +		/* Force rewriting of prefetch registers to avoid
>>> +		 * S3 resume issues on Intel PCI bridges that occur when
>>> +		 * these registers are not explicitly written.
>>> +		 */
>>> +		pci_restore_config_space_range(pdev, 9, 11, 0, true);
>>> +		pci_restore_config_space_range(pdev, 0, 8, 0, false);
>>>   	} else {
>>> -		pci_restore_config_space_range(pdev, 0, 15, 0);
>>> +		pci_restore_config_space_range(pdev, 0, 15, 0, false);
>>>   	}
>>>   }
>>>   
>>> -- 
>>> 2.17.1
>>>

^ permalink raw reply

* RE: [PATCH V2 net-next 00/10] Cleanups, minor additions & fixes for HNS3 driver
From: Salil Mehta @ 2018-09-29 20:43 UTC (permalink / raw)
  To: David Miller
  Cc: Zhuangyuzeng (Yisen), lipeng (Y), mehta.salil@opnsrc.net,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Linuxarm
In-Reply-To: <20180929.104644.1898007175155937602.davem@davemloft.net>

Hi David,

> From: David Miller [mailto:davem@davemloft.net]
> Sent: Saturday, September 29, 2018 6:47 PM
> To: Salil Mehta <salil.mehta@huawei.com>
> Cc: Zhuangyuzeng (Yisen) <yisen.zhuang@huawei.com>; lipeng (Y)
> <lipeng321@huawei.com>; mehta.salil@opnsrc.net; netdev@vger.kernel.org;
> linux-kernel@vger.kernel.org; Linuxarm <linuxarm@huawei.com>
> Subject: Re: [PATCH V2 net-next 00/10] Cleanups, minor additions &
> fixes for HNS3 driver
> 
> From: Salil Mehta <salil.mehta@huawei.com>
> Date: Sat, 29 Sep 2018 15:56:12 +0100
> 
> > This patch-set contains cleans-ups, minor changes and fixes to the
> HNS3 driver.
> >
> > Change Summary:
> > v1->v2
> >   * Fixed Kbuild error due to missed patch in the current submission.
> >     For now, replaced HNAE3_REVISION_ID_21 macro with 0x21
> >   * Fixed issues identified by Eric Dumazet and spelling mistakes by
> David Miller
> >     Link: https://lkml.org/lkml/2018/9/28/842
> >
> > Note:
> > Hi David,
> > From v1->v2 changes only exists in below patch
> >      "net: hns3: Add serdes parallel inner loopback support"
> 
> I already applied v1, so you have to send me a build fix for that
> broken
> patch.
> 
> Nevermind, I'll do it myself, I can't have my tree broken like this for
> days.
> 
> In the future, when I've applied your changes, they cannot be reverted.
> You must send me relative fixups to what is in my tree already.

Ok sure, got it. Will take care in future.
Thanks so much for the help this time.

Best regards
Salil.

> 
> Thank you.

^ permalink raw reply

* RE: [PATCH] hv_netvsc: remove ndo_poll_controller
From: Haiyang Zhang @ 2018-09-29 14:12 UTC (permalink / raw)
  To: Stephen Hemminger, netdev@vger.kernel.org; +Cc: Stephen Hemminger, Eric Dumazet
In-Reply-To: <20180929125256.25994-1-sthemmin@microsoft.com>



> -----Original Message-----
> From: Stephen Hemminger <stephen@networkplumber.org>
> Sent: Saturday, September 29, 2018 8:53 AM
> To: netdev@vger.kernel.org
> Cc: Stephen Hemminger <sthemmin@microsoft.com>; Haiyang Zhang
> <haiyangz@microsoft.com>; Eric Dumazet <edumazet@google.com>
> Subject: [PATCH] hv_netvsc: remove ndo_poll_controller
> 
> Similar to other patches from ERic.
> 
> As diagnosed by Song Liu, ndo_poll_controller() can be very dangerous on
> loaded hosts, since the cpu calling ndo_poll_controller() might steal all NAPI
> contexts (for all RX/TX queues of the NIC). This capture can last for unlimited
> amount of time, since one cpu is generally not able to drain all the queues
> under load.
> 
> In netvsc driver it uses NAPI for TX completions. The default poll_napi will do
> this for us now and avoid the capture.
> 
> Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
> Cc: Haiyang Zhang <haiyangz@microsoft.com>
> Cc: Eric Dumazet <edumazet@google.com>
> ---

Thank you.
Reviewed-by: Haiyang Zhang <haiyangz@microsoft.com>

^ permalink raw reply

* Re: [PATCH] net: phy: Fix a unused function gcc warning.
From: Florian Fainelli @ 2018-09-29 20:36 UTC (permalink / raw)
  To: zhong jiang, davem; +Cc: andrew, netdev, linux-kernel
In-Reply-To: <1538197903-37168-1-git-send-email-zhongjiang@huawei.com>



On September 28, 2018 10:11:43 PM PDT, zhong jiang <zhongjiang@huawei.com> wrote:
>Fix the following compile warning:
>
>drivers/net/phy/mdio-bcm-unimac.c:321:12: warning:
>'unimac_mdio_suspend' defined but not used [-Wunused-function]
> static int unimac_mdio_suspend(struct device *d)
>            ^
>drivers/net/phy/mdio-bcm-unimac.c:330:12: warning: 'unimac_mdio_resume'
>defined but not used [-Wunused-function]
> static int unimac_mdio_resume(struct device *d)
>
>Signed-off-by: zhong jiang <zhongjiang@huawei.com>

Thank you, Arnd already sent a patch for this which got accepted:

https://patchwork.ozlabs.org/patch/975088/
-- 
Florian

^ permalink raw reply

* Re: [v2, 1/5] net: dpaa2: move DPAA2 PTP driver out of staging/
From: Andrew Lunn @ 2018-09-29 19:46 UTC (permalink / raw)
  To: Yangbo Lu
  Cc: devel, netdev, Richard Cochran, linux-kernel, Greg Kroah-Hartman,
	David S . Miller
In-Reply-To: <20180929072645.20027-1-yangbo.lu@nxp.com>

> +++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
> @@ -0,0 +1,15 @@
> +config FSL_DPAA2_ETH
> +	tristate "Freescale DPAA2 Ethernet"
> +	depends on FSL_MC_BUS && FSL_MC_DPIO

Could you add in here COMPILE_TEST? 

> +	depends on NETDEVICES && ETHERNET

With the move out of staging, i don't think these two are required.

     Andrew

^ permalink raw reply

* Re: [PATCH v3 net-next 9/9] devlink: Add Documentation/networking/devlink-params-bnxt.txt
From: Jiri Pirko @ 2018-09-29 12:53 UTC (permalink / raw)
  To: Vasundhara Volam; +Cc: davem, michael.chan, netdev, jiri, jakub.kicinski
In-Reply-To: <1538116103-12356-10-git-send-email-vasundhara-v.volam@broadcom.com>

Fri, Sep 28, 2018 at 08:28:23AM CEST, vasundhara-v.volam@broadcom.com wrote:
>This patch adds a new file to add information about configuration
>parameters that are supported by bnxt_en driver via devlink.
>
>Cc: "David S. Miller" <davem@davemloft.net>
>Cc: Jonathan Corbet <corbet@lwn.net>
>Cc: linux-doc@vger.kernel.org
>Cc: Jiri Pirko <jiri@mellanox.com>
>Cc: Michael Chan <michael.chan@broadcom.com>
>Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
>---
> Documentation/networking/devlink-params-bnxt.txt | 22 ++++++++++++++++++++++
> 1 file changed, 22 insertions(+)
> create mode 100644 Documentation/networking/devlink-params-bnxt.txt
>
>diff --git a/Documentation/networking/devlink-params-bnxt.txt b/Documentation/networking/devlink-params-bnxt.txt
>new file mode 100644
>index 0000000..c7bc9d8
>--- /dev/null
>+++ b/Documentation/networking/devlink-params-bnxt.txt
>@@ -0,0 +1,22 @@
>+enable_sriov		[DEVICE, GENERIC]
>+			Type: Boolean

No need to list "Type" here. You have it in devlink-params.txt for
generic params already.


>+			Configuration mode: Permanent
>+
>+ignore_ari		[DEVICE, GENERIC]
>+			Type: Boolean
>+			Configuration mode: Permanent
>+
>+msix_vec_per_pf_max	[DEVICE, GENERIC]
>+			Type: u32
>+			Configuration mode: Permanent
>+
>+msix_vec_per_pf_min	[DEVICE, GENERIC]
>+			Type: u32
>+			Configuration mode: Permanent
>+
>+gre_ver_check		[DEVICE, DRIVER-SPECIFIC]
>+			Generic Routing Encapsulation (GRE) version check will
>+			be enabled in the device. If disabled, device skips
>+			version checking for incoming packets.
>+			Type: Boolean
>+			Configuration mode: Permanent
>-- 
>1.8.3.1
>

^ permalink raw reply

* Re: [PATCH] hv_netvsc: remove ndo_poll_controller
From: Stephen Hemminger @ 2018-09-29 12:54 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Haiyang Zhang, Eric Dumazet
In-Reply-To: <20180929125256.25994-1-sthemmin@microsoft.com>

On Sat, 29 Sep 2018 14:52:56 +0200
Stephen Hemminger <stephen@networkplumber.org> wrote:

> Similar to other patches from ERic.
> 
> As diagnosed by Song Liu, ndo_poll_controller() can
> be very dangerous on loaded hosts, since the cpu
> calling ndo_poll_controller() might steal all NAPI
> contexts (for all RX/TX queues of the NIC). This capture
> can last for unlimited amount of time, since one
> cpu is generally not able to drain all the queues under load.
> 
> In netvsc driver it uses NAPI for TX completions. The default
> poll_napi will do this for us now and avoid the capture.
> 
> Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
> Cc: Haiyang Zhang <haiyangz@microsoft.com>
> Cc: Eric Dumazet <edumazet@google.com>

Forgot to label this, it is for net-next.

^ permalink raw reply

* [PATCH] hv_netvsc: remove ndo_poll_controller
From: Stephen Hemminger @ 2018-09-29 12:52 UTC (permalink / raw)
  To: netdev; +Cc: Stephen Hemminger, Haiyang Zhang, Eric Dumazet

Similar to other patches from ERic.

As diagnosed by Song Liu, ndo_poll_controller() can
be very dangerous on loaded hosts, since the cpu
calling ndo_poll_controller() might steal all NAPI
contexts (for all RX/TX queues of the NIC). This capture
can last for unlimited amount of time, since one
cpu is generally not able to drain all the queues under load.

In netvsc driver it uses NAPI for TX completions. The default
poll_napi will do this for us now and avoid the capture.

Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com>
Cc: Haiyang Zhang <haiyangz@microsoft.com>
Cc: Eric Dumazet <edumazet@google.com>
---
 drivers/net/hyperv/netvsc_drv.c | 23 -----------------------
 1 file changed, 23 deletions(-)

diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index ec699741170b..d7f843463bf2 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -1564,26 +1564,6 @@ netvsc_set_rxnfc(struct net_device *ndev, struct ethtool_rxnfc *info)
 	return -EOPNOTSUPP;
 }
 
-#ifdef CONFIG_NET_POLL_CONTROLLER
-static void netvsc_poll_controller(struct net_device *dev)
-{
-	struct net_device_context *ndc = netdev_priv(dev);
-	struct netvsc_device *ndev;
-	int i;
-
-	rcu_read_lock();
-	ndev = rcu_dereference(ndc->nvdev);
-	if (ndev) {
-		for (i = 0; i < ndev->num_chn; i++) {
-			struct netvsc_channel *nvchan = &ndev->chan_table[i];
-
-			napi_schedule(&nvchan->napi);
-		}
-	}
-	rcu_read_unlock();
-}
-#endif
-
 static u32 netvsc_get_rxfh_key_size(struct net_device *dev)
 {
 	return NETVSC_HASH_KEYLEN;
@@ -1811,9 +1791,6 @@ static const struct net_device_ops device_ops = {
 	.ndo_set_mac_address =		netvsc_set_mac_addr,
 	.ndo_select_queue =		netvsc_select_queue,
 	.ndo_get_stats64 =		netvsc_get_stats64,
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller =		netvsc_poll_controller,
-#endif
 };
 
 /*
-- 
2.17.1

^ permalink raw reply related

* Re: [PATCH] net: arp, ipv6: handle special case of tap device
From: David Miller @ 2018-09-29 18:40 UTC (permalink / raw)
  To: vdronov; +Cc: kuznet, yoshfuji, netdev, syzkaller, linux-kernel
In-Reply-To: <20180926093018.6646-1-vdronov@redhat.com>

From: Vladis Dronov <vdronov@redhat.com>
Date: Wed, 26 Sep 2018 11:30:18 +0200

> @@ -187,7 +187,14 @@ EXPORT_SYMBOL(arp_tbl);
>  
>  int arp_mc_map(__be32 addr, u8 *haddr, struct net_device *dev, int dir)
>  {
> -	switch (dev->type) {
> +	unsigned short type = dev->type;
> +
> +#if IS_ENABLED(CONFIG_TAP)
> +	if (dev->rtnl_link_ops && !strcmp(dev->rtnl_link_ops->kind, "tun"))
> +		type = ARPHRD_ETHER;
> +#endif /* CONFIG_TAP */

This is insanely ugly.

dev->type determines the link layer header layout and size.

You can fix the kernel, but userspace AF_PACKET applications are still
going to be broken by this behavior.  And that is just the tip of the
iceberg.

I'm not applying this, sorry.  I think tun/tap should be prevented from
allowing the dev->type to be changed, unless it will make those changes
adjust the link layer headers properly as well.

Sorry.

^ permalink raw reply

* Re: [PATCH net-next] net: caif: fix return type of ndo_start_xmit function
From: David Miller @ 2018-09-29 18:38 UTC (permalink / raw)
  To: yuehaibing; +Cc: dmitry.tarnyagin, linux-kernel, netdev
In-Reply-To: <20180926092705.28880-1-yuehaibing@huawei.com>

From: YueHaibing <yuehaibing@huawei.com>
Date: Wed, 26 Sep 2018 17:27:05 +0800

> @@ -1014,7 +1014,7 @@ static int cfhsi_xmit(struct sk_buff *skb, struct net_device *dev)
>  	int prio;
>  
>  	if (!dev)
> -		return -EINVAL;
> +		return NETDEV_TX_BUSY;
>  
>  	cfhsi = netdev_priv(dev);
>  

Even though the return type of ndo_start_xmit is netdev_tx_t, negative error codes are
still allowed I believe.

Look, reviewing these are pretty stressful for me, because you aren't documenting your
changes and in many cases the transformations look incorrect.

I'm tossing the rest of your changes in this area for now, sorry.

Please double check your work and resubmit this at some time in the not-too-near
future.

Thank you.

^ permalink raw reply

* Re: [PATCH net v2 0/7] net: usb: Check for Wake-on-LAN modes
From: David Miller @ 2018-09-29 18:32 UTC (permalink / raw)
  To: f.fainelli
  Cc: netdev, woojung.huh, UNGLinuxDriver, steve.glendinning, keescook,
	akurz, hayeswang, kai.heng.feng, grundler, zhongjiang, bigeasy,
	ran.wang_1, edumazet, linux-usb, linux-kernel
In-Reply-To: <20180928231856.3587-1-f.fainelli@gmail.com>

From: Florian Fainelli <f.fainelli@gmail.com>
Date: Fri, 28 Sep 2018 16:18:49 -0700

> Most of our USB Ethernet drivers don't seem to be checking properly
> whether the user is supplying a correct Wake-on-LAN mode to enter, so
> the experience as an user could be confusing, since it would generally
> lead to either no wake-up, or the device not being marked for wake-up.
> 
> Please review!
> 
> Changes in v2:
> 
> - fixed lan78xx handling, thanks Woojung!

Series applied, thanks Florian.

^ permalink raw reply

* Re: [PATCH net 0/8] rxrpc: Fixes
From: David Miller @ 2018-09-29 18:28 UTC (permalink / raw)
  To: dhowells; +Cc: netdev, linux-afs, linux-kernel
In-Reply-To: <153812939111.10469.179989653628053410.stgit@warthog.procyon.org.uk>

From: David Howells <dhowells@redhat.com>
Date: Fri, 28 Sep 2018 11:09:51 +0100

> Here are some miscellaneous fixes for AF_RXRPC:

Pulled, thanks David.

^ permalink raw reply

* [net-next, PATCH 2/2, v3] net: socionext: add XDP support
From: Ilias Apalodimas @ 2018-09-29 11:28 UTC (permalink / raw)
  To: netdev, jaswinder.singh
  Cc: ard.biesheuvel, masami.hiramatsu, arnd, bjorn.topel,
	magnus.karlsson, brouer, daniel, ast, jesus.sanchez-palencia,
	vinicius.gomes, makita.toshiaki, Ilias Apalodimas
In-Reply-To: <1538220482-16129-1-git-send-email-ilias.apalodimas@linaro.org>

Add basic XDP support. The interface only supports 1 Tx queue for now
so locking is introduced on the Tx queue if XDP is enabled to make sure
.ndo_start_xmit and .ndo_xdp_xmit won't corrupt Tx ring

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 drivers/net/ethernet/socionext/netsec.c | 345 +++++++++++++++++++++++++++++---
 1 file changed, 318 insertions(+), 27 deletions(-)

diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 8f788a1..2b29363 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -9,6 +9,9 @@
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/netlink.h>
+#include <linux/bpf.h>
+#include <linux/bpf_trace.h>
 
 #include <net/tcp.h>
 #include <net/ip6_checksum.h>
@@ -238,6 +241,15 @@
 
 #define NETSEC_F_NETSEC_VER_MAJOR_NUM(x)	((x) & 0xffff0000)
 
+#define NETSEC_XDP_PASS          0
+#define NETSEC_XDP_CONSUMED      BIT(0)
+#define NETSEC_XDP_TX            BIT(1)
+#define NETSEC_XDP_REDIR         BIT(2)
+#define NETSEC_XDP_RX_OK (NETSEC_XDP_PASS | NETSEC_XDP_TX | NETSEC_XDP_REDIR)
+
+#define NETSEC_RXBUF_HEADROOM (max(XDP_PACKET_HEADROOM, NET_SKB_PAD) + \
+			       NET_IP_ALIGN)
+
 enum ring_id {
 	NETSEC_RING_TX = 0,
 	NETSEC_RING_RX
@@ -256,11 +268,16 @@ struct netsec_desc_ring {
 	void *vaddr;
 	u16 pkt_cnt;
 	u16 head, tail;
+	u16 xdp_xmit; /* netsec_xdp_xmit packets */
+	bool is_xdp;
+	struct xdp_rxq_info xdp_rxq;
+	spinlock_t lock; /* XDP tx queue locking */
 };
 
 struct netsec_priv {
 	struct netsec_desc_ring desc_ring[NETSEC_RING_MAX];
 	struct ethtool_coalesce et_coalesce;
+	struct bpf_prog *xdp_prog;
 	spinlock_t reglock; /* protect reg access */
 	struct napi_struct napi;
 	phy_interface_t phy_interface;
@@ -297,6 +314,8 @@ struct netsec_rx_pkt_info {
 };
 
 static void netsec_rx_fill(struct netsec_priv *priv, u16 from, u16 num);
+static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog,
+			  struct xdp_buff *xdp);
 
 static void *netsec_alloc_rx_data(struct netsec_priv *priv,
 				  dma_addr_t *dma_addr, u16 *len);
@@ -590,6 +609,8 @@ static int netsec_clean_tx_dring(struct netsec_priv *priv, int budget)
 	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_TX];
 	unsigned int pkts, bytes;
 
+	if (dring->is_xdp)
+		spin_lock(&dring->lock);
 	dring->pkt_cnt += netsec_read(priv, NETSEC_REG_NRM_TX_DONE_PKTCNT);
 
 	if (dring->pkt_cnt < budget)
@@ -615,13 +636,23 @@ static int netsec_clean_tx_dring(struct netsec_priv *priv, int budget)
 
 		dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
 				 DMA_TO_DEVICE);
-		if (eop) {
-			pkts++;
+
+		if (!eop) {
+			*desc = (struct netsec_desc){};
+			continue;
+		}
+
+		if (!desc->skb) {
+			skb_free_frag(desc->addr);
+		} else {
 			bytes += desc->skb->len;
 			dev_kfree_skb(desc->skb);
 		}
+		pkts++;
 		*desc = (struct netsec_desc){};
 	}
+	if (dring->is_xdp)
+		spin_unlock(&dring->lock);
 	dring->pkt_cnt -= budget;
 
 	priv->ndev->stats.tx_packets += budget;
@@ -656,11 +687,30 @@ static void netsec_adv_desc(u16 *idx)
 		*idx = 0;
 }
 
+static void netsec_xdp_ring_tx_db(struct netsec_priv *priv, u16 pkts)
+{
+	if (likely(pkts))
+		netsec_write(priv, NETSEC_REG_NRM_TX_PKTCNT, pkts);
+}
+
+static void netsec_finalize_xdp_rx(struct netsec_priv *priv, u32 xdp_res,
+				   u16 pkts)
+{
+	if (xdp_res & NETSEC_XDP_REDIR)
+		xdp_do_flush_map();
+
+	if (xdp_res & NETSEC_XDP_TX)
+		netsec_xdp_ring_tx_db(priv, pkts);
+}
+
 static int netsec_process_rx(struct netsec_priv *priv, int budget)
 {
 	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
+	struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog);
 	struct net_device *ndev = priv->ndev;
-	struct sk_buff *skb;
+	struct sk_buff *skb = NULL;
+	u16 xdp_xmit = 0;
+	u32 xdp_act = 0;
 	int done = 0;
 
 	while (done < budget) {
@@ -668,8 +718,10 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
 		struct netsec_desc *desc = &dring->desc[idx];
 		struct netsec_rx_pkt_info rpi;
-		u16 pkt_len, desc_len;
+		u32 xdp_result = XDP_PASS;
 		dma_addr_t dma_handle;
+		u16 pkt_len, desc_len;
+		struct xdp_buff xdp;
 		void *buf_addr;
 
 		if (de->attr & (1U << NETSEC_RX_PKT_OWN_FIELD))
@@ -706,7 +758,23 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 					DMA_FROM_DEVICE);
 		prefetch(desc->addr);
 
-		skb = build_skb(desc->addr, desc->len);
+		xdp.data_hard_start = desc->addr;
+		xdp.data = desc->addr + NETSEC_RXBUF_HEADROOM;
+		xdp_set_data_meta_invalid(&xdp);
+		xdp.data_end = xdp.data + pkt_len;
+		xdp.rxq = &dring->xdp_rxq;
+
+		if (xdp_prog) {
+			xdp_result = netsec_run_xdp(priv, xdp_prog, &xdp);
+			if (xdp_result != NETSEC_XDP_PASS) {
+				xdp_act |= xdp_result;
+				if (xdp_result == NETSEC_XDP_TX)
+					xdp_xmit++;
+				goto next;
+			}
+		}
+
+		skb = build_skb(xdp.data_hard_start, desc->len);
 		if (unlikely(!skb)) {
 			dma_unmap_single(priv->dev, dma_handle, desc_len,
 					 DMA_TO_DEVICE);
@@ -715,30 +783,35 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 				  "rx failed to alloc skb\n");
 			break;
 		}
-		dma_unmap_single_attrs(priv->dev, desc->dma_addr, desc->len,
-				       DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
 
-		/* Update the descriptor with fresh buffers */
-		desc->len = desc_len;
-		desc->dma_addr = dma_handle;
-		desc->addr = buf_addr;
-
-		skb_put(skb, pkt_len);
+		skb_reserve(skb, xdp.data - xdp.data_hard_start);
+		skb_put(skb, xdp.data_end - xdp.data);
 		skb->protocol = eth_type_trans(skb, priv->ndev);
 
 		if (priv->rx_cksum_offload_flag &&
 		    rpi.rx_cksum_result == NETSEC_RX_CKSUM_OK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-		if (napi_gro_receive(&priv->napi, skb) != GRO_DROP) {
+next:
+		if ((skb && napi_gro_receive(&priv->napi, skb) != GRO_DROP) ||
+		    xdp_result & NETSEC_XDP_RX_OK) {
 			ndev->stats.rx_packets++;
-			ndev->stats.rx_bytes += pkt_len;
+			ndev->stats.rx_bytes += xdp.data_end - xdp.data;
 		}
 
+		dma_unmap_single_attrs(priv->dev, desc->dma_addr, desc->len,
+				       DMA_FROM_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+
+		/* Update the descriptor with fresh buffers */
+		desc->len = desc_len;
+		desc->dma_addr = dma_handle;
+		desc->addr = buf_addr;
 		netsec_rx_fill(priv, idx, 1);
 		netsec_adv_desc(&dring->tail);
 	}
 
+	netsec_finalize_xdp_rx(priv, xdp_act, xdp_xmit);
+
 	return done;
 }
 
@@ -805,7 +878,9 @@ static void netsec_set_tx_de(struct netsec_priv *priv,
 	de->data_buf_addr_lw = lower_32_bits(desc->dma_addr);
 	de->buf_len_info = (tx_ctrl->tcp_seg_len << 16) | desc->len;
 	de->attr = attr;
-	dma_wmb();
+	/* under spin_lock if using XDP */
+	if (!dring->is_xdp)
+		dma_wmb();
 
 	dring->desc[idx] = *desc;
 	dring->desc[idx].skb = skb;
@@ -824,6 +899,8 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
 	u16 tso_seg_len = 0;
 	int filled;
 
+	if (dring->is_xdp)
+		spin_lock_bh(&dring->lock);
 	/* differentiate between full/emtpy ring */
 	if (dring->head >= dring->tail)
 		filled = dring->head - dring->tail;
@@ -831,6 +908,8 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
 		filled = dring->head + DESC_NUM - dring->tail;
 
 	if (DESC_NUM - filled < 2) { /* if less than 2 available */
+		if (dring->is_xdp)
+			spin_unlock_bh(&dring->lock);
 		netif_err(priv, drv, priv->ndev, "%s: TxQFull!\n", __func__);
 		netif_stop_queue(priv->ndev);
 		dma_wmb();
@@ -864,6 +943,8 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
 	tx_desc.dma_addr = dma_map_single(priv->dev, skb->data,
 					  skb_headlen(skb), DMA_TO_DEVICE);
 	if (dma_mapping_error(priv->dev, tx_desc.dma_addr)) {
+		if (dring->is_xdp)
+			spin_unlock_bh(&dring->lock);
 		netif_err(priv, drv, priv->ndev,
 			  "%s: DMA mapping failed\n", __func__);
 		ndev->stats.tx_dropped++;
@@ -877,6 +958,8 @@ static netdev_tx_t netsec_netdev_start_xmit(struct sk_buff *skb,
 	netdev_sent_queue(priv->ndev, skb->len);
 
 	netsec_set_tx_de(priv, dring, &tx_ctrl, &tx_desc, skb);
+	if (dring->is_xdp)
+		spin_unlock_bh(&dring->lock);
 	netsec_write(priv, NETSEC_REG_NRM_TX_PKTCNT, 1); /* submit another tx */
 
 	return NETDEV_TX_OK;
@@ -891,6 +974,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id)
 	if (!dring->vaddr || !dring->desc)
 		return;
 
+	if (xdp_rxq_info_is_reg(&dring->xdp_rxq))
+		xdp_rxq_info_unreg(&dring->xdp_rxq);
+
 	for (idx = 0; idx < DESC_NUM; idx++) {
 		desc = &dring->desc[idx];
 		if (!desc->addr)
@@ -930,24 +1016,24 @@ static void netsec_free_dring(struct netsec_priv *priv, int id)
 static void *netsec_alloc_rx_data(struct netsec_priv *priv,
 				  dma_addr_t *dma_handle, u16 *desc_len)
 {
-	size_t len = priv->ndev->mtu + ETH_HLEN + 2 * VLAN_HLEN + NET_SKB_PAD +
-		NET_IP_ALIGN;
+	size_t total_len = SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	size_t payload_len = priv->ndev->mtu + ETH_HLEN + 2 * VLAN_HLEN;
 	dma_addr_t mapping;
 	void *buf;
 
-	len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
-	len = SKB_DATA_ALIGN(len);
+	total_len += SKB_DATA_ALIGN(payload_len + NETSEC_RXBUF_HEADROOM);
 
-	buf = napi_alloc_frag(len);
+	buf = napi_alloc_frag(total_len);
 	if (!buf)
 		return NULL;
 
-	mapping = dma_map_single(priv->dev, buf, len, DMA_FROM_DEVICE);
+	mapping = dma_map_single(priv->dev, buf + NETSEC_RXBUF_HEADROOM,
+				 payload_len, DMA_FROM_DEVICE);
 	if (unlikely(dma_mapping_error(priv->dev, mapping)))
 		goto err_out;
 
 	*dma_handle = mapping;
-	*desc_len = len;
+	*desc_len = total_len;
 
 	return buf;
 
@@ -990,10 +1076,27 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
 	return -ENOMEM;
 }
 
+static void netsec_setup_tx_dring(struct netsec_priv *priv)
+{
+	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_TX];
+	struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog);
+
+	if (xdp_prog)
+		dring->is_xdp = true;
+	else
+		dring->is_xdp = false;
+}
+
 static int netsec_setup_rx_dring(struct netsec_priv *priv)
 {
 	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
-	int i;
+	struct bpf_prog *xdp_prog = READ_ONCE(priv->xdp_prog);
+	int i, err;
+
+	if (xdp_prog)
+		dring->is_xdp = true;
+	else
+		dring->is_xdp = false;
 
 	for (i = 0; i < DESC_NUM; i++) {
 		struct netsec_desc *desc = &dring->desc[i];
@@ -1002,20 +1105,29 @@ static int netsec_setup_rx_dring(struct netsec_priv *priv)
 		u16 len;
 
 		buf = netsec_alloc_rx_data(priv, &dma_handle, &len);
-		if (!buf) {
-			netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
+		if (!buf)
 			goto err_out;
-		}
 		desc->dma_addr = dma_handle;
 		desc->addr = buf;
 		desc->len = len;
 	}
 
 	netsec_rx_fill(priv, 0, DESC_NUM);
+	err = xdp_rxq_info_reg(&dring->xdp_rxq, priv->ndev, 0);
+	if (err)
+		goto err_out;
+
+	err = xdp_rxq_info_reg_mem_model(&dring->xdp_rxq, MEM_TYPE_PAGE_SHARED,
+					 NULL);
+	if (err) {
+		xdp_rxq_info_unreg(&dring->xdp_rxq);
+		goto err_out;
+	}
 
 	return 0;
 
 err_out:
+	netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
 	return -ENOMEM;
 }
 
@@ -1290,6 +1402,7 @@ static int netsec_netdev_open(struct net_device *ndev)
 
 	pm_runtime_get_sync(priv->dev);
 
+	netsec_setup_tx_dring(priv);
 	ret = netsec_setup_rx_dring(priv);
 	if (ret) {
 		netif_err(priv, probe, priv->ndev,
@@ -1387,6 +1500,9 @@ static int netsec_netdev_init(struct net_device *ndev)
 	if (ret)
 		goto err2;
 
+	spin_lock_init(&priv->desc_ring[NETSEC_RING_TX].lock);
+	spin_lock_init(&priv->desc_ring[NETSEC_RING_RX].lock);
+
 	return 0;
 err2:
 	netsec_free_dring(priv, NETSEC_RING_RX);
@@ -1419,6 +1535,179 @@ static int netsec_netdev_ioctl(struct net_device *ndev, struct ifreq *ifr,
 	return phy_mii_ioctl(ndev->phydev, ifr, cmd);
 }
 
+/* The current driver only supports 1 Txq, this should run under spin_lock() */
+static u32 netsec_xdp_queue_one(struct netsec_priv *priv,
+				struct xdp_frame *xdpf)
+
+{
+	struct netsec_desc_ring *tx_ring = &priv->desc_ring[NETSEC_RING_TX];
+	struct netsec_tx_pkt_ctrl tx_ctrl = {};
+	struct netsec_desc tx_desc;
+	dma_addr_t dma_handle;
+	u16 filled;
+
+	if (tx_ring->head >= tx_ring->tail)
+		filled = tx_ring->head - tx_ring->tail;
+	else
+		filled = tx_ring->head + DESC_NUM - tx_ring->tail;
+
+	if (DESC_NUM - filled <= 1)
+		return NETSEC_XDP_CONSUMED;
+
+	dma_handle = dma_map_single(priv->dev, xdpf->data, xdpf->len,
+				    DMA_TO_DEVICE);
+	if (dma_mapping_error(priv->dev, dma_handle))
+		return NETSEC_XDP_CONSUMED;
+
+	tx_ctrl.cksum_offload_flag = false;
+	tx_ctrl.tcp_seg_offload_flag = false;
+	tx_ctrl.tcp_seg_len = 0;
+
+	tx_desc.dma_addr = dma_handle;
+	tx_desc.addr = xdpf->data;
+	tx_desc.len = xdpf->len;
+
+	netsec_set_tx_de(priv, tx_ring, &tx_ctrl, &tx_desc, NULL);
+
+	return NETSEC_XDP_TX;
+}
+
+static int netsec_xdp_xmit(struct net_device *ndev, int n,
+			   struct xdp_frame **frames, u32 flags)
+{
+	struct netsec_priv *priv = netdev_priv(ndev);
+	struct netsec_desc_ring *tx_ring = &priv->desc_ring[NETSEC_RING_TX];
+	int drops = 0;
+	int i;
+
+	if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+		return -EINVAL;
+
+	spin_lock(&tx_ring->lock);
+	for (i = 0; i < n; i++) {
+		struct xdp_frame *xdpf = frames[i];
+		int err;
+
+		err = netsec_xdp_queue_one(priv, xdpf);
+		if (err != NETSEC_XDP_TX) {
+			xdp_return_frame_rx_napi(xdpf);
+			drops++;
+		} else {
+			tx_ring->xdp_xmit++;
+		}
+	}
+	spin_unlock(&tx_ring->lock);
+
+	if (unlikely(flags & XDP_XMIT_FLUSH)) {
+		netsec_xdp_ring_tx_db(priv, tx_ring->xdp_xmit);
+		tx_ring->xdp_xmit = 0;
+	}
+
+	return n - drops;
+}
+
+static u32 netsec_xdp_xmit_back(struct netsec_priv *priv, struct xdp_buff *xdp)
+{
+	struct netsec_desc_ring *tx_ring = &priv->desc_ring[NETSEC_RING_TX];
+	struct xdp_frame *xdpf = convert_to_xdp_frame(xdp);
+	u32 ret;
+
+	if (unlikely(!xdpf))
+		return NETSEC_XDP_CONSUMED;
+
+	spin_lock(&tx_ring->lock);
+	ret = netsec_xdp_queue_one(priv, xdpf);
+	spin_unlock(&tx_ring->lock);
+
+	return ret;
+}
+
+static u32 netsec_run_xdp(struct netsec_priv *priv, struct bpf_prog *prog,
+			  struct xdp_buff *xdp)
+{
+	u32 ret = NETSEC_XDP_PASS;
+	int err;
+	u32 act;
+
+	rcu_read_lock();
+	act = bpf_prog_run_xdp(prog, xdp);
+
+	switch (act) {
+	case XDP_PASS:
+		ret = NETSEC_XDP_PASS;
+		break;
+	case XDP_TX:
+		ret = netsec_xdp_xmit_back(priv, xdp);
+		if (ret != NETSEC_XDP_TX)
+			xdp_return_buff(xdp);
+		break;
+	case XDP_REDIRECT:
+		err = xdp_do_redirect(priv->ndev, xdp, prog);
+		if (!err) {
+			ret = NETSEC_XDP_REDIR;
+		} else {
+			ret = NETSEC_XDP_CONSUMED;
+			xdp_return_buff(xdp);
+		}
+		break;
+	default:
+		bpf_warn_invalid_xdp_action(act);
+		/* fall through */
+	case XDP_ABORTED:
+		trace_xdp_exception(priv->ndev, prog, act);
+		/* fall through -- handle aborts by dropping packet */
+	case XDP_DROP:
+		ret = NETSEC_XDP_CONSUMED;
+		xdp_return_buff(xdp);
+		break;
+	}
+
+	rcu_read_unlock();
+
+	return ret;
+}
+
+static int netsec_xdp_setup(struct netsec_priv *priv, struct bpf_prog *prog,
+			    struct netlink_ext_ack *extack)
+{
+	struct net_device *dev = priv->ndev;
+	struct bpf_prog *old_prog;
+
+	/* For now just support only the usual MTU sized frames */
+	if (prog && dev->mtu > 1500) {
+		NL_SET_ERR_MSG_MOD(extack, "Jumbo frames not supported on XDP");
+		return -EOPNOTSUPP;
+	}
+
+	if (netif_running(dev))
+		netsec_netdev_stop(dev);
+
+	/* Detach old prog, if any */
+	old_prog = xchg(&priv->xdp_prog, prog);
+	if (old_prog)
+		bpf_prog_put(old_prog);
+
+	if (netif_running(dev))
+		netsec_netdev_open(dev);
+
+	return 0;
+}
+
+static int netsec_xdp(struct net_device *ndev, struct netdev_bpf *xdp)
+{
+	struct netsec_priv *priv = netdev_priv(ndev);
+
+	switch (xdp->command) {
+	case XDP_SETUP_PROG:
+		return netsec_xdp_setup(priv, xdp->prog, xdp->extack);
+	case XDP_QUERY_PROG:
+		xdp->prog_id = priv->xdp_prog ? priv->xdp_prog->aux->id : 0;
+		return 0;
+	default:
+		return -EINVAL;
+	}
+}
+
 static const struct net_device_ops netsec_netdev_ops = {
 	.ndo_init		= netsec_netdev_init,
 	.ndo_uninit		= netsec_netdev_uninit,
@@ -1429,6 +1718,8 @@ static const struct net_device_ops netsec_netdev_ops = {
 	.ndo_set_mac_address    = eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= netsec_netdev_ioctl,
+	.ndo_xdp_xmit		= netsec_xdp_xmit,
+	.ndo_bpf		= netsec_xdp,
 };
 
 static int netsec_of_probe(struct platform_device *pdev,
-- 
2.7.4

^ permalink raw reply related

* [net-next, PATCH 1/2, v3] net: socionext: different approach on DMA
From: Ilias Apalodimas @ 2018-09-29 11:28 UTC (permalink / raw)
  To: netdev, jaswinder.singh
  Cc: ard.biesheuvel, masami.hiramatsu, arnd, bjorn.topel,
	magnus.karlsson, brouer, daniel, ast, jesus.sanchez-palencia,
	vinicius.gomes, makita.toshiaki, Ilias Apalodimas
In-Reply-To: <1538220482-16129-1-git-send-email-ilias.apalodimas@linaro.org>

Current driver dynamically allocates an skb and maps it as DMA rx buffer.
A following patch introduces XDP functionality, so we need a
different allocation scheme. Buffers are allocated dynamically and
mapped into hardware. During the Rx operation the driver uses
build_skb() to produce the necessary buffers for the network stack

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
---
 drivers/net/ethernet/socionext/netsec.c | 238 +++++++++++++++++---------------
 1 file changed, 129 insertions(+), 109 deletions(-)

diff --git a/drivers/net/ethernet/socionext/netsec.c b/drivers/net/ethernet/socionext/netsec.c
index 7aa5ebb..8f788a1 100644
--- a/drivers/net/ethernet/socionext/netsec.c
+++ b/drivers/net/ethernet/socionext/netsec.c
@@ -296,6 +296,11 @@ struct netsec_rx_pkt_info {
 	bool err_flag;
 };
 
+static void netsec_rx_fill(struct netsec_priv *priv, u16 from, u16 num);
+
+static void *netsec_alloc_rx_data(struct netsec_priv *priv,
+				  dma_addr_t *dma_addr, u16 *len);
+
 static void netsec_write(struct netsec_priv *priv, u32 reg_addr, u32 val)
 {
 	writel(val, priv->ioaddr + reg_addr);
@@ -556,34 +561,10 @@ static const struct ethtool_ops netsec_ethtool_ops = {
 
 /************* NETDEV_OPS FOLLOW *************/
 
-static struct sk_buff *netsec_alloc_skb(struct netsec_priv *priv,
-					struct netsec_desc *desc)
-{
-	struct sk_buff *skb;
-
-	if (device_get_dma_attr(priv->dev) == DEV_DMA_COHERENT) {
-		skb = netdev_alloc_skb_ip_align(priv->ndev, desc->len);
-	} else {
-		desc->len = L1_CACHE_ALIGN(desc->len);
-		skb = netdev_alloc_skb(priv->ndev, desc->len);
-	}
-	if (!skb)
-		return NULL;
-
-	desc->addr = skb->data;
-	desc->dma_addr = dma_map_single(priv->dev, desc->addr, desc->len,
-					DMA_FROM_DEVICE);
-	if (dma_mapping_error(priv->dev, desc->dma_addr)) {
-		dev_kfree_skb_any(skb);
-		return NULL;
-	}
-	return skb;
-}
 
 static void netsec_set_rx_de(struct netsec_priv *priv,
 			     struct netsec_desc_ring *dring, u16 idx,
-			     const struct netsec_desc *desc,
-			     struct sk_buff *skb)
+			     const struct netsec_desc *desc)
 {
 	struct netsec_de *de = dring->vaddr + DESC_SZ * idx;
 	u32 attr = (1 << NETSEC_RX_PKT_OWN_FIELD) |
@@ -602,59 +583,6 @@ static void netsec_set_rx_de(struct netsec_priv *priv,
 	dring->desc[idx].dma_addr = desc->dma_addr;
 	dring->desc[idx].addr = desc->addr;
 	dring->desc[idx].len = desc->len;
-	dring->desc[idx].skb = skb;
-}
-
-static struct sk_buff *netsec_get_rx_de(struct netsec_priv *priv,
-					struct netsec_desc_ring *dring,
-					u16 idx,
-					struct netsec_rx_pkt_info *rxpi,
-					struct netsec_desc *desc, u16 *len)
-{
-	struct netsec_de de = {};
-
-	memcpy(&de, dring->vaddr + DESC_SZ * idx, DESC_SZ);
-
-	*len = de.buf_len_info >> 16;
-
-	rxpi->err_flag = (de.attr >> NETSEC_RX_PKT_ER_FIELD) & 1;
-	rxpi->rx_cksum_result = (de.attr >> NETSEC_RX_PKT_CO_FIELD) & 3;
-	rxpi->err_code = (de.attr >> NETSEC_RX_PKT_ERR_FIELD) &
-							NETSEC_RX_PKT_ERR_MASK;
-	*desc = dring->desc[idx];
-	return desc->skb;
-}
-
-static struct sk_buff *netsec_get_rx_pkt_data(struct netsec_priv *priv,
-					      struct netsec_rx_pkt_info *rxpi,
-					      struct netsec_desc *desc,
-					      u16 *len)
-{
-	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
-	struct sk_buff *tmp_skb, *skb = NULL;
-	struct netsec_desc td;
-	int tail;
-
-	*rxpi = (struct netsec_rx_pkt_info){};
-
-	td.len = priv->ndev->mtu + 22;
-
-	tmp_skb = netsec_alloc_skb(priv, &td);
-
-	tail = dring->tail;
-
-	if (!tmp_skb) {
-		netsec_set_rx_de(priv, dring, tail, &dring->desc[tail],
-				 dring->desc[tail].skb);
-	} else {
-		skb = netsec_get_rx_de(priv, dring, tail, rxpi, desc, len);
-		netsec_set_rx_de(priv, dring, tail, &td, tmp_skb);
-	}
-
-	/* move tail ahead */
-	dring->tail = (dring->tail + 1) % DESC_NUM;
-
-	return skb;
 }
 
 static int netsec_clean_tx_dring(struct netsec_priv *priv, int budget)
@@ -721,19 +649,28 @@ static int netsec_process_tx(struct netsec_priv *priv, int budget)
 	return done;
 }
 
+static void netsec_adv_desc(u16 *idx)
+{
+	*idx = *idx + 1;
+	if (unlikely(*idx >= DESC_NUM))
+		*idx = 0;
+}
+
 static int netsec_process_rx(struct netsec_priv *priv, int budget)
 {
 	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
 	struct net_device *ndev = priv->ndev;
-	struct netsec_rx_pkt_info rx_info;
-	int done = 0;
-	struct netsec_desc desc;
 	struct sk_buff *skb;
-	u16 len;
+	int done = 0;
 
 	while (done < budget) {
 		u16 idx = dring->tail;
 		struct netsec_de *de = dring->vaddr + (DESC_SZ * idx);
+		struct netsec_desc *desc = &dring->desc[idx];
+		struct netsec_rx_pkt_info rpi;
+		u16 pkt_len, desc_len;
+		dma_addr_t dma_handle;
+		void *buf_addr;
 
 		if (de->attr & (1U << NETSEC_RX_PKT_OWN_FIELD))
 			break;
@@ -744,28 +681,62 @@ static int netsec_process_rx(struct netsec_priv *priv, int budget)
 		 */
 		dma_rmb();
 		done++;
-		skb = netsec_get_rx_pkt_data(priv, &rx_info, &desc, &len);
-		if (unlikely(!skb) || rx_info.err_flag) {
+
+		pkt_len = de->buf_len_info >> 16;
+		rpi.err_code = (de->attr >> NETSEC_RX_PKT_ERR_FIELD) &
+			NETSEC_RX_PKT_ERR_MASK;
+		rpi.err_flag = (de->attr >> NETSEC_RX_PKT_ER_FIELD) & 1;
+		if (rpi.err_flag) {
 			netif_err(priv, drv, priv->ndev,
-				  "%s: rx fail err(%d)\n",
-				  __func__, rx_info.err_code);
+				  "%s: rx fail err(%d)\n", __func__,
+				  rpi.err_code);
 			ndev->stats.rx_dropped++;
+			netsec_adv_desc(&dring->tail);
+			/* reuse buffer page frag */
+			netsec_rx_fill(priv, idx, 1);
 			continue;
 		}
+		rpi.rx_cksum_result = (de->attr >> NETSEC_RX_PKT_CO_FIELD) & 3;
 
-		dma_unmap_single(priv->dev, desc.dma_addr, desc.len,
-				 DMA_FROM_DEVICE);
-		skb_put(skb, len);
+		buf_addr = netsec_alloc_rx_data(priv, &dma_handle, &desc_len);
+		if (unlikely(!buf_addr))
+			break;
+
+		dma_sync_single_for_cpu(priv->dev, desc->dma_addr, pkt_len,
+					DMA_FROM_DEVICE);
+		prefetch(desc->addr);
+
+		skb = build_skb(desc->addr, desc->len);
+		if (unlikely(!skb)) {
+			dma_unmap_single(priv->dev, dma_handle, desc_len,
+					 DMA_TO_DEVICE);
+			skb_free_frag(buf_addr);
+			netif_err(priv, drv, priv->ndev,
+				  "rx failed to alloc skb\n");
+			break;
+		}
+		dma_unmap_single_attrs(priv->dev, desc->dma_addr, desc->len,
+				       DMA_TO_DEVICE, DMA_ATTR_SKIP_CPU_SYNC);
+
+		/* Update the descriptor with fresh buffers */
+		desc->len = desc_len;
+		desc->dma_addr = dma_handle;
+		desc->addr = buf_addr;
+
+		skb_put(skb, pkt_len);
 		skb->protocol = eth_type_trans(skb, priv->ndev);
 
 		if (priv->rx_cksum_offload_flag &&
-		    rx_info.rx_cksum_result == NETSEC_RX_CKSUM_OK)
+		    rpi.rx_cksum_result == NETSEC_RX_CKSUM_OK)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		if (napi_gro_receive(&priv->napi, skb) != GRO_DROP) {
 			ndev->stats.rx_packets++;
-			ndev->stats.rx_bytes += len;
+			ndev->stats.rx_bytes += pkt_len;
 		}
+
+		netsec_rx_fill(priv, idx, 1);
+		netsec_adv_desc(&dring->tail);
 	}
 
 	return done;
@@ -928,7 +899,10 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id)
 		dma_unmap_single(priv->dev, desc->dma_addr, desc->len,
 				 id == NETSEC_RING_RX ? DMA_FROM_DEVICE :
 							      DMA_TO_DEVICE);
-		dev_kfree_skb(desc->skb);
+		if (id == NETSEC_RING_RX)
+			skb_free_frag(desc->addr);
+		else if (id == NETSEC_RING_TX)
+			dev_kfree_skb(desc->skb);
 	}
 
 	memset(dring->desc, 0, sizeof(struct netsec_desc) * DESC_NUM);
@@ -953,50 +927,96 @@ static void netsec_free_dring(struct netsec_priv *priv, int id)
 	dring->desc = NULL;
 }
 
+static void *netsec_alloc_rx_data(struct netsec_priv *priv,
+				  dma_addr_t *dma_handle, u16 *desc_len)
+{
+	size_t len = priv->ndev->mtu + ETH_HLEN + 2 * VLAN_HLEN + NET_SKB_PAD +
+		NET_IP_ALIGN;
+	dma_addr_t mapping;
+	void *buf;
+
+	len += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
+	len = SKB_DATA_ALIGN(len);
+
+	buf = napi_alloc_frag(len);
+	if (!buf)
+		return NULL;
+
+	mapping = dma_map_single(priv->dev, buf, len, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, mapping)))
+		goto err_out;
+
+	*dma_handle = mapping;
+	*desc_len = len;
+
+	return buf;
+
+err_out:
+	skb_free_frag(buf);
+	return NULL;
+}
+
+static void netsec_rx_fill(struct netsec_priv *priv, u16 from, u16 num)
+{
+	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
+	u16 idx = from;
+
+	while (num) {
+		netsec_set_rx_de(priv, dring, idx, &dring->desc[idx]);
+		idx++;
+		if (idx >= DESC_NUM)
+			idx = 0;
+		num--;
+	}
+}
+
 static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
 {
 	struct netsec_desc_ring *dring = &priv->desc_ring[id];
-	int ret = 0;
 
 	dring->vaddr = dma_zalloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
 					   &dring->desc_dma, GFP_KERNEL);
-	if (!dring->vaddr) {
-		ret = -ENOMEM;
+	if (!dring->vaddr)
 		goto err;
-	}
 
 	dring->desc = kcalloc(DESC_NUM, sizeof(*dring->desc), GFP_KERNEL);
-	if (!dring->desc) {
-		ret = -ENOMEM;
+	if (!dring->desc)
 		goto err;
-	}
 
 	return 0;
 err:
 	netsec_free_dring(priv, id);
 
-	return ret;
+	return -ENOMEM;
 }
 
 static int netsec_setup_rx_dring(struct netsec_priv *priv)
 {
 	struct netsec_desc_ring *dring = &priv->desc_ring[NETSEC_RING_RX];
-	struct netsec_desc desc;
-	struct sk_buff *skb;
-	int n;
+	int i;
 
-	desc.len = priv->ndev->mtu + 22;
+	for (i = 0; i < DESC_NUM; i++) {
+		struct netsec_desc *desc = &dring->desc[i];
+		dma_addr_t dma_handle;
+		void *buf;
+		u16 len;
 
-	for (n = 0; n < DESC_NUM; n++) {
-		skb = netsec_alloc_skb(priv, &desc);
-		if (!skb) {
+		buf = netsec_alloc_rx_data(priv, &dma_handle, &len);
+		if (!buf) {
 			netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
-			return -ENOMEM;
+			goto err_out;
 		}
-		netsec_set_rx_de(priv, dring, n, &desc, skb);
+		desc->dma_addr = dma_handle;
+		desc->addr = buf;
+		desc->len = len;
 	}
 
+	netsec_rx_fill(priv, 0, DESC_NUM);
+
 	return 0;
+
+err_out:
+	return -ENOMEM;
 }
 
 static int netsec_netdev_load_ucode_region(struct netsec_priv *priv, u32 reg,
-- 
2.7.4

^ permalink raw reply related

* [net-next, PATCH 0/2, v3] net: socionext: XDP support
From: Ilias Apalodimas @ 2018-09-29 11:28 UTC (permalink / raw)
  To: netdev, jaswinder.singh
  Cc: ard.biesheuvel, masami.hiramatsu, arnd, bjorn.topel,
	magnus.karlsson, brouer, daniel, ast, jesus.sanchez-palencia,
	vinicius.gomes, makita.toshiaki, Ilias Apalodimas

This patch series adds AF_XDP support socionext netsec driver
In addition the new dma allocation scheme offers a 10% boost on Rx
pps rate using 64b packets

- patch [1/2]: Use a different allocation scheme for Rx DMA buffers to 
  prepare the driver for AF_XDP support
- patch [2/2]: Add XDP support without zero-copy

test and performance numbers (64b packets):
-------------------------------------------
- Normal SKBs on Rx: ~217kpps
test: pktgen -> intel i210 -> netsec -> XDP_TX/XDP_REDIRECT
- XDP_TX: 320kpps
- XDP_REDIRECT: 320kpps

qemu -> pktgen -> virtio -> ndo_xdp_xmit -> netsec
- ndo_xdp_xmit: Could not send more than 120kpps. Interface forwarded that 
                with success

Changes since v2:
 - Always allocate Rx buffers with XDP_PACKET_HEADROOM
 
 Björn Töpel:
 - Added locking in the Tx queue

 Jesper Dangaard Brouer:
 - Added support for .ndo_xdp_xmit
 - XDP_TX does not flush every packet

Changes since v1:
- patch [2/2]:
 Toshiaki Makita:
 - Added XDP_PACKET_HEADROOM
 - Fixed a bug on XDP_PASS case
 - Using extact for error messaging instead of netdev_warn, when
   trying to setup XDP

Ilias Apalodimas (2):
  net: socionext: different approach on DMA
  net: socionext: add XDP support

 drivers/net/ethernet/socionext/netsec.c | 541 +++++++++++++++++++++++++-------
 1 file changed, 426 insertions(+), 115 deletions(-)

-- 
2.7.4

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox