* [PATCH] net: sunrpc: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-20 16:48 UTC (permalink / raw)
To: Trond Myklebust, Anna Schumaker, J. Bruce Fields, Jeff Layton,
David S. Miller
Cc: linux-nfs, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.
net/sunrpc/clnt.c | 11 +++++++++++
net/sunrpc/xprt.c | 1 +
net/sunrpc/xprtsock.c | 4 ++++
3 files changed, 16 insertions(+)
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 2ad827d..d25b077 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1586,6 +1586,7 @@ call_reserveresult(struct rpc_task *task)
switch (status) {
case -ENOMEM:
rpc_delay(task, HZ >> 2);
+ /* fall through */
case -EAGAIN: /* woken up; retry */
task->tk_action = call_retry_reserve;
return;
@@ -1647,10 +1648,13 @@ call_refreshresult(struct rpc_task *task)
/* Use rate-limiting and a max number of retries if refresh
* had status 0 but failed to update the cred.
*/
+ /* fall through */
case -ETIMEDOUT:
rpc_delay(task, 3*HZ);
+ /* fall through */
case -EAGAIN:
status = -EACCES;
+ /* fall through */
case -EKEYEXPIRED:
if (!task->tk_cred_retry)
break;
@@ -1911,6 +1915,7 @@ call_connect_status(struct rpc_task *task)
task->tk_action = call_bind;
return;
}
+ /* fall through */
case -ECONNRESET:
case -ECONNABORTED:
case -ENETUNREACH:
@@ -1924,6 +1929,7 @@ call_connect_status(struct rpc_task *task)
break;
/* retry with existing socket, after a delay */
rpc_delay(task, 3*HZ);
+ /* fall through */
case -EAGAIN:
/* Check for timeouts before looping back to call_bind */
case -ETIMEDOUT:
@@ -2025,6 +2031,7 @@ call_transmit_status(struct rpc_task *task)
rpc_exit(task, task->tk_status);
break;
}
+ /* fall through */
case -ECONNRESET:
case -ECONNABORTED:
case -EADDRINUSE:
@@ -2145,6 +2152,7 @@ call_status(struct rpc_task *task)
* were a timeout.
*/
rpc_delay(task, 3*HZ);
+ /* fall through */
case -ETIMEDOUT:
task->tk_action = call_timeout;
break;
@@ -2152,14 +2160,17 @@ call_status(struct rpc_task *task)
case -ECONNRESET:
case -ECONNABORTED:
rpc_force_rebind(clnt);
+ /* fall through */
case -EADDRINUSE:
rpc_delay(task, 3*HZ);
+ /* fall through */
case -EPIPE:
case -ENOTCONN:
task->tk_action = call_bind;
break;
case -ENOBUFS:
rpc_delay(task, HZ>>2);
+ /* fall through */
case -EAGAIN:
task->tk_action = call_transmit;
break;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index 1a39ad1..197883f 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1139,6 +1139,7 @@ void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
case -EAGAIN:
xprt_add_backlog(xprt, task);
dprintk("RPC: waiting for request slot\n");
+ /* fall through */
default:
task->tk_status = -EAGAIN;
}
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index c1841f2..684e356 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -551,6 +551,7 @@ static int xs_local_send_request(struct rpc_task *task)
default:
dprintk("RPC: sendmsg returned unrecognized error %d\n",
-status);
+ /* fall through */
case -EPIPE:
xs_close(xprt);
status = -ENOTCONN;
@@ -1610,6 +1611,7 @@ static void xs_tcp_state_change(struct sock *sk)
xprt->connect_cookie++;
clear_bit(XPRT_CONNECTED, &xprt->state);
xs_tcp_force_close(xprt);
+ /* fall through */
case TCP_CLOSING:
/*
* If the server closed down the connection, make sure that
@@ -2367,6 +2369,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
switch (ret) {
case 0:
xs_set_srcport(transport, sock);
+ /* fall through */
case -EINPROGRESS:
/* SYN_SENT! */
if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
@@ -2418,6 +2421,7 @@ static void xs_tcp_setup_socket(struct work_struct *work)
default:
printk("%s: connect returned unhandled error %d\n",
__func__, status);
+ /* fall through */
case -EADDRNOTAVAIL:
/* We're probably in TIME_WAIT. Get rid of existing socket,
* and retry
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net] dccp/tcp: fix ireq->opt races
From: kbuild test robot @ 2017-10-20 16:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: kbuild-all, David Miller, netdev, edumazet
In-Reply-To: <1508269854.31614.114.camel@edumazet-glaptop3.roam.corp.google.com>
[-- Attachment #1: Type: text/plain, Size: 15070 bytes --]
Hi Eric,
[auto build test WARNING on net/master]
url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
config: ia64-allmodconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 6.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=ia64
All warnings (new ones prefixed by >>):
In file included from arch/ia64/include/uapi/asm/intrinsics.h:21:0,
from arch/ia64/include/asm/intrinsics.h:10,
from arch/ia64/include/asm/atomic.h:17,
from include/linux/atomic.h:4,
from include/linux/rcupdate.h:38,
from net/ipv4/cipso_ipv4.c:40:
net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/cmpxchg.h:56:16: note: in definition of macro 'xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/cmpxchg.h:33:10: note: in definition of macro '__xchg'
switch (size) { \
^~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
In file included from arch/ia64/include/asm/gcc_intrin.h:9:0,
from arch/ia64/include/uapi/asm/intrinsics.h:19,
from arch/ia64/include/asm/intrinsics.h:10,
from arch/ia64/include/asm/atomic.h:17,
from include/linux/atomic.h:4,
from include/linux/rcupdate.h:38,
from net/ipv4/cipso_ipv4.c:40:
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:279:40: note: in definition of macro 'ia64_xchg1'
: "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:287:16: note: in definition of macro 'ia64_xchg2'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:295:16: note: in definition of macro 'ia64_xchg4'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:303:16: note: in definition of macro 'ia64_xchg8'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
>> net/ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
net/ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
opt = req_inet->opt;
^~
net/ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
cipso_v4_delopt(&req_inet->opt);
^~
--
In file included from arch/ia64/include/uapi/asm/intrinsics.h:21:0,
from arch/ia64/include/asm/intrinsics.h:10,
from arch/ia64/include/asm/atomic.h:17,
from include/linux/atomic.h:4,
from include/linux/rcupdate.h:38,
from net//ipv4/cipso_ipv4.c:40:
net//ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/cmpxchg.h:56:16: note: in definition of macro 'xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/cmpxchg.h:33:10: note: in definition of macro '__xchg'
switch (size) { \
^~~~
net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
In file included from arch/ia64/include/asm/gcc_intrin.h:9:0,
from arch/ia64/include/uapi/asm/intrinsics.h:19,
from arch/ia64/include/asm/intrinsics.h:10,
from arch/ia64/include/asm/atomic.h:17,
from include/linux/atomic.h:4,
from include/linux/rcupdate.h:38,
from net//ipv4/cipso_ipv4.c:40:
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:279:40: note: in definition of macro 'ia64_xchg1'
: "=r" (ia64_intri_res) : "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:287:16: note: in definition of macro 'ia64_xchg2'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:295:16: note: in definition of macro 'ia64_xchg4'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net//ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/ia64/include/uapi/asm/gcc_intrin.h:303:16: note: in definition of macro 'ia64_xchg8'
: "r" (ptr), "r" (x) : "memory"); \
^~~
>> arch/ia64/include/uapi/asm/cmpxchg.h:56:23: note: in expansion of macro '__xchg'
((__typeof__(*(ptr))) __xchg((unsigned long) (x), (ptr), sizeof(*(ptr))))
^~~~~~
net//ipv4/cipso_ipv4.c:1954:8: note: in expansion of macro 'xchg'
opt = xchg(&req_inet->opt, opt);
^~~~
net//ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
net//ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
opt = req_inet->opt;
^~
net//ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
cipso_v4_delopt(&req_inet->opt);
^~
vim +/xchg +1954 net/ipv4/cipso_ipv4.c
446fda4f2 Paul Moore 2006-08-03 1898
446fda4f2 Paul Moore 2006-08-03 1899 /**
389fb800a Paul Moore 2009-03-27 1900 * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
389fb800a Paul Moore 2009-03-27 1901 * @req: the connection request socket
389fb800a Paul Moore 2009-03-27 1902 * @doi_def: the CIPSO DOI to use
389fb800a Paul Moore 2009-03-27 1903 * @secattr: the specific security attributes of the socket
014ab19a6 Paul Moore 2008-10-10 1904 *
014ab19a6 Paul Moore 2008-10-10 1905 * Description:
389fb800a Paul Moore 2009-03-27 1906 * Set the CIPSO option on the given socket using the DOI definition and
389fb800a Paul Moore 2009-03-27 1907 * security attributes passed to the function. Returns zero on success and
389fb800a Paul Moore 2009-03-27 1908 * negative values on failure.
014ab19a6 Paul Moore 2008-10-10 1909 *
014ab19a6 Paul Moore 2008-10-10 1910 */
389fb800a Paul Moore 2009-03-27 1911 int cipso_v4_req_setattr(struct request_sock *req,
389fb800a Paul Moore 2009-03-27 1912 const struct cipso_v4_doi *doi_def,
389fb800a Paul Moore 2009-03-27 1913 const struct netlbl_lsm_secattr *secattr)
014ab19a6 Paul Moore 2008-10-10 1914 {
389fb800a Paul Moore 2009-03-27 1915 int ret_val = -EPERM;
389fb800a Paul Moore 2009-03-27 1916 unsigned char *buf = NULL;
389fb800a Paul Moore 2009-03-27 1917 u32 buf_len;
389fb800a Paul Moore 2009-03-27 1918 u32 opt_len;
f6d8bd051 Eric Dumazet 2011-04-21 1919 struct ip_options_rcu *opt = NULL;
389fb800a Paul Moore 2009-03-27 1920 struct inet_request_sock *req_inet;
014ab19a6 Paul Moore 2008-10-10 1921
389fb800a Paul Moore 2009-03-27 1922 /* We allocate the maximum CIPSO option size here so we are probably
389fb800a Paul Moore 2009-03-27 1923 * being a little wasteful, but it makes our life _much_ easier later
389fb800a Paul Moore 2009-03-27 1924 * on and after all we are only talking about 40 bytes. */
389fb800a Paul Moore 2009-03-27 1925 buf_len = CIPSO_V4_OPT_LEN_MAX;
389fb800a Paul Moore 2009-03-27 1926 buf = kmalloc(buf_len, GFP_ATOMIC);
51456b291 Ian Morris 2015-04-03 1927 if (!buf) {
389fb800a Paul Moore 2009-03-27 1928 ret_val = -ENOMEM;
389fb800a Paul Moore 2009-03-27 1929 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1930 }
389fb800a Paul Moore 2009-03-27 1931
389fb800a Paul Moore 2009-03-27 1932 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
389fb800a Paul Moore 2009-03-27 1933 if (ret_val < 0)
389fb800a Paul Moore 2009-03-27 1934 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1935 buf_len = ret_val;
389fb800a Paul Moore 2009-03-27 1936
389fb800a Paul Moore 2009-03-27 1937 /* We can't use ip_options_get() directly because it makes a call to
389fb800a Paul Moore 2009-03-27 1938 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
389fb800a Paul Moore 2009-03-27 1939 * we won't always have CAP_NET_RAW even though we _always_ want to
389fb800a Paul Moore 2009-03-27 1940 * set the IPOPT_CIPSO option. */
389fb800a Paul Moore 2009-03-27 1941 opt_len = (buf_len + 3) & ~3;
389fb800a Paul Moore 2009-03-27 1942 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
51456b291 Ian Morris 2015-04-03 1943 if (!opt) {
389fb800a Paul Moore 2009-03-27 1944 ret_val = -ENOMEM;
389fb800a Paul Moore 2009-03-27 1945 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1946 }
f6d8bd051 Eric Dumazet 2011-04-21 1947 memcpy(opt->opt.__data, buf, buf_len);
f6d8bd051 Eric Dumazet 2011-04-21 1948 opt->opt.optlen = opt_len;
f6d8bd051 Eric Dumazet 2011-04-21 1949 opt->opt.cipso = sizeof(struct iphdr);
389fb800a Paul Moore 2009-03-27 1950 kfree(buf);
389fb800a Paul Moore 2009-03-27 1951 buf = NULL;
389fb800a Paul Moore 2009-03-27 1952
389fb800a Paul Moore 2009-03-27 1953 req_inet = inet_rsk(req);
389fb800a Paul Moore 2009-03-27 @1954 opt = xchg(&req_inet->opt, opt);
f6d8bd051 Eric Dumazet 2011-04-21 1955 if (opt)
4f9c8c1b0 Paul E. McKenney 2012-01-06 1956 kfree_rcu(opt, rcu);
389fb800a Paul Moore 2009-03-27 1957
389fb800a Paul Moore 2009-03-27 1958 return 0;
389fb800a Paul Moore 2009-03-27 1959
389fb800a Paul Moore 2009-03-27 1960 req_setattr_failure:
389fb800a Paul Moore 2009-03-27 1961 kfree(buf);
389fb800a Paul Moore 2009-03-27 1962 kfree(opt);
389fb800a Paul Moore 2009-03-27 1963 return ret_val;
389fb800a Paul Moore 2009-03-27 1964 }
389fb800a Paul Moore 2009-03-27 1965
:::::: The code at line 1954 was first introduced by commit
:::::: 389fb800ac8be2832efedd19978a2b8ced37eb61 netlabel: Label incoming TCP connections correctly in SELinux
:::::: TO: Paul Moore <paul.moore@hp.com>
:::::: CC: James Morris <jmorris@namei.org>
---
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: 48800 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] net: netrom: refactor code in nr_add_node
From: walter harms @ 2017-10-20 16:54 UTC (permalink / raw)
To: Gustavo A. R. Silva; +Cc: Ralf Baechle, David S. Miller, linux-hams, netdev
In-Reply-To: <20171020110600.Horde.X15IwxxrG50sNBWbTzaM1pB@gator4166.hostgator.com>
Am 20.10.2017 18:06, schrieb Gustavo A. R. Silva:
> Hi Walter,
>
> Quoting walter harms <wharms@bfs.de>:
>
>> Am 19.10.2017 19:27, schrieb Gustavo A. R. Silva:
>>> Code refactoring in order to make the code easier to read and maintain.
>>>
>>> Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
>>> ---
>>> This code was tested by compilation only (GCC 7.2.0 was used).
>>>
>>> net/netrom/nr_route.c | 63
>>> ++++++++++++++++-----------------------------------
>>> 1 file changed, 20 insertions(+), 43 deletions(-)
>>>
>>> diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
>>> index fc9cadc..1e5165f 100644
>>> --- a/net/netrom/nr_route.c
>>> +++ b/net/netrom/nr_route.c
>>> @@ -80,6 +80,23 @@ static struct nr_neigh
>>> *nr_neigh_get_dev(ax25_address *callsign,
>>>
>>> static void nr_remove_neigh(struct nr_neigh *);
>>>
>>> +/* re-sort the routes in quality order. */
>>> +static inline void re_sort_routes(struct nr_node *nr_node, int ix_x,
>>> int ix_y)
>>> +{
>>> + struct nr_route nr_route;
>>> +
>>> + if (nr_node->routes[ix_y].quality >
>>> nr_node->routes[ix_x].quality) {
>>> + if (nr_node->which == ix_x)
>>> + nr_node->which = ix_y;
>>> + else if (nr_node->which == ix_y)
>>> + nr_node->which = ix_x;
>>> +
>>> + nr_route = nr_node->routes[ix_x];
>>> + nr_node->routes[ix_x] = nr_node->routes[ix_y];
>>> + nr_node->routes[ix_y] = nr_route;
>>> + }
>>> +}
>>> +
>>
>>
>> Good idea, a bit of nit picking ..
>> does ix_ has a special meaning ? otherwise x,y would be sufficient.
>
> ix typical stands for index, but I think just x and y are fine too.
>
>> From the code below i can see: y=x+1 Perhaps that can be used.
>>
>
> So are you proposing to use two arguments instead of three?
>
> re_sort_routes(nr_node, 0);
>
I am not sure, i would wait a bit and see if what improves readability.
as Kevin Dawson pointed out: this is a sort here.
Maybe there a nice way to do something like that (i do not know):
case 3:
re_sort_routes(nr_node, 1,2)
case 2:
re_sort_routes(nr_node, 0,1)
case 1:
break;
The question is: Is the sorted list needed or simply the maximum ?
NTL is a good thing to chop down the function in smaller digestible
peaces.
re,
wh
>
>> kernel.h has a swap() macro. so you can
>> swap(nr_node->routes[x],nr_node->routes[y]);
>>
>
> Nice, I will use that macro.
>
>> hope that helps,
>
> Definitely. I appreciate your comments.
>
> Thanks!
> --
> Gustavo A. R. Silva
>
>
>
>
>
>
>
^ permalink raw reply
* Re: [PATCH net] dccp/tcp: fix ireq->opt races
From: kbuild test robot @ 2017-10-20 16:53 UTC (permalink / raw)
To: Eric Dumazet; +Cc: kbuild-all, David Miller, netdev, edumazet
In-Reply-To: <1508269854.31614.114.camel@edumazet-glaptop3.roam.corp.google.com>
[-- Attachment #1: Type: text/plain, Size: 7802 bytes --]
Hi Eric,
[auto build test ERROR on net/master]
url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
config: blackfin-allyesconfig (attached as .config)
compiler: bfin-uclinux-gcc (GCC) 6.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=blackfin
All errors (new ones prefixed by >>):
In file included from arch/blackfin/include/asm/atomic.h:10:0,
from include/linux/atomic.h:4,
from include/linux/rcupdate.h:38,
from net/ipv4/cipso_ipv4.c:40:
net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_setattr':
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/blackfin/include/asm/cmpxchg.h:130:37: note: in definition of macro 'xchg'
#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
^~~
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/blackfin/include/asm/cmpxchg.h:130:71: note: in definition of macro 'xchg'
#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
^~~
>> net/ipv4/cipso_ipv4.c:1954:22: error: 'struct inet_request_sock' has no member named 'opt'
opt = xchg(&req_inet->opt, opt);
^
arch/blackfin/include/asm/cmpxchg.h:130:86: note: in definition of macro 'xchg'
#define xchg(ptr, x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
^~~
net/ipv4/cipso_ipv4.c: In function 'cipso_v4_req_delattr':
net/ipv4/cipso_ipv4.c:2073:16: error: 'struct inet_request_sock' has no member named 'opt'
opt = req_inet->opt;
^~
net/ipv4/cipso_ipv4.c:2077:27: error: 'struct inet_request_sock' has no member named 'opt'
cipso_v4_delopt(&req_inet->opt);
^~
vim +1954 net/ipv4/cipso_ipv4.c
446fda4f2 Paul Moore 2006-08-03 1898
446fda4f2 Paul Moore 2006-08-03 1899 /**
389fb800a Paul Moore 2009-03-27 1900 * cipso_v4_req_setattr - Add a CIPSO option to a connection request socket
389fb800a Paul Moore 2009-03-27 1901 * @req: the connection request socket
389fb800a Paul Moore 2009-03-27 1902 * @doi_def: the CIPSO DOI to use
389fb800a Paul Moore 2009-03-27 1903 * @secattr: the specific security attributes of the socket
014ab19a6 Paul Moore 2008-10-10 1904 *
014ab19a6 Paul Moore 2008-10-10 1905 * Description:
389fb800a Paul Moore 2009-03-27 1906 * Set the CIPSO option on the given socket using the DOI definition and
389fb800a Paul Moore 2009-03-27 1907 * security attributes passed to the function. Returns zero on success and
389fb800a Paul Moore 2009-03-27 1908 * negative values on failure.
014ab19a6 Paul Moore 2008-10-10 1909 *
014ab19a6 Paul Moore 2008-10-10 1910 */
389fb800a Paul Moore 2009-03-27 1911 int cipso_v4_req_setattr(struct request_sock *req,
389fb800a Paul Moore 2009-03-27 1912 const struct cipso_v4_doi *doi_def,
389fb800a Paul Moore 2009-03-27 1913 const struct netlbl_lsm_secattr *secattr)
014ab19a6 Paul Moore 2008-10-10 1914 {
389fb800a Paul Moore 2009-03-27 1915 int ret_val = -EPERM;
389fb800a Paul Moore 2009-03-27 1916 unsigned char *buf = NULL;
389fb800a Paul Moore 2009-03-27 1917 u32 buf_len;
389fb800a Paul Moore 2009-03-27 1918 u32 opt_len;
f6d8bd051 Eric Dumazet 2011-04-21 1919 struct ip_options_rcu *opt = NULL;
389fb800a Paul Moore 2009-03-27 1920 struct inet_request_sock *req_inet;
014ab19a6 Paul Moore 2008-10-10 1921
389fb800a Paul Moore 2009-03-27 1922 /* We allocate the maximum CIPSO option size here so we are probably
389fb800a Paul Moore 2009-03-27 1923 * being a little wasteful, but it makes our life _much_ easier later
389fb800a Paul Moore 2009-03-27 1924 * on and after all we are only talking about 40 bytes. */
389fb800a Paul Moore 2009-03-27 1925 buf_len = CIPSO_V4_OPT_LEN_MAX;
389fb800a Paul Moore 2009-03-27 1926 buf = kmalloc(buf_len, GFP_ATOMIC);
51456b291 Ian Morris 2015-04-03 1927 if (!buf) {
389fb800a Paul Moore 2009-03-27 1928 ret_val = -ENOMEM;
389fb800a Paul Moore 2009-03-27 1929 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1930 }
389fb800a Paul Moore 2009-03-27 1931
389fb800a Paul Moore 2009-03-27 1932 ret_val = cipso_v4_genopt(buf, buf_len, doi_def, secattr);
389fb800a Paul Moore 2009-03-27 1933 if (ret_val < 0)
389fb800a Paul Moore 2009-03-27 1934 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1935 buf_len = ret_val;
389fb800a Paul Moore 2009-03-27 1936
389fb800a Paul Moore 2009-03-27 1937 /* We can't use ip_options_get() directly because it makes a call to
389fb800a Paul Moore 2009-03-27 1938 * ip_options_get_alloc() which allocates memory with GFP_KERNEL and
389fb800a Paul Moore 2009-03-27 1939 * we won't always have CAP_NET_RAW even though we _always_ want to
389fb800a Paul Moore 2009-03-27 1940 * set the IPOPT_CIPSO option. */
389fb800a Paul Moore 2009-03-27 1941 opt_len = (buf_len + 3) & ~3;
389fb800a Paul Moore 2009-03-27 1942 opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC);
51456b291 Ian Morris 2015-04-03 1943 if (!opt) {
389fb800a Paul Moore 2009-03-27 1944 ret_val = -ENOMEM;
389fb800a Paul Moore 2009-03-27 1945 goto req_setattr_failure;
389fb800a Paul Moore 2009-03-27 1946 }
f6d8bd051 Eric Dumazet 2011-04-21 1947 memcpy(opt->opt.__data, buf, buf_len);
f6d8bd051 Eric Dumazet 2011-04-21 1948 opt->opt.optlen = opt_len;
f6d8bd051 Eric Dumazet 2011-04-21 1949 opt->opt.cipso = sizeof(struct iphdr);
389fb800a Paul Moore 2009-03-27 1950 kfree(buf);
389fb800a Paul Moore 2009-03-27 1951 buf = NULL;
389fb800a Paul Moore 2009-03-27 1952
389fb800a Paul Moore 2009-03-27 1953 req_inet = inet_rsk(req);
389fb800a Paul Moore 2009-03-27 @1954 opt = xchg(&req_inet->opt, opt);
f6d8bd051 Eric Dumazet 2011-04-21 1955 if (opt)
4f9c8c1b0 Paul E. McKenney 2012-01-06 1956 kfree_rcu(opt, rcu);
389fb800a Paul Moore 2009-03-27 1957
389fb800a Paul Moore 2009-03-27 1958 return 0;
389fb800a Paul Moore 2009-03-27 1959
389fb800a Paul Moore 2009-03-27 1960 req_setattr_failure:
389fb800a Paul Moore 2009-03-27 1961 kfree(buf);
389fb800a Paul Moore 2009-03-27 1962 kfree(opt);
389fb800a Paul Moore 2009-03-27 1963 return ret_val;
389fb800a Paul Moore 2009-03-27 1964 }
389fb800a Paul Moore 2009-03-27 1965
:::::: The code at line 1954 was first introduced by commit
:::::: 389fb800ac8be2832efedd19978a2b8ced37eb61 netlabel: Label incoming TCP connections correctly in SELinux
:::::: TO: Paul Moore <paul.moore@hp.com>
:::::: CC: James Morris <jmorris@namei.org>
---
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: 46054 bytes --]
^ permalink raw reply
* Re: Get rid of RCU callbacks in TC filters?
From: Paul E. McKenney @ 2017-10-20 16:56 UTC (permalink / raw)
To: Cong Wang
Cc: Jamal Hadi Salim, Chris Mi, Linux Kernel Network Developers,
Daniel Borkmann, Eric Dumazet, David Miller, Jiri Pirko
In-Reply-To: <CAM_iQpWwaQuxZMidkVXsjDVwGcW+u-h5rczG2CO0s1RamRVUYQ@mail.gmail.com>
On Thu, Oct 19, 2017 at 08:26:01PM -0700, Cong Wang wrote:
> On Wed, Oct 18, 2017 at 12:35 PM, Paul E. McKenney
> <paulmck@linux.vnet.ibm.com> wrote:
> > On Wed, Oct 18, 2017 at 10:36:28AM -0700, Cong Wang wrote:
> >> Hi, all
> >>
> >> Recently, the RCU callbacks used in TC filters and TC actions keep
> >> drawing my attention, they introduce at least 4 race condition bugs:
> >>
> >> 1. A simple one fixed by Daniel:
> >>
> >> commit c78e1746d3ad7d548bdf3fe491898cc453911a49
> >> Author: Daniel Borkmann <daniel@iogearbox.net>
> >> Date: Wed May 20 17:13:33 2015 +0200
> >>
> >> net: sched: fix call_rcu() race on classifier module unloads
> >>
> >> 2. A very nasty one fixed by me:
> >>
> >> commit 1697c4bb5245649a23f06a144cc38c06715e1b65
> >> Author: Cong Wang <xiyou.wangcong@gmail.com>
> >> Date: Mon Sep 11 16:33:32 2017 -0700
> >>
> >> net_sched: carefully handle tcf_block_put()
> >>
> >> 3. Two more bugs found by Chris:
> >> https://patchwork.ozlabs.org/patch/826696/
> >> https://patchwork.ozlabs.org/patch/826695/
> >>
> >>
> >> Usually RCU callbacks are simple, however for TC filters and actions,
> >> they are complex because at least TC actions could be destroyed
> >> together with the TC filter in one callback. And RCU callbacks are
> >> invoked in BH context, without locking they are parallel too. All of
> >> these contribute to the cause of these nasty bugs. It looks like they
> >> bring us more problems than benefits.
> >>
> >> Therefore, I have been thinking about getting rid of these callbacks,
> >> because they are not strictly necessary, callers of these call_rcu()
> >> are all on slow path and have RTNL lock, so blocking is permitted in
> >> their contexts, and _I think_ it does not harm to use
> >> synchronize_rcu() on slow paths, at least I can argue RTNL lock is
> >> already there and is a bottleneck if we really care. :)
> >>
> >> There are 3 solutions here:
> >>
> >> 1) Get rid of these RCU callbacks and use synchronize_rcu(). The
> >> downside is this could hurt the performance of deleting TC filters,
> >> but again it is slow path comparing to skb classification path. Note,
> >> it is _not_ merely replacing call_rcu() with synchronize_rcu(),
> >> because many call_rcu()'s are actually in list iterations, we have to
> >> use a local list and call list_del_rcu()+list_add() before
> >> synchronize_rcu() (Or is there any other API I am not aware of?). If
> >> people really hate synchronize_rcu() because of performance, we could
> >> also defer the work to a workqueue and callers could keep their
> >> performance as they are.
> >>
> >> 2) Introduce a spinlock to serialize these RCU callbacks. But as I
> >> said in commit 1697c4bb5245 ("net_sched: carefully handle
> >> tcf_block_put()"), it is very hard to do because of tcf_chain_dump().
> >> Potentially we need to do a lot of work to make it possible, if not
> >> impossible.
> >>
> >> 3) Keep these RCU callbacks and fix all race conditions. Like what
> >> Chris tries to do in his patchset, but my argument is that we can not
> >> prove we are really race-free even with Chris' patches and his patches
> >> are already large enough.
> >>
> >>
> >> What do you think? Any other ideas?
> >
> > 4) Move from call_rcu() to synchronize_rcu(), but if feasible use one
> > synchronize_rcu() for multiple deletions/iterations.
>
> This is what I meant by using a local list, perhaps I didn't make it clear.
Ah, got it.
> > 5) Keep call_rcu(), but have the RCU callback schedule a workqueue.
> > The workqueue could then use blocking primitives, for example, acquiring
> > RTNL.
>
> Yeah, this could work too but we would get one more async...
>
> filter delete -> call_rcu() -> schedule_work() -> action destroy
True, but on the other hand you get to hold RTNL.
> > 6) As with #5, have the RCU callback schedule a workqueue, but aggregate
> > workqueue scheduling using a timer. This would reduce the number of
> > RTNL acquisitions.
>
> Ouch, sounds like even one more async:
>
> filter delete -> call_rcu() -> schedule_work() -> timer -> flush_work()
> -> action destroy
>
> :-(
Indeed, the price of scalability and performance is often added
asynchronous action at a distance. But sometimes you can have
scalability, performance, -and- synchronous action. Not sure that this
is one of those cases, but perhaps someone will come up with some trick
that we are not yet seeing.
And again, one benefit you get from the added asynchrony is the ability
to acquire RTNL. Another is increased batching, allowing the overhead
of acquiring RTNL to be amortized over a larger number of updates.
> > 7) As with #5, have the RCU callback schedule a workqueue, but have each
> > iterator accumulate a list of things removed and do call_rcu() on the
> > list. This is an alternative way of aggregating to reduce the number
> > of RTNL acquisitions.
>
> Yeah, this seems working too.
>
> > There are many other ways to skin this cat.
>
> We still have to pick one. :) Any preference? I want to keep it as simple
> as possible, otherwise some day I would not understand it either.
I must defer to the people who actually fully understand this code.
> Thanks for all the ideas!
Please let me know how it goes!
Thanx, Paul
^ permalink raw reply
* [PATCH] net: tipc: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-20 17:01 UTC (permalink / raw)
To: Jon Maloy, Ying Xue, David S. Miller
Cc: netdev, tipc-discussion, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.
net/tipc/bearer.c | 1 +
net/tipc/link.c | 3 ++-
net/tipc/socket.c | 4 ++--
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 47ec121..786dcfd 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -615,6 +615,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
case NETDEV_CHANGE:
if (netif_carrier_ok(dev))
break;
+ /* fall through */
case NETDEV_UP:
test_and_set_bit_lock(0, &b->up);
break;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 870b9b8..fc1714e 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1051,6 +1051,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
skb_queue_tail(mc_inputq, skb);
return true;
}
+ /* fall through */
case CONN_MANAGER:
skb_queue_tail(inputq, skb);
return true;
@@ -1463,7 +1464,7 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
if ((less_eq(msg_session(hdr), l->peer_session)) &&
(l->peer_session != ANY_SESSION))
break;
- /* fall thru' */
+ /* fall through */
case ACTIVATE_MSG:
diff --git a/net/tipc/socket.c b/net/tipc/socket.c
index 2bbab4f..ce6cd01 100644
--- a/net/tipc/socket.c
+++ b/net/tipc/socket.c
@@ -730,7 +730,7 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock,
case TIPC_ESTABLISHED:
if (!tsk->cong_link_cnt && !tsk_conn_cong(tsk))
revents |= POLLOUT;
- /* fall thru' */
+ /* fall through */
case TIPC_LISTEN:
case TIPC_CONNECTING:
if (skb)
@@ -2341,7 +2341,7 @@ static int tipc_connect(struct socket *sock, struct sockaddr *dest,
* case is EINPROGRESS, rather than EALREADY.
*/
res = -EINPROGRESS;
- /* fall thru' */
+ /* fall through */
case TIPC_CONNECTING:
if (!timeout) {
if (previous == TIPC_CONNECTING)
--
2.7.4
^ permalink raw reply related
* [PATCH] net: af_unix: mark expected switch fall-through
From: Gustavo A. R. Silva @ 2017-10-20 17:05 UTC (permalink / raw)
To: David S. Miller; +Cc: netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.
net/unix/af_unix.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 7f46bab..a9ee634 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -814,6 +814,7 @@ static int unix_create(struct net *net, struct socket *sock, int protocol,
*/
case SOCK_RAW:
sock->type = SOCK_DGRAM;
+ /* fall through */
case SOCK_DGRAM:
sock->ops = &unix_dgram_ops;
break;
--
2.7.4
^ permalink raw reply related
* Re: [Intel-wired-lan] [PATCH] [v2] i40e: avoid 64-bit division where possible
From: Alexander Duyck @ 2017-10-20 17:10 UTC (permalink / raw)
To: Nambiar, Amritha
Cc: Arnd Bergmann, Netdev, Mitch Williams,
linux-kernel@vger.kernel.org, intel-wired-lan,
Björn Töpel, Filip Sadowski, David S. Miller
In-Reply-To: <ae467f28-a972-dc2d-1bc8-e8ce4c7d9d68@intel.com>
On Tue, Oct 17, 2017 at 10:37 PM, Nambiar, Amritha
<amritha.nambiar@intel.com> wrote:
> On 10/17/2017 10:33 AM, Alexander Duyck wrote:
>> On Tue, Oct 17, 2017 at 8:49 AM, Arnd Bergmann <arnd@arndb.de> wrote:
>>> The new bandwidth calculation caused a link error on 32-bit
>>> architectures, like
>>>
>>> ERROR: "__aeabi_uldivmod" [drivers/net/ethernet/intel/i40e/i40e.ko] undefined!
>>>
>>> The problem is the max_tx_rate calculation that uses 64-bit integers.
>>> This is not really necessary since the numbers are in MBit/s so
>>> they won't be higher than 40000 for the highest support rate, and
>>> are guaranteed to not exceed 2^32 in future generations either.
>>>
>>> Another patch from Alan Brady fixed the link error by adding
>>> many calls to do_div(), which makes the code less efficent and
>>> less readable than necessary.
>>>
>>> This changes the representation to 'u32' when dealing with MBit/s
>>> and uses div_u64() to convert from u64 numbers in byte/s, reverting
>>> parts of Alan's earlier fix that have become obsolete now.
>>>
>
> This patch breaks the functionality while converting the rates in
> bytes/s provided by tc-layer into the Mbit/s in the driver.
> I40E_BW_MBPS_DIVISOR defined in Alan's patch should be used for the
> conversion, and not I40E_BW_CREDIT_DIVISOR which does the incorrect
> math. I40E_BW_CREDIT_DIVISOR is in place because the device uses credit
> rates in values of 50Mbps.
Can we get the patch that was applied to the tree pulled? The patch
itself contained some bugs as Amritha had pointed out, but it looks
like there was some sort of merge conflict or something and now I
cannot get the tree to build without having to revert the patch since
somehow the code around i40e_rebuild_channels changed and is now
throwing errors because "credits" wasn't replaced and is still
accessed in the dev_dbg command.
- Alex
^ permalink raw reply
* [PATCH] net: wireless: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-20 17:21 UTC (permalink / raw)
To: Johannes Berg, David S. Miller
Cc: linux-wireless, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.
net/wireless/chan.c | 2 ++
net/wireless/nl80211.c | 10 ++++++++++
net/wireless/scan.c | 3 ++-
net/wireless/wext-compat.c | 2 ++
4 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index eb82427..6072613 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -741,6 +741,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
case NL80211_CHAN_WIDTH_20:
if (!ht_cap->ht_supported)
return false;
+ /* fall through */
case NL80211_CHAN_WIDTH_20_NOHT:
prohibited_flags |= IEEE80211_CHAN_NO_20MHZ;
width = 20;
@@ -763,6 +764,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
return false;
+ /* fall through */
case NL80211_CHAN_WIDTH_80:
if (!vht_cap->vht_supported)
return false;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fce2cbe..a8bbb6c 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1509,6 +1509,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 1:
if (nla_put(msg, NL80211_ATTR_CIPHER_SUITES,
sizeof(u32) * rdev->wiphy.n_cipher_suites,
@@ -1555,6 +1556,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 2:
if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES,
rdev->wiphy.interface_modes))
@@ -1562,6 +1564,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 3:
nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS);
if (!nl_bands)
@@ -1587,6 +1590,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->chan_start++;
if (state->split)
break;
+ /* fall through */
default:
/* add frequencies */
nl_freqs = nla_nest_start(
@@ -1640,6 +1644,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 4:
nl_cmds = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_COMMANDS);
if (!nl_cmds)
@@ -1666,6 +1671,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 5:
if (rdev->ops->remain_on_channel &&
(rdev->wiphy.flags & WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL) &&
@@ -1683,6 +1689,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 6:
#ifdef CONFIG_PM
if (nl80211_send_wowlan(msg, rdev, state->split))
@@ -1693,6 +1700,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
#else
state->split_start++;
#endif
+ /* fall through */
case 7:
if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES,
rdev->wiphy.software_iftypes))
@@ -1705,6 +1713,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
state->split_start++;
if (state->split)
break;
+ /* fall through */
case 8:
if ((rdev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME) &&
nla_put_u32(msg, NL80211_ATTR_DEVICE_AP_SME,
@@ -4192,6 +4201,7 @@ static int parse_station_flags(struct genl_info *info,
params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
BIT(NL80211_STA_FLAG_MFP) |
BIT(NL80211_STA_FLAG_AUTHORIZED);
+ /* fall through */
default:
return -EINVAL;
}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 9f0901f..ebfb6d8 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1139,7 +1139,8 @@ cfg80211_inform_bss_data(struct wiphy *wiphy,
switch (ftype) {
case CFG80211_BSS_FTYPE_BEACON:
ies->from_beacon = true;
- /* fall through to assign */
+ /* to assign */
+ /* fall through */
case CFG80211_BSS_FTYPE_UNKNOWN:
rcu_assign_pointer(tmp.pub.beacon_ies, ies);
break;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 5d4a02c..a8d96e7 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1333,6 +1333,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
wstats.qual.qual = sig + 110;
break;
}
+ /* fall through */
case CFG80211_SIGNAL_TYPE_UNSPEC:
if (sinfo.filled & BIT(NL80211_STA_INFO_SIGNAL)) {
wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED;
@@ -1341,6 +1342,7 @@ static struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev)
wstats.qual.qual = sinfo.signal;
break;
}
+ /* fall through */
default:
wstats.qual.updated |= IW_QUAL_LEVEL_INVALID;
wstats.qual.updated |= IW_QUAL_QUAL_INVALID;
--
2.7.4
^ permalink raw reply related
* removing bridge in vlan_filtering mode requests delete of attached ports main MAC address
From: Keller, Jacob E @ 2017-10-20 17:23 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: Malek, Patryk, Vlad Yasevich
Hi,
We've run into an issue with bridges set in vlan_filtering mode. Basically, if we attach a device to a bridge which has enabled vlan_filtering, and then remove the bridge, we end up requesting the driver of the attached device to remove its own MAC HW address.
In i40e, at least, this causes the driver to actually delete such an address and then it will no longer receive any traffic.
To reproduce this:
a) brctl addbr br0
b) brctl addif br0 enp<n>
# enable vlan filtering
c) echo 1 >/sys/class/net/br0/bridge/vlan_filtering
d) brctl delbr br0
Specifically this appears to happen because of how we automatically enter static configuration for routes when vlan_filtering is enabled, and we call br_fdb_unsync_static which will clear all the routes from the fdb table for the device. See commit 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.", 2014-05-16) for more details.
This happens to include the devices own default address, which results in the bug.
I'm not sure if this is a driver bug, or if it's a bug in the bridging code.
Who would know more about this and what to do about this?
One obvious solution is to hard code the i40e device driver so that it does not actually delete the HW address from the unicast filter list. This could work, but seems to me like its papering over the problem. Is this just a known thing that drivers should be aware of? I don't really know...
An alternative solution would be to possibly ignore any fdb addresses which specifically target that port?
Any ideas?
Regards,
Jake
^ permalink raw reply
* [PATCH] net: x25: mark expected switch fall-throughs
From: Gustavo A. R. Silva @ 2017-10-20 17:37 UTC (permalink / raw)
To: Andrew Hendry, David S. Miller
Cc: linux-x25, netdev, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <garsilva@embeddedor.com>
---
This code was tested by compilation only (GCC 7.2.0 was used).
Please, verify if the actual intention of the code is to fall through.
net/x25/x25_facilities.c | 2 +-
net/x25/x25_in.c | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c
index 997ff7b..ad1734d 100644
--- a/net/x25/x25_facilities.c
+++ b/net/x25/x25_facilities.c
@@ -103,7 +103,7 @@ int x25_parse_facilities(struct sk_buff *skb, struct x25_facilities *facilities,
*vc_fac_mask |= X25_MASK_REVERSE;
break;
}
-
+ /*fall through */
case X25_FAC_THROUGHPUT:
facilities->throughput = p[1];
*vc_fac_mask |= X25_MASK_THROUGHPUT;
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c
index 7ac5009..3c12cae 100644
--- a/net/x25/x25_in.c
+++ b/net/x25/x25_in.c
@@ -345,6 +345,7 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp
case X25_RESET_REQUEST:
x25_write_internal(sk, X25_RESET_CONFIRMATION);
+ /* fall through */
case X25_RESET_CONFIRMATION: {
x25_stop_timer(sk);
x25->condition = 0x00;
--
2.7.4
^ permalink raw reply related
* Re: [PATCH net] dccp/tcp: fix ireq->opt races
From: Eric Dumazet @ 2017-10-20 17:38 UTC (permalink / raw)
To: kbuild test robot; +Cc: kbuild-all, David Miller, netdev, edumazet
In-Reply-To: <201710210027.nxMZ7dfs%fengguang.wu@intel.com>
On Sat, 2017-10-21 at 00:53 +0800, kbuild test robot wrote:
> Hi Eric,
>
> [auto build test WARNING on net/master]
>
> url: https://github.com/0day-ci/linux/commits/Eric-Dumazet/dccp-tcp-fix-ireq-opt-races/20171021-001234
> config: ia64-allmodconfig (attached as .config)
> compiler: ia64-linux-gcc (GCC) 6.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=ia64
Thanks, v4 of the patch should fix this.
https://patchwork.ozlabs.org/patch/828713/
^ permalink raw reply
* [PATCH net-next] nfp: use struct fields for 8 bit-wide access
From: Simon Horman @ 2017-10-20 17:49 UTC (permalink / raw)
To: David Miller, Jakub Kicinski
Cc: netdev, oss-drivers, Pieter Jansen van Vuuren, Simon Horman
From: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Use direct access struct fields rather than PREP_FIELD()
macros to manipulate the jump ID and length, both of which
are exactly 8-bits wide. This simplifies the code somewhat.
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com>
Acked-by: Jakub Kicinski <jakub.kicinski@netronome.com>
---
drivers/net/ethernet/netronome/nfp/flower/action.c | 87 +++++++---------------
drivers/net/ethernet/netronome/nfp/flower/cmsg.h | 26 ++++---
2 files changed, 39 insertions(+), 74 deletions(-)
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index 1194c47ef827..0a5fc9f8545f 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -47,13 +47,9 @@
static void nfp_fl_pop_vlan(struct nfp_fl_pop_vlan *pop_vlan)
{
size_t act_size = sizeof(struct nfp_fl_pop_vlan);
- u16 tmp_pop_vlan_op;
- tmp_pop_vlan_op =
- FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID, NFP_FL_ACTION_OPCODE_POP_VLAN);
-
- pop_vlan->a_op = cpu_to_be16(tmp_pop_vlan_op);
+ pop_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_POP_VLAN;
+ pop_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
pop_vlan->reserved = 0;
}
@@ -64,14 +60,9 @@ nfp_fl_push_vlan(struct nfp_fl_push_vlan *push_vlan,
size_t act_size = sizeof(struct nfp_fl_push_vlan);
struct tcf_vlan *vlan = to_vlan(action);
u16 tmp_push_vlan_tci;
- u16 tmp_push_vlan_op;
-
- tmp_push_vlan_op =
- FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID, NFP_FL_ACTION_OPCODE_PUSH_VLAN);
- push_vlan->a_op = cpu_to_be16(tmp_push_vlan_op);
- /* Set action push vlan parameters. */
+ push_vlan->head.jump_id = NFP_FL_ACTION_OPCODE_PUSH_VLAN;
+ push_vlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
push_vlan->reserved = 0;
push_vlan->vlan_tpid = tcf_vlan_push_proto(action);
@@ -101,16 +92,12 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
int *tun_out_cnt)
{
size_t act_size = sizeof(struct nfp_fl_output);
- u16 tmp_output_op, tmp_flags;
struct net_device *out_dev;
+ u16 tmp_flags;
int ifindex;
- /* Set action opcode to output action. */
- tmp_output_op =
- FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID, NFP_FL_ACTION_OPCODE_OUTPUT);
-
- output->a_op = cpu_to_be16(tmp_output_op);
+ output->head.jump_id = NFP_FL_ACTION_OPCODE_OUTPUT;
+ output->head.len_lw = act_size >> NFP_FL_LW_SIZ;
ifindex = tcf_mirred_ifindex(action);
out_dev = __dev_get_by_index(dev_net(in_dev), ifindex);
@@ -161,7 +148,6 @@ static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
{
size_t act_size = sizeof(struct nfp_fl_pre_tunnel);
struct nfp_fl_pre_tunnel *pre_tun_act;
- u16 tmp_pre_tun_op;
/* Pre_tunnel action must be first on action list.
* If other actions already exist they need pushed forward.
@@ -173,11 +159,8 @@ static struct nfp_fl_pre_tunnel *nfp_fl_pre_tunnel(char *act_data, int act_len)
memset(pre_tun_act, 0, act_size);
- tmp_pre_tun_op =
- FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID, NFP_FL_ACTION_OPCODE_PRE_TUNNEL);
-
- pre_tun_act->a_op = cpu_to_be16(tmp_pre_tun_op);
+ pre_tun_act->head.jump_id = NFP_FL_ACTION_OPCODE_PRE_TUNNEL;
+ pre_tun_act->head.len_lw = act_size >> NFP_FL_LW_SIZ;
return pre_tun_act;
}
@@ -190,7 +173,6 @@ nfp_fl_set_vxlan(struct nfp_fl_set_vxlan *set_vxlan,
struct ip_tunnel_info *vxlan = tcf_tunnel_info(action);
size_t act_size = sizeof(struct nfp_fl_set_vxlan);
u32 tmp_set_vxlan_type_index = 0;
- u16 tmp_set_vxlan_op;
/* Currently support one pre-tunnel so index is always 0. */
int pretun_idx = 0;
@@ -199,12 +181,8 @@ nfp_fl_set_vxlan(struct nfp_fl_set_vxlan *set_vxlan,
return -EOPNOTSUPP;
}
- tmp_set_vxlan_op =
- FIELD_PREP(NFP_FL_ACT_LEN_LW, act_size >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID,
- NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL);
-
- set_vxlan->a_op = cpu_to_be16(tmp_set_vxlan_op);
+ set_vxlan->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_TUNNEL;
+ set_vxlan->head.len_lw = act_size >> NFP_FL_LW_SIZ;
/* Set tunnel type and pre-tunnel index. */
tmp_set_vxlan_type_index |=
@@ -240,7 +218,6 @@ static int
nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
struct nfp_fl_set_eth *set_eth)
{
- u16 tmp_set_eth_op;
u32 exact, mask;
if (off + 4 > ETH_ALEN * 2)
@@ -256,11 +233,8 @@ nfp_fl_set_eth(const struct tc_action *action, int idx, u32 off,
&set_eth->eth_addr_mask[off]);
set_eth->reserved = cpu_to_be16(0);
- tmp_set_eth_op = FIELD_PREP(NFP_FL_ACT_LEN_LW,
- sizeof(*set_eth) >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID,
- NFP_FL_ACTION_OPCODE_SET_ETHERNET);
- set_eth->a_op = cpu_to_be16(tmp_set_eth_op);
+ set_eth->head.jump_id = NFP_FL_ACTION_OPCODE_SET_ETHERNET;
+ set_eth->head.len_lw = sizeof(*set_eth) >> NFP_FL_LW_SIZ;
return 0;
}
@@ -269,7 +243,6 @@ static int
nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
struct nfp_fl_set_ip4_addrs *set_ip_addr)
{
- u16 tmp_set_ipv4_op;
__be32 exact, mask;
/* We are expecting tcf_pedit to return a big endian value */
@@ -293,11 +266,8 @@ nfp_fl_set_ip4(const struct tc_action *action, int idx, u32 off,
}
set_ip_addr->reserved = cpu_to_be16(0);
- tmp_set_ipv4_op = FIELD_PREP(NFP_FL_ACT_LEN_LW,
- sizeof(*set_ip_addr) >> NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID,
- NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS);
- set_ip_addr->a_op = cpu_to_be16(tmp_set_ipv4_op);
+ set_ip_addr->head.jump_id = NFP_FL_ACTION_OPCODE_SET_IPV4_ADDRS;
+ set_ip_addr->head.len_lw = sizeof(*set_ip_addr) >> NFP_FL_LW_SIZ;
return 0;
}
@@ -306,16 +276,12 @@ static void
nfp_fl_set_ip6_helper(int opcode_tag, int idx, __be32 exact, __be32 mask,
struct nfp_fl_set_ipv6_addr *ip6)
{
- u16 tmp_set_op;
-
ip6->ipv6[idx % 4].mask = mask;
ip6->ipv6[idx % 4].exact = exact;
ip6->reserved = cpu_to_be16(0);
- tmp_set_op = FIELD_PREP(NFP_FL_ACT_LEN_LW, sizeof(*ip6) >>
- NFP_FL_LW_SIZ) |
- FIELD_PREP(NFP_FL_ACT_JMP_ID, opcode_tag);
- ip6->a_op = cpu_to_be16(tmp_set_op);
+ ip6->head.jump_id = opcode_tag;
+ ip6->head.len_lw = sizeof(*ip6) >> NFP_FL_LW_SIZ;
}
static int
@@ -352,7 +318,6 @@ nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off,
struct nfp_fl_set_tport *set_tport, int opcode)
{
u32 exact, mask;
- u16 tmp_set_op;
if (off)
return -EOPNOTSUPP;
@@ -367,10 +332,8 @@ nfp_fl_set_tport(const struct tc_action *action, int idx, u32 off,
set_tport->tp_port_mask);
set_tport->reserved = cpu_to_be16(0);
- tmp_set_op = FIELD_PREP(NFP_FL_ACT_LEN_LW,
- sizeof(*set_tport) >> NFP_FL_LW_SIZ);
- tmp_set_op |= FIELD_PREP(NFP_FL_ACT_JMP_ID, opcode);
- set_tport->a_op = cpu_to_be16(tmp_set_op);
+ set_tport->head.jump_id = opcode;
+ set_tport->head.len_lw = sizeof(*set_tport) >> NFP_FL_LW_SIZ;
return 0;
}
@@ -428,15 +391,15 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
return err;
}
- if (set_eth.a_op) {
+ if (set_eth.head.len_lw) {
act_size = sizeof(set_eth);
memcpy(nfp_action, &set_eth, act_size);
*a_len += act_size;
- } else if (set_ip_addr.a_op) {
+ } else if (set_ip_addr.head.len_lw) {
act_size = sizeof(set_ip_addr);
memcpy(nfp_action, &set_ip_addr, act_size);
*a_len += act_size;
- } else if (set_ip6_dst.a_op && set_ip6_src.a_op) {
+ } else if (set_ip6_dst.head.len_lw && set_ip6_src.head.len_lw) {
/* TC compiles set src and dst IPv6 address as a single action,
* the hardware requires this to be 2 separate actions.
*/
@@ -448,15 +411,15 @@ nfp_fl_pedit(const struct tc_action *action, char *nfp_action, int *a_len)
memcpy(&nfp_action[sizeof(set_ip6_src)], &set_ip6_dst,
act_size);
*a_len += act_size;
- } else if (set_ip6_dst.a_op) {
+ } else if (set_ip6_dst.head.len_lw) {
act_size = sizeof(set_ip6_dst);
memcpy(nfp_action, &set_ip6_dst, act_size);
*a_len += act_size;
- } else if (set_ip6_src.a_op) {
+ } else if (set_ip6_src.head.len_lw) {
act_size = sizeof(set_ip6_src);
memcpy(nfp_action, &set_ip6_src, act_size);
*a_len += act_size;
- } else if (set_tport.a_op) {
+ } else if (set_tport.head.len_lw) {
act_size = sizeof(set_tport);
memcpy(nfp_action, &set_tport, act_size);
*a_len += act_size;
diff --git a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
index f7b7242a22bc..64e87f8e7089 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
+++ b/drivers/net/ethernet/netronome/nfp/flower/cmsg.h
@@ -86,9 +86,6 @@
#define NFP_FL_ACTION_OPCODE_PRE_TUNNEL 17
#define NFP_FL_ACTION_OPCODE_NUM 32
-#define NFP_FL_ACT_JMP_ID GENMASK(15, 8)
-#define NFP_FL_ACT_LEN_LW GENMASK(7, 0)
-
#define NFP_FL_OUT_FLAGS_LAST BIT(15)
#define NFP_FL_OUT_FLAGS_USE_TUN BIT(4)
#define NFP_FL_OUT_FLAGS_TYPE_IDX GENMASK(2, 0)
@@ -113,15 +110,20 @@ enum nfp_flower_tun_type {
NFP_FL_TUNNEL_VXLAN = 2,
};
+struct nfp_fl_act_head {
+ u8 jump_id;
+ u8 len_lw;
+};
+
struct nfp_fl_set_eth {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
u8 eth_addr_mask[ETH_ALEN * 2];
u8 eth_addr_val[ETH_ALEN * 2];
};
struct nfp_fl_set_ip4_addrs {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
__be32 ipv4_src_mask;
__be32 ipv4_src;
@@ -130,7 +132,7 @@ struct nfp_fl_set_ip4_addrs {
};
struct nfp_fl_set_ipv6_addr {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
struct {
__be32 mask;
@@ -139,27 +141,27 @@ struct nfp_fl_set_ipv6_addr {
};
struct nfp_fl_set_tport {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
u8 tp_port_mask[4];
u8 tp_port_val[4];
};
struct nfp_fl_output {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 flags;
__be32 port;
};
struct nfp_fl_push_vlan {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
__be16 vlan_tpid;
__be16 vlan_tci;
};
struct nfp_fl_pop_vlan {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
};
@@ -178,7 +180,7 @@ struct nfp_flower_meta_one {
};
struct nfp_fl_pre_tunnel {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
__be32 ipv4_dst;
/* reserved for use with IPv6 addresses */
@@ -186,7 +188,7 @@ struct nfp_fl_pre_tunnel {
};
struct nfp_fl_set_vxlan {
- __be16 a_op;
+ struct nfp_fl_act_head head;
__be16 reserved;
__be64 tun_id;
__be32 tun_type_index;
--
2.11.0
^ permalink raw reply related
* Re: [PATCH v3 2/4] macb: Kill PHY reset code
From: Florian Fainelli @ 2017-10-20 18:04 UTC (permalink / raw)
To: Geert Uytterhoeven, David S . Miller, Andrew Lunn, Simon Horman,
Magnus Damm
Cc: Sergei Shtylyov, Rob Herring, Mark Rutland, Nicolas Ferre,
netdev-u79uwXL29TY76Z2rM5mHXA, devicetree-u79uwXL29TY76Z2rM5mHXA,
linux-renesas-soc-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1508487261-18524-3-git-send-email-geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
On 10/20/2017 01:14 AM, Geert Uytterhoeven wrote:
> From: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
>
> With the phylib now being aware of the "reset-gpios" PHY node property,
> there should be no need to frob the PHY reset in this driver anymore...
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov-M4DtvfQ/ZS1MRgGoP+s0PdBPR1lH4CV8@public.gmane.org>
> Acked-by: Nicolas Ferre <nicolas.ferre-AIFe0yeh4nAAvxtiuMwx3w@public.gmane.org>
> Signed-off-by: Geert Uytterhoeven <geert+renesas-gXvu3+zWzMSzQB+pC5nmwQ@public.gmane.org>
Reviewed-by: Florian Fainelli <f.fainelli-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
--
Florian
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [PATCH net-next 0/5] bpf: add support for BASE_RTT
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
This patch set adds the following functionality to socket_ops BPF
programs.
1) Add bpf helper function bpf_getsocketops. Currently only supports
TCP_CONGESTION
2) Add BPF_SOCKET_OPS_BASE_RTT op to get the base RTT of the
connection. In general, the base RTT indicates the threshold such
that RTTs above it indicate congestion. More details in the
relevant patches.
Consists of the following patches:
[PATCH net-next 1/5] bpf: add support for BPF_SOCK_OPS_BASE_RTT
[PATCH net-next 2/5] bpf: Adding helper function bpf_getsockops
[PATCH net-next 3/5] bpf: Add BPF_SOCKET_OPS_BASE_RTT support to
[PATCH net-next 4/5] bpf: sample BPF_SOCKET_OPS_BASE_RTT program
[PATCH net-next 5/5] bpf: create samples/bpf/tcp_bpf.readme
include/uapi/linux/bpf.h | 26 +++++++++++--
net/core/filter.c | 46 ++++++++++++++++++++++-
net/ipv4/tcp_nv.c | 40 +++++++++++++++++++-
samples/bpf/Makefile | 1 +
samples/bpf/tcp_basertt_kern.c | 78 +++++++++++++++++++++++++++++++++++++++
samples/bpf/tcp_bbf.readme | 27 ++++++++++++++
tools/testing/selftests/bpf/bpf_helpers.h | 3 ++
7 files changed, 214 insertions(+), 7 deletions(-)
^ permalink raw reply
* [PATCH net-next 5/5] bpf: create samples/bpf/tcp_bpf.readme
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
In-Reply-To: <20171020180543.4156833-1-brakmo@fb.com>
Readme file explaining how to create a cgroupv2 and attach one
of the tcp_*_kern.o socket_ops BPF program.
Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked_by: Alexei Starovoitov <ast@fb.com>
---
samples/bpf/tcp_bbf.readme | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
create mode 100644 samples/bpf/tcp_bbf.readme
diff --git a/samples/bpf/tcp_bbf.readme b/samples/bpf/tcp_bbf.readme
new file mode 100644
index 0000000..3692056
--- /dev/null
+++ b/samples/bpf/tcp_bbf.readme
@@ -0,0 +1,27 @@
+This file describes how to run the tcp_*_kern.o tcp_bpf (or socket_ops)
+programs. These programs attach to a cgroupv2. The following commands create
+a cgroupv2 and attach a bash shell to the group.
+
+ mkdir -p /tmp/cgroupv2
+ mount -t cgroup2 none /tmp/cgroupv2
+ mkdir -p /tmp/cgroupv2/foo
+ bash
+ echo $$ >> /tmp/cgroupv2/foo/cgroup.procs
+
+Anything that runs under this shell belongs to the foo cgroupv2 To load
+(attach) one of the tcp_*_kern.o programs:
+
+ ./load_sock_ops -l /tmp/cgroupv2/foo tcp_basertt_kern.o
+
+If the "-l" flag is used, the load_sock_ops program will continue to run
+printing the BPF log buffer. The tcp_*_kern.o programs use special print
+functions to print logging information (if enabled by the ifdef).
+
+If using netperf/netserver to create traffic, you need to run them under the
+cgroupv2 to which the BPF programs are attached (i.e. under bash shell
+attached to the cgroupv2).
+
+To remove (unattach) a socket_ops BPF program from a cgroupv2:
+
+ ./load_sock_ops -r /tmp/cgroupv2/foo
+
--
2.9.5
^ permalink raw reply related
* [PATCH net-next 3/5] bpf: Add BPF_SOCKET_OPS_BASE_RTT support to tcp_nv
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
In-Reply-To: <20171020180543.4156833-1-brakmo@fb.com>
TCP_NV will try to get the base RTT from a socket_ops BPF program if one
is loaded. NV will then use the base RTT to bound its min RTT (its
notion of the base RTT). It uses the base RTT as an upper bound and 80%
of the base RTT as its lower bound.
In other words, NV will consider filtered RTTs larger than base RTT as a
sign of congestion. As a result, there is no minRTT inflation when there
is a lot of congestion. For example, in a DC where the RTTs are less
than 40us when there is no congestion, a base RTT value of 80us improves
the performance of NV. The difference between the uncongested RTT and
the base RTT provided represents how much queueing we are willing to
have (in practice it can be higher).
NV has been tunned to reduce congestion when there are many flows at the
cost of one flow not achieving full bandwith utilization. When a
reasonable base RTT is provided, one NV flow can now fully utilize the
full bandwidth. In addition, the performance is also improved when there
are many flows.
In the following examples the NV results are using a kernel with this
patch set (i.e. both NV results are using the new nv_loss_dec_factor).
With one host sending to another host and only one flow the
goodputs are:
Cubic: 9.3 Gbps, NV: 5.5 Gbps, NV (baseRTT=80us): 9.2 Gbps
With 2 hosts sending to one host (1 flow per host, the goodput per flow
is:
Cubic: 4.6 Gbps, NV: 4.5 Gbps, NV (baseRTT=80us)L 4.6 Gbps
But the RTTs seen by a ping process in the sender is:
Cubic: 3.3ms NV: 97us, NV (baseRTT=80us): 146us
With a lot of flows things look even better for NV with baseRTT. Here we
have 3 hosts sending to one host. Each sending host has 6 flows: 1
stream, 4x1MB RPC, 1x10KB RPC. Cubic, NV and NV with baseRTT all fully
utilize the full available bandwidth. However, the distribution of
bandwidth among the flows is very different. For the 10KB RPC flow:
Cubic: 27Mbps, NV: 111Mbps, NV (baseRTT=80us): 222Mbps
The 99% latencies for the 10KB flows are:
Cubic: 26ms, NV: 1ms, NV (baseRTT=80us): 500us
The RTT seen by a ping process at the senders:
Cubic: 3.2ms NV: 720us, NV (baseRTT=80us): 330us
Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Acked_by: Alexei Starovoitov <ast@fb.com>
---
net/ipv4/tcp_nv.c | 40 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 38 insertions(+), 2 deletions(-)
diff --git a/net/ipv4/tcp_nv.c b/net/ipv4/tcp_nv.c
index 1ff7398..a978e3f 100644
--- a/net/ipv4/tcp_nv.c
+++ b/net/ipv4/tcp_nv.c
@@ -39,7 +39,7 @@
* nv_cong_dec_mult Decrease cwnd by X% (30%) of congestion when detected
* nv_ssthresh_factor On congestion set ssthresh to this * <desired cwnd> / 8
* nv_rtt_factor RTT averaging factor
- * nv_loss_dec_factor Decrease cwnd by this (50%) when losses occur
+ * nv_loss_dec_factor Decrease cwnd to this (80%) when losses occur
* nv_dec_eval_min_calls Wait this many RTT measurements before dec cwnd
* nv_inc_eval_min_calls Wait this many RTT measurements before inc cwnd
* nv_ssthresh_eval_min_calls Wait this many RTT measurements before stopping
@@ -61,7 +61,7 @@ static int nv_min_cwnd __read_mostly = 2;
static int nv_cong_dec_mult __read_mostly = 30 * 128 / 100; /* = 30% */
static int nv_ssthresh_factor __read_mostly = 8; /* = 1 */
static int nv_rtt_factor __read_mostly = 128; /* = 1/2*old + 1/2*new */
-static int nv_loss_dec_factor __read_mostly = 512; /* => 50% */
+static int nv_loss_dec_factor __read_mostly = 819; /* => 80% */
static int nv_cwnd_growth_rate_neg __read_mostly = 8;
static int nv_cwnd_growth_rate_pos __read_mostly; /* 0 => fixed like Reno */
static int nv_dec_eval_min_calls __read_mostly = 60;
@@ -101,6 +101,11 @@ struct tcpnv {
u32 nv_last_rtt; /* last rtt */
u32 nv_min_rtt; /* active min rtt. Used to determine slope */
u32 nv_min_rtt_new; /* min rtt for future use */
+ u32 nv_base_rtt; /* If non-zero it represents the threshold for
+ * congestion */
+ u32 nv_lower_bound_rtt; /* Used in conjunction with nv_base_rtt. It is
+ * set to 80% of nv_base_rtt. It helps reduce
+ * unfairness between flows */
u32 nv_rtt_max_rate; /* max rate seen during current RTT */
u32 nv_rtt_start_seq; /* current RTT ends when packet arrives
* acking beyond nv_rtt_start_seq */
@@ -132,9 +137,24 @@ static inline void tcpnv_reset(struct tcpnv *ca, struct sock *sk)
static void tcpnv_init(struct sock *sk)
{
struct tcpnv *ca = inet_csk_ca(sk);
+ int base_rtt;
tcpnv_reset(ca, sk);
+ /* See if base_rtt is available from socket_ops bpf program.
+ * It is meant to be used in environments, such as communication
+ * within a datacenter, where we have reasonable estimates of
+ * RTTs
+ */
+ base_rtt = tcp_call_bpf(sk, BPF_SOCK_OPS_BASE_RTT);
+ if (base_rtt > 0) {
+ ca->nv_base_rtt = base_rtt;
+ ca->nv_lower_bound_rtt = (base_rtt * 205) >> 8; /* 80% */
+ } else {
+ ca->nv_base_rtt = 0;
+ ca->nv_lower_bound_rtt = 0;
+ }
+
ca->nv_allow_cwnd_growth = 1;
ca->nv_min_rtt_reset_jiffies = jiffies + 2 * HZ;
ca->nv_min_rtt = NV_INIT_RTT;
@@ -144,6 +164,19 @@ static void tcpnv_init(struct sock *sk)
ca->cwnd_growth_factor = 0;
}
+/* If provided, apply upper (base_rtt) and lower (lower_bound_rtt)
+ * bounds to RTT.
+ */
+inline u32 nv_get_bounded_rtt(struct tcpnv *ca, u32 val)
+{
+ if (ca->nv_lower_bound_rtt > 0 && val < ca->nv_lower_bound_rtt)
+ return ca->nv_lower_bound_rtt;
+ else if (ca->nv_base_rtt > 0 && val > ca->nv_base_rtt)
+ return ca->nv_base_rtt;
+ else
+ return val;
+}
+
static void tcpnv_cong_avoid(struct sock *sk, u32 ack, u32 acked)
{
struct tcp_sock *tp = tcp_sk(sk);
@@ -265,6 +298,9 @@ static void tcpnv_acked(struct sock *sk, const struct ack_sample *sample)
if (ca->nv_eval_call_cnt < 255)
ca->nv_eval_call_cnt++;
+ /* Apply bounds to rtt. Only used to update min_rtt */
+ avg_rtt = nv_get_bounded_rtt(ca, avg_rtt);
+
/* update min rtt if necessary */
if (avg_rtt < ca->nv_min_rtt)
ca->nv_min_rtt = avg_rtt;
--
2.9.5
^ permalink raw reply related
* [PATCH net-next 2/5] bpf: Adding helper function bpf_getsockops
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
In-Reply-To: <20171020180543.4156833-1-brakmo@fb.com>
Adding support for helper function bpf_getsockops to socket_ops BPF
programs. This patch only supports TCP_CONGESTION.
Signed-off-by: Vlad Vysotsky <vlad@cs.ucla.edu>
Acked-by: Lawrence Brakmo <brakmo@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
include/uapi/linux/bpf.h | 19 ++++++++++---
net/core/filter.c | 46 ++++++++++++++++++++++++++++++-
tools/testing/selftests/bpf/bpf_helpers.h | 3 ++
3 files changed, 63 insertions(+), 5 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 1aca744..f650346 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -613,12 +613,22 @@ union bpf_attr {
* int bpf_setsockopt(bpf_socket, level, optname, optval, optlen)
* Calls setsockopt. Not all opts are available, only those with
* integer optvals plus TCP_CONGESTION.
- * Supported levels: SOL_SOCKET and IPROTO_TCP
+ * Supported levels: SOL_SOCKET and IPPROTO_TCP
* @bpf_socket: pointer to bpf_socket
- * @level: SOL_SOCKET or IPROTO_TCP
+ * @level: SOL_SOCKET or IPPROTO_TCP
* @optname: option name
* @optval: pointer to option value
- * @optlen: length of optval in byes
+ * @optlen: length of optval in bytes
+ * Return: 0 or negative error
+ *
+ * int bpf_getsockopt(bpf_socket, level, optname, optval, optlen)
+ * Calls getsockopt. Not all opts are available.
+ * Supported levels: IPPROTO_TCP
+ * @bpf_socket: pointer to bpf_socket
+ * @level: IPPROTO_TCP
+ * @optname: option name
+ * @optval: pointer to option value
+ * @optlen: length of optval in bytes
* Return: 0 or negative error
*
* int bpf_skb_adjust_room(skb, len_diff, mode, flags)
@@ -721,7 +731,8 @@ union bpf_attr {
FN(sock_map_update), \
FN(xdp_adjust_meta), \
FN(perf_event_read_value), \
- FN(perf_prog_read_value),
+ FN(perf_prog_read_value), \
+ FN(getsockopt),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
diff --git a/net/core/filter.c b/net/core/filter.c
index 09e011f..ccf62f4 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3273,7 +3273,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
static const struct bpf_func_proto bpf_setsockopt_proto = {
.func = bpf_setsockopt,
- .gpl_only = true,
+ .gpl_only = false,
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_CTX,
.arg2_type = ARG_ANYTHING,
@@ -3282,6 +3282,48 @@ static const struct bpf_func_proto bpf_setsockopt_proto = {
.arg5_type = ARG_CONST_SIZE,
};
+BPF_CALL_5(bpf_getsockopt, struct bpf_sock_ops_kern *, bpf_sock,
+ int, level, int, optname, char *, optval, int, optlen)
+{
+ struct sock *sk = bpf_sock->sk;
+ int ret = 0;
+
+ if (!sk_fullsock(sk))
+ goto err_clear;
+
+#ifdef CONFIG_INET
+ if (level == SOL_TCP && sk->sk_prot->getsockopt == tcp_getsockopt) {
+ if (optname == TCP_CONGESTION) {
+ struct inet_connection_sock *icsk = inet_csk(sk);
+
+ if (!icsk->icsk_ca_ops || optlen <= 1)
+ goto err_clear;
+ strncpy(optval, icsk->icsk_ca_ops->name, optlen);
+ optval[optlen - 1] = 0;
+ } else {
+ goto err_clear;
+ }
+ } else {
+ goto err_clear;
+ }
+ return ret;
+#endif
+err_clear:
+ memset(optval, 0, optlen);
+ return -EINVAL;
+}
+
+static const struct bpf_func_proto bpf_getsockopt_proto = {
+ .func = bpf_getsockopt,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_PTR_TO_UNINIT_MEM,
+ .arg5_type = ARG_CONST_SIZE,
+};
+
static const struct bpf_func_proto *
bpf_base_func_proto(enum bpf_func_id func_id)
{
@@ -3460,6 +3502,8 @@ static const struct bpf_func_proto *
switch (func_id) {
case BPF_FUNC_setsockopt:
return &bpf_setsockopt_proto;
+ case BPF_FUNC_getsockopt:
+ return &bpf_getsockopt_proto;
case BPF_FUNC_sock_map_update:
return &bpf_sock_map_update_proto;
default:
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index e25dbf6..609514f 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -67,6 +67,9 @@ static int (*bpf_xdp_adjust_meta)(void *ctx, int offset) =
static int (*bpf_setsockopt)(void *ctx, int level, int optname, void *optval,
int optlen) =
(void *) BPF_FUNC_setsockopt;
+static int (*bpf_getsockopt)(void *ctx, int level, int optname, void *optval,
+ int optlen) =
+ (void *) BPF_FUNC_getsockopt;
static int (*bpf_sk_redirect_map)(void *map, int key, int flags) =
(void *) BPF_FUNC_sk_redirect_map;
static int (*bpf_sock_map_update)(void *map, void *key, void *value,
--
2.9.5
^ permalink raw reply related
* [PATCH net-next 1/5] bpf: add support for BPF_SOCK_OPS_BASE_RTT
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
In-Reply-To: <20171020180543.4156833-1-brakmo@fb.com>
A congestion control algorithm can make a call to the BPF socket_ops
program to request the base RTT. The base RTT can be congestion control
dependent and is meant to represent a congestion threshold such that
RTTs above it indicate congestion. This is especially useful for flows
within a DC where the base RTT is easy to obtain.
Being provided a base RTT solves a basic problem in RTT based congestion
avoidance algorithms (such as Vegas, NV and BBR). Although it is easy
to get the base RTT when the network is not congested, it is very
diffcult to do when it is very congested. Newer connections get an
inflated value of the base RTT leading to unfariness (newer flows with a
larger base RTT get more bandwidth). As a result, RTT based congestion
avoidance algorithms tend to update their base RTTs to improve fairness.
In very congested networks this can lead to base RTT inflation, reducing
the ability of these RTT based congestion control algorithms to prevent
congestion.
Note that in my experiments with TCP-NV, the base RTT provided can be
much larger than the actual hardware RTT. For example, experimenting
with hosts within a rack where the hardware RTT is 16-20us, I've used
base RTTs up to 150us. The effect of using a larger base RTT is that the
congestion avoidance algorithm will allow more queueing. When there are
only a few flows the main effect is larger measured RTTs and RPC
latencies due to the increased queueing. When there are a lot of flows,
a larger base RTT can lead to more congestion and more packet drops.
For this case, where the hardware RTT is 20us, a base RTT of 80us
produces good results.
This patch only introduces BPF_SOCK_OPS_BASE_RTT, a later patch in this
set adds support for using it in TCP-NV. Further study and testing is
needed before support can be added to other delay based congestion
avoidance algorithms.
Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Acked-by: Alexei Starovoitov <ast@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
---
include/uapi/linux/bpf.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index d83f95e..1aca744 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -955,6 +955,13 @@ enum {
BPF_SOCK_OPS_NEEDS_ECN, /* If connection's congestion control
* needs ECN
*/
+ BPF_SOCK_OPS_BASE_RTT, /* Get base RTT. The correct value is
+ * based on the path and may be
+ * dependent on the congestion control
+ * algorithm. In general it indicates
+ * a congestion threshold. RTTs above
+ * this indicate congestion
+ */
};
#define TCP_BPF_IW 1001 /* Set TCP initial congestion window */
--
2.9.5
^ permalink raw reply related
* [PATCH net-next 4/5] bpf: sample BPF_SOCKET_OPS_BASE_RTT program
From: Lawrence Brakmo @ 2017-10-20 18:05 UTC (permalink / raw)
To: netdev
Cc: Kernel Team, Alexei Starovoitov, Daniel Borkmann, Blake Matheny,
Lawrence Brakmo
In-Reply-To: <20171020180543.4156833-1-brakmo@fb.com>
Sample socket_ops BPF program to test the BPF helper function
bpf_getsocketops and the new socket_ops op BPF_SOCKET_OPS_BASE_RTT.
The program provides a base RTT of 80us when the calling flow is
within a DC (as determined by the IPV6 prefix) and the congestion
algorithm is "nv".
Signed-off-by: Lawrence Brakmo <brakmo@fb.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Acked_by: Alexei Starovoitov <ast@fb.com>
---
samples/bpf/Makefile | 1 +
samples/bpf/tcp_basertt_kern.c | 78 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
create mode 100644 samples/bpf/tcp_basertt_kern.c
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 3534ccf..ea2b9e6 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -129,6 +129,7 @@ always += tcp_bufs_kern.o
always += tcp_cong_kern.o
always += tcp_iw_kern.o
always += tcp_clamp_kern.o
+always += tcp_basertt_kern.o
always += xdp_redirect_kern.o
always += xdp_redirect_map_kern.o
always += xdp_redirect_cpu_kern.o
diff --git a/samples/bpf/tcp_basertt_kern.c b/samples/bpf/tcp_basertt_kern.c
new file mode 100644
index 0000000..4bf4fc5
--- /dev/null
+++ b/samples/bpf/tcp_basertt_kern.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2017 Facebook
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2 of the GNU General Public
+ * License as published by the Free Software Foundation.
+ *
+ * BPF program to set base_rtt to 80us when host is running TCP-NV and
+ * both hosts are in the same datacenter (as determined by IPv6 prefix).
+ *
+ * Use load_sock_ops to load this BPF program.
+ */
+
+#include <uapi/linux/bpf.h>
+#include <uapi/linux/tcp.h>
+#include <uapi/linux/if_ether.h>
+#include <uapi/linux/if_packet.h>
+#include <uapi/linux/ip.h>
+#include <linux/socket.h>
+#include "bpf_helpers.h"
+#include "bpf_endian.h"
+
+#define DEBUG 1
+
+#define bpf_printk(fmt, ...) \
+({ \
+ char ____fmt[] = fmt; \
+ bpf_trace_printk(____fmt, sizeof(____fmt), \
+ ##__VA_ARGS__); \
+})
+
+SEC("sockops")
+int bpf_basertt(struct bpf_sock_ops *skops)
+{
+ char cong[20];
+ char nv[] = "nv";
+ int rv = 0, n;
+ int op;
+
+ op = (int) skops->op;
+
+#ifdef DEBUG
+ bpf_printk("BPF command: %d\n", op);
+#endif
+
+ /* Check if both hosts are in the same datacenter. For this
+ * example they are if the 1st 5.5 bytes in the IPv6 address
+ * are the same.
+ */
+ if (skops->family == AF_INET6 &&
+ skops->local_ip6[0] == skops->remote_ip6[0] &&
+ (bpf_ntohl(skops->local_ip6[1]) & 0xfff00000) ==
+ (bpf_ntohl(skops->remote_ip6[1]) & 0xfff00000)) {
+ switch (op) {
+ case BPF_SOCK_OPS_BASE_RTT:
+ n = bpf_getsockopt(skops, SOL_TCP, TCP_CONGESTION,
+ cong, sizeof(cong));
+ if (!n && !__builtin_memcmp(cong, nv, sizeof(nv)+1)) {
+ /* Set base_rtt to 80us */
+ rv = 80;
+ } else if (n) {
+ rv = n;
+ } else {
+ rv = -1;
+ }
+ break;
+ default:
+ rv = -1;
+ }
+ } else {
+ rv = -1;
+ }
+#ifdef DEBUG
+ bpf_printk("Returning %d\n", rv);
+#endif
+ skops->reply = rv;
+ return 1;
+}
+char _license[] SEC("license") = "GPL";
--
2.9.5
^ permalink raw reply related
* RE: removing bridge in vlan_filtering mode requests delete of attached ports main MAC address
From: Keller, Jacob E @ 2017-10-20 18:06 UTC (permalink / raw)
To: netdev@vger.kernel.org; +Cc: Malek, Patryk, Vlad Yasevich, Keller, Jacob E
> -----Original Message-----
> From: Keller, Jacob E
> Sent: Friday, October 20, 2017 10:23 AM
> To: netdev@vger.kernel.org
> Cc: Malek, Patryk <patryk.malek@intel.com>; 'Vlad Yasevich'
> <vyasevic@redhat.com>
> Subject: removing bridge in vlan_filtering mode requests delete of attached
> ports main MAC address
>
> Hi,
>
> We've run into an issue with bridges set in vlan_filtering mode. Basically, if we
> attach a device to a bridge which has enabled vlan_filtering, and then remove the
> bridge, we end up requesting the driver of the attached device to remove its
> own MAC HW address.
>
> In i40e, at least, this causes the driver to actually delete such an address and then
> it will no longer receive any traffic.
>
> To reproduce this:
>
> a) brctl addbr br0
> b) brctl addif br0 enp<n>
> # enable vlan filtering
> c) echo 1 >/sys/class/net/br0/bridge/vlan_filtering
> d) brctl delbr br0
>
> Specifically this appears to happen because of how we automatically enter static
> configuration for routes when vlan_filtering is enabled, and we call
> br_fdb_unsync_static which will clear all the routes from the fdb table for the
> device. See commit 2796d0c648c9 ("bridge: Automatically manage port
> promiscuous mode.", 2014-05-16) for more details.
>
> This happens to include the devices own default address, which results in the
> bug.
>
> I'm not sure if this is a driver bug, or if it's a bug in the bridging code.
>
> Who would know more about this and what to do about this?
>
> One obvious solution is to hard code the i40e device driver so that it does not
> actually delete the HW address from the unicast filter list. This could work, but
> seems to me like its papering over the problem. Is this just a known thing that
> drivers should be aware of? I don't really know...
>
> An alternative solution would be to possibly ignore any fdb addresses which
> specifically target that port?
>
> Any ideas?
For the record, adding a check to prevent unsync_static from removing addresses which are targetting the specific port does work to resolve this specific issue, but I'm sure it's not the correct solution as I expect that would cause other problems.
Thanks,
Jake
>
> Regards,
> Jake
^ permalink raw reply
* Re: [PATCH v3 1/4] phylib: Add device reset GPIO support
From: Florian Fainelli @ 2017-10-20 18:11 UTC (permalink / raw)
To: Geert Uytterhoeven, David S . Miller, Andrew Lunn, Simon Horman,
Magnus Damm
Cc: Sergei Shtylyov, Rob Herring, Mark Rutland, Nicolas Ferre, netdev,
devicetree, linux-renesas-soc, linux-kernel
In-Reply-To: <1508487261-18524-2-git-send-email-geert+renesas@glider.be>
On 10/20/2017 01:14 AM, Geert Uytterhoeven wrote:
> From: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> The PHY devices sometimes do have their reset signal (maybe even power
> supply?) tied to some GPIO and sometimes it also does happen that a boot
> loader does not leave it deasserted. So far this issue has been attacked
> from (as I believe) a wrong angle: by teaching the MAC driver to manipulate
> the GPIO in question; that solution, when applied to the device trees, led
> to adding the PHY reset GPIO properties to the MAC device node, with one
> exception: Cadence MACB driver which could handle the "reset-gpios" prop
> in a PHY device subnode. I believe that the correct approach is to teach
> the 'phylib' to get the MDIO device reset GPIO from the device tree node
> corresponding to this device -- which this patch is doing...
>
> Note that I had to modify the AT803x PHY driver as it would stop working
> otherwise -- it made use of the reset GPIO for its own purposes...
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
> Acked-by: Rob Herring <robh@kernel.org>
> Acked-by: Florian Fainelli <f.fainelli@gmail.com>
This is a new patch as far as PHYLIB is concerned, so not quite accurate
anymore. Thanks for picking that up, this looks good, with a few minor
things here and there.
> [geert: Propagate actual errors from fwnode_get_named_gpiod()]
> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
> ---
> This has gained a dependency on "[PATCH v2] of_mdio: Fix broken PHY IRQ
> in case of probe deferral"
> (https://www.spinics.net/lists/linux-renesas-soc/msg19442.html), as v3
> needs to propagate errors from of_mdiobus_register_phy() and
> of_mdiobus_register_device() [*].
>
> v3:
> - Fix fwnode_get_named_gpiod() call due to added parameters (which
> allowed to eliminate the gpiod_direction_output() call),
> - Undelete one blank line in the AT803x driver,
> - Resolve rejects, refresh patch,
> - Reword/reformat changelog,
> - Take over from Sergei,
> - Add Acked-by,
> - Remove unneeded gpiod check, as gpiod_set_value() handles NULL fine,
> - Handle fwnode_get_named_gpiod() errors correctly:
> - -ENOENT is ignored (the GPIO is optional), and turned into NULL,
> which allowed to remove all later !IS_ERR() checks,
> - Other errors (incl. -EPROBE_DEFER) are propagated [*],
>
> v2:
> - Reformat changelog,
> - Resolve rejects, refresh patch.
> ---
> Documentation/devicetree/bindings/net/phy.txt | 2 ++
> drivers/net/phy/at803x.c | 18 +++------------
> drivers/net/phy/mdio_bus.c | 4 ++++
> drivers/net/phy/mdio_device.c | 26 +++++++++++++++++++--
> drivers/net/phy/phy_device.c | 33 +++++++++++++++++++++++++--
> drivers/of/of_mdio.c | 23 +++++++++++++++++++
> include/linux/mdio.h | 3 +++
> include/linux/phy.h | 5 ++++
> 8 files changed, 95 insertions(+), 19 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
> index 77d0b2a61ffa96fc..c05479f5ac7cc837 100644
> --- a/Documentation/devicetree/bindings/net/phy.txt
> +++ b/Documentation/devicetree/bindings/net/phy.txt
> @@ -53,6 +53,8 @@ Optional Properties:
> to ensure the integrated PHY is used. The absence of this property indicates
> the muxers should be configured so that the external PHY is used.
>
> +- reset-gpios: The GPIO phandle and specifier for the PHY reset signal.
> +
> Example:
>
> ethernet-phy@0 {
> diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
> index 5f93e6add56394f2..15b4560aeb5de759 100644
> --- a/drivers/net/phy/at803x.c
> +++ b/drivers/net/phy/at803x.c
You most certainly want to make the conversion of the at803x.c driver as
a separate patch, there is no reason why it should be folded within the
patch teaching PHYLIB about PHY reset through GPIOs. More on that below.
> @@ -71,7 +71,6 @@ MODULE_LICENSE("GPL");
>
> struct at803x_priv {
> bool phy_reset:1;
> - struct gpio_desc *gpiod_reset;
> };
>
> struct at803x_context {
> @@ -254,22 +253,11 @@ static int at803x_probe(struct phy_device *phydev)
> {
> struct device *dev = &phydev->mdio.dev;
> struct at803x_priv *priv;
> - struct gpio_desc *gpiod_reset;
>
> priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> if (!priv)
> return -ENOMEM;
>
> - if (phydev->drv->phy_id != ATH8030_PHY_ID)
> - goto does_not_require_reset_workaround;
We have lost that bit now, see below.
> -
> - gpiod_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
> - if (IS_ERR(gpiod_reset))
> - return PTR_ERR(gpiod_reset);
> -
> - priv->gpiod_reset = gpiod_reset;
> -
> -does_not_require_reset_workaround:
> phydev->priv = priv;
>
> return 0;
> @@ -343,14 +331,14 @@ static void at803x_link_change_notify(struct phy_device *phydev)
> * cannot recover from by software.
> */
> if (phydev->state == PHY_NOLINK) {
> - if (priv->gpiod_reset && !priv->phy_reset) {
> + if (phydev->mdio.reset && !priv->phy_reset) {
and phydev->drv->phy_id == ATH8030_PHY_ID, the workaround is not
applicable to all PHY devices.
> struct at803x_context context;
>
> at803x_context_save(phydev, &context);
>
> - gpiod_set_value(priv->gpiod_reset, 1);
> + phy_device_reset(phydev, 1);
> msleep(1);
> - gpiod_set_value(priv->gpiod_reset, 0);
> + phy_device_reset(phydev, 0);
> msleep(1);
>
> at803x_context_restore(phydev, &context);
> diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
> index 2df7b62c1a36811e..da6e5366d641a416 100644
> --- a/drivers/net/phy/mdio_bus.c
> +++ b/drivers/net/phy/mdio_bus.c
> @@ -38,6 +38,7 @@
> #include <linux/phy.h>
> #include <linux/io.h>
> #include <linux/uaccess.h>
> +#include <linux/gpio/consumer.h>
>
> #include <asm/irq.h>
>
> @@ -420,6 +421,9 @@ void mdiobus_unregister(struct mii_bus *bus)
> if (!mdiodev)
> continue;
>
> + if (mdiodev->reset)
> + gpiod_put(mdiodev->reset);
> +
> mdiodev->device_remove(mdiodev);
> mdiodev->device_free(mdiodev);
> }
> diff --git a/drivers/net/phy/mdio_device.c b/drivers/net/phy/mdio_device.c
> index e24f28924af8953d..6926db11ae888174 100644
> --- a/drivers/net/phy/mdio_device.c
> +++ b/drivers/net/phy/mdio_device.c
> @@ -12,6 +12,8 @@
> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
>
> #include <linux/errno.h>
> +#include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
> #include <linux/init.h>
> #include <linux/interrupt.h>
> #include <linux/kernel.h>
> @@ -114,6 +116,12 @@ void mdio_device_remove(struct mdio_device *mdiodev)
> }
> EXPORT_SYMBOL(mdio_device_remove);
>
> +void mdio_device_reset(struct mdio_device *mdiodev, int value)
> +{
> + gpiod_set_value(mdiodev->reset, value);
> +}
> +EXPORT_SYMBOL(mdio_device_reset);
> +
> /**
> * mdio_probe - probe an MDIO device
> * @dev: device to probe
> @@ -128,9 +136,16 @@ static int mdio_probe(struct device *dev)
> struct mdio_driver *mdiodrv = to_mdio_driver(drv);
> int err = 0;
>
> - if (mdiodrv->probe)
> + if (mdiodrv->probe) {
> + /* Deassert the reset signal */
> + mdio_device_reset(mdiodev, 0);
> +
> err = mdiodrv->probe(mdiodev);
>
> + /* Assert the reset signal */
> + mdio_device_reset(mdiodev, 1);
Really? Don't you want to do that only if err is non zero?
> + }
> +
> return err;
> }
>
> @@ -140,9 +155,16 @@ static int mdio_remove(struct device *dev)
> struct device_driver *drv = mdiodev->dev.driver;
> struct mdio_driver *mdiodrv = to_mdio_driver(drv);
>
> - if (mdiodrv->remove)
> + if (mdiodrv->remove) {
> + /* Deassert the reset signal */
> + mdio_device_reset(mdiodev, 0);
> +
Why would that be necessary here? If we remove the driver, we probed it,
so we should already be de-asserted, no?
> mdiodrv->remove(mdiodev);
>
> + /* Assert the reset signal */
> + mdio_device_reset(mdiodev, 1);
> + }
> +
> return 0;
> }
>
> diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
> index 67f25ac29025c539..e694b0ecf780d096 100644
> --- a/drivers/net/phy/phy_device.c
> +++ b/drivers/net/phy/phy_device.c
> @@ -632,6 +632,9 @@ int phy_device_register(struct phy_device *phydev)
> if (err)
> return err;
>
> + /* Deassert the reset signal */
> + phy_device_reset(phydev, 0);
> +
> /* Run all of the fixups for this PHY */
> err = phy_scan_fixups(phydev);
> if (err) {
> @@ -647,9 +650,15 @@ int phy_device_register(struct phy_device *phydev)
> goto out;
> }
>
> + /* Assert the reset signal */
> + phy_device_reset(phydev, 1);
Same here, I don't think you can safely assert the PHY reset signal here
and have no side effects. I see the intent now, you want to keep it in
reset for as long as possible, possibly to minimize power consumption?
Depending on how the reset signal is wired and how the PHY HW is
designed, this may cause the PHY to lose all of the programming done,
probably not a good idea.
> +
> return 0;
>
> out:
> + /* Assert the reset signal */
> + phy_device_reset(phydev, 1);
> +
> mdiobus_unregister_device(&phydev->mdio);
> return err;
> }
> @@ -849,6 +858,9 @@ int phy_init_hw(struct phy_device *phydev)
> {
> int ret = 0;
>
> + /* Deassert the reset signal */
> + phy_device_reset(phydev, 0);
> +
> if (!phydev->drv || !phydev->drv->config_init)
> return 0;
>
> @@ -1126,6 +1138,9 @@ void phy_detach(struct phy_device *phydev)
> put_device(&phydev->mdio.dev);
> if (ndev_owner != bus->owner)
> module_put(bus->owner);
> +
> + /* Assert the reset signal */
> + phy_device_reset(phydev, 1);
> }
> EXPORT_SYMBOL(phy_detach);
>
> @@ -1811,9 +1826,16 @@ static int phy_probe(struct device *dev)
> /* Set the state to READY by default */
> phydev->state = PHY_READY;
>
> - if (phydev->drv->probe)
> + if (phydev->drv->probe) {
> + /* Deassert the reset signal */
> + phy_device_reset(phydev, 0);
> +
> err = phydev->drv->probe(phydev);
>
> + /* Assert the reset signal */
> + phy_device_reset(phydev, 1);
Same as for the MDIO device probe, we can't do that unless we return non
zero from probe.
> + }
> +
> mutex_unlock(&phydev->lock);
>
> return err;
> @@ -1829,8 +1851,15 @@ static int phy_remove(struct device *dev)
> phydev->state = PHY_DOWN;
> mutex_unlock(&phydev->lock);
>
> - if (phydev->drv && phydev->drv->remove)
> + if (phydev->drv && phydev->drv->remove) {
> + /* Deassert the reset signal */
> + phy_device_reset(phydev, 0);
> +
> phydev->drv->remove(phydev);
> +
> + /* Assert the reset signal */
> + phy_device_reset(phydev, 1);
> + }
> phydev->drv = NULL;
>
> return 0;
> diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
> index 98258583abb0b405..3d044119c032d176 100644
> --- a/drivers/of/of_mdio.c
> +++ b/drivers/of/of_mdio.c
> @@ -47,6 +47,7 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id)
> static int of_mdiobus_register_phy(struct mii_bus *mdio,
> struct device_node *child, u32 addr)
> {
> + struct gpio_desc *gpiod;
> struct phy_device *phy;
> bool is_c45;
> int rc;
> @@ -55,10 +56,22 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
> is_c45 = of_device_is_compatible(child,
> "ethernet-phy-ieee802.3-c45");
>
> + /* Deassert the optional reset signal */
> + gpiod = fwnode_get_named_gpiod(&child->fwnode, "reset-gpios", 0,
> + GPIOD_OUT_LOW, "PHY reset");
> + if (PTR_ERR(gpiod) == -ENOENT)
> + gpiod = NULL;
> + else if (IS_ERR(gpiod))
> + return PTR_ERR(gpiod);
> +
> if (!is_c45 && !of_get_phy_id(child, &phy_id))
> phy = phy_device_create(mdio, addr, phy_id, 0, NULL);
> else
> phy = get_phy_device(mdio, addr, is_c45);
> +
> + /* Assert the reset signal again */
> + gpiod_set_value(gpiod, 1);
You have a phy_device reference now, so why not call phy_device_reset()
directly here?
> +
> if (IS_ERR(phy))
> return PTR_ERR(phy);
>
> @@ -81,6 +94,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio,
> * can be looked up later */
> of_node_get(child);
> phy->mdio.dev.of_node = child;
> + phy->mdio.reset = gpiod;
>
> /* All data is now stored in the phy struct;
> * register it */
> @@ -100,6 +114,7 @@ static int of_mdiobus_register_device(struct mii_bus *mdio,
> struct device_node *child, u32 addr)
> {
> struct mdio_device *mdiodev;
> + struct gpio_desc *gpiod;
> int rc;
>
> mdiodev = mdio_device_create(mdio, addr);
> @@ -112,6 +127,14 @@ static int of_mdiobus_register_device(struct mii_bus *mdio,
> of_node_get(child);
> mdiodev->dev.of_node = child;
>
> + gpiod = fwnode_get_named_gpiod(&child->fwnode, "reset-gpios", 0,
> + GPIOD_ASIS, "PHY reset");
> + if (PTR_ERR(gpiod) == -ENOENT)
> + gpiod = NULL;
> + else if (IS_ERR(gpiod))
> + return PTR_ERR(gpiod);
> + mdiodev->reset = gpiod;
There is some obvious and non desireable duplication of code between
"pure" mdio_device and phy_device paths here, can you factor this such
that there is a common function storing gpiod into a mdio_device's reset
member in both cases?
Also, there is some asymetry being exposed here, the GPIO descriptor is
acquired from OF specific code, but is released in the generic MDIO
device layer, can we find a way to make that symmetrical?
--
Florian
^ permalink raw reply
* [PATCH net-next 0/3] tun: timer cleanups
From: Eric Dumazet @ 2017-10-20 18:29 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet, Jason Wang
While working on a syzkaller issue that might have been
fixed already by Cong Wang in commit 0ad646c81b21
("tun: call dev_get_valid_name() before register_netdevice()")
I made three small changes related to flow_gc_timer.
Eric Dumazet (3):
tun: do not block BH again in tun_flow_cleanup()
tun: avoid extra timer schedule in tun_flow_cleanup()
tun: do not arm flow_gc_timer in tun_flow_init()
drivers/net/tun.c | 15 ++++++++-------
1 file changed, 8 insertions(+), 7 deletions(-)
--
2.15.0.rc0.271.g36b669edcc-goog
^ permalink raw reply
* [PATCH net-next 1/3] tun: do not block BH again in tun_flow_cleanup()
From: Eric Dumazet @ 2017-10-20 18:29 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet, Jason Wang
In-Reply-To: <20171020182957.32729-1-edumazet@google.com>
tun_flow_cleanup() being a timer callback, it is already
running in BH context.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/tun.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 3b41c36eae904fec5d11f51ed9fde0e060bba27e..f9541f7f9fb7592b50ac818702006f4f1042b448 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -454,7 +454,7 @@ static void tun_flow_cleanup(unsigned long data)
tun_debug(KERN_INFO, tun, "tun_flow_cleanup\n");
- spin_lock_bh(&tun->lock);
+ spin_lock(&tun->lock);
for (i = 0; i < TUN_NUM_FLOW_ENTRIES; i++) {
struct tun_flow_entry *e;
struct hlist_node *n;
@@ -472,7 +472,7 @@ static void tun_flow_cleanup(unsigned long data)
if (count)
mod_timer(&tun->flow_gc_timer, round_jiffies_up(next_timer));
- spin_unlock_bh(&tun->lock);
+ spin_unlock(&tun->lock);
}
static void tun_flow_update(struct tun_struct *tun, u32 rxhash,
--
2.15.0.rc0.271.g36b669edcc-goog
^ permalink raw reply related
* [PATCH net-next 2/3] tun: avoid extra timer schedule in tun_flow_cleanup()
From: Eric Dumazet @ 2017-10-20 18:29 UTC (permalink / raw)
To: David S . Miller; +Cc: netdev, Eric Dumazet, Eric Dumazet, Jason Wang
In-Reply-To: <20171020182957.32729-1-edumazet@google.com>
If tun_flow_cleanup() deleted all flows, no need to
arm the timer again. It will be armed next time
tun_flow_update() is called.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
drivers/net/tun.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index f9541f7f9fb7592b50ac818702006f4f1042b448..995887de5a98283382a631bcb8dfd874a4037ed3 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -461,11 +461,14 @@ static void tun_flow_cleanup(unsigned long data)
hlist_for_each_entry_safe(e, n, &tun->flows[i], hash_link) {
unsigned long this_timer;
- count++;
+
this_timer = e->updated + delay;
- if (time_before_eq(this_timer, jiffies))
+ if (time_before_eq(this_timer, jiffies)) {
tun_flow_delete(tun, e);
- else if (time_before(this_timer, next_timer))
+ continue;
+ }
+ count++;
+ if (time_before(this_timer, next_timer))
next_timer = this_timer;
}
}
--
2.15.0.rc0.271.g36b669edcc-goog
^ 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