* [PATCH v2] selftests: net: add in_netns.sh TEST_GEN_PROGS_EXTENDED
From: Anders Roxell @ 2018-04-25 21:32 UTC (permalink / raw)
To: davem, shuah; +Cc: netdev, linux-kselftest, linux-kernel, Anders Roxell
In-Reply-To: <20180425.132513.1786379382285267245.davem@davemloft.net>
Script in_netns.sh is a utility function and not its own test so it
shouldn't be part of the TEST_PROGS. The in_netns.sh get used by
run_afpackettests.
To install in_netns.sh without being added to the main run_kselftest.sh
script use the TEST_GEN_PROGS_EXTENDED variable.
Fixes: 5ff9c1a3dd92 ("selftests: net: add in_netns.sh to TEST_PROGS")
Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
---
respin against the 'net' tree.
tools/testing/selftests/net/Makefile | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 8f1e13d2e547..daf5effec3f0 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -5,7 +5,8 @@ CFLAGS = -Wall -Wl,--no-as-needed -O2 -g
CFLAGS += -I../../../../usr/include/
TEST_PROGS := run_netsocktests run_afpackettests test_bpf.sh netdevice.sh rtnetlink.sh
-TEST_PROGS += fib_tests.sh fib-onlink-tests.sh in_netns.sh pmtu.sh
+TEST_PROGS += fib_tests.sh fib-onlink-tests.sh pmtu.sh
+TEST_GEN_PROGS_EXTENDED := in_netns.sh
TEST_GEN_FILES = socket
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy
TEST_GEN_PROGS = reuseport_bpf reuseport_bpf_cpu reuseport_bpf_numa
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Siwei Liu @ 2018-04-25 21:38 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Alexander Duyck, virtio-dev, Jiri Pirko, Jakub Kicinski,
Sridhar Samudrala, virtualization, Netdev, David Miller
In-Reply-To: <20180423230037-mutt-send-email-mst@kernel.org>
On Mon, Apr 23, 2018 at 1:06 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Mon, Apr 23, 2018 at 12:44:39PM -0700, Siwei Liu wrote:
>> On Mon, Apr 23, 2018 at 10:56 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > On Mon, Apr 23, 2018 at 10:44:40AM -0700, Stephen Hemminger wrote:
>> >> On Mon, 23 Apr 2018 20:24:56 +0300
>> >> "Michael S. Tsirkin" <mst@redhat.com> wrote:
>> >>
>> >> > On Mon, Apr 23, 2018 at 10:04:06AM -0700, Stephen Hemminger wrote:
>> >> > > > >
>> >> > > > >I will NAK patches to change to common code for netvsc especially the
>> >> > > > >three device model. MS worked hard with distro vendors to support transparent
>> >> > > > >mode, ans we really can't have a new model; or do backport.
>> >> > > > >
>> >> > > > >Plus, DPDK is now dependent on existing model.
>> >> > > >
>> >> > > > Sorry, but nobody here cares about dpdk or other similar oddities.
>> >> > >
>> >> > > The network device model is a userspace API, and DPDK is a userspace application.
>> >> >
>> >> > It is userspace but are you sure dpdk is actually poking at netdevs?
>> >> > AFAIK it's normally banging device registers directly.
>> >> >
>> >> > > You can't go breaking userspace even if you don't like the application.
>> >> >
>> >> > Could you please explain how is the proposed patchset breaking
>> >> > userspace? Ignoring DPDK for now, I don't think it changes the userspace
>> >> > API at all.
>> >> >
>> >>
>> >> The DPDK has a device driver vdev_netvsc which scans the Linux network devices
>> >> to look for Linux netvsc device and the paired VF device and setup the
>> >> DPDK environment. This setup creates a DPDK failsafe (bondingish) instance
>> >> and sets up TAP support over the Linux netvsc device as well as the Mellanox
>> >> VF device.
>> >>
>> >> So it depends on existing 2 device model. You can't go to a 3 device model
>> >> or start hiding devices from userspace.
>> >
>> > Okay so how does the existing patch break that? IIUC does not go to
>> > a 3 device model since netvsc calls failover_register directly.
>> >
>> >> Also, I am working on associating netvsc and VF device based on serial number
>> >> rather than MAC address. The serial number is how Windows works now, and it makes
>> >> sense for Linux and Windows to use the same mechanism if possible.
>> >
>> > Maybe we should support same for virtio ...
>> > Which serial do you mean? From vpd?
>> >
>> > I guess you will want to keep supporting MAC for old hypervisors?
>> >
>> > It all seems like a reasonable thing to support in the generic core.
>>
>> That's the reason why I chose explicit identifier rather than rely on
>> MAC address to bind/pair a device. MAC address can change. Even if it
>> can't, malicious guest user can fake MAC address to skip binding.
>>
>> -Siwei
>
> Address should be sampled at device creation to prevent this
> kind of hack. Not that it buys the malicious user much:
> if you can poke at MAC addresses you probably already can
> break networking.
I don't understand why poking at MAC address may potentially break
networking. Unlike VF, passthrough PCI endpoint device has its freedom
to change the MAC address. Even on a VF setup it's not neccessarily
always safe to assume the VF's MAC address cannot or shouldn't be
changed. That depends on the specific need whether the host admin
wants to restrict guest from changing the MAC address, although in
most cases it's true.
I understand we can use the perm_addr to distinguish. But as said,
this will pose limitation of flexible configuration where one can
assign VFs with identical MAC address at all while each VF belongs to
different PF and/or different subnet for e.g. load balancing. And
furthermore, the QEMU device model never uses MAC address to be
interpreted as an identifier, which requires to be unique per VM
instance. Why we're introducing this inconsistency?
-Siwei
>
>
>
>
>>
>> >
>> > --
>> > MST
^ permalink raw reply
* Re: [PATCH][net-next] net: ip tos cgroup
From: kbuild test robot @ 2018-04-25 21:39 UTC (permalink / raw)
To: Li RongQing; +Cc: kbuild-all, netdev
In-Reply-To: <1523936161-11676-1-git-send-email-lirongqing@baidu.com>
[-- Attachment #1: Type: text/plain, Size: 1241 bytes --]
Hi Li,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net/master]
[also build test ERROR on v4.17-rc2 next-20180424]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Li-RongQing/net-ip-tos-cgroup/20180417-204807
config: arm-dove_defconfig (attached as .config)
compiler: arm-linux-gnueabi-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm
All errors (new ones prefixed by >>):
In file included from net/ipv4/af_inet.c:123:0:
>> include/net/tos_cgroup.h:10:29: error: field 'css' has incomplete type
struct cgroup_subsys_state css;
^~~
vim +/css +10 include/net/tos_cgroup.h
8
9 struct tos_cgroup_state {
> 10 struct cgroup_subsys_state css;
11 u32 tos;
12 };
13
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 17596 bytes --]
^ permalink raw reply
* Re: [bpf PATCH v2] bpf: fix for lex/yacc build error with gcc-5
From: Daniel Borkmann @ 2018-04-25 21:42 UTC (permalink / raw)
To: John Fastabend, ast, jbenc; +Cc: netdev
In-Reply-To: <20180425212245.25999.21181.stgit@john-Precision-Tower-5810>
On 04/25/2018 11:22 PM, John Fastabend wrote:
> Fix build error found with Ubuntu shipped gcc-5
>
> ~/git/bpf/tools/bpf$ make all
>
> Auto-detecting system features:
> ... libbfd: [ OFF ]
> ... disassembler-four-args: [ OFF ]
>
> CC bpf_jit_disasm.o
> LINK bpf_jit_disasm
> CC bpf_dbg.o
> /home/john/git/bpf/tools/bpf/bpf_dbg.c: In function ‘cmd_load’:
> /home/john/git/bpf/tools/bpf/bpf_dbg.c:1077:13: warning: ‘cont’ may be used uninitialized in this function [-Wmaybe-uninitialized]
> } else if (matches(subcmd, "pcap") == 0) {
> ^
> LINK bpf_dbg
> CC bpf_asm.o
> make: *** No rule to make target `bpf_exp.yacc.o', needed by `bpf_asm'. Stop.
>
> Fixes: 5a8997f20715 ("tools: bpf: respect output directory during build")
> Signed-off-by: John Fastabend <john.fastabend@gmail.com>
Applied to bpf, thanks John! Will see to get that annoying bpf_dbg warn out
of the way if no one beats me to it. ;)
^ permalink raw reply
* [PATCH v2 net-next 0/2] tcp: mmap: rework zerocopy receive
From: Eric Dumazet @ 2018-04-25 21:43 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Andy Lutomirski, linux-kernel, linux-mm, Eric Dumazet,
Eric Dumazet
syzbot reported a lockdep issue caused by tcp mmap() support.
I implemented Andy Lutomirski nice suggestions to resolve the
issue and increase scalability as well.
First patch is adding a new setsockopt() operation and changes mmap()
behavior.
Second patch changes tcp_mmap reference program.
v2:
Added a missing page align of zc->length in tcp_zerocopy_receive()
Properly clear zc->recv_skip_hint in case user request was completed.
Eric Dumazet (2):
tcp: add TCP_ZEROCOPY_RECEIVE support for zerocopy receive
selftests: net: tcp_mmap must use TCP_ZEROCOPY_RECEIVE
include/uapi/linux/tcp.h | 8 ++
net/ipv4/tcp.c | 189 +++++++++++++------------
tools/testing/selftests/net/tcp_mmap.c | 63 +++++----
3 files changed, 142 insertions(+), 118 deletions(-)
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply
* [PATCH v2 net-next 1/2] tcp: add TCP_ZEROCOPY_RECEIVE support for zerocopy receive
From: Eric Dumazet @ 2018-04-25 21:43 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Andy Lutomirski, linux-kernel, linux-mm, Eric Dumazet,
Eric Dumazet, Soheil Hassas Yeganeh
In-Reply-To: <20180425214307.159264-1-edumazet@google.com>
When adding tcp mmap() implementation, I forgot that socket lock
had to be taken before current->mm->mmap_sem. syzbot eventually caught
the bug.
Since we can not lock the socket in tcp mmap() handler we have to
split the operation in two phases.
1) mmap() on a tcp socket simply reserves VMA space, and nothing else.
This operation does not involve any TCP locking.
2) setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) implements
the transfert of pages from skbs to one VMA.
This operation only uses down_read(¤t->mm->mmap_sem) after
holding TCP lock, thus solving the lockdep issue.
This new implementation was suggested by Andy Lutomirski with great details.
Benefits are :
- Better scalability, in case multiple threads reuse VMAS
(without mmap()/munmap() calls) since mmap_sem wont be write locked.
- Better error recovery.
The previous mmap() model had to provide the expected size of the
mapping. If for some reason one part could not be mapped (partial MSS),
the whole operation had to be aborted.
With the tcp_zerocopy_receive struct, kernel can report how
many bytes were successfuly mapped, and how many bytes should
be read to skip the problematic sequence.
- No more memory allocation to hold an array of page pointers.
16 MB mappings needed 32 KB for this array, potentially using vmalloc() :/
- skbs are freed while mmap_sem has been released
Following patch makes the change in tcp_mmap tool to demonstrate
one possible use of mmap() and setsockopt(... TCP_ZEROCOPY_RECEIVE ...)
Note that memcg might require additional changes.
Fixes: 93ab6cc69162 ("tcp: implement mmap() for zero copy receive")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Suggested-by: Andy Lutomirski <luto@kernel.org>
Cc: linux-mm@kvack.org
Cc: Soheil Hassas Yeganeh <soheil@google.com>
---
include/uapi/linux/tcp.h | 8 ++
net/ipv4/tcp.c | 189 ++++++++++++++++++++-------------------
2 files changed, 106 insertions(+), 91 deletions(-)
diff --git a/include/uapi/linux/tcp.h b/include/uapi/linux/tcp.h
index 379b08700a542d49bbce9b4b49b17879d00b69bb..e9e8373b34b9ddc735329341b91f455bf5c0b17c 100644
--- a/include/uapi/linux/tcp.h
+++ b/include/uapi/linux/tcp.h
@@ -122,6 +122,7 @@ enum {
#define TCP_MD5SIG_EXT 32 /* TCP MD5 Signature with extensions */
#define TCP_FASTOPEN_KEY 33 /* Set the key for Fast Open (cookie) */
#define TCP_FASTOPEN_NO_COOKIE 34 /* Enable TFO without a TFO cookie */
+#define TCP_ZEROCOPY_RECEIVE 35
struct tcp_repair_opt {
__u32 opt_code;
@@ -276,4 +277,11 @@ struct tcp_diag_md5sig {
__u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN];
};
+/* setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...) */
+
+struct tcp_zerocopy_receive {
+ __u64 address; /* in: address of mapping */
+ __u32 length; /* in/out: number of bytes to map/mapped */
+ __u32 recv_skip_hint; /* out: amount of bytes to skip */
+};
#endif /* _UAPI_LINUX_TCP_H */
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index dfd090ea54ad47112fc23c61180b5bf8edd2c736..9b9cbb837ff8d6cdd85515429f699e113c55b37b 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1726,118 +1726,111 @@ int tcp_set_rcvlowat(struct sock *sk, int val)
}
EXPORT_SYMBOL(tcp_set_rcvlowat);
-/* When user wants to mmap X pages, we first need to perform the mapping
- * before freeing any skbs in receive queue, otherwise user would be unable
- * to fallback to standard recvmsg(). This happens if some data in the
- * requested block is not exactly fitting in a page.
- *
- * We only support order-0 pages for the moment.
- * mmap() on TCP is very strict, there is no point
- * trying to accommodate with pathological layouts.
- */
+static const struct vm_operations_struct tcp_vm_ops = {
+};
+
int tcp_mmap(struct file *file, struct socket *sock,
struct vm_area_struct *vma)
{
- unsigned long size = vma->vm_end - vma->vm_start;
- unsigned int nr_pages = size >> PAGE_SHIFT;
- struct page **pages_array = NULL;
- u32 seq, len, offset, nr = 0;
- struct sock *sk = sock->sk;
- const skb_frag_t *frags;
+ if (vma->vm_flags & (VM_WRITE | VM_EXEC))
+ return -EPERM;
+ vma->vm_flags &= ~(VM_MAYWRITE | VM_MAYEXEC);
+
+ /* Instruct vm_insert_page() to not down_read(mmap_sem) */
+ vma->vm_flags |= VM_MIXEDMAP;
+
+ vma->vm_ops = &tcp_vm_ops;
+ return 0;
+}
+EXPORT_SYMBOL(tcp_mmap);
+
+static int tcp_zerocopy_receive(struct sock *sk,
+ struct tcp_zerocopy_receive *zc)
+{
+ unsigned long address = (unsigned long)zc->address;
+ const skb_frag_t *frags = NULL;
+ u32 length = 0, seq, offset;
+ struct vm_area_struct *vma;
+ struct sk_buff *skb = NULL;
struct tcp_sock *tp;
- struct sk_buff *skb;
int ret;
- if (vma->vm_pgoff || !nr_pages)
+ if (address & (PAGE_SIZE - 1) || address != zc->address)
return -EINVAL;
- if (vma->vm_flags & VM_WRITE)
- return -EPERM;
- /* TODO: Maybe the following is not needed if pages are COW */
- vma->vm_flags &= ~VM_MAYWRITE;
-
- lock_sock(sk);
-
- ret = -ENOTCONN;
if (sk->sk_state == TCP_LISTEN)
- goto out;
+ return -ENOTCONN;
sock_rps_record_flow(sk);
- if (tcp_inq(sk) < size) {
- ret = sock_flag(sk, SOCK_DONE) ? -EIO : -EAGAIN;
+ down_read(¤t->mm->mmap_sem);
+
+ ret = -EINVAL;
+ vma = find_vma(current->mm, address);
+ if (!vma || vma->vm_start > address || vma->vm_ops != &tcp_vm_ops)
goto out;
- }
+ zc->length = min_t(unsigned long, zc->length, vma->vm_end - address);
+
tp = tcp_sk(sk);
seq = tp->copied_seq;
- /* Abort if urgent data is in the area */
- if (unlikely(tp->urg_data)) {
- u32 urg_offset = tp->urg_seq - seq;
+ zc->length = min_t(u32, zc->length, tcp_inq(sk));
+ zc->length &= ~(PAGE_SIZE - 1);
- ret = -EINVAL;
- if (urg_offset < size)
- goto out;
- }
- ret = -ENOMEM;
- pages_array = kvmalloc_array(nr_pages, sizeof(struct page *),
- GFP_KERNEL);
- if (!pages_array)
- goto out;
- skb = tcp_recv_skb(sk, seq, &offset);
- ret = -EINVAL;
-skb_start:
- /* We do not support anything not in page frags */
- offset -= skb_headlen(skb);
- if ((int)offset < 0)
- goto out;
- if (skb_has_frag_list(skb))
- goto out;
- len = skb->data_len - offset;
- frags = skb_shinfo(skb)->frags;
- while (offset) {
- if (frags->size > offset)
- goto out;
- offset -= frags->size;
- frags++;
- }
- while (nr < nr_pages) {
- if (len) {
- if (len < PAGE_SIZE)
- goto out;
- if (frags->size != PAGE_SIZE || frags->page_offset)
- goto out;
- pages_array[nr++] = skb_frag_page(frags);
- frags++;
- len -= PAGE_SIZE;
- seq += PAGE_SIZE;
- continue;
- }
- skb = skb->next;
- offset = seq - TCP_SKB_CB(skb)->seq;
- goto skb_start;
- }
- /* OK, we have a full set of pages ready to be inserted into vma */
- for (nr = 0; nr < nr_pages; nr++) {
- ret = vm_insert_page(vma, vma->vm_start + (nr << PAGE_SHIFT),
- pages_array[nr]);
- if (ret)
- goto out;
- }
- /* operation is complete, we can 'consume' all skbs */
- tp->copied_seq = seq;
- tcp_rcv_space_adjust(sk);
-
- /* Clean up data we have read: This will do ACK frames. */
- tcp_recv_skb(sk, seq, &offset);
- tcp_cleanup_rbuf(sk, size);
+ zap_page_range(vma, address, zc->length);
+ zc->recv_skip_hint = 0;
ret = 0;
+ while (length + PAGE_SIZE <= zc->length) {
+ if (zc->recv_skip_hint < PAGE_SIZE) {
+ if (skb) {
+ skb = skb->next;
+ offset = seq - TCP_SKB_CB(skb)->seq;
+ } else {
+ skb = tcp_recv_skb(sk, seq, &offset);
+ }
+
+ zc->recv_skip_hint = skb->len - offset;
+ offset -= skb_headlen(skb);
+ if ((int)offset < 0 || skb_has_frag_list(skb))
+ break;
+ frags = skb_shinfo(skb)->frags;
+ while (offset) {
+ if (frags->size > offset)
+ goto out;
+ offset -= frags->size;
+ frags++;
+ }
+ }
+ if (frags->size != PAGE_SIZE || frags->page_offset)
+ break;
+ ret = vm_insert_page(vma, address + length,
+ skb_frag_page(frags));
+ if (ret)
+ break;
+ length += PAGE_SIZE;
+ seq += PAGE_SIZE;
+ zc->recv_skip_hint -= PAGE_SIZE;
+ frags++;
+ }
out:
- release_sock(sk);
- kvfree(pages_array);
+ up_read(¤t->mm->mmap_sem);
+ if (length) {
+ tp->copied_seq = seq;
+ tcp_rcv_space_adjust(sk);
+
+ /* Clean up data we have read: This will do ACK frames. */
+ tcp_recv_skb(sk, seq, &offset);
+ tcp_cleanup_rbuf(sk, length);
+ ret = 0;
+ if (length == zc->length)
+ zc->recv_skip_hint = 0;
+ } else {
+ if (!zc->recv_skip_hint && sock_flag(sk, SOCK_DONE))
+ ret = -EIO;
+ }
+ zc->length = length;
return ret;
}
-EXPORT_SYMBOL(tcp_mmap);
static void tcp_update_recv_tstamps(struct sk_buff *skb,
struct scm_timestamping *tss)
@@ -2738,6 +2731,20 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
return tcp_fastopen_reset_cipher(net, sk, key, sizeof(key));
}
+ case TCP_ZEROCOPY_RECEIVE: {
+ struct tcp_zerocopy_receive zc;
+
+ if (optlen != sizeof(zc))
+ return -EINVAL;
+ if (copy_from_user(&zc, optval, optlen))
+ return -EFAULT;
+ lock_sock(sk);
+ err = tcp_zerocopy_receive(sk, &zc);
+ release_sock(sk);
+ if (!err && copy_to_user(optval, &zc, optlen))
+ err = -EFAULT;
+ return err;
+ }
default:
/* fallthru */
break;
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* [PATCH v2 net-next 2/2] selftests: net: tcp_mmap must use TCP_ZEROCOPY_RECEIVE
From: Eric Dumazet @ 2018-04-25 21:43 UTC (permalink / raw)
To: David S . Miller
Cc: netdev, Andy Lutomirski, linux-kernel, linux-mm, Eric Dumazet,
Eric Dumazet, Soheil Hassas Yeganeh
In-Reply-To: <20180425214307.159264-1-edumazet@google.com>
After prior kernel change, mmap() on TCP socket only reserves VMA.
We have to use setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE, ...)
to perform the transfert of pages from skbs in TCP receive queue into such VMA.
struct tcp_zerocopy_receive {
__u64 address; /* in: address of mapping */
__u32 length; /* in/out: number of bytes to map/mapped */
__u32 recv_skip_hint; /* out: amount of bytes to skip */
};
After a successful setsockopt(...TCP_ZEROCOPY_RECEIVE...), @length contains
number of bytes that were mapped, and @recv_skip_hint contains number of bytes
that should be read using conventional read()/recv()/recvmsg() system calls,
to skip a sequence of bytes that can not be mapped, because not properly page
aligned.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Soheil Hassas Yeganeh <soheil@google.com>
---
tools/testing/selftests/net/tcp_mmap.c | 63 +++++++++++++++-----------
1 file changed, 36 insertions(+), 27 deletions(-)
diff --git a/tools/testing/selftests/net/tcp_mmap.c b/tools/testing/selftests/net/tcp_mmap.c
index dea342fe6f4e88b5709d2ac37b2fc9a2a320bf44..5b381cdbdd6319556ba4e3dad530fae8f13f5a9b 100644
--- a/tools/testing/selftests/net/tcp_mmap.c
+++ b/tools/testing/selftests/net/tcp_mmap.c
@@ -76,9 +76,10 @@
#include <time.h>
#include <sys/time.h>
#include <netinet/in.h>
-#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <poll.h>
+#include <linux/tcp.h>
+#include <assert.h>
#ifndef MSG_ZEROCOPY
#define MSG_ZEROCOPY 0x4000000
@@ -134,11 +135,12 @@ void hash_zone(void *zone, unsigned int length)
void *child_thread(void *arg)
{
unsigned long total_mmap = 0, total = 0;
+ struct tcp_zerocopy_receive zc;
unsigned long delta_usec;
int flags = MAP_SHARED;
struct timeval t0, t1;
char *buffer = NULL;
- void *oaddr = NULL;
+ void *addr = NULL;
double throughput;
struct rusage ru;
int lu, fd;
@@ -153,41 +155,45 @@ void *child_thread(void *arg)
perror("malloc");
goto error;
}
+ if (zflg) {
+ addr = mmap(NULL, chunk_size, PROT_READ, flags, fd, 0);
+ if (addr == (void *)-1)
+ zflg = 0;
+ }
while (1) {
struct pollfd pfd = { .fd = fd, .events = POLLIN, };
int sub;
poll(&pfd, 1, 10000);
if (zflg) {
- void *naddr;
+ int res;
- naddr = mmap(oaddr, chunk_size, PROT_READ, flags, fd, 0);
- if (naddr == (void *)-1) {
- if (errno == EAGAIN) {
- /* That is if SO_RCVLOWAT is buggy */
- usleep(1000);
- continue;
- }
- if (errno == EINVAL) {
- flags = MAP_SHARED;
- oaddr = NULL;
- goto fallback;
- }
- if (errno != EIO)
- perror("mmap()");
+ zc.address = (__u64)addr;
+ zc.length = chunk_size;
+ zc.recv_skip_hint = 0;
+ res = setsockopt(fd, IPPROTO_TCP, TCP_ZEROCOPY_RECEIVE,
+ &zc, sizeof(zc));
+ if (res == -1)
break;
+
+ if (zc.length) {
+ assert(zc.length <= chunk_size);
+ total_mmap += zc.length;
+ if (xflg)
+ hash_zone(addr, zc.length);
+ total += zc.length;
}
- total_mmap += chunk_size;
- if (xflg)
- hash_zone(naddr, chunk_size);
- total += chunk_size;
- if (!keepflag) {
- flags |= MAP_FIXED;
- oaddr = naddr;
+ if (zc.recv_skip_hint) {
+ assert(zc.recv_skip_hint <= chunk_size);
+ lu = read(fd, buffer, zc.recv_skip_hint);
+ if (lu > 0) {
+ if (xflg)
+ hash_zone(buffer, lu);
+ total += lu;
+ }
}
continue;
}
-fallback:
sub = 0;
while (sub < chunk_size) {
lu = read(fd, buffer + sub, chunk_size - sub);
@@ -228,6 +234,8 @@ void *child_thread(void *arg)
error:
free(buffer);
close(fd);
+ if (zflg)
+ munmap(addr, chunk_size);
pthread_exit(0);
}
@@ -371,7 +379,8 @@ int main(int argc, char *argv[])
setup_sockaddr(cfg_family, host, &listenaddr);
if (mss &&
- setsockopt(fdlisten, SOL_TCP, TCP_MAXSEG, &mss, sizeof(mss)) == -1) {
+ setsockopt(fdlisten, IPPROTO_TCP, TCP_MAXSEG,
+ &mss, sizeof(mss)) == -1) {
perror("setsockopt TCP_MAXSEG");
exit(1);
}
@@ -402,7 +411,7 @@ int main(int argc, char *argv[])
setup_sockaddr(cfg_family, host, &addr);
if (mss &&
- setsockopt(fd, SOL_TCP, TCP_MAXSEG, &mss, sizeof(mss)) == -1) {
+ setsockopt(fd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)) == -1) {
perror("setsockopt TCP_MAXSEG");
exit(1);
}
--
2.17.0.441.gb46fe60e1d-goog
^ permalink raw reply related
* Re: [PATCH net-next v2 2/2] openvswitch: Support conntrack zone limit
From: Yi-Hung Wei @ 2018-04-25 21:51 UTC (permalink / raw)
To: Pravin Shelar; +Cc: Linux Kernel Network Developers
In-Reply-To: <CAOrHB_DHAjUp8Mf1_d-uKiiJPqUmwOvQDCTveFuvEhj9oJ-DhQ@mail.gmail.com>
>> +#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
>> +#define OVS_CT_LIMIT_UNLIMITED 0
>> +#define OVS_CT_LIMIT_DEFAULT OVS_CT_LIMIT_UNLIMITED
>> +#define CT_LIMIT_HASH_BUCKETS 512
>> +
> Can you use static key when the limit is not set.
> This would avoid overhead in datapath when these limits are not used.
>
Thanks Parvin for the review. I'm not sure about the 'static key'
part, are you suggesting that say if we can have a flag to check if no
one has ever set the ct_limit? If the ct_limit feature is not used
so far, then instead of look up the hash table for the zone limit, we
just return the default unlimited value. So that we can avoid the
overhead of checking ct_limit.
>> +struct ovs_ct_limit {
>> + /* Elements in ovs_ct_limit_info->limits hash table */
>> + struct hlist_node hlist_node;
>> + struct rcu_head rcu;
>> + u16 zone;
>> + u32 limit;
>> +};
>> +
> ...
>> /* Lookup connection and confirm if unconfirmed. */
>> static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
>> const struct ovs_conntrack_info *info,
>> @@ -1054,6 +1176,13 @@ static int ovs_ct_commit(struct net *net, struct sw_flow_key *key,
>> if (!ct)
>> return 0;
>>
>> +#if IS_ENABLED(CONFIG_NETFILTER_CONNCOUNT)
>> + err = ovs_ct_check_limit(net, info,
>> + &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
>> + if (err)
>> + return err;
>> +#endif
>> +
>
> This could be checked during flow install time, so that only permitted
> flows would have 'ct commit' action, we can avoid per packet cost
> checking the limit.
It seems to me that it would be hard to check the # of connections of
a flow in the flow installation stage. For example, if we have a
datapath flow that performs “ct commit” action on all UDP traffic from
in_port 1, then it could be various combinations of 5-tuple that form
various # of connections. Therefore, it would be hard to do the
admission control there.
> returning error code form ovs_ct_commit() is lost in datapath and it
> would be hard to debug packet lost in case of the limit is reached. So
> another advantage of checking the limit in flow install be better
> traceability. datapath would return error to usespace and it can log
> the error code.
Thanks for pointing out the error code from ovs_ct_commit() will be
lost in the datapath. In this case, shall we consider to report the
packet drop by some rate_limit logging such as net_warn_ratelimited()
or net_info_ratelimited()?
Thanks,
-Yi-Hung
^ permalink raw reply
* Loan Offer
From: Coleman Krosberg @ 2018-04-25 21:53 UTC (permalink / raw)
Thank you for your time,
We are looking for clients in your area of residents with good business or project that requires financing
to execute, or who wants a loan to do business, we do give loans with low interest.
Please get back to me if you are interested in this or you know anybody who has good business ideas but
lack the necessary capital to fund his projects or business so we can establish working relationship.
Yours Sincerely,
Coleman Krosberg MBA, CFA
Ak Bank Financial Rep
Investment analyst.
^ permalink raw reply
* pull-request: bpf 2018-04-25
From: Daniel Borkmann @ 2018-04-25 22:04 UTC (permalink / raw)
To: davem; +Cc: daniel, ast, netdev
Hi David,
The following pull-request contains BPF updates for your *net* tree.
The main changes are:
1) Fix to clear the percpu metadata_dst that could otherwise carry
stale ip_tunnel_info, from William.
2) Fix that reduces the number of passes in x64 JIT with regards to
dead code sanitation to avoid risk of prog rejection, from Gianluca.
3) Several fixes of sockmap programs, besides others, fixing a double
page_put() in error path, missing refcount hold for pinned sockmap,
adding required -target bpf for clang in sample Makefile, from John.
4) Fix to disable preemption in __BPF_PROG_RUN_ARRAY() paths, from Roman.
5) Fix tools/bpf/ Makefile with regards to a lex/yacc build error
seen on older gcc-5, from John.
Please consider pulling these changes from:
git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
Would be great if you have a chance to merge net into net-next after
that since sockmap fixes are needed in bpf-next later on to avoid
ugly merge conflicts.
Thanks a lot!
----------------------------------------------------------------
The following changes since commit 77621f024d6be732e43366a42203486b6ec89acd:
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf (2018-04-23 16:22:24 -0400)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
for you to fetch changes up to 9c299a32ede98dc9faafb267034ed830a15304db:
bpf: fix for lex/yacc build error with gcc-5 (2018-04-25 23:27:46 +0200)
----------------------------------------------------------------
Daniel Borkmann (1):
Merge branch 'bpf-sockmap-fixes'
Gianluca Borello (1):
bpf, x64: fix JIT emission for dead code
John Fastabend (6):
bpf: Document sockmap '-target bpf' requirement for PROG_TYPE_SK_MSG
bpf: sockmap sample use clang flag, -target bpf
bpf: sockmap, map_release does not hold refcnt for pinned maps
bpf: sockmap, sk_wait_event needed to handle blocking cases
bpf: sockmap, fix double page_put on ENOMEM error in redirect path
bpf: fix for lex/yacc build error with gcc-5
Roman Gushchin (1):
bpf: disable and restore preemption in __BPF_PROG_RUN_ARRAY
William Tu (1):
bpf: clear the ip_tunnel_info.
Documentation/bpf/bpf_devel_QA.txt | 10 +++++++-
arch/x86/net/bpf_jit_comp.c | 12 ++++++++-
include/linux/bpf.h | 4 ++-
kernel/bpf/arraymap.c | 3 ++-
kernel/bpf/sockmap.c | 51 +++++++++++++++++++++++++++++++++++---
kernel/bpf/syscall.c | 4 +--
net/core/filter.c | 1 +
samples/sockmap/Makefile | 7 ++++--
tools/bpf/Makefile | 2 ++
9 files changed, 82 insertions(+), 12 deletions(-)
^ permalink raw reply
* [bpf PATCH] bpf: fix uninitialized variable in bpf tools
From: John Fastabend @ 2018-04-25 22:08 UTC (permalink / raw)
To: ast, daniel, jbenc; +Cc: netdev
Here the variable cont is used as the saved_pointer for a call to
strtok_r(). It is safe to use the value uninitialized in this
context however and the later reference is only ever used if
the strtok_r is successful. But, 'gcc-5' at least doesn't have all
this knowledge so initialize cont to NULL. Additionally, do the
natural NULL check before accessing just for completness.
The warning is the following:
./bpf/tools/bpf/bpf_dbg.c: In function ‘cmd_load’:
./bpf/tools/bpf/bpf_dbg.c:1077:13: warning: ‘cont’ may be used uninitialized in this function [-Wmaybe-uninitialized]
} else if (matches(subcmd, "pcap") == 0) {
Fixes: fd981e3c321a "filter: bpf_dbg: add minimal bpf debugger"
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
---
tools/bpf/bpf_dbg.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tools/bpf/bpf_dbg.c b/tools/bpf/bpf_dbg.c
index 4f254bc..61b9aa5 100644
--- a/tools/bpf/bpf_dbg.c
+++ b/tools/bpf/bpf_dbg.c
@@ -1063,7 +1063,7 @@ static int cmd_load_pcap(char *file)
static int cmd_load(char *arg)
{
- char *subcmd, *cont, *tmp = strdup(arg);
+ char *subcmd, *cont = NULL, *tmp = strdup(arg);
int ret = CMD_OK;
subcmd = strtok_r(tmp, " ", &cont);
@@ -1073,7 +1073,10 @@ static int cmd_load(char *arg)
bpf_reset();
bpf_reset_breakpoints();
- ret = cmd_load_bpf(cont);
+ if (!cont)
+ ret = CMD_ERR;
+ else
+ ret = cmd_load_bpf(cont);
} else if (matches(subcmd, "pcap") == 0) {
ret = cmd_load_pcap(cont);
} else {
^ permalink raw reply related
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: James Bottomley @ 2018-04-25 22:17 UTC (permalink / raw)
To: Mikulas Patocka, David Rientjes
Cc: dm-devel, eric.dumazet, mst, netdev, jasowang, Randy Dunlap,
linux-kernel, Matthew Wilcox, Michal Hocko, linux-mm, edumazet,
Andrew Morton, virtualization, David Miller, Vlastimil Babka
In-Reply-To: <alpine.LRH.2.02.1804251720090.9428@file01.intranet.prod.int.rdu2.redhat.com>
On Wed, 2018-04-25 at 17:22 -0400, Mikulas Patocka wrote:
>
> On Wed, 25 Apr 2018, David Rientjes wrote:
>
> > On Wed, 25 Apr 2018, Mikulas Patocka wrote:
> >
> > > From: Mikulas Patocka <mpatocka@redhat.com>
> > > Subject: [PATCH] fault-injection: introduce kvmalloc fallback
> > > options
> > >
> > > This patch introduces a fault-injection option
> > > "kvmalloc_fallback". This option makes kvmalloc randomly fall
> > > back to vmalloc.
> > >
> > > Unfortunately, some kernel code has bugs - it uses kvmalloc and
> > > then uses DMA-API on the returned memory or frees it with kfree.
> > > Such bugs were found in the virtio-net driver, dm-integrity or
> > > RHEL7 powerpc-specific code. This options helps to test for these
> > > bugs.
> > >
> > > The patch introduces a config option
> > > FAIL_KVMALLOC_FALLBACK_PROBABILITY.
> > > It can be enabled in distribution debug kernels, so that kvmalloc
> > > abuse can be tested by the users. The default can be overridden
> > > with "kvmalloc_fallback" parameter or in
> > > /sys/kernel/debug/kvmalloc_fallback/.
> > >
> >
> > Do we really need the new config option? This could just be
> > manually tunable via fault injection IIUC.
>
> We do, because we want to enable it in RHEL and Fedora debugging
> kernels, so that it will be tested by the users.
>
> The users won't use some extra magic kernel options or debugfs files.
If it can be enabled via a tunable, then the distro can turn it on
without the user having to do anything. If you want to present the
user with a different boot option, you can (just have the tunable set
on the command line), but being tunable driven means that you don't
have to choose that option, you could automatically enable it under a
range of circumstances. I think most sane distributions would want
that flexibility.
Kconfig proliferation, conversely, is a bit of a nightmare from both
the user and the tester's point of view, so we're trying to avoid it
unless absolutely necessary.
James
^ permalink raw reply
* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Michael S. Tsirkin @ 2018-04-25 22:22 UTC (permalink / raw)
To: Siwei Liu
Cc: Stephen Hemminger, Jiri Pirko, Sridhar Samudrala, David Miller,
Netdev, virtualization, virtio-dev, Brandeburg, Jesse,
Alexander Duyck, Jakub Kicinski, Jason Wang
In-Reply-To: <CADGSJ22WMxXEtR9QpRa9_ZqgmTbgWHZz2j4hsUnRJrM9zTsW4w@mail.gmail.com>
On Wed, Apr 25, 2018 at 02:38:57PM -0700, Siwei Liu wrote:
> On Mon, Apr 23, 2018 at 1:06 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> > On Mon, Apr 23, 2018 at 12:44:39PM -0700, Siwei Liu wrote:
> >> On Mon, Apr 23, 2018 at 10:56 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
> >> > On Mon, Apr 23, 2018 at 10:44:40AM -0700, Stephen Hemminger wrote:
> >> >> On Mon, 23 Apr 2018 20:24:56 +0300
> >> >> "Michael S. Tsirkin" <mst@redhat.com> wrote:
> >> >>
> >> >> > On Mon, Apr 23, 2018 at 10:04:06AM -0700, Stephen Hemminger wrote:
> >> >> > > > >
> >> >> > > > >I will NAK patches to change to common code for netvsc especially the
> >> >> > > > >three device model. MS worked hard with distro vendors to support transparent
> >> >> > > > >mode, ans we really can't have a new model; or do backport.
> >> >> > > > >
> >> >> > > > >Plus, DPDK is now dependent on existing model.
> >> >> > > >
> >> >> > > > Sorry, but nobody here cares about dpdk or other similar oddities.
> >> >> > >
> >> >> > > The network device model is a userspace API, and DPDK is a userspace application.
> >> >> >
> >> >> > It is userspace but are you sure dpdk is actually poking at netdevs?
> >> >> > AFAIK it's normally banging device registers directly.
> >> >> >
> >> >> > > You can't go breaking userspace even if you don't like the application.
> >> >> >
> >> >> > Could you please explain how is the proposed patchset breaking
> >> >> > userspace? Ignoring DPDK for now, I don't think it changes the userspace
> >> >> > API at all.
> >> >> >
> >> >>
> >> >> The DPDK has a device driver vdev_netvsc which scans the Linux network devices
> >> >> to look for Linux netvsc device and the paired VF device and setup the
> >> >> DPDK environment. This setup creates a DPDK failsafe (bondingish) instance
> >> >> and sets up TAP support over the Linux netvsc device as well as the Mellanox
> >> >> VF device.
> >> >>
> >> >> So it depends on existing 2 device model. You can't go to a 3 device model
> >> >> or start hiding devices from userspace.
> >> >
> >> > Okay so how does the existing patch break that? IIUC does not go to
> >> > a 3 device model since netvsc calls failover_register directly.
> >> >
> >> >> Also, I am working on associating netvsc and VF device based on serial number
> >> >> rather than MAC address. The serial number is how Windows works now, and it makes
> >> >> sense for Linux and Windows to use the same mechanism if possible.
> >> >
> >> > Maybe we should support same for virtio ...
> >> > Which serial do you mean? From vpd?
> >> >
> >> > I guess you will want to keep supporting MAC for old hypervisors?
> >> >
> >> > It all seems like a reasonable thing to support in the generic core.
> >>
> >> That's the reason why I chose explicit identifier rather than rely on
> >> MAC address to bind/pair a device. MAC address can change. Even if it
> >> can't, malicious guest user can fake MAC address to skip binding.
> >>
> >> -Siwei
> >
> > Address should be sampled at device creation to prevent this
> > kind of hack. Not that it buys the malicious user much:
> > if you can poke at MAC addresses you probably already can
> > break networking.
>
> I don't understand why poking at MAC address may potentially break
> networking.
Set a MAC address to match another device on the same LAN,
packets will stop reaching that MAC.
> Unlike VF, passthrough PCI endpoint device has its freedom
> to change the MAC address. Even on a VF setup it's not neccessarily
> always safe to assume the VF's MAC address cannot or shouldn't be
> changed. That depends on the specific need whether the host admin
> wants to restrict guest from changing the MAC address, although in
> most cases it's true.
>
> I understand we can use the perm_addr to distinguish. But as said,
> this will pose limitation of flexible configuration where one can
> assign VFs with identical MAC address at all while each VF belongs to
> different PF and/or different subnet for e.g. load balancing.
> And
> furthermore, the QEMU device model never uses MAC address to be
> interpreted as an identifier, which requires to be unique per VM
> instance. Why we're introducing this inconsistency?
>
> -Siwei
Because it addresses most of the issues and is simple. That's already
much better than what we have now which is nothing unless guest
configures things manually.
I think ideally the infrastructure should suppport flexible matching of
NICs - netvsc is already reported to be moving to some kind of serial
address.
> >
> >
> >
> >
> >>
> >> >
> >> > --
> >> > MST
^ permalink raw reply
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-25 22:42 UTC (permalink / raw)
To: James Bottomley
Cc: David Rientjes, dm-devel, eric.dumazet, mst, netdev, jasowang,
Randy Dunlap, linux-kernel, Matthew Wilcox, Michal Hocko,
linux-mm, edumazet, Andrew Morton, virtualization, David Miller,
Vlastimil Babka
In-Reply-To: <1524694663.4100.21.camel@HansenPartnership.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 2372 bytes --]
On Wed, 25 Apr 2018, James Bottomley wrote:
> On Wed, 2018-04-25 at 17:22 -0400, Mikulas Patocka wrote:
> >
> > On Wed, 25 Apr 2018, David Rientjes wrote:
> > >
> > > Do we really need the new config option? This could just be
> > > manually tunable via fault injection IIUC.
> >
> > We do, because we want to enable it in RHEL and Fedora debugging
> > kernels, so that it will be tested by the users.
> >
> > The users won't use some extra magic kernel options or debugfs files.
>
> If it can be enabled via a tunable, then the distro can turn it on
> without the user having to do anything.
You need to enable it on boot. Enabling it when the kernel starts to
execute userspace code is already too late (because you would miss
kvmalloc calls in the kernel boot path).
These are files in the kernel-debug rpm package. Where would you put the
extra kernel parameter to enable this feature? None of these files contain
kernel parameters.
kernel-debug /boot/.vmlinuz-3.10.0-693.21.1.el7.x86_64.debug.hmac
kernel-debug /boot/System.map-3.10.0-693.21.1.el7.x86_64.debug
kernel-debug /boot/config-3.10.0-693.21.1.el7.x86_64.debug
kernel-debug /boot/initramfs-3.10.0-693.21.1.el7.x86_64.debug.img
kernel-debug /boot/symvers-3.10.0-693.21.1.el7.x86_64.debug.gz
kernel-debug /boot/vmlinuz-3.10.0-693.21.1.el7.x86_64.debug
kernel-debug /etc/ld.so.conf.d/kernel-3.10.0-693.21.1.el7.x86_64.debug.conf
kernel-debug /lib/modules/3.10.0-693.21.1.el7.x86_64.debug
> If you want to present the user with a different boot option, you can
> (just have the tunable set on the command line), but being tunable
> driven means that you don't have to choose that option, you could
> automatically enable it under a range of circumstances. I think most
> sane distributions would want that flexibility.
>
> Kconfig proliferation, conversely, is a bit of a nightmare from both
> the user and the tester's point of view, so we're trying to avoid it
> unless absolutely necessary.
>
> James
I already offered that we don't need to introduce a new kernel option and
we can bind this feature to any other kernel option, that is enabled in
the debug kernel, for example CONFIG_DEBUG_SG. Michal said no and he said
that he wants a new kernel option instead.
Mikulas
^ permalink raw reply
* Re: [PATCH net-next 3/3] net: phy: Enable C45 PHYs with vendor specific address space
From: kbuild test robot @ 2018-04-25 22:46 UTC (permalink / raw)
To: Vicentiu Galanopulo
Cc: kbuild-all, andrew, robh, netdev, linux-kernel, mark.rutland,
davem, marcel, devicetree, alexandru.marginean, madalin.bucur,
vicentiu.galanopulo
In-Reply-To: <20180417090233.21548-4-vicentiu.galanopulo@nxp.com>
[-- Attachment #1: Type: text/plain, Size: 726 bytes --]
Hi Vicentiu,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on net-next/master]
url: https://github.com/0day-ci/linux/commits/Vicentiu-Galanopulo/net-phy-Enable-C45-vendor-specific-MDIO-register-addr-space/20180418-014927
config: x86_64-randconfig-b0-04260315 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-16) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64
All errors (new ones prefixed by >>):
>> ERROR: "get_vend_spec_addr_phy_device" [drivers/of/of_mdio.ko] undefined!
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 25865 bytes --]
^ permalink raw reply
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: David Rientjes @ 2018-04-25 22:49 UTC (permalink / raw)
To: Mikulas Patocka
Cc: James Bottomley, dm-devel, eric.dumazet, mst, netdev, jasowang,
Randy Dunlap, linux-kernel, Matthew Wilcox, Michal Hocko,
linux-mm, edumazet, Andrew Morton, virtualization, David Miller,
Vlastimil Babka
In-Reply-To: <alpine.LRH.2.02.1804251830540.25124@file01.intranet.prod.int.rdu2.redhat.com>
On Wed, 25 Apr 2018, Mikulas Patocka wrote:
> You need to enable it on boot. Enabling it when the kernel starts to
> execute userspace code is already too late (because you would miss
> kvmalloc calls in the kernel boot path).
>
Is your motivation that since kvmalloc() never falls back to vmalloc() on
boot because fragmentation is not be an issue at boot that we should catch
bugs where it would matter if it had fallen back? If we are worrying
about falling back to vmalloc before even initscripts have run I think we
have bigger problems.
^ permalink raw reply
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-25 22:56 UTC (permalink / raw)
To: David Rientjes
Cc: James Bottomley, dm-devel, eric.dumazet, mst, netdev, jasowang,
Randy Dunlap, linux-kernel, Matthew Wilcox, Michal Hocko,
linux-mm, edumazet, Andrew Morton, virtualization, David Miller,
Vlastimil Babka
In-Reply-To: <alpine.DEB.2.21.1804251546240.58229@chino.kir.corp.google.com>
On Wed, 25 Apr 2018, David Rientjes wrote:
> On Wed, 25 Apr 2018, Mikulas Patocka wrote:
>
> > You need to enable it on boot. Enabling it when the kernel starts to
> > execute userspace code is already too late (because you would miss
> > kvmalloc calls in the kernel boot path).
>
> Is your motivation that since kvmalloc() never falls back to vmalloc() on
> boot because fragmentation is not be an issue at boot that we should catch
> bugs where it would matter if it had fallen back? If we are worrying
> about falling back to vmalloc before even initscripts have run I think we
> have bigger problems.
The same driver can be compiled directly into the kernel or be loaded as a
module. If the user (or the person preparing distro kernel) compiles the
driver directly into the kernel, kvmalloc should be tested on that driver,
because a different user or distribution can compile that driver as a
module.
Mikulas
^ permalink raw reply
* Re: [PATCH v7 net-next 4/4] netvsc: refactor notifier/event handling code to use the failover framework
From: Siwei Liu @ 2018-04-25 22:57 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: Stephen Hemminger, Jiri Pirko, Sridhar Samudrala, David Miller,
Netdev, virtualization, virtio-dev, Brandeburg, Jesse,
Alexander Duyck, Jakub Kicinski, Jason Wang
In-Reply-To: <20180426011221-mutt-send-email-mst@kernel.org>
On Wed, Apr 25, 2018 at 3:22 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Wed, Apr 25, 2018 at 02:38:57PM -0700, Siwei Liu wrote:
>> On Mon, Apr 23, 2018 at 1:06 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> > On Mon, Apr 23, 2018 at 12:44:39PM -0700, Siwei Liu wrote:
>> >> On Mon, Apr 23, 2018 at 10:56 AM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> >> > On Mon, Apr 23, 2018 at 10:44:40AM -0700, Stephen Hemminger wrote:
>> >> >> On Mon, 23 Apr 2018 20:24:56 +0300
>> >> >> "Michael S. Tsirkin" <mst@redhat.com> wrote:
>> >> >>
>> >> >> > On Mon, Apr 23, 2018 at 10:04:06AM -0700, Stephen Hemminger wrote:
>> >> >> > > > >
>> >> >> > > > >I will NAK patches to change to common code for netvsc especially the
>> >> >> > > > >three device model. MS worked hard with distro vendors to support transparent
>> >> >> > > > >mode, ans we really can't have a new model; or do backport.
>> >> >> > > > >
>> >> >> > > > >Plus, DPDK is now dependent on existing model.
>> >> >> > > >
>> >> >> > > > Sorry, but nobody here cares about dpdk or other similar oddities.
>> >> >> > >
>> >> >> > > The network device model is a userspace API, and DPDK is a userspace application.
>> >> >> >
>> >> >> > It is userspace but are you sure dpdk is actually poking at netdevs?
>> >> >> > AFAIK it's normally banging device registers directly.
>> >> >> >
>> >> >> > > You can't go breaking userspace even if you don't like the application.
>> >> >> >
>> >> >> > Could you please explain how is the proposed patchset breaking
>> >> >> > userspace? Ignoring DPDK for now, I don't think it changes the userspace
>> >> >> > API at all.
>> >> >> >
>> >> >>
>> >> >> The DPDK has a device driver vdev_netvsc which scans the Linux network devices
>> >> >> to look for Linux netvsc device and the paired VF device and setup the
>> >> >> DPDK environment. This setup creates a DPDK failsafe (bondingish) instance
>> >> >> and sets up TAP support over the Linux netvsc device as well as the Mellanox
>> >> >> VF device.
>> >> >>
>> >> >> So it depends on existing 2 device model. You can't go to a 3 device model
>> >> >> or start hiding devices from userspace.
>> >> >
>> >> > Okay so how does the existing patch break that? IIUC does not go to
>> >> > a 3 device model since netvsc calls failover_register directly.
>> >> >
>> >> >> Also, I am working on associating netvsc and VF device based on serial number
>> >> >> rather than MAC address. The serial number is how Windows works now, and it makes
>> >> >> sense for Linux and Windows to use the same mechanism if possible.
>> >> >
>> >> > Maybe we should support same for virtio ...
>> >> > Which serial do you mean? From vpd?
>> >> >
>> >> > I guess you will want to keep supporting MAC for old hypervisors?
>> >> >
>> >> > It all seems like a reasonable thing to support in the generic core.
>> >>
>> >> That's the reason why I chose explicit identifier rather than rely on
>> >> MAC address to bind/pair a device. MAC address can change. Even if it
>> >> can't, malicious guest user can fake MAC address to skip binding.
>> >>
>> >> -Siwei
>> >
>> > Address should be sampled at device creation to prevent this
>> > kind of hack. Not that it buys the malicious user much:
>> > if you can poke at MAC addresses you probably already can
>> > break networking.
>>
>> I don't understand why poking at MAC address may potentially break
>> networking.
>
> Set a MAC address to match another device on the same LAN,
> packets will stop reaching that MAC.
What I meant was guest users may create a virtual link, say veth that
has exactly the same MAC address as that for the VF, which can easily
get around of the binding procedure. There's no explicit flag to
identify a VF or pass-through device AFAIK. And sometimes this happens
maybe due to user misconfiguring the link. This process should be
hardened to avoid from any potential configuration errors.
>
>> Unlike VF, passthrough PCI endpoint device has its freedom
>> to change the MAC address. Even on a VF setup it's not neccessarily
>> always safe to assume the VF's MAC address cannot or shouldn't be
>> changed. That depends on the specific need whether the host admin
>> wants to restrict guest from changing the MAC address, although in
>> most cases it's true.
>>
>> I understand we can use the perm_addr to distinguish. But as said,
>> this will pose limitation of flexible configuration where one can
>> assign VFs with identical MAC address at all while each VF belongs to
>> different PF and/or different subnet for e.g. load balancing.
>> And
>> furthermore, the QEMU device model never uses MAC address to be
>> interpreted as an identifier, which requires to be unique per VM
>> instance. Why we're introducing this inconsistency?
>>
>> -Siwei
>
> Because it addresses most of the issues and is simple. That's already
> much better than what we have now which is nothing unless guest
> configures things manually.
Did you see my QEMU patch for using BDF as the grouping identifier?
And there can be others like what you suggested, but the point is that
it's requried to support explicit grouping mechanism from day one,
before the backup property cast into stones. This is orthogonal to
device model being proposed, be it 1-netdev or not. Delaying it would
just mean support and compatibility burden, appearing more like a
design flaw rather than a feature to add later on.
>
> I think ideally the infrastructure should suppport flexible matching of
> NICs - netvsc is already reported to be moving to some kind of serial
> address.
>
As Stephen said, Hyper-V supports the serial UUID thing from day-one.
It's just the Linux netvsc guest driver itself does not leverage that
ID from the very beginging.
Regards,
-Siwei
>
>> >
>> >
>> >
>> >
>> >>
>> >> >
>> >> > --
>> >> > MST
^ permalink raw reply
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: Mikulas Patocka @ 2018-04-25 23:00 UTC (permalink / raw)
To: James Bottomley
Cc: eric.dumazet, mst, netdev, Randy Dunlap, linux-kernel,
Matthew Wilcox, Michal Hocko, linux-mm, dm-devel, Vlastimil Babka,
David Rientjes, Andrew Morton, virtualization, David Miller,
edumazet
In-Reply-To: <1524694663.4100.21.camel@HansenPartnership.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1285 bytes --]
On Wed, 25 Apr 2018, James Bottomley wrote:
> > > Do we really need the new config option? This could just be
> > > manually tunable via fault injection IIUC.
> >
> > We do, because we want to enable it in RHEL and Fedora debugging
> > kernels, so that it will be tested by the users.
> >
> > The users won't use some extra magic kernel options or debugfs files.
>
> If it can be enabled via a tunable, then the distro can turn it on
> without the user having to do anything. If you want to present the
> user with a different boot option, you can (just have the tunable set
> on the command line), but being tunable driven means that you don't
> have to choose that option, you could automatically enable it under a
> range of circumstances. I think most sane distributions would want
> that flexibility.
>
> Kconfig proliferation, conversely, is a bit of a nightmare from both
> the user and the tester's point of view, so we're trying to avoid it
> unless absolutely necessary.
>
> James
BTW. even developers who compile their own kernel should have this enabled
by a CONFIG option - because if the developer sees the option when
browsing through menuconfig, he may enable it. If he doesn't see the
option, he won't even know that such an option exists.
Mikulas
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: [dm-devel] [PATCH v5] fault-injection: introduce kvmalloc fallback options
From: James Bottomley @ 2018-04-25 23:08 UTC (permalink / raw)
To: Mikulas Patocka
Cc: David Rientjes, dm-devel, eric.dumazet, mst, netdev, jasowang,
Randy Dunlap, linux-kernel, Matthew Wilcox, Michal Hocko,
linux-mm, edumazet, Andrew Morton, virtualization, David Miller,
Vlastimil Babka
In-Reply-To: <alpine.LRH.2.02.1804251857070.31135@file01.intranet.prod.int.rdu2.redhat.com>
On Wed, 2018-04-25 at 19:00 -0400, Mikulas Patocka wrote:
>
> On Wed, 25 Apr 2018, James Bottomley wrote:
>
> > > > Do we really need the new config option? This could just be
> > > > manually tunable via fault injection IIUC.
> > >
> > > We do, because we want to enable it in RHEL and Fedora debugging
> > > kernels, so that it will be tested by the users.
> > >
> > > The users won't use some extra magic kernel options or debugfs
> files.
> >
> > If it can be enabled via a tunable, then the distro can turn it on
> > without the user having to do anything. If you want to present the
> > user with a different boot option, you can (just have the tunable
> set
> > on the command line), but being tunable driven means that you don't
> > have to choose that option, you could automatically enable it under
> a
> > range of circumstances. I think most sane distributions would want
> > that flexibility.
> >
> > Kconfig proliferation, conversely, is a bit of a nightmare from
> both
> > the user and the tester's point of view, so we're trying to avoid
> it
> > unless absolutely necessary.
> >
> > James
>
> BTW. even developers who compile their own kernel should have this
> enabled by a CONFIG option - because if the developer sees the option
> when browsing through menuconfig, he may enable it. If he doesn't see
> the option, he won't even know that such an option exists.
I may be an atypical developer but I'd rather have a root canal than
browse through menuconfig options. The way to get people to learn
about new debugging options is to blog about it (or write an lwn.net
article) which google will find the next time I ask it how I debug XXX.
Google (probably as a service to humanity) rarely turns up Kconfig
options in response to a query.
James
^ permalink raw reply
* [PATCH net] net: systemport: Correclty disambiguate driver instances
From: Florian Fainelli @ 2018-04-25 23:21 UTC (permalink / raw)
To: netdev; +Cc: davem, vivien.didelot, Florian Fainelli
While adding the DSA notifier, we will be sending DSA notifications with
info->master that is going to point to a particular net_device instance.
Our logic in bcm_sysport_map_queues() correctly disambiguates net_device
instances that are not covered by our own driver, but it will not make
sure that info->master points to a particular driver instance that we
are interested in. In a system where e.g: two or more SYSTEMPORT
instances are registered, this would lead in programming two or more
times the queue mapping, completely messing with the logic which does
the queue/port allocation and tracking.
Fix this by looking at the notifier_block pointer which is unique per
instance and allows us to go back to our driver private structure, and
in turn to the backing net_device instance.
Fixes: d156576362c0 ("net: systemport: Establish lower/upper queue mapping")
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
---
drivers/net/ethernet/broadcom/bcmsysport.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index f9a3c1a76d5d..0c2b0fab81cf 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -2144,14 +2144,21 @@ static const struct net_device_ops bcm_sysport_netdev_ops = {
.ndo_select_queue = bcm_sysport_select_queue,
};
-static int bcm_sysport_map_queues(struct net_device *dev,
+static int bcm_sysport_map_queues(struct notifier_block *nb,
struct dsa_notifier_register_info *info)
{
- struct bcm_sysport_priv *priv = netdev_priv(dev);
struct bcm_sysport_tx_ring *ring;
+ struct bcm_sysport_priv *priv;
struct net_device *slave_dev;
unsigned int num_tx_queues;
unsigned int q, start, port;
+ struct net_device *dev;
+
+ priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
+ if (priv->netdev != info->master)
+ return 0;
+
+ dev = info->master;
/* We can't be setting up queue inspection for non directly attached
* switches
@@ -2174,6 +2181,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
if (priv->is_lite)
netif_set_real_num_tx_queues(slave_dev,
slave_dev->num_tx_queues / 2);
+
num_tx_queues = slave_dev->real_num_tx_queues;
if (priv->per_port_num_tx_queues &&
@@ -2201,7 +2209,7 @@ static int bcm_sysport_map_queues(struct net_device *dev,
return 0;
}
-static int bcm_sysport_dsa_notifier(struct notifier_block *unused,
+static int bcm_sysport_dsa_notifier(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct dsa_notifier_register_info *info;
@@ -2211,7 +2219,7 @@ static int bcm_sysport_dsa_notifier(struct notifier_block *unused,
info = ptr;
- return notifier_from_errno(bcm_sysport_map_queues(info->master, info));
+ return notifier_from_errno(bcm_sysport_map_queues(nb, info));
}
#define REV_FMT "v%2x.%02x"
--
2.14.1
^ permalink raw reply related
* Re: [RFC bpf-next 8/9] bpf: Provide helper to do lookups in kernel FIB table
From: David Ahern @ 2018-04-25 23:24 UTC (permalink / raw)
To: Daniel Borkmann, netdev, ast; +Cc: shm, roopa, brouer, toke, john.fastabend
In-Reply-To: <9488a57d-5559-b69f-631e-71cada1c1d2d@iogearbox.net>
On 4/25/18 1:55 PM, Daniel Borkmann wrote:
>> @@ -3861,6 +4090,8 @@ sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>> return &bpf_get_socket_cookie_proto;
>> case BPF_FUNC_get_socket_uid:
>> return &bpf_get_socket_uid_proto;
>> + case BPF_FUNC_fib_lookup:
>> + return &bpf_fib_lookup_proto;
> This part doesn't belong to sk_filter_func_proto(), but to the
> tc_cls_act_func_proto() instead.
oops, somewhere in all of the re-basing it got added to the wrong
function. Will fix.
>
>> default:
>> return bpf_base_func_proto(func_id);
>> }
>> @@ -3957,6 +4188,8 @@ xdp_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
>> return &bpf_xdp_redirect_map_proto;
>> case BPF_FUNC_xdp_adjust_tail:
>> return &bpf_xdp_adjust_tail_proto;
>> + case BPF_FUNC_fib_lookup:
>> + return &bpf_fib_lookup_proto;
> Basically, you're using the very same bpf_fib_lookup_proto for
> both XDP and skb. In the skb case, you're reusing the two functions
> bpf_ipv{4,6}_fib_lookup(), so when you get the netdev pointer for
> retrieving the netns, you'll crash at dev_net(ctx->rxq->dev) since
> this is XDP only and not skb meta data.
>
> Therefore, as mentioned, pass the netdev to bpf_ipv{4,6}_fib_lookup()
> to have it generic and have bpf_xdp_fib_lookup_proto and
> bpf_skb_fib_lookup_proto where both are under the case BPF_FUNC_fib_lookup
> in the respective *func_proto(), but using the proper prototypes according
> to their correct context. Meaning, both reuse bpf_ipv{4,6}_fib_lookup()
> from each of their BPF_CALL_4() helper implementation.
ok. I have been focused on the xdp program and not the tc path. Will fix.
^ permalink raw reply
* [PATCH net-next v8 0/4] Enable virtio_net to act as a standby for a passthru device
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh, jiri, aaron.f.brown
This is another update based on feedback from MST and Stephen on the
last patchset. Hopefully this series can be integrated and any further
enhancements can be made on top of this patchset.
v8:
- Made the failover managment routines more robust by updating the feature
bits/other fields in the failover netdev when slave netdevs are
registered/unregistered. (mst)
- added support for handling vlans.
- Limited the changes in netvsc to only use the notifier/event/lookups
from the failover module. The slave register/unregister/link-change
handlers are only updated to use the getbymac routine to get the
upper netdev. There is no change in their functionality. (stephen)
- renamed structs/function/file names to use net_failover prefix. (mst)
The main motivation for this patch is to enable cloud service providers
to provide an accelerated datapath to virtio-net enabled VMs in a
transparent manner with no/minimal guest userspace changes. This also
enables hypervisor controlled live migration to be supported with VMs that
have direct attached SR-IOV VF devices.
Patch 1 introduces a new feature bit VIRTIO_NET_F_STANDBY that can be
used by hypervisor to indicate that virtio_net interface should act as
a standby for another device with the same MAC address.
Patch 2 introduces a failover module that provides a generic interface for
paravirtual drivers to listen for netdev register/unregister/link change
events from pci ethernet devices with the same MAC and takeover their
datapath. The notifier and event handling code is based on the existing
netvsc implementation. It provides 2 sets of interfaces to paravirtual
drivers to support 2-netdev(netvsc) and 3-netdev(virtio_net) models.
Patch 3 extends virtio_net to use alternate datapath when available and
registered. When STANDBY feature is enabled, virtio_net driver creates
an additional 'failover' netdev that acts as a master device and controls
2 slave devices. The original virtio_net netdev is registered as
'standby' netdev and a passthru/vf device with the same MAC gets
registered as 'primary' netdev. Both 'standby' and 'primary' netdevs are
associated with the same 'pci' device. The user accesses the network
interface via 'failover' netdev. The 'failover' netdev chooses 'primary'
netdev as default for transmits when it is available with link up and
running.
Patch 4 refactors netvsc to use the registration/notification framework
supported by failover module.
As this patch series is initially focusing on usecases where hypervisor
fully controls the VM networking and the guest is not expected to directly
configure any hardware settings, it doesn't expose all the ndo/ethtool ops
that are supported by virtio_net at this time. To support additional usecases,
it should be possible to enable additional ops later by caching the state
in virtio netdev and replaying when the 'primary' netdev gets registered.
The hypervisor needs to enable only one datapath at any time so that packets
don't get looped back to the VM over the other datapath. When a VF is
plugged, the virtio datapath link state can be marked as down.
At the time of live migration, the hypervisor needs to unplug the VF device
from the guest on the source host and reset the MAC filter of the VF to
initiate failover of datapath to virtio before starting the migration. After
the migration is completed, the destination hypervisor sets the MAC filter
on the VF and plugs it back to the guest to switch over to VF datapath.
This patch is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2
v7
- Rename 'bypass/active/backup' terminology with 'failover/primary/standy'
(jiri, mst)
- re-arranged dev_open() and dev_set_mtu() calls in the register routines
so that they don't get called for 2-netdev model. (stephen)
- fixed select_queue() routine to do queue selection based on VF if it is
registered as primary. (stephen)
- minor bugfixes
v6 RFC:
Simplified virtio_net changes by moving all the ndo_ops of the
bypass_netdev and create/destroy of bypass_netdev to 'bypass' module.
avoided 2 phase registration(driver + instances).
introduced IFF_BYPASS/IFF_BYPASS_SLAVE dev->priv_flags
replaced mutex with a spinlock
v5 RFC:
Based on Jiri's comments, moved the common functionality to a 'bypass'
module so that the same notifier and event handlers to handle child
register/unregister/link change events can be shared between virtio_net
and netvsc.
Improved error handling based on Siwei's comments.
v4:
- Based on the review comments on the v3 version of the RFC patch and
Jakub's suggestion for the naming issue with 3 netdev solution,
proposed 3 netdev in-driver bonding solution for virtio-net.
v3 RFC:
- Introduced 3 netdev model and pointed out a couple of issues with
that model and proposed 2 netdev model to avoid these issues.
- Removed broadcast/multicast optimization and only use virtio as
backup path when VF is unplugged.
v2 RFC:
- Changed VIRTIO_NET_F_MASTER to VIRTIO_NET_F_BACKUP (mst)
- made a small change to the virtio-net xmit path to only use VF datapath
for unicasts. Broadcasts/multicasts use virtio datapath. This avoids
east-west broadcasts to go over the PCI link.
- added suppport for the feature bit in qemu
Sridhar Samudrala (4):
virtio_net: Introduce VIRTIO_NET_F_STANDBY feature bit
net: Introduce generic failover module
virtio_net: Extend virtio to use VF datapath when available
netvsc: refactor notifier/event handling code to use the failover
framework
drivers/net/Kconfig | 1 +
drivers/net/hyperv/Kconfig | 1 +
drivers/net/hyperv/hyperv_net.h | 2 +
drivers/net/hyperv/netvsc_drv.c | 134 ++----
drivers/net/virtio_net.c | 37 +-
include/linux/netdevice.h | 16 +
include/net/net_failover.h | 94 +++++
include/uapi/linux/virtio_net.h | 3 +
net/Kconfig | 18 +
net/core/Makefile | 1 +
net/core/net_failover.c | 892 ++++++++++++++++++++++++++++++++++++++++
11 files changed, 1086 insertions(+), 113 deletions(-)
create mode 100644 include/net/net_failover.h
create mode 100644 net/core/net_failover.c
--
2.14.3
^ permalink raw reply
* [PATCH net-next v8 1/4] virtio_net: Introduce VIRTIO_NET_F_STANDBY feature bit
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>
This feature bit can be used by hypervisor to indicate virtio_net device to
act as a standby for another device with the same MAC address.
VIRTIO_NET_F_STANDBY is defined as bit 62 as it is a device feature bit.
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
drivers/net/virtio_net.c | 2 +-
include/uapi/linux/virtio_net.h | 3 +++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 3b5991734118..51a085b1a242 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2999,7 +2999,7 @@ static struct virtio_device_id id_table[] = {
VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
VIRTIO_NET_F_CTRL_MAC_ADDR, \
VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
- VIRTIO_NET_F_SPEED_DUPLEX
+ VIRTIO_NET_F_SPEED_DUPLEX, VIRTIO_NET_F_STANDBY
static unsigned int features[] = {
VIRTNET_FEATURES,
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index 5de6ed37695b..a3715a3224c1 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -57,6 +57,9 @@
* Steering */
#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */
+#define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device
+ * with the same MAC.
+ */
#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */
#ifndef VIRTIO_NET_NO_LEGACY
--
2.14.3
^ permalink raw reply related
* [PATCH net-next v8 2/4] net: Introduce generic failover module
From: Sridhar Samudrala @ 2018-04-25 23:59 UTC (permalink / raw)
To: mst, stephen, davem, netdev, virtualization, virtio-dev,
jesse.brandeburg, alexander.h.duyck, kubakici, sridhar.samudrala,
jasowang, loseweigh, jiri, aaron.f.brown
In-Reply-To: <1524700768-38627-1-git-send-email-sridhar.samudrala@intel.com>
This provides a generic interface for paravirtual drivers to listen
for netdev register/unregister/link change events from pci ethernet
devices with the same MAC and takeover their datapath. The notifier and
event handling code is based on the existing netvsc implementation.
It exposes 2 sets of interfaces to the paravirtual drivers.
1. For paravirtual drivers like virtio_net that use 3 netdev model, the
the failover module provides interfaces to create/destroy additional
master netdev and all the slave events are managed internally.
net_failover_create()
net_failover_destroy()
A failover netdev is created that acts a master device and controls 2
slave devices. The original virtio_net netdev is registered as 'standby'
netdev and a passthru/vf device with the same MAC gets registered as
'primary' netdev. Both 'standby' and 'primary' netdevs are associated
with the same 'pci' device. The user accesses the network interface via
'failover' netdev. The 'failover' netdev chooses 'primary' netdev as
default for transmits when it is available with link up and running.
2. For existing netvsc driver that uses 2 netdev model, no master netdev
is created. The paravirtual driver registers each instance of netvsc
as a 'failover' netdev along with a set of ops to manage the slave
events. There is no 'standby' netdev in this model. A passthru/vf device
with the same MAC gets registered as 'primary' netdev.
net_failover_register()
net_failover_unregister()
Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
include/linux/netdevice.h | 16 +
include/net/net_failover.h | 94 +++++
net/Kconfig | 18 +
net/core/Makefile | 1 +
net/core/net_failover.c | 892 +++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1021 insertions(+)
create mode 100644 include/net/net_failover.h
create mode 100644 net/core/net_failover.c
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 14e0777ffcfb..b04dbf7dcf1b 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1401,6 +1401,8 @@ struct net_device_ops {
* entity (i.e. the master device for bridged veth)
* @IFF_MACSEC: device is a MACsec device
* @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
+ * @IFF_FAILOVER: device is a failover master device
+ * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
*/
enum netdev_priv_flags {
IFF_802_1Q_VLAN = 1<<0,
@@ -1430,6 +1432,8 @@ enum netdev_priv_flags {
IFF_PHONY_HEADROOM = 1<<24,
IFF_MACSEC = 1<<25,
IFF_NO_RX_HANDLER = 1<<26,
+ IFF_FAILOVER = 1<<27,
+ IFF_FAILOVER_SLAVE = 1<<28,
};
#define IFF_802_1Q_VLAN IFF_802_1Q_VLAN
@@ -1458,6 +1462,8 @@ enum netdev_priv_flags {
#define IFF_RXFH_CONFIGURED IFF_RXFH_CONFIGURED
#define IFF_MACSEC IFF_MACSEC
#define IFF_NO_RX_HANDLER IFF_NO_RX_HANDLER
+#define IFF_FAILOVER IFF_FAILOVER
+#define IFF_FAILOVER_SLAVE IFF_FAILOVER_SLAVE
/**
* struct net_device - The DEVICE structure.
@@ -4308,6 +4314,16 @@ static inline bool netif_is_rxfh_configured(const struct net_device *dev)
return dev->priv_flags & IFF_RXFH_CONFIGURED;
}
+static inline bool netif_is_failover(const struct net_device *dev)
+{
+ return dev->priv_flags & IFF_FAILOVER;
+}
+
+static inline bool netif_is_failover_slave(const struct net_device *dev)
+{
+ return dev->priv_flags & IFF_FAILOVER_SLAVE;
+}
+
/* This device needs to keep skb dst for qdisc enqueue or ndo_start_xmit() */
static inline void netif_keep_dst(struct net_device *dev)
{
diff --git a/include/net/net_failover.h b/include/net/net_failover.h
new file mode 100644
index 000000000000..8d431685634a
--- /dev/null
+++ b/include/net/net_failover.h
@@ -0,0 +1,94 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2018, Intel Corporation. */
+
+#ifndef _NET_FAILOVER_H
+#define _NET_FAILOVER_H
+
+#include <linux/netdevice.h>
+
+struct net_failover_ops {
+ int (*slave_register)(struct net_device *slave_dev,
+ struct net_device *failover_dev);
+ int (*slave_unregister)(struct net_device *slave_dev,
+ struct net_device *failover_dev);
+ int (*slave_link_change)(struct net_device *slave_dev,
+ struct net_device *failover_dev);
+};
+
+struct net_failover {
+ struct list_head list;
+ struct net_device __rcu *failover_dev;
+ struct net_failover_ops __rcu *ops;
+};
+
+/* failover state */
+struct net_failover_info {
+ /* primary netdev with same MAC */
+ struct net_device __rcu *primary_dev;
+
+ /* standby netdev */
+ struct net_device __rcu *standby_dev;
+
+ /* primary netdev stats */
+ struct rtnl_link_stats64 primary_stats;
+
+ /* standby netdev stats */
+ struct rtnl_link_stats64 standby_stats;
+
+ /* aggregated stats */
+ struct rtnl_link_stats64 failover_stats;
+
+ /* spinlock while updating stats */
+ spinlock_t stats_lock;
+};
+
+#if IS_ENABLED(CONFIG_NET_FAILOVER)
+
+/* Paravirtual drivers supporting 3-netdev model can use these 2 interfaces to
+ * create and destroy a failover device.
+ */
+int net_failover_create(struct net_device *standby_dev,
+ struct net_failover **pfailover);
+void net_failover_destroy(struct net_failover *failover);
+
+/* Paravirtual drivers supporting 2-netdev model can use these 2 interfaces to
+ * register and unregister a failover device.
+ */
+int net_failover_register(struct net_device *standby_dev,
+ struct net_failover_ops *ops,
+ struct net_failover **pfailover);
+void net_failover_unregister(struct net_failover *failover);
+
+int net_failover_slave_unregister(struct net_device *slave_dev);
+
+#else
+
+static inline int net_failover_create(struct net_device *standby_dev,
+ struct net_failover **pfailover)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void net_failover_destroy(struct net_failover *failover)
+{
+}
+
+static inline int net_failover_register(struct net_device *standby_dev,
+ struct net_failover_ops *ops,
+ struct net_failover **pfailover)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline void net_failover_unregister(struct net_failover *failover)
+{
+}
+
+static inline int net_failover_slave_unregister(struct net_device *slave_dev)
+{
+ return 0;
+}
+
+#endif
+
+#endif /* _NET_FAILOVER_H */
diff --git a/net/Kconfig b/net/Kconfig
index 6fa1a4493b8c..e8fe3163c5d3 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -426,6 +426,24 @@ config MAY_USE_DEVLINK
config PAGE_POOL
bool
+config NET_FAILOVER
+ tristate "Failover interface"
+ help
+ This provides a generic interface for paravirtual drivers to listen
+ for netdev register/unregister/link change events from pci ethernet
+ devices with the same MAC and takeover their datapath. This also
+ enables live migration of a VM with direct attached VF by failing
+ over to the paravirtual datapath when the VF is unplugged.
+
+config MAY_USE_NET_FAILOVER
+ tristate
+ default m if NET_FAILOVER=m
+ default y if NET_FAILOVER=y || NET_FAILOVER=n
+ help
+ Drivers using the failover infrastructure should have a dependency
+ on MAY_USE_NET_FAILOVER to ensure they do not cause link errors when
+ failover is a loadable module and the driver using it is built-in.
+
endif # if NET
# Used by archs to tell that they support BPF JIT compiler plus which flavour.
diff --git a/net/core/Makefile b/net/core/Makefile
index 7080417f8bc8..283ed9b0e581 100644
--- a/net/core/Makefile
+++ b/net/core/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_DST_CACHE) += dst_cache.o
obj-$(CONFIG_HWBM) += hwbm.o
obj-$(CONFIG_NET_DEVLINK) += devlink.o
obj-$(CONFIG_GRO_CELLS) += gro_cells.o
+obj-$(CONFIG_NET_FAILOVER) += net_failover.o
diff --git a/net/core/net_failover.c b/net/core/net_failover.c
new file mode 100644
index 000000000000..ac164be17563
--- /dev/null
+++ b/net/core/net_failover.c
@@ -0,0 +1,892 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2018, Intel Corporation. */
+
+/* A common module to handle registrations and notifications for paravirtual
+ * drivers to enable accelerated datapath and support VF live migration.
+ *
+ * The notifier and event handling code is based on netvsc driver and failover
+ * netdev management routines are based on bond/team driver.
+ *
+ */
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/netpoll.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+#include <linux/pci.h>
+#include <net/sch_generic.h>
+#include <uapi/linux/if_arp.h>
+#include <net/net_failover.h>
+
+static LIST_HEAD(net_failover_list);
+static DEFINE_SPINLOCK(net_failover_lock);
+
+static int net_failover_open(struct net_device *dev)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *primary_dev, *standby_dev;
+ int err;
+
+ netif_carrier_off(dev);
+ netif_tx_wake_all_queues(dev);
+
+ primary_dev = rtnl_dereference(nfo_info->primary_dev);
+ if (primary_dev) {
+ err = dev_open(primary_dev);
+ if (err)
+ goto err_primary_open;
+ }
+
+ standby_dev = rtnl_dereference(nfo_info->standby_dev);
+ if (standby_dev) {
+ err = dev_open(standby_dev);
+ if (err)
+ goto err_standby_open;
+ }
+
+ return 0;
+
+err_standby_open:
+ dev_close(primary_dev);
+err_primary_open:
+ netif_tx_disable(dev);
+ return err;
+}
+
+static int net_failover_close(struct net_device *dev)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *slave_dev;
+
+ netif_tx_disable(dev);
+
+ slave_dev = rtnl_dereference(nfo_info->primary_dev);
+ if (slave_dev)
+ dev_close(slave_dev);
+
+ slave_dev = rtnl_dereference(nfo_info->standby_dev);
+ if (slave_dev)
+ dev_close(slave_dev);
+
+ return 0;
+}
+
+static netdev_tx_t net_failover_drop_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ atomic_long_inc(&dev->tx_dropped);
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+}
+
+static bool net_failover_xmit_ready(struct net_device *dev)
+{
+ return netif_running(dev) && netif_carrier_ok(dev);
+}
+
+static netdev_tx_t net_failover_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *xmit_dev;
+
+ /* Try xmit via primary netdev followed by standby netdev */
+ xmit_dev = rcu_dereference_bh(nfo_info->primary_dev);
+ if (!xmit_dev || !net_failover_xmit_ready(xmit_dev)) {
+ xmit_dev = rcu_dereference_bh(nfo_info->standby_dev);
+ if (!xmit_dev || !net_failover_xmit_ready(xmit_dev))
+ return net_failover_drop_xmit(skb, dev);
+ }
+
+ skb->dev = xmit_dev;
+ skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+
+ return dev_queue_xmit(skb);
+}
+
+static u16 net_failover_select_queue(struct net_device *dev,
+ struct sk_buff *skb, void *accel_priv,
+ select_queue_fallback_t fallback)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *primary_dev;
+ u16 txq;
+
+ rcu_read_lock();
+ primary_dev = rcu_dereference(nfo_info->primary_dev);
+ if (primary_dev) {
+ const struct net_device_ops *ops = primary_dev->netdev_ops;
+
+ if (ops->ndo_select_queue)
+ txq = ops->ndo_select_queue(primary_dev, skb,
+ accel_priv, fallback);
+ else
+ txq = fallback(primary_dev, skb);
+
+ qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
+
+ return txq;
+ }
+
+ txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+ /* Save the original txq to restore before passing to the driver */
+ qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
+
+ if (unlikely(txq >= dev->real_num_tx_queues)) {
+ do {
+ txq -= dev->real_num_tx_queues;
+ } while (txq >= dev->real_num_tx_queues);
+ }
+
+ return txq;
+}
+
+/* fold stats, assuming all rtnl_link_stats64 fields are u64, but
+ * that some drivers can provide 32bit values only.
+ */
+static void net_failover_fold_stats(struct rtnl_link_stats64 *_res,
+ const struct rtnl_link_stats64 *_new,
+ const struct rtnl_link_stats64 *_old)
+{
+ const u64 *new = (const u64 *)_new;
+ const u64 *old = (const u64 *)_old;
+ u64 *res = (u64 *)_res;
+ int i;
+
+ for (i = 0; i < sizeof(*_res) / sizeof(u64); i++) {
+ u64 nv = new[i];
+ u64 ov = old[i];
+ s64 delta = nv - ov;
+
+ /* detects if this particular field is 32bit only */
+ if (((nv | ov) >> 32) == 0)
+ delta = (s64)(s32)((u32)nv - (u32)ov);
+
+ /* filter anomalies, some drivers reset their stats
+ * at down/up events.
+ */
+ if (delta > 0)
+ res[i] += delta;
+ }
+}
+
+static void net_failover_get_stats(struct net_device *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ const struct rtnl_link_stats64 *new;
+ struct rtnl_link_stats64 temp;
+ struct net_device *slave_dev;
+
+ spin_lock(&nfo_info->stats_lock);
+ memcpy(stats, &nfo_info->failover_stats, sizeof(*stats));
+
+ rcu_read_lock();
+
+ slave_dev = rcu_dereference(nfo_info->primary_dev);
+ if (slave_dev) {
+ new = dev_get_stats(slave_dev, &temp);
+ net_failover_fold_stats(stats, new, &nfo_info->primary_stats);
+ memcpy(&nfo_info->primary_stats, new, sizeof(*new));
+ }
+
+ slave_dev = rcu_dereference(nfo_info->standby_dev);
+ if (slave_dev) {
+ new = dev_get_stats(slave_dev, &temp);
+ net_failover_fold_stats(stats, new, &nfo_info->standby_stats);
+ memcpy(&nfo_info->standby_stats, new, sizeof(*new));
+ }
+
+ rcu_read_unlock();
+
+ memcpy(&nfo_info->failover_stats, stats, sizeof(*stats));
+ spin_unlock(&nfo_info->stats_lock);
+}
+
+static int net_failover_change_mtu(struct net_device *dev, int new_mtu)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *primary_dev, *standby_dev;
+ int ret = 0;
+
+ primary_dev = rcu_dereference(nfo_info->primary_dev);
+ if (primary_dev) {
+ ret = dev_set_mtu(primary_dev, new_mtu);
+ if (ret)
+ return ret;
+ }
+
+ standby_dev = rcu_dereference(nfo_info->standby_dev);
+ if (standby_dev) {
+ ret = dev_set_mtu(standby_dev, new_mtu);
+ if (ret) {
+ dev_set_mtu(primary_dev, dev->mtu);
+ return ret;
+ }
+ }
+
+ dev->mtu = new_mtu;
+
+ return 0;
+}
+
+static void net_failover_set_rx_mode(struct net_device *dev)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *slave_dev;
+
+ rcu_read_lock();
+
+ slave_dev = rcu_dereference(nfo_info->primary_dev);
+ if (slave_dev) {
+ dev_uc_sync_multiple(slave_dev, dev);
+ dev_mc_sync_multiple(slave_dev, dev);
+ }
+
+ slave_dev = rcu_dereference(nfo_info->standby_dev);
+ if (slave_dev) {
+ dev_uc_sync_multiple(slave_dev, dev);
+ dev_mc_sync_multiple(slave_dev, dev);
+ }
+
+ rcu_read_unlock();
+}
+
+static int net_failover_vlan_rx_add_vid(struct net_device *dev, __be16 proto,
+ u16 vid)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *primary_dev, *standby_dev;
+ int ret = 0;
+
+ primary_dev = rcu_dereference(nfo_info->primary_dev);
+ if (primary_dev) {
+ ret = vlan_vid_add(primary_dev, proto, vid);
+ if (ret)
+ return ret;
+ }
+
+ standby_dev = rcu_dereference(nfo_info->standby_dev);
+ if (standby_dev) {
+ ret = vlan_vid_add(standby_dev, proto, vid);
+ if (ret)
+ vlan_vid_del(primary_dev, proto, vid);
+ }
+
+ return ret;
+}
+
+static int net_failover_vlan_rx_kill_vid(struct net_device *dev, __be16 proto,
+ u16 vid)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *slave_dev;
+
+ slave_dev = rcu_dereference(nfo_info->primary_dev);
+ if (slave_dev)
+ vlan_vid_del(slave_dev, proto, vid);
+
+ slave_dev = rcu_dereference(nfo_info->standby_dev);
+ if (slave_dev)
+ vlan_vid_del(slave_dev, proto, vid);
+
+ return 0;
+}
+
+static const struct net_device_ops failover_dev_ops = {
+ .ndo_open = net_failover_open,
+ .ndo_stop = net_failover_close,
+ .ndo_start_xmit = net_failover_start_xmit,
+ .ndo_select_queue = net_failover_select_queue,
+ .ndo_get_stats64 = net_failover_get_stats,
+ .ndo_change_mtu = net_failover_change_mtu,
+ .ndo_set_rx_mode = net_failover_set_rx_mode,
+ .ndo_vlan_rx_add_vid = net_failover_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = net_failover_vlan_rx_kill_vid,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_features_check = passthru_features_check,
+};
+
+#define FAILOVER_NAME "failover"
+#define FAILOVER_VERSION "0.1"
+
+static void nfo_ethtool_get_drvinfo(struct net_device *dev,
+ struct ethtool_drvinfo *drvinfo)
+{
+ strlcpy(drvinfo->driver, FAILOVER_NAME, sizeof(drvinfo->driver));
+ strlcpy(drvinfo->version, FAILOVER_VERSION, sizeof(drvinfo->version));
+}
+
+static int nfo_ethtool_get_link_ksettings(struct net_device *dev,
+ struct ethtool_link_ksettings *cmd)
+{
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *slave_dev;
+
+ slave_dev = rtnl_dereference(nfo_info->primary_dev);
+ if (!slave_dev || !net_failover_xmit_ready(slave_dev)) {
+ slave_dev = rtnl_dereference(nfo_info->standby_dev);
+ if (!slave_dev || !net_failover_xmit_ready(slave_dev)) {
+ cmd->base.duplex = DUPLEX_UNKNOWN;
+ cmd->base.port = PORT_OTHER;
+ cmd->base.speed = SPEED_UNKNOWN;
+
+ return 0;
+ }
+ }
+
+ return __ethtool_get_link_ksettings(slave_dev, cmd);
+}
+
+static const struct ethtool_ops failover_ethtool_ops = {
+ .get_drvinfo = nfo_ethtool_get_drvinfo,
+ .get_link = ethtool_op_get_link,
+ .get_link_ksettings = nfo_ethtool_get_link_ksettings,
+};
+
+static struct net_device *net_failover_get_bymac(u8 *mac,
+ struct net_failover_ops **ops)
+{
+ struct net_device *failover_dev;
+ struct net_failover *failover;
+
+ spin_lock(&net_failover_lock);
+ list_for_each_entry(failover, &net_failover_list, list) {
+ failover_dev = rtnl_dereference(failover->failover_dev);
+ if (ether_addr_equal(failover_dev->perm_addr, mac)) {
+ *ops = rtnl_dereference(failover->ops);
+ spin_unlock(&net_failover_lock);
+ return failover_dev;
+ }
+ }
+ spin_unlock(&net_failover_lock);
+ return NULL;
+}
+
+/* Called when slave dev is injecting data into network stack.
+ * Change the associated network device from lower dev to virtio.
+ * note: already called with rcu_read_lock
+ */
+static rx_handler_result_t net_failover_handle_frame(struct sk_buff **pskb)
+{
+ struct sk_buff *skb = *pskb;
+ struct net_device *ndev = rcu_dereference(skb->dev->rx_handler_data);
+
+ skb->dev = ndev;
+
+ return RX_HANDLER_ANOTHER;
+}
+
+#define FAILOVER_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_FRAGLIST | NETIF_F_ALL_TSO | \
+ NETIF_F_HIGHDMA | NETIF_F_LRO)
+
+#define FAILOVER_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
+ NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
+
+static void net_failover_compute_features(struct net_device *dev)
+{
+ u32 vlan_features = FAILOVER_VLAN_FEATURES & NETIF_F_ALL_FOR_ALL;
+ netdev_features_t enc_features = FAILOVER_ENC_FEATURES;
+ unsigned short max_hard_header_len = ETH_HLEN;
+ unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
+ IFF_XMIT_DST_RELEASE_PERM;
+ struct net_failover_info *nfo_info = netdev_priv(dev);
+ struct net_device *primary_dev, *standby_dev;
+
+ primary_dev = rcu_dereference(nfo_info->primary_dev);
+ if (primary_dev) {
+ vlan_features =
+ netdev_increment_features(vlan_features,
+ primary_dev->vlan_features,
+ FAILOVER_VLAN_FEATURES);
+ enc_features =
+ netdev_increment_features(enc_features,
+ primary_dev->hw_enc_features,
+ FAILOVER_ENC_FEATURES);
+
+ dst_release_flag &= primary_dev->priv_flags;
+ if (primary_dev->hard_header_len > max_hard_header_len)
+ max_hard_header_len = primary_dev->hard_header_len;
+ }
+
+ standby_dev = rcu_dereference(nfo_info->standby_dev);
+ if (standby_dev) {
+ vlan_features =
+ netdev_increment_features(vlan_features,
+ standby_dev->vlan_features,
+ FAILOVER_VLAN_FEATURES);
+ enc_features =
+ netdev_increment_features(enc_features,
+ standby_dev->hw_enc_features,
+ FAILOVER_ENC_FEATURES);
+
+ dst_release_flag &= standby_dev->priv_flags;
+ if (standby_dev->hard_header_len > max_hard_header_len)
+ max_hard_header_len = standby_dev->hard_header_len;
+ }
+
+ dev->vlan_features = vlan_features;
+ dev->hw_enc_features = enc_features | NETIF_F_GSO_ENCAP_ALL;
+ dev->hard_header_len = max_hard_header_len;
+
+ dev->priv_flags &= ~IFF_XMIT_DST_RELEASE;
+ if (dst_release_flag == (IFF_XMIT_DST_RELEASE |
+ IFF_XMIT_DST_RELEASE_PERM))
+ dev->priv_flags |= IFF_XMIT_DST_RELEASE;
+
+ netdev_change_features(dev);
+}
+
+static int net_failover_slave_register(struct net_device *slave_dev)
+{
+ struct net_failover_info *nfo_info;
+ struct net_failover_ops *nfo_ops;
+ struct net_device *failover_dev;
+ bool slave_is_standby;
+ u32 orig_mtu;
+ int err;
+
+ ASSERT_RTNL();
+
+ failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+ if (!failover_dev)
+ goto done;
+
+ if (failover_dev->type != slave_dev->type)
+ goto done;
+
+ if (nfo_ops && nfo_ops->slave_register)
+ return nfo_ops->slave_register(slave_dev, failover_dev);
+
+ nfo_info = netdev_priv(failover_dev);
+ slave_is_standby = (slave_dev->dev.parent == failover_dev->dev.parent);
+ if (slave_is_standby ? rtnl_dereference(nfo_info->standby_dev) :
+ rtnl_dereference(nfo_info->primary_dev)) {
+ netdev_err(failover_dev, "%s attempting to register as slave dev when %s already present\n",
+ slave_dev->name,
+ slave_is_standby ? "standby" : "primary");
+ goto done;
+ }
+
+ /* We want to allow only a direct attached VF device as a primary
+ * netdev. As there is no easy way to check for a VF device, restrict
+ * this to a pci device.
+ */
+ if (!slave_is_standby && (!slave_dev->dev.parent ||
+ !dev_is_pci(slave_dev->dev.parent)))
+ goto done;
+
+ if (failover_dev->features & NETIF_F_VLAN_CHALLENGED &&
+ vlan_uses_dev(failover_dev)) {
+ netdev_err(failover_dev, "Device %s is VLAN challenged and failover device has VLAN set up\n",
+ failover_dev->name);
+ goto done;
+ }
+
+ /* Align MTU of slave with failover dev */
+ orig_mtu = slave_dev->mtu;
+ err = dev_set_mtu(slave_dev, failover_dev->mtu);
+ if (err) {
+ netdev_err(failover_dev, "unable to change mtu of %s to %u register failed\n",
+ slave_dev->name, failover_dev->mtu);
+ goto done;
+ }
+
+ dev_hold(slave_dev);
+
+ if (netif_running(failover_dev)) {
+ err = dev_open(slave_dev);
+ if (err && (err != -EBUSY)) {
+ netdev_err(failover_dev, "Opening slave %s failed err:%d\n",
+ slave_dev->name, err);
+ goto err_dev_open;
+ }
+ }
+
+ netif_addr_lock_bh(failover_dev);
+ dev_uc_sync_multiple(slave_dev, failover_dev);
+ dev_uc_sync_multiple(slave_dev, failover_dev);
+ netif_addr_unlock_bh(failover_dev);
+
+ err = vlan_vids_add_by_dev(slave_dev, failover_dev);
+ if (err) {
+ netdev_err(failover_dev, "Failed to add vlan ids to device %s err:%d\n",
+ slave_dev->name, err);
+ goto err_vlan_add;
+ }
+
+ err = netdev_rx_handler_register(slave_dev, net_failover_handle_frame,
+ failover_dev);
+ if (err) {
+ netdev_err(slave_dev, "can not register failover rx handler (err = %d)\n",
+ err);
+ goto err_handler_register;
+ }
+
+ err = netdev_upper_dev_link(slave_dev, failover_dev, NULL);
+ if (err) {
+ netdev_err(slave_dev, "can not set failover device %s (err = %d)\n",
+ failover_dev->name, err);
+ goto err_upper_link;
+ }
+
+ slave_dev->priv_flags |= IFF_FAILOVER_SLAVE;
+
+ if (slave_is_standby) {
+ rcu_assign_pointer(nfo_info->standby_dev, slave_dev);
+ dev_get_stats(nfo_info->standby_dev, &nfo_info->standby_stats);
+ } else {
+ rcu_assign_pointer(nfo_info->primary_dev, slave_dev);
+ dev_get_stats(nfo_info->primary_dev, &nfo_info->primary_stats);
+ failover_dev->min_mtu = slave_dev->min_mtu;
+ failover_dev->max_mtu = slave_dev->max_mtu;
+ }
+
+ net_failover_compute_features(failover_dev);
+
+ call_netdevice_notifiers(NETDEV_JOIN, slave_dev);
+
+ netdev_info(failover_dev, "failover %s slave:%s registered\n",
+ slave_is_standby ? "standby" : "primary", slave_dev->name);
+
+ goto done;
+
+err_upper_link:
+ netdev_rx_handler_unregister(slave_dev);
+err_handler_register:
+ vlan_vids_del_by_dev(slave_dev, failover_dev);
+err_vlan_add:
+ dev_uc_unsync(slave_dev, failover_dev);
+ dev_mc_unsync(slave_dev, failover_dev);
+ dev_close(slave_dev);
+err_dev_open:
+ dev_put(slave_dev);
+ dev_set_mtu(slave_dev, orig_mtu);
+done:
+ return NOTIFY_DONE;
+}
+
+int net_failover_slave_unregister(struct net_device *slave_dev)
+{
+ struct net_device *standby_dev, *primary_dev;
+ struct net_failover_info *nfo_info;
+ struct net_failover_ops *nfo_ops;
+ struct net_device *failover_dev;
+ bool slave_is_standby;
+
+ if (!netif_is_failover_slave(slave_dev))
+ goto done;
+
+ ASSERT_RTNL();
+
+ failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+ if (!failover_dev)
+ goto done;
+
+ if (nfo_ops && nfo_ops->slave_unregister)
+ return nfo_ops->slave_unregister(slave_dev, failover_dev);
+
+ nfo_info = netdev_priv(failover_dev);
+ primary_dev = rtnl_dereference(nfo_info->primary_dev);
+ standby_dev = rtnl_dereference(nfo_info->standby_dev);
+
+ if (slave_dev != primary_dev && slave_dev != standby_dev)
+ goto done;
+
+ slave_is_standby = (slave_dev->dev.parent == failover_dev->dev.parent);
+
+ netdev_rx_handler_unregister(slave_dev);
+ netdev_upper_dev_unlink(slave_dev, failover_dev);
+ vlan_vids_del_by_dev(slave_dev, failover_dev);
+ dev_uc_unsync(slave_dev, failover_dev);
+ dev_mc_unsync(slave_dev, failover_dev);
+ dev_close(slave_dev);
+ slave_dev->priv_flags &= ~IFF_FAILOVER_SLAVE;
+
+ nfo_info = netdev_priv(failover_dev);
+ net_failover_get_stats(failover_dev, &nfo_info->failover_stats);
+
+ if (slave_is_standby) {
+ RCU_INIT_POINTER(nfo_info->standby_dev, NULL);
+ } else {
+ RCU_INIT_POINTER(nfo_info->primary_dev, NULL);
+ if (standby_dev) {
+ failover_dev->min_mtu = standby_dev->min_mtu;
+ failover_dev->max_mtu = standby_dev->max_mtu;
+ }
+ }
+
+ dev_put(slave_dev);
+
+ net_failover_compute_features(failover_dev);
+
+ netdev_info(failover_dev, "failover %s slave:%s unregistered\n",
+ slave_is_standby ? "standby" : "primary", slave_dev->name);
+
+done:
+ return NOTIFY_DONE;
+}
+EXPORT_SYMBOL_GPL(net_failover_slave_unregister);
+
+static int net_failover_slave_link_change(struct net_device *slave_dev)
+{
+ struct net_device *failover_dev, *primary_dev, *standby_dev;
+ struct net_failover_info *nfo_info;
+ struct net_failover_ops *nfo_ops;
+
+ if (!netif_is_failover_slave(slave_dev))
+ goto done;
+
+ ASSERT_RTNL();
+
+ failover_dev = net_failover_get_bymac(slave_dev->perm_addr, &nfo_ops);
+ if (!failover_dev)
+ goto done;
+
+ if (nfo_ops && nfo_ops->slave_link_change)
+ return nfo_ops->slave_link_change(slave_dev, failover_dev);
+
+ if (!netif_running(failover_dev))
+ return 0;
+
+ nfo_info = netdev_priv(failover_dev);
+
+ primary_dev = rtnl_dereference(nfo_info->primary_dev);
+ standby_dev = rtnl_dereference(nfo_info->standby_dev);
+
+ if (slave_dev != primary_dev && slave_dev != standby_dev)
+ goto done;
+
+ if ((primary_dev && net_failover_xmit_ready(primary_dev)) ||
+ (standby_dev && net_failover_xmit_ready(standby_dev))) {
+ netif_carrier_on(failover_dev);
+ netif_tx_wake_all_queues(failover_dev);
+ } else {
+ net_failover_get_stats(failover_dev, &nfo_info->failover_stats);
+ netif_carrier_off(failover_dev);
+ netif_tx_stop_all_queues(failover_dev);
+ }
+
+done:
+ return NOTIFY_DONE;
+}
+
+static int
+net_failover_event(struct notifier_block *this, unsigned long event, void *ptr)
+{
+ struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+ /* Skip parent events */
+ if (netif_is_failover(event_dev))
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case NETDEV_REGISTER:
+ return net_failover_slave_register(event_dev);
+ case NETDEV_UNREGISTER:
+ return net_failover_slave_unregister(event_dev);
+ case NETDEV_UP:
+ case NETDEV_DOWN:
+ case NETDEV_CHANGE:
+ return net_failover_slave_link_change(event_dev);
+ default:
+ return NOTIFY_DONE;
+ }
+}
+
+static struct notifier_block net_failover_notifier = {
+ .notifier_call = net_failover_event,
+};
+
+static void nfo_register_existing_slave(struct net_device *failover_dev)
+{
+ struct net *net = dev_net(failover_dev);
+ struct net_device *dev;
+
+ rtnl_lock();
+ for_each_netdev(net, dev) {
+ if (netif_is_failover(dev))
+ continue;
+ if (ether_addr_equal(failover_dev->perm_addr, dev->perm_addr))
+ net_failover_slave_register(dev);
+ }
+ rtnl_unlock();
+}
+
+int net_failover_register(struct net_device *dev, struct net_failover_ops *ops,
+ struct net_failover **pfailover)
+{
+ struct net_failover *failover;
+
+ failover = kzalloc(sizeof(*failover), GFP_KERNEL);
+ if (!failover)
+ return -ENOMEM;
+
+ rcu_assign_pointer(failover->ops, ops);
+ dev_hold(dev);
+ dev->priv_flags |= IFF_FAILOVER;
+ rcu_assign_pointer(failover->failover_dev, dev);
+
+ spin_lock(&net_failover_lock);
+ list_add_tail(&failover->list, &net_failover_list);
+ spin_unlock(&net_failover_lock);
+
+ netdev_info(dev, "failover master:%s registered\n", dev->name);
+
+ nfo_register_existing_slave(dev);
+
+ *pfailover = failover;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(net_failover_register);
+
+void net_failover_unregister(struct net_failover *failover)
+{
+ struct net_device *failover_dev;
+
+ failover_dev = rcu_dereference(failover->failover_dev);
+
+ netdev_info(failover_dev, "failover master:%s unregistered\n",
+ failover_dev->name);
+
+ failover_dev->priv_flags &= ~IFF_FAILOVER;
+ dev_put(failover_dev);
+
+ spin_lock(&net_failover_lock);
+ list_del(&failover->list);
+ spin_unlock(&net_failover_lock);
+
+ kfree(failover);
+}
+EXPORT_SYMBOL_GPL(net_failover_unregister);
+
+int net_failover_create(struct net_device *standby_dev,
+ struct net_failover **pfailover)
+{
+ struct device *dev = standby_dev->dev.parent;
+ struct net_device *failover_dev;
+ int err;
+
+ /* Alloc at least 2 queues, for now we are going with 16 assuming
+ * that VF devices being enslaved won't have too many queues.
+ */
+ failover_dev = alloc_etherdev_mq(sizeof(struct net_failover_info), 16);
+ if (!failover_dev) {
+ dev_err(dev, "Unable to allocate failover_netdev!\n");
+ return -ENOMEM;
+ }
+
+ dev_net_set(failover_dev, dev_net(standby_dev));
+ SET_NETDEV_DEV(failover_dev, dev);
+
+ failover_dev->netdev_ops = &failover_dev_ops;
+ failover_dev->ethtool_ops = &failover_ethtool_ops;
+
+ /* Initialize the device options */
+ failover_dev->priv_flags |= IFF_UNICAST_FLT | IFF_NO_QUEUE;
+ failover_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE |
+ IFF_TX_SKB_SHARING);
+
+ /* don't acquire failover netdev's netif_tx_lock when transmitting */
+ failover_dev->features |= NETIF_F_LLTX;
+
+ /* Don't allow failover devices to change network namespaces. */
+ failover_dev->features |= NETIF_F_NETNS_LOCAL;
+
+ failover_dev->hw_features = FAILOVER_VLAN_FEATURES |
+ NETIF_F_HW_VLAN_CTAG_TX |
+ NETIF_F_HW_VLAN_CTAG_RX |
+ NETIF_F_HW_VLAN_CTAG_FILTER;
+
+ failover_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL;
+ failover_dev->features |= failover_dev->hw_features;
+
+ memcpy(failover_dev->dev_addr, standby_dev->dev_addr,
+ failover_dev->addr_len);
+
+ failover_dev->min_mtu = standby_dev->min_mtu;
+ failover_dev->max_mtu = standby_dev->max_mtu;
+
+ err = register_netdev(failover_dev);
+ if (err < 0) {
+ dev_err(dev, "Unable to register failover_dev!\n");
+ goto err_register_netdev;
+ }
+
+ netif_carrier_off(failover_dev);
+
+ err = net_failover_register(failover_dev, NULL, pfailover);
+ if (err < 0)
+ goto err_failover_register;
+
+ return 0;
+
+err_failover_register:
+ unregister_netdev(failover_dev);
+err_register_netdev:
+ free_netdev(failover_dev);
+
+ return err;
+}
+EXPORT_SYMBOL_GPL(net_failover_create);
+
+void net_failover_destroy(struct net_failover *failover)
+{
+ struct net_failover_info *nfo_info;
+ struct net_device *failover_dev;
+ struct net_device *slave_dev;
+
+ if (!failover)
+ return;
+
+ failover_dev = rcu_dereference(failover->failover_dev);
+ nfo_info = netdev_priv(failover_dev);
+
+ netif_device_detach(failover_dev);
+
+ rtnl_lock();
+
+ slave_dev = rtnl_dereference(nfo_info->primary_dev);
+ if (slave_dev)
+ net_failover_slave_unregister(slave_dev);
+
+ slave_dev = rtnl_dereference(nfo_info->standby_dev);
+ if (slave_dev)
+ net_failover_slave_unregister(slave_dev);
+
+ net_failover_unregister(failover);
+
+ unregister_netdevice(failover_dev);
+
+ rtnl_unlock();
+
+ free_netdev(failover_dev);
+}
+EXPORT_SYMBOL_GPL(net_failover_destroy);
+
+static __init int
+net_failover_init(void)
+{
+ register_netdevice_notifier(&net_failover_notifier);
+
+ return 0;
+}
+module_init(net_failover_init);
+
+static __exit
+void net_failover_exit(void)
+{
+ unregister_netdevice_notifier(&net_failover_notifier);
+}
+module_exit(net_failover_exit);
+
+MODULE_DESCRIPTION("Failover infrastructure/interface for Paravirtual drivers");
+MODULE_LICENSE("GPL v2");
--
2.14.3
^ permalink raw reply related
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