* [PATCH v2 net-next] tcp: add TCPMemoryPressuresChrono counter
From: Eric Dumazet @ 2017-06-07 20:29 UTC (permalink / raw)
To: David Miller; +Cc: netdev
In-Reply-To: <1496776767.736.11.camel@edumazet-glaptop3.roam.corp.google.com>
From: Eric Dumazet <edumazet@google.com>
DRAM supply shortage and poor memory pressure tracking in TCP
stack makes any change in SO_SNDBUF/SO_RCVBUF (or equivalent autotuning
limits) and tcp_mem[] quite hazardous.
TCPMemoryPressures SNMP counter is an indication of tcp_mem sysctl
limits being hit, but only tracking number of transitions.
If TCP stack behavior under stress was perfect :
1) It would maintain memory usage close to the limit.
2) Memory pressure state would be entered for short times.
We certainly prefer 100 events lasting 10ms compared to one event
lasting 200 seconds.
This patch adds a new SNMP counter tracking cumulative duration of
memory pressure events, given in ms units.
$ cat /proc/sys/net/ipv4/tcp_mem
3088 4117 6176
$ grep TCP /proc/net/sockstat
TCP: inuse 180 orphan 0 tw 2 alloc 234 mem 4140
$ nstat -n ; sleep 10 ; nstat |grep Pressure
TcpExtTCPMemoryPressures 1700
TcpExtTCPMemoryPressuresChrono 5209
v2: Used EXPORT_SYMBOL_GPL() instead of EXPORT_SYMBOL() as David
instructed.
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
include/net/sock.h | 22 ++--------------------
include/net/tcp.h | 3 ++-
include/uapi/linux/snmp.h | 1 +
net/core/sock.c | 20 ++++++++++++++++++++
net/decnet/af_decnet.c | 2 +-
net/ipv4/proc.c | 1 +
net/ipv4/tcp.c | 31 +++++++++++++++++++++++++------
net/ipv4/tcp_ipv4.c | 1 +
net/ipv6/tcp_ipv6.c | 1 +
net/sctp/socket.c | 2 +-
10 files changed, 55 insertions(+), 29 deletions(-)
diff --git a/include/net/sock.h b/include/net/sock.h
index 3467d9e89e7dba1c35fa44a6268a28735f795319..858891c36f94ad2577726d6d21cf871dbcd55d98 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1080,6 +1080,7 @@ struct proto {
bool (*stream_memory_free)(const struct sock *sk);
/* Memory pressure */
void (*enter_memory_pressure)(struct sock *sk);
+ void (*leave_memory_pressure)(struct sock *sk);
atomic_long_t *memory_allocated; /* Current allocated memory. */
struct percpu_counter *sockets_allocated; /* Current number of sockets. */
/*
@@ -1088,7 +1089,7 @@ struct proto {
* All the __sk_mem_schedule() is of this nature: accounting
* is strict, actions are advisory and have some latency.
*/
- int *memory_pressure;
+ unsigned long *memory_pressure;
long *sysctl_mem;
int *sysctl_wmem;
int *sysctl_rmem;
@@ -1193,25 +1194,6 @@ static inline bool sk_under_memory_pressure(const struct sock *sk)
return !!*sk->sk_prot->memory_pressure;
}
-static inline void sk_leave_memory_pressure(struct sock *sk)
-{
- int *memory_pressure = sk->sk_prot->memory_pressure;
-
- if (!memory_pressure)
- return;
-
- if (*memory_pressure)
- *memory_pressure = 0;
-}
-
-static inline void sk_enter_memory_pressure(struct sock *sk)
-{
- if (!sk->sk_prot->enter_memory_pressure)
- return;
-
- sk->sk_prot->enter_memory_pressure(sk);
-}
-
static inline long
sk_memory_allocated(const struct sock *sk)
{
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 28b577a35786ddc9b223b54dd387e59910d9c521..9b7cf93392d7f850d539f8b51333f2ba13e8856f 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -279,7 +279,7 @@ extern int sysctl_tcp_pacing_ca_ratio;
extern atomic_long_t tcp_memory_allocated;
extern struct percpu_counter tcp_sockets_allocated;
-extern int tcp_memory_pressure;
+extern unsigned long tcp_memory_pressure;
/* optimized version of sk_under_memory_pressure() for TCP sockets */
static inline bool tcp_under_memory_pressure(const struct sock *sk)
@@ -1322,6 +1322,7 @@ extern void tcp_openreq_init_rwin(struct request_sock *req,
const struct dst_entry *dst);
void tcp_enter_memory_pressure(struct sock *sk);
+void tcp_leave_memory_pressure(struct sock *sk);
static inline int keepalive_intvl_when(const struct tcp_sock *tp)
{
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index 95cffcb21dfdba7c974706131d0f43e21435e82d..d8569329579816213255169d0c183f4400835f7b 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -228,6 +228,7 @@ enum
LINUX_MIB_TCPABORTONLINGER, /* TCPAbortOnLinger */
LINUX_MIB_TCPABORTFAILED, /* TCPAbortFailed */
LINUX_MIB_TCPMEMORYPRESSURES, /* TCPMemoryPressures */
+ LINUX_MIB_TCPMEMORYPRESSURESCHRONO, /* TCPMemoryPressuresChrono */
LINUX_MIB_TCPSACKDISCARD, /* TCPSACKDiscard */
LINUX_MIB_TCPDSACKIGNOREDOLD, /* TCPSACKIgnoredOld */
LINUX_MIB_TCPDSACKIGNOREDNOUNDO, /* TCPSACKIgnoredNoUndo */
diff --git a/net/core/sock.c b/net/core/sock.c
index bef844127e0182091678b9d57f7ec85c5241748d..ad8a4bc841267a442a1da3c56ef1cf074f9825b9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2076,6 +2076,26 @@ int sock_cmsg_send(struct sock *sk, struct msghdr *msg,
}
EXPORT_SYMBOL(sock_cmsg_send);
+static void sk_enter_memory_pressure(struct sock *sk)
+{
+ if (!sk->sk_prot->enter_memory_pressure)
+ return;
+
+ sk->sk_prot->enter_memory_pressure(sk);
+}
+
+static void sk_leave_memory_pressure(struct sock *sk)
+{
+ if (sk->sk_prot->leave_memory_pressure) {
+ sk->sk_prot->leave_memory_pressure(sk);
+ } else {
+ unsigned long *memory_pressure = sk->sk_prot->memory_pressure;
+
+ if (memory_pressure && *memory_pressure)
+ *memory_pressure = 0;
+ }
+}
+
/* On 32bit arches, an skb frag is limited to 2^15 */
#define SKB_FRAG_PAGE_ORDER get_order(32768)
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
index 405483a07efc7ac2efcfe86e285a7673547c9691..73a0399dc7a277178b0a432a067172131dce99ee 100644
--- a/net/decnet/af_decnet.c
+++ b/net/decnet/af_decnet.c
@@ -447,7 +447,7 @@ static void dn_destruct(struct sock *sk)
dst_release(rcu_dereference_check(sk->sk_dst_cache, 1));
}
-static int dn_memory_pressure;
+static unsigned long dn_memory_pressure;
static void dn_enter_memory_pressure(struct sock *sk)
{
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c
index fa44e752a9a3f8eb9957314149ae15e6df10465a..43eb6567b3a0a2add9a1d36019eae5b6d5caf657 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -250,6 +250,7 @@ static const struct snmp_mib snmp4_net_list[] = {
SNMP_MIB_ITEM("TCPAbortOnLinger", LINUX_MIB_TCPABORTONLINGER),
SNMP_MIB_ITEM("TCPAbortFailed", LINUX_MIB_TCPABORTFAILED),
SNMP_MIB_ITEM("TCPMemoryPressures", LINUX_MIB_TCPMEMORYPRESSURES),
+ SNMP_MIB_ITEM("TCPMemoryPressuresChrono", LINUX_MIB_TCPMEMORYPRESSURESCHRONO),
SNMP_MIB_ITEM("TCPSACKDiscard", LINUX_MIB_TCPSACKDISCARD),
SNMP_MIB_ITEM("TCPDSACKIgnoredOld", LINUX_MIB_TCPDSACKIGNOREDOLD),
SNMP_MIB_ITEM("TCPDSACKIgnoredNoUndo", LINUX_MIB_TCPDSACKIGNOREDNOUNDO),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 87981fcdfcf20c6846ea3474dce1e640aea6e092..cc8fd8b747a47e9b66492ecdf27256ef6d879877 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -320,17 +320,36 @@ struct tcp_splice_state {
* All the __sk_mem_schedule() is of this nature: accounting
* is strict, actions are advisory and have some latency.
*/
-int tcp_memory_pressure __read_mostly;
-EXPORT_SYMBOL(tcp_memory_pressure);
+unsigned long tcp_memory_pressure __read_mostly;
+EXPORT_SYMBOL_GPL(tcp_memory_pressure);
void tcp_enter_memory_pressure(struct sock *sk)
{
- if (!tcp_memory_pressure) {
+ unsigned long val;
+
+ if (tcp_memory_pressure)
+ return;
+ val = jiffies;
+
+ if (!val)
+ val--;
+ if (!cmpxchg(&tcp_memory_pressure, 0, val))
NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURES);
- tcp_memory_pressure = 1;
- }
}
-EXPORT_SYMBOL(tcp_enter_memory_pressure);
+EXPORT_SYMBOL_GPL(tcp_enter_memory_pressure);
+
+void tcp_leave_memory_pressure(struct sock *sk)
+{
+ unsigned long val;
+
+ if (!tcp_memory_pressure)
+ return;
+ val = xchg(&tcp_memory_pressure, 0);
+ if (val)
+ NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPMEMORYPRESSURESCHRONO,
+ jiffies_to_msecs(jiffies - val));
+}
+EXPORT_SYMBOL_GPL(tcp_leave_memory_pressure);
/* Convert seconds to retransmits based on initial and max timeout */
static u8 secs_to_retrans(int seconds, int timeout, int rto_max)
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 191b2f78b19d2c8d62c59cc046bd608687679619..d19933949373ca019fd06fa310a506efd29718cb 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2387,6 +2387,7 @@ struct proto tcp_prot = {
.unhash = inet_unhash,
.get_port = inet_csk_get_port,
.enter_memory_pressure = tcp_enter_memory_pressure,
+ .leave_memory_pressure = tcp_leave_memory_pressure,
.stream_memory_free = tcp_stream_memory_free,
.sockets_allocated = &tcp_sockets_allocated,
.orphan_count = &tcp_orphan_count,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 233edfabe1dbceaeb6cdd42a2bb379072aeee361..f6592790d9f93bf40f3e5432c945bca20b28ff34 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -1909,6 +1909,7 @@ struct proto tcpv6_prot = {
.unhash = inet_unhash,
.get_port = inet_csk_get_port,
.enter_memory_pressure = tcp_enter_memory_pressure,
+ .leave_memory_pressure = tcp_leave_memory_pressure,
.stream_memory_free = tcp_stream_memory_free,
.sockets_allocated = &tcp_sockets_allocated,
.memory_allocated = &tcp_memory_allocated,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 0822046e4f3f5a1acd3f5382d915bf9004a25c1c..5f58dd03e3ace38b9c4babbe2d92f0a3f98a4b68 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -103,7 +103,7 @@ static int sctp_autobind(struct sock *sk);
static void sctp_sock_migrate(struct sock *, struct sock *,
struct sctp_association *, sctp_socket_type_t);
-static int sctp_memory_pressure;
+static unsigned long sctp_memory_pressure;
static atomic_long_t sctp_memory_allocated;
struct percpu_counter sctp_sockets_allocated;
^ permalink raw reply related
* Re: [net-intel-i40e] question about assignment overwrite
From: Jeff Kirsher @ 2017-06-07 20:34 UTC (permalink / raw)
To: Mauro Rodrigues
Cc: Gustavo A. R. Silva, intel-wired-lan, netdev, linux-kernel
In-Reply-To: <20170607195526.GA26867@korriban>
[-- Attachment #1: Type: text/plain, Size: 3367 bytes --]
On Wed, 2017-06-07 at 16:55 -0300, Mauro Rodrigues wrote:
> On Wed, May 17, 2017 at 10:49:11PM -0700, Jeff Kirsher wrote:
> > On Wed, 2017-05-17 at 15:48 -0500, Gustavo A. R. Silva wrote:
> > > While looking into Coverity ID 1408956 I ran into the following
> > > piece
> > > of code at drivers/net/ethernet/intel/i40e/i40e_main.c:8807:
> > >
> > > 8807 if (pf->hw.mac.type == I40E_MAC_X722) {
> > > 8808 pf->flags |= I40E_FLAG_RSS_AQ_CAPABLE
> > > 8809 | I40E_FLAG_128_QP_RSS_CAPABLE
> > > 8810 | I40E_FLAG_HW_ATR_EVICT_CAPABLE
> > > 8811 | I40E_FLAG_OUTER_UDP_CSUM_CAPABLE
> > > 8812 | I40E_FLAG_WB_ON_ITR_CAPABLE
> > > 8813 |
> > > I40E_FLAG_MULTIPLE_TCP_UDP_RSS_PCTYPE
> > > 8814 | I40E_FLAG_NO_PCI_LINK_CHECK
> > > 8815 | I40E_FLAG_USE_SET_LLDP_MIB
> > > 8816 | I40E_FLAG_GENEVE_OFFLOAD_CAPABLE
> > > 8817 | I40E_FLAG_PTP_L4_CAPABLE
> > > 8818 | I40E_FLAG_WOL_MC_MAGIC_PKT_WAKE;
> > > 8819 } else if ((pf->hw.aq.api_maj_ver > 1) ||
> > > 8820 ((pf->hw.aq.api_maj_ver == 1) &&
> > > 8821 (pf->hw.aq.api_min_ver > 4))) {
> > > 8822 /* Supported in FW API version higher than 1.4 */
> > > 8823 pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
> > > 8824 pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
> > > 8825 } else {
> > > 8826 pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
> > > 8827 }
> > >
> > > The issue here is that the assignment at line 8823 is overwritten
> > > by
> > > the code at line 8824.
> > >
> > > I'm suspicious that line 8824 should be remove and a patch like the
> > > following can be applied:
> > >
> > > index d5c9c9e..48ffa73 100644
> > > --- a/drivers/net/ethernet/intel/i40e/i40e_main.c
> > > +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
> > > @@ -8821,7 +8821,6 @@ static int i40e_sw_init(struct i40e_pf *pf)
> > > (pf->hw.aq.api_min_ver > 4))) {
> > > /* Supported in FW API version higher than 1.4 */
> > > pf->flags |= I40E_FLAG_GENEVE_OFFLOAD_CAPABLE;
> > > - pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
> > > } else {
> > > pf->flags = I40E_FLAG_HW_ATR_EVICT_CAPABLE;
> > > }
> > >
> > > What do you think?
> >
> > This issue is already fixed in my dev-queue branch on my next-queue
> > tree.
>
> Hi Jeff, are you planning to push this fix into net branch anytime soon?
>
> Thanks,
>
> Mauro
The patch that fixed this issue is already in David Miller's net-next tree.
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH net-next] net: phy: use of_mdio_parse_addr
From: Jon Mason @ 2017-06-07 20:53 UTC (permalink / raw)
To: Liviu Dudau
Cc: David Miller, Andrew Lunn, Florian Fainelli, Network Development,
open list, BCM Kernel Feedback
In-Reply-To: <20170607161854.GC4389@bart.dudau.co.uk>
On Wed, Jun 7, 2017 at 12:18 PM, Liviu Dudau <liviu@dudau.co.uk> wrote:
> On Fri, Jun 02, 2017 at 02:22:51PM -0400, David Miller wrote:
>> From: Jon Mason <jon.mason@broadcom.com>
>> Date: Wed, 31 May 2017 15:43:30 -0400
>>
>> > use of_mdio_parse_addr() in place of an OF read of reg and a bounds
>> > check (which is litterally the exact same thing that
>> > of_mdio_parse_addr() does)
>> >
>> > Signed-off-by: Jon Mason <jon.mason@broadcom.com>
>>
>> Applied, thanks Jon.
>
> This makes linux-next fail the modules_install target as depmod detects 2 circular
> dependencies. Reverting this patch fixes the issue.
>
> depmod: ERROR: Cycle detected: libphy -> of_mdio -> fixed_phy -> libphy
> depmod: ERROR: Cycle detected: libphy -> of_mdio -> libphy
> depmod: ERROR: Found 3 modules in dependency cycles!
> make[1]: *** [/home/dliviu/devel/kernel/Makefile:1245: _modinst_post] Error 1
I did not test this as modules. Sorry.
It would be ugly to duplicate the code in both place, and the code in
question does not seem to really need to be in a C file. Perhaps it
can be moved to a header file as an inline function, which would solve
this dependency. Would this be acceptable?
Thanks,
Jon
>
> This is on an ARCH=arm build, build I doubt it makes a difference. Let me know if
> you need some .config values in order to reproduce.
>
> Best regards,
> Liviu
>
^ permalink raw reply
* Re: [PATCH net-next] net: phy: use of_mdio_parse_addr
From: Florian Fainelli @ 2017-06-07 20:54 UTC (permalink / raw)
To: Jon Mason, Liviu Dudau
Cc: David Miller, Andrew Lunn, Florian Fainelli, Network Development,
open list, BCM Kernel Feedback
In-Reply-To: <CAC3K-4pH51jhKyEfq0mYDNz-+ir5VRe_Kzb082Gd+wiAxiGF7Q@mail.gmail.com>
On 06/07/2017 01:53 PM, Jon Mason wrote:
> On Wed, Jun 7, 2017 at 12:18 PM, Liviu Dudau <liviu@dudau.co.uk> wrote:
>> On Fri, Jun 02, 2017 at 02:22:51PM -0400, David Miller wrote:
>>> From: Jon Mason <jon.mason@broadcom.com>
>>> Date: Wed, 31 May 2017 15:43:30 -0400
>>>
>>>> use of_mdio_parse_addr() in place of an OF read of reg and a bounds
>>>> check (which is litterally the exact same thing that
>>>> of_mdio_parse_addr() does)
>>>>
>>>> Signed-off-by: Jon Mason <jon.mason@broadcom.com>
>>>
>>> Applied, thanks Jon.
>>
>> This makes linux-next fail the modules_install target as depmod detects 2 circular
>> dependencies. Reverting this patch fixes the issue.
>>
>> depmod: ERROR: Cycle detected: libphy -> of_mdio -> fixed_phy -> libphy
>> depmod: ERROR: Cycle detected: libphy -> of_mdio -> libphy
>> depmod: ERROR: Found 3 modules in dependency cycles!
>> make[1]: *** [/home/dliviu/devel/kernel/Makefile:1245: _modinst_post] Error 1
>
> I did not test this as modules. Sorry.
>
> It would be ugly to duplicate the code in both place, and the code in
> question does not seem to really need to be in a C file. Perhaps it
> can be moved to a header file as an inline function, which would solve
> this dependency. Would this be acceptable?
You read my mind, was just going to suggest doing that.
--
Florian
^ permalink raw reply
* [RESEND PATCH 0/4] Missing QRTR features
From: Bjorn Andersson @ 2017-06-07 21:07 UTC (permalink / raw)
To: David S. Miller
Cc: Arun Kumar Neelakantam, netdev, linux-arm-msm, linux-kernel,
Courtney Cavin
The QMUX specification covers packet routing as well as service life cycle and
discovery. The current implementation of qrtr supports the prior part, but in
order to fully implement service management on-top a few more parts are needed.
The first patch in the series serves the purpose of reducing duplication in
patch two and three.
The second and third patch adds two qrtr-level notifications required by the
specification, in order to notify local and remote service controllers about
dying clients.
The last patch serves the purpose of notifying local clients about the presence
of a local service register, allowing them to register services as well as
querying for remote registered services.
Bjorn Andersson (4):
net: qrtr: Refactor packet allocation
net: qrtr: Inject BYE on remote termination
net: qrtr: Broadcast DEL_CLIENT message when endpoint is closed
net: qrtr: Inform open sockets about new controller
net/qrtr/qrtr.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 98 insertions(+), 6 deletions(-)
--
2.12.0
^ permalink raw reply
* [RESEND PATCH 1/4] net: qrtr: Refactor packet allocation
From: Bjorn Andersson @ 2017-06-07 21:07 UTC (permalink / raw)
To: David S. Miller
Cc: Arun Kumar Neelakantam, netdev, linux-arm-msm, linux-kernel,
Courtney Cavin
In-Reply-To: <20170607210739.27263-1-bjorn.andersson@linaro.org>
Extract the allocation and filling in the control message header fields
to a separate function in order to reuse this in subsequent patches.
Cc: Courtney Cavin <ccavin@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
net/qrtr/qrtr.c | 25 +++++++++++++++++++------
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index a9a8c7d5a4a9..86d35ed50da9 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -245,14 +245,11 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
}
EXPORT_SYMBOL_GPL(qrtr_endpoint_post);
-/* Allocate and construct a resume-tx packet. */
-static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
- u32 dst_node, u32 port)
+static struct sk_buff *qrtr_alloc_ctrl_packet(u32 type, size_t pkt_len,
+ u32 src_node, u32 dst_node)
{
- const int pkt_len = 20;
struct qrtr_hdr *hdr;
struct sk_buff *skb;
- __le32 *buf;
skb = alloc_skb(QRTR_HDR_SIZE + pkt_len, GFP_KERNEL);
if (!skb)
@@ -261,7 +258,7 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
hdr = (struct qrtr_hdr *)skb_put(skb, QRTR_HDR_SIZE);
hdr->version = cpu_to_le32(QRTR_PROTO_VER);
- hdr->type = cpu_to_le32(QRTR_TYPE_RESUME_TX);
+ hdr->type = cpu_to_le32(type);
hdr->src_node_id = cpu_to_le32(src_node);
hdr->src_port_id = cpu_to_le32(QRTR_PORT_CTRL);
hdr->confirm_rx = cpu_to_le32(0);
@@ -269,6 +266,22 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
hdr->dst_node_id = cpu_to_le32(dst_node);
hdr->dst_port_id = cpu_to_le32(QRTR_PORT_CTRL);
+ return skb;
+}
+
+/* Allocate and construct a resume-tx packet. */
+static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
+ u32 dst_node, u32 port)
+{
+ const int pkt_len = 20;
+ struct sk_buff *skb;
+ __le32 *buf;
+
+ skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_RESUME_TX, pkt_len,
+ src_node, dst_node);
+ if (!skb)
+ return NULL;
+
buf = (__le32 *)skb_put(skb, pkt_len);
memset(buf, 0, pkt_len);
buf[0] = cpu_to_le32(QRTR_TYPE_RESUME_TX);
--
2.12.0
^ permalink raw reply related
* [RESEND PATCH 3/4] net: qrtr: Broadcast DEL_CLIENT message when endpoint is closed
From: Bjorn Andersson @ 2017-06-07 21:07 UTC (permalink / raw)
To: David S. Miller
Cc: Arun Kumar Neelakantam, netdev, linux-arm-msm, linux-kernel,
Courtney Cavin
In-Reply-To: <20170607210739.27263-1-bjorn.andersson@linaro.org>
Per the QMUXv2 protocol specificiation a DEL_CLIENT message should be
broadcasted when an endpoint is disconnected.
The protocol specification does suggest that the router can keep track
of which nodes the endpoint has been communicating with to not wake up
sleeping remotes unecessarily, but implementation of this suggestion is
left for the future.
Cc: Courtney Cavin <ccavin@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
net/qrtr/qrtr.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index e8cbab23d667..d7516098b5aa 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -112,6 +112,7 @@ struct qrtr_node {
};
static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb);
+static int qrtr_bcast_enqueue(struct qrtr_node *node, struct sk_buff *skb);
/* Release node resources and free the node.
*
@@ -312,6 +313,26 @@ static struct sk_buff *qrtr_alloc_local_bye(u32 src_node)
return skb;
}
+static struct sk_buff *qrtr_alloc_del_client(struct sockaddr_qrtr *sq)
+{
+ const int pkt_len = 20;
+ struct sk_buff *skb;
+ __le32 *buf;
+
+ skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_DEL_CLIENT, pkt_len,
+ sq->sq_node, QRTR_NODE_BCAST);
+ if (!skb)
+ return NULL;
+
+ buf = (__le32 *)skb_put(skb, pkt_len);
+ memset(buf, 0, pkt_len);
+ buf[0] = cpu_to_le32(QRTR_TYPE_DEL_CLIENT);
+ buf[1] = cpu_to_le32(sq->sq_node);
+ buf[2] = cpu_to_le32(sq->sq_port);
+
+ return skb;
+}
+
static struct qrtr_sock *qrtr_port_lookup(int port);
static void qrtr_port_put(struct qrtr_sock *ipc);
@@ -448,8 +469,15 @@ static void qrtr_port_put(struct qrtr_sock *ipc)
/* Remove port assignment. */
static void qrtr_port_remove(struct qrtr_sock *ipc)
{
+ struct sk_buff *skb;
int port = ipc->us.sq_port;
+ skb = qrtr_alloc_del_client(&ipc->us);
+ if (skb) {
+ skb_set_owner_w(skb, &ipc->sk);
+ qrtr_bcast_enqueue(NULL, skb);
+ }
+
if (port == QRTR_PORT_CTRL)
port = 0;
--
2.12.0
^ permalink raw reply related
* [RESEND PATCH 4/4] net: qrtr: Inform open sockets about new controller
From: Bjorn Andersson @ 2017-06-07 21:07 UTC (permalink / raw)
To: David S. Miller
Cc: Arun Kumar Neelakantam, netdev, linux-arm-msm, linux-kernel,
Courtney Cavin
In-Reply-To: <20170607210739.27263-1-bjorn.andersson@linaro.org>
As the higher level communication only deals with "services" the
a service directory is required to keep track of local and remote
services. In order for qrtr clients to be informed about when the
service directory implementation is available some event needs to be
passed to them.
Rather than introducing support for broadcasting such a message in-band
to all open local sockets we flag each socket with ENETRESET, as there
are no other expected operations that would benefit from having support
from locally broadcasting messages.
Cc: Courtney Cavin <ccavin@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
net/qrtr/qrtr.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index d7516098b5aa..c7a5d861906b 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -530,6 +530,26 @@ static int qrtr_port_assign(struct qrtr_sock *ipc, int *port)
return 0;
}
+/* Reset all non-control ports */
+static void qrtr_reset_ports(void)
+{
+ struct qrtr_sock *ipc;
+ int id;
+
+ mutex_lock(&qrtr_port_lock);
+ idr_for_each_entry(&qrtr_ports, ipc, id) {
+ /* Don't reset control port */
+ if (id == 0)
+ continue;
+
+ sock_hold(&ipc->sk);
+ ipc->sk.sk_err = ENETRESET;
+ wake_up_interruptible(sk_sleep(&ipc->sk));
+ sock_put(&ipc->sk);
+ }
+ mutex_unlock(&qrtr_port_lock);
+}
+
/* Bind socket to address.
*
* Socket should be locked upon call.
@@ -558,6 +578,10 @@ static int __qrtr_bind(struct socket *sock,
sock_reset_flag(sk, SOCK_ZAPPED);
+ /* Notify all open ports about the new controller */
+ if (port == QRTR_PORT_CTRL)
+ qrtr_reset_ports();
+
return 0;
}
--
2.12.0
^ permalink raw reply related
* [RESEND PATCH 2/4] net: qrtr: Inject BYE on remote termination
From: Bjorn Andersson @ 2017-06-07 21:07 UTC (permalink / raw)
To: David S. Miller
Cc: Arun Kumar Neelakantam, netdev, linux-arm-msm, linux-kernel,
Courtney Cavin
In-Reply-To: <20170607210739.27263-1-bjorn.andersson@linaro.org>
Per the QMUX protocol specification a terminating node can send a BYE
control message to signal that the link is going down, upon receiving
this all information about remote services should be discarded and local
clients should be notified.
In the event that the link was brought down abruptly the router is
supposed to act like a BYE message has arrived. As there is no harm in
receiving an extra BYE from the remote this patch implements the latter
by injecting a BYE when the link to the remote is unregistered.
The name service will receive the BYE and can implement the notification
to the local clients.
Cc: Courtney Cavin <ccavin@gmail.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
---
net/qrtr/qrtr.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c
index 86d35ed50da9..e8cbab23d667 100644
--- a/net/qrtr/qrtr.c
+++ b/net/qrtr/qrtr.c
@@ -111,6 +111,8 @@ struct qrtr_node {
struct list_head item;
};
+static int qrtr_local_enqueue(struct qrtr_node *node, struct sk_buff *skb);
+
/* Release node resources and free the node.
*
* Do not call directly, use qrtr_node_release. To be used with
@@ -291,6 +293,25 @@ static struct sk_buff *qrtr_alloc_resume_tx(u32 src_node,
return skb;
}
+/* Allocate and construct a BYE message to signal remote termination */
+static struct sk_buff *qrtr_alloc_local_bye(u32 src_node)
+{
+ const int pkt_len = 20;
+ struct sk_buff *skb;
+ __le32 *buf;
+
+ skb = qrtr_alloc_ctrl_packet(QRTR_TYPE_BYE, pkt_len,
+ src_node, qrtr_local_nid);
+ if (!skb)
+ return NULL;
+
+ buf = (__le32 *)skb_put(skb, pkt_len);
+ memset(buf, 0, pkt_len);
+ buf[0] = cpu_to_le32(QRTR_TYPE_BYE);
+
+ return skb;
+}
+
static struct qrtr_sock *qrtr_port_lookup(int port);
static void qrtr_port_put(struct qrtr_sock *ipc);
@@ -382,11 +403,17 @@ EXPORT_SYMBOL_GPL(qrtr_endpoint_register);
void qrtr_endpoint_unregister(struct qrtr_endpoint *ep)
{
struct qrtr_node *node = ep->node;
+ struct sk_buff *skb;
mutex_lock(&node->ep_lock);
node->ep = NULL;
mutex_unlock(&node->ep_lock);
+ /* Notify the local controller about the event */
+ skb = qrtr_alloc_local_bye(node->nid);
+ if (skb)
+ qrtr_local_enqueue(NULL, skb);
+
qrtr_node_release(node);
ep->node = NULL;
}
--
2.12.0
^ permalink raw reply related
* Re: [PATCH V2 1/3] Documentation: devicetree: add multiple cpu port DSA binding
From: Rob Herring @ 2017-06-07 21:10 UTC (permalink / raw)
To: Florian Fainelli
Cc: John Crispin, Andrew Lunn, Vivien Didelot, David S . Miller,
Sean Wang, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <69dd02a6-59f9-59df-f630-0ebd948451c4-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
On Tue, May 30, 2017 at 02:32:29PM -0700, Florian Fainelli wrote:
> On 05/30/2017 03:44 AM, John Crispin wrote:
> > Extend the DSA binding documentation, adding the new property required
> > when there is more than one CPU port attached to the switch.
> >
> > Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > Signed-off-by: John Crispin <john-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>
> > ---
> > Documentation/devicetree/bindings/net/dsa/dsa.txt | 61 ++++++++++++++++++++++-
> > 1 file changed, 60 insertions(+), 1 deletion(-)
> >
> > diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > index cfe8f64eca4f..c164eb38ccc5 100644
> > --- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > +++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > @@ -55,6 +55,11 @@ A user port has the following optional property:
> > - label : Describes the label associated with this port, which
> > will become the netdev name.
> >
> > +- cpu : Option for non "cpu"/"dsa" ports. A phandle to a
> > + "cpu" port, which will be used for passing packets
> > + from this port to the host. If not present, the first
> > + "cpu" port will be used.
>
> So this option essentially allow us to "partition" the switch between
> vectors of ports and their upstream/CPU port.
Could this be more generic? This is basically saying route all packets
on this port to another port. Maybe there's some usecase to route to
non-cpu ports?
> While using Device Tree is an obvious choice for making the initial
> partitioning, it seems like we are missing a configuration mechanism
> whereby we can properly assign ports to a specific upstream CPU port.
What determines how things are routed/partitioned? If it is purely user
choice then I don't think this should be in DT.
> Let's move the actual discussion into patch 2 in order not to pollute
> the DT maintainers' inbox.
--
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
* Re: [PATCH net-next 0/3] rxrpc: Tx length parameter
From: David Howells @ 2017-06-07 21:11 UTC (permalink / raw)
Cc: dhowells, netdev, linux-afs, linux-kernel
In-Reply-To: <149685280179.8474.3836343127280242150.stgit@warthog.procyon.org.uk>
David Howells <dhowells@redhat.com> wrote:
> (3) Introduce the RXRPC_TX_LENGTH cmsg. This can be provided on the first
> sendmsg() that contributes data to a client call request or a service
> call reply. If provided, the user must provide exactly that amount of
> data or an error will be incurred.
I forgot to change struct rxrpc_send_params::tx_total_len from u64 to s64.
Will repost.
David
^ permalink raw reply
* [PATCH net-next 0/3] rxrpc: Tx length parameter
From: David Howells @ 2017-06-07 21:12 UTC (permalink / raw)
To: netdev; +Cc: dhowells, linux-afs, linux-kernel
Here's a set of patches that allows someone initiating a client call with
AF_RXRPC to indicate upfront the total amount of data that will be
transmitted. This will allow AF_RXRPC to encrypt directly from source
buffer to packet rather than having to copy into the buffer and only
encrypt when it's full (the encrypted portion of the packet starts with a
length and so we can't encrypt until we know what the length will be).
The three patches are:
(1) Provide a means of finding out what control message types are actually
supported. EINVAL is reported if an unsupported cmsg type is seen, so
we don't want to set the new cmsg unless we know it will be accepted.
(2) Consolidate some stuff into a struct to reduce the parameter count on
the function that parses the cmsg buffer.
(3) Introduce the RXRPC_TX_LENGTH cmsg. This can be provided on the first
sendmsg() that contributes data to a client call request or a service
call reply. If provided, the user must provide exactly that amount of
data or an error will be incurred.
Changes in version 2:
(*) struct rxrpc_send_params::tx_total_len should be s64 not u64. Thanks to
Julia Lawall for reporting this.
The patches can be found here also:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=rxrpc-rewrite
Tagged thusly:
git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
rxrpc-rewrite-20170607-v2
David
---
David Howells (3):
rxrpc: Provide a getsockopt call to query what cmsgs types are supported
rxrpc: Consolidate sendmsg parameters
rxrpc: Provide a cmsg to specify the amount of Tx data for a call
Documentation/networking/rxrpc.txt | 43 +++++++++++
fs/afs/rxrpc.c | 18 +++++
include/linux/rxrpc.h | 25 ++++---
include/net/af_rxrpc.h | 2 +
net/rxrpc/af_rxrpc.c | 35 +++++++++
net/rxrpc/ar-internal.h | 3 +
net/rxrpc/call_object.c | 3 +
net/rxrpc/sendmsg.c | 135 +++++++++++++++++++++++++-----------
8 files changed, 207 insertions(+), 57 deletions(-)
^ permalink raw reply
* [PATCH net-next 1/3] rxrpc: Provide a getsockopt call to query what cmsgs types are supported
From: David Howells @ 2017-06-07 21:12 UTC (permalink / raw)
To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <149686995195.21359.17550471913376009423.stgit@warthog.procyon.org.uk>
Provide a getsockopt() call that can query what cmsg types are supported by
AF_RXRPC.
---
Documentation/networking/rxrpc.txt | 9 +++++++++
include/linux/rxrpc.h | 24 ++++++++++++++----------
net/rxrpc/af_rxrpc.c | 30 +++++++++++++++++++++++++++++-
3 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index 18078e630a63..bce8e10a2a8e 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -406,6 +406,10 @@ calls, to invoke certain actions and to report certain conditions. These are:
future communication to that server and RXRPC_UPGRADE_SERVICE should no
longer be set.
+The symbol RXRPC__SUPPORTED is defined as one more than the highest control
+message type supported. At run time this can be queried by means of the
+RXRPC_SUPPORTED_CMSG socket option (see below).
+
==============
SOCKET OPTIONS
@@ -459,6 +463,11 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
must point to an array of two unsigned short ints. The first is the
service ID to upgrade from and the second the service ID to upgrade to.
+ (*) RXRPC_SUPPORTED_CMSG
+
+ This is a read-only option that writes an int into the buffer indicating
+ the highest control message type supported.
+
========
SECURITY
diff --git a/include/linux/rxrpc.h b/include/linux/rxrpc.h
index 707910c6c6c5..bdd3175b9a48 100644
--- a/include/linux/rxrpc.h
+++ b/include/linux/rxrpc.h
@@ -38,6 +38,7 @@ struct sockaddr_rxrpc {
#define RXRPC_EXCLUSIVE_CONNECTION 3 /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */
#define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */
#define RXRPC_UPGRADEABLE_SERVICE 5 /* Upgrade service[0] -> service[1] */
+#define RXRPC_SUPPORTED_CMSG 6 /* Get highest supported control message type */
/*
* RxRPC control messages
@@ -45,16 +46,19 @@ struct sockaddr_rxrpc {
* - terminal messages mean that a user call ID tag can be recycled
* - s/r/- indicate whether these are applicable to sendmsg() and/or recvmsg()
*/
-#define RXRPC_USER_CALL_ID 1 /* sr: user call ID specifier */
-#define RXRPC_ABORT 2 /* sr: abort request / notification [terminal] */
-#define RXRPC_ACK 3 /* -r: [Service] RPC op final ACK received [terminal] */
-#define RXRPC_NET_ERROR 5 /* -r: network error received [terminal] */
-#define RXRPC_BUSY 6 /* -r: server busy received [terminal] */
-#define RXRPC_LOCAL_ERROR 7 /* -r: local error generated [terminal] */
-#define RXRPC_NEW_CALL 8 /* -r: [Service] new incoming call notification */
-#define RXRPC_ACCEPT 9 /* s-: [Service] accept request */
-#define RXRPC_EXCLUSIVE_CALL 10 /* s-: Call should be on exclusive connection */
-#define RXRPC_UPGRADE_SERVICE 11 /* s-: Request service upgrade for client call */
+enum rxrpc_cmsg_type {
+ RXRPC_USER_CALL_ID = 1, /* sr: user call ID specifier */
+ RXRPC_ABORT = 2, /* sr: abort request / notification [terminal] */
+ RXRPC_ACK = 3, /* -r: [Service] RPC op final ACK received [terminal] */
+ RXRPC_NET_ERROR = 5, /* -r: network error received [terminal] */
+ RXRPC_BUSY = 6, /* -r: server busy received [terminal] */
+ RXRPC_LOCAL_ERROR = 7, /* -r: local error generated [terminal] */
+ RXRPC_NEW_CALL = 8, /* -r: [Service] new incoming call notification */
+ RXRPC_ACCEPT = 9, /* s-: [Service] accept request */
+ RXRPC_EXCLUSIVE_CALL = 10, /* s-: Call should be on exclusive connection */
+ RXRPC_UPGRADE_SERVICE = 11, /* s-: Request service upgrade for client call */
+ RXRPC__SUPPORTED
+};
/*
* RxRPC security levels
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 0c4dc4a7832c..44a52b82bb5d 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -582,6 +582,34 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
}
/*
+ * Get socket options.
+ */
+static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *_optlen)
+{
+ int optlen;
+
+ if (level != SOL_RXRPC)
+ return -EOPNOTSUPP;
+
+ if (get_user(optlen, _optlen))
+ return -EFAULT;
+
+ switch (optname) {
+ case RXRPC_SUPPORTED_CMSG:
+ if (optlen < sizeof(int))
+ return -ETOOSMALL;
+ if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
+ put_user(sizeof(int), _optlen))
+ return -EFAULT;
+ return 0;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+/*
* permit an RxRPC socket to be polled
*/
static unsigned int rxrpc_poll(struct file *file, struct socket *sock,
@@ -784,7 +812,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
.listen = rxrpc_listen,
.shutdown = rxrpc_shutdown,
.setsockopt = rxrpc_setsockopt,
- .getsockopt = sock_no_getsockopt,
+ .getsockopt = rxrpc_getsockopt,
.sendmsg = rxrpc_sendmsg,
.recvmsg = rxrpc_recvmsg,
.mmap = sock_no_mmap,
^ permalink raw reply related
* [PATCH net-next 2/3] rxrpc: Consolidate sendmsg parameters
From: David Howells @ 2017-06-07 21:12 UTC (permalink / raw)
To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <149686995195.21359.17550471913376009423.stgit@warthog.procyon.org.uk>
Consolidate the sendmsg control message parameters into a struct rather
than passing them individually through the argument list of
rxrpc_sendmsg_cmsg(). This makes it easier to add more parameters.
Signed-off-by: David Howells <dhowells@redhat.com>
---
net/rxrpc/sendmsg.c | 83 +++++++++++++++++++++++++--------------------------
1 file changed, 41 insertions(+), 42 deletions(-)
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 5a4801e7f560..d939a5b1abc3 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -28,6 +28,14 @@ enum rxrpc_command {
RXRPC_CMD_REJECT_BUSY, /* [server] reject a call as busy */
};
+struct rxrpc_send_params {
+ unsigned long user_call_ID; /* User's call ID */
+ u32 abort_code; /* Abort code to Tx (if abort) */
+ enum rxrpc_command command : 8; /* The command to implement */
+ bool exclusive; /* Shared or exclusive call */
+ bool upgrade; /* If the connection is upgradeable */
+};
+
/*
* wait for space to appear in the transmit/ACK window
* - caller holds the socket locked
@@ -362,19 +370,12 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
/*
* extract control messages from the sendmsg() control buffer
*/
-static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
- unsigned long *user_call_ID,
- enum rxrpc_command *command,
- u32 *abort_code,
- bool *_exclusive,
- bool *_upgrade)
+static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
{
struct cmsghdr *cmsg;
bool got_user_ID = false;
int len;
- *command = RXRPC_CMD_SEND_DATA;
-
if (msg->msg_controllen == 0)
return -EINVAL;
@@ -394,45 +395,43 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
if (msg->msg_flags & MSG_CMSG_COMPAT) {
if (len != sizeof(u32))
return -EINVAL;
- *user_call_ID = *(u32 *) CMSG_DATA(cmsg);
+ p->user_call_ID = *(u32 *)CMSG_DATA(cmsg);
} else {
if (len != sizeof(unsigned long))
return -EINVAL;
- *user_call_ID = *(unsigned long *)
+ p->user_call_ID = *(unsigned long *)
CMSG_DATA(cmsg);
}
- _debug("User Call ID %lx", *user_call_ID);
got_user_ID = true;
break;
case RXRPC_ABORT:
- if (*command != RXRPC_CMD_SEND_DATA)
+ if (p->command != RXRPC_CMD_SEND_DATA)
return -EINVAL;
- *command = RXRPC_CMD_SEND_ABORT;
- if (len != sizeof(*abort_code))
+ p->command = RXRPC_CMD_SEND_ABORT;
+ if (len != sizeof(p->abort_code))
return -EINVAL;
- *abort_code = *(unsigned int *) CMSG_DATA(cmsg);
- _debug("Abort %x", *abort_code);
- if (*abort_code == 0)
+ p->abort_code = *(unsigned int *)CMSG_DATA(cmsg);
+ if (p->abort_code == 0)
return -EINVAL;
break;
case RXRPC_ACCEPT:
- if (*command != RXRPC_CMD_SEND_DATA)
+ if (p->command != RXRPC_CMD_SEND_DATA)
return -EINVAL;
- *command = RXRPC_CMD_ACCEPT;
+ p->command = RXRPC_CMD_ACCEPT;
if (len != 0)
return -EINVAL;
break;
case RXRPC_EXCLUSIVE_CALL:
- *_exclusive = true;
+ p->exclusive = true;
if (len != 0)
return -EINVAL;
break;
case RXRPC_UPGRADE_SERVICE:
- *_upgrade = true;
+ p->upgrade = true;
if (len != 0)
return -EINVAL;
break;
@@ -455,8 +454,7 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg,
*/
static struct rxrpc_call *
rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
- unsigned long user_call_ID, bool exclusive,
- bool upgrade)
+ struct rxrpc_send_params *p)
__releases(&rx->sk.sk_lock.slock)
{
struct rxrpc_conn_parameters cp;
@@ -480,10 +478,10 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
cp.local = rx->local;
cp.key = rx->key;
cp.security_level = rx->min_sec_level;
- cp.exclusive = rx->exclusive | exclusive;
- cp.upgrade = upgrade;
+ cp.exclusive = rx->exclusive | p->exclusive;
+ cp.upgrade = p->upgrade;
cp.service_id = srx->srx_service;
- call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, GFP_KERNEL);
+ call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID, GFP_KERNEL);
/* The socket is now unlocked */
_leave(" = %p\n", call);
@@ -499,26 +497,28 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
__releases(&rx->sk.sk_lock.slock)
{
enum rxrpc_call_state state;
- enum rxrpc_command cmd;
struct rxrpc_call *call;
- unsigned long user_call_ID = 0;
- bool exclusive = false;
- bool upgrade = true;
- u32 abort_code = 0;
int ret;
+ struct rxrpc_send_params p = {
+ .user_call_ID = 0,
+ .abort_code = 0,
+ .command = RXRPC_CMD_SEND_DATA,
+ .exclusive = false,
+ .upgrade = true,
+ };
+
_enter("");
- ret = rxrpc_sendmsg_cmsg(msg, &user_call_ID, &cmd, &abort_code,
- &exclusive, &upgrade);
+ ret = rxrpc_sendmsg_cmsg(msg, &p);
if (ret < 0)
goto error_release_sock;
- if (cmd == RXRPC_CMD_ACCEPT) {
+ if (p.command == RXRPC_CMD_ACCEPT) {
ret = -EINVAL;
if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
goto error_release_sock;
- call = rxrpc_accept_call(rx, user_call_ID, NULL);
+ call = rxrpc_accept_call(rx, p.user_call_ID, NULL);
/* The socket is now unlocked. */
if (IS_ERR(call))
return PTR_ERR(call);
@@ -526,13 +526,12 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
return 0;
}
- call = rxrpc_find_call_by_user_ID(rx, user_call_ID);
+ call = rxrpc_find_call_by_user_ID(rx, p.user_call_ID);
if (!call) {
ret = -EBADSLT;
- if (cmd != RXRPC_CMD_SEND_DATA)
+ if (p.command != RXRPC_CMD_SEND_DATA)
goto error_release_sock;
- call = rxrpc_new_client_call_for_sendmsg(rx, msg, user_call_ID,
- exclusive, upgrade);
+ call = rxrpc_new_client_call_for_sendmsg(rx, msg, &p);
/* The socket is now unlocked... */
if (IS_ERR(call))
return PTR_ERR(call);
@@ -565,11 +564,11 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
if (state >= RXRPC_CALL_COMPLETE) {
/* it's too late for this call */
ret = -ESHUTDOWN;
- } else if (cmd == RXRPC_CMD_SEND_ABORT) {
+ } else if (p.command == RXRPC_CMD_SEND_ABORT) {
ret = 0;
- if (rxrpc_abort_call("CMD", call, 0, abort_code, -ECONNABORTED))
+ if (rxrpc_abort_call("CMD", call, 0, p.abort_code, -ECONNABORTED))
ret = rxrpc_send_abort_packet(call);
- } else if (cmd != RXRPC_CMD_SEND_DATA) {
+ } else if (p.command != RXRPC_CMD_SEND_DATA) {
ret = -EINVAL;
} else if (rxrpc_is_client_call(call) &&
state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
^ permalink raw reply related
* [PATCH net-next 3/3] rxrpc: Provide a cmsg to specify the amount of Tx data for a call
From: David Howells @ 2017-06-07 21:12 UTC (permalink / raw)
To: netdev; +Cc: dhowells, linux-afs, linux-kernel
In-Reply-To: <149686995195.21359.17550471913376009423.stgit@warthog.procyon.org.uk>
Provide a control message that can be specified on the first sendmsg() of a
client call or the first sendmsg() of a service response to indicate the
total length of the data to be transmitted for that call.
Currently, because the length of the payload of an encrypted DATA packet is
encrypted in front of the data, the packet cannot be encrypted until we
know how much data it will hold.
By specifying the length at the beginning of the transmit phase, each DATA
packet length can be set before we start loading data from userspace (where
several sendmsg() calls may contribute to a particular packet).
An error will be returned if too little or too much data is presented in
the Tx phase.
Signed-off-by: David Howells <dhowells@redhat.com>
---
Documentation/networking/rxrpc.txt | 34 +++++++++++++++++++++++
fs/afs/rxrpc.c | 18 +++++++++++-
include/linux/rxrpc.h | 1 +
include/net/af_rxrpc.h | 2 +
net/rxrpc/af_rxrpc.c | 5 +++
net/rxrpc/ar-internal.h | 3 +-
net/rxrpc/call_object.c | 3 ++
net/rxrpc/sendmsg.c | 54 +++++++++++++++++++++++++++++++++++-
8 files changed, 115 insertions(+), 5 deletions(-)
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt
index bce8e10a2a8e..8c70ba5dee4d 100644
--- a/Documentation/networking/rxrpc.txt
+++ b/Documentation/networking/rxrpc.txt
@@ -327,6 +327,7 @@ calls, to invoke certain actions and to report certain conditions. These are:
RXRPC_ACCEPT s-- n/a Accept new call
RXRPC_EXCLUSIVE_CALL s-- n/a Make an exclusive client call
RXRPC_UPGRADE_SERVICE s-- n/a Client call can be upgraded
+ RXRPC_TX_LENGTH s-- data len Total length of Tx data
(SRT = usable in Sendmsg / delivered by Recvmsg / Terminal message)
@@ -406,6 +407,19 @@ calls, to invoke certain actions and to report certain conditions. These are:
future communication to that server and RXRPC_UPGRADE_SERVICE should no
longer be set.
+ (*) RXRPC_TX_LENGTH
+
+ This is used to inform the kernel of the total amount of data that is
+ going to be transmitted by a call (whether in a client request or a
+ service response). If given, it allows the kernel to encrypt from the
+ userspace buffer directly to the packet buffers, rather than copying into
+ the buffer and then encrypting in place. This may only be given with the
+ first sendmsg() providing data for a call. EMSGSIZE will be generated if
+ the amount of data actually given is different.
+
+ This takes a parameter of __s64 type that indicates how much will be
+ transmitted. This may not be less than zero.
+
The symbol RXRPC__SUPPORTED is defined as one more than the highest control
message type supported. At run time this can be queried by means of the
RXRPC_SUPPORTED_CMSG socket option (see below).
@@ -577,6 +591,9 @@ A client would issue an operation by:
MSG_MORE should be set in msghdr::msg_flags on all but the last part of
the request. Multiple requests may be made simultaneously.
+ An RXRPC_TX_LENGTH control message can also be specified on the first
+ sendmsg() call.
+
If a call is intended to go to a destination other than the default
specified through connect(), then msghdr::msg_name should be set on the
first request message of that call.
@@ -764,6 +781,7 @@ The kernel interface functions are as follows:
struct sockaddr_rxrpc *srx,
struct key *key,
unsigned long user_call_ID,
+ s64 tx_total_len,
gfp_t gfp);
This allocates the infrastructure to make a new RxRPC call and assigns
@@ -780,6 +798,11 @@ The kernel interface functions are as follows:
control data buffer. It is entirely feasible to use this to point to a
kernel data structure.
+ tx_total_len is the amount of data the caller is intending to transmit
+ with this call (or -1 if unknown at this point). Setting the data size
+ allows the kernel to encrypt directly to the packet buffers, thereby
+ saving a copy. The value may not be less than -1.
+
If this function is successful, an opaque reference to the RxRPC call is
returned. The caller now holds a reference on this and it must be
properly ended.
@@ -931,6 +954,17 @@ The kernel interface functions are as follows:
This is used to find the remote peer address of a call.
+ (*) Set the total transmit data size on a call.
+
+ void rxrpc_kernel_set_tx_length(struct socket *sock,
+ struct rxrpc_call *call,
+ s64 tx_total_len);
+
+ This sets the amount of data that the caller is intending to transmit on a
+ call. It's intended to be used for setting the reply size as the request
+ size should be set when the call is begun. tx_total_len may not be less
+ than zero.
+
=======================
CONFIGURABLE PARAMETERS
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c
index d5990eb160bd..02781e78ffb6 100644
--- a/fs/afs/rxrpc.c
+++ b/fs/afs/rxrpc.c
@@ -341,6 +341,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
struct msghdr msg;
struct kvec iov[1];
size_t offset;
+ s64 tx_total_len;
u32 abort_code;
int ret;
@@ -364,9 +365,20 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
srx.transport.sin.sin_port = call->port;
memcpy(&srx.transport.sin.sin_addr, addr, 4);
+ /* Work out the length we're going to transmit. This is awkward for
+ * calls such as FS.StoreData where there's an extra injection of data
+ * after the initial fixed part.
+ */
+ tx_total_len = call->request_size;
+ if (call->send_pages) {
+ tx_total_len += call->last_to - call->first_offset;
+ tx_total_len += (call->last - call->first) * PAGE_SIZE;
+ }
+
/* create a call */
rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
- (unsigned long) call, gfp,
+ (unsigned long)call,
+ tx_total_len, gfp,
(async ?
afs_wake_up_async_call :
afs_wake_up_call_waiter));
@@ -738,6 +750,8 @@ void afs_send_empty_reply(struct afs_call *call)
_enter("");
+ rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, 0);
+
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, NULL, 0, 0);
@@ -772,6 +786,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
_enter("");
+ rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, len);
+
iov[0].iov_base = (void *) buf;
iov[0].iov_len = len;
msg.msg_name = NULL;
diff --git a/include/linux/rxrpc.h b/include/linux/rxrpc.h
index bdd3175b9a48..7343f71783dc 100644
--- a/include/linux/rxrpc.h
+++ b/include/linux/rxrpc.h
@@ -57,6 +57,7 @@ enum rxrpc_cmsg_type {
RXRPC_ACCEPT = 9, /* s-: [Service] accept request */
RXRPC_EXCLUSIVE_CALL = 10, /* s-: Call should be on exclusive connection */
RXRPC_UPGRADE_SERVICE = 11, /* s-: Request service upgrade for client call */
+ RXRPC_TX_LENGTH = 12, /* s-: Total length of Tx data */
RXRPC__SUPPORTED
};
diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h
index b5f5187f488c..c172709787af 100644
--- a/include/net/af_rxrpc.h
+++ b/include/net/af_rxrpc.h
@@ -33,6 +33,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
struct sockaddr_rxrpc *,
struct key *,
unsigned long,
+ s64,
gfp_t,
rxrpc_notify_rx_t);
int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
@@ -46,5 +47,6 @@ void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
struct sockaddr_rxrpc *);
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
rxrpc_user_attach_call_t, unsigned long, gfp_t);
+void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
#endif /* _NET_RXRPC_H */
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 44a52b82bb5d..58ae0db52ea1 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -262,6 +262,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
* @srx: The address of the peer to contact
* @key: The security context to use (defaults to socket setting)
* @user_call_ID: The ID to use
+ * @tx_total_len: Total length of data to transmit during the call (or -1)
* @gfp: The allocation constraints
* @notify_rx: Where to send notifications instead of socket queue
*
@@ -276,6 +277,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
struct sockaddr_rxrpc *srx,
struct key *key,
unsigned long user_call_ID,
+ s64 tx_total_len,
gfp_t gfp,
rxrpc_notify_rx_t notify_rx)
{
@@ -303,7 +305,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
cp.security_level = 0;
cp.exclusive = false;
cp.service_id = srx->srx_service;
- call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, gfp);
+ call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
+ gfp);
/* The socket has been unlocked. */
if (!IS_ERR(call))
call->notify_rx = notify_rx;
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index e9b536cb0acf..adbf37946450 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -528,6 +528,7 @@ struct rxrpc_call {
struct rb_node sock_node; /* Node in rx->calls */
struct sk_buff *tx_pending; /* Tx socket buffer being filled */
wait_queue_head_t waitq; /* Wait queue for channel or Tx */
+ s64 tx_total_len; /* Total length left to be transmitted (or -1) */
__be32 crypto_buf[2]; /* Temporary packet crypto buffer */
unsigned long user_call_ID; /* user-defined call ID */
unsigned long flags;
@@ -683,7 +684,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t);
struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
struct rxrpc_conn_parameters *,
struct sockaddr_rxrpc *,
- unsigned long, gfp_t);
+ unsigned long, s64, gfp_t);
void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
struct sk_buff *);
void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 692110808baa..423030fd93be 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -127,6 +127,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
rwlock_init(&call->state_lock);
atomic_set(&call->usage, 1);
call->debug_id = atomic_inc_return(&rxrpc_debug_id);
+ call->tx_total_len = -1;
memset(&call->sock_node, 0xed, sizeof(call->sock_node));
@@ -201,6 +202,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
struct rxrpc_conn_parameters *cp,
struct sockaddr_rxrpc *srx,
unsigned long user_call_ID,
+ s64 tx_total_len,
gfp_t gfp)
__releases(&rx->sk.sk_lock.slock)
{
@@ -219,6 +221,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
return call;
}
+ call->tx_total_len = tx_total_len;
trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
here, (const void *)user_call_ID);
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index d939a5b1abc3..2e636a525a65 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -29,6 +29,7 @@ enum rxrpc_command {
};
struct rxrpc_send_params {
+ s64 tx_total_len; /* Total Tx data length (if send data) */
unsigned long user_call_ID; /* User's call ID */
u32 abort_code; /* Abort code to Tx (if abort) */
enum rxrpc_command command : 8; /* The command to implement */
@@ -207,6 +208,13 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
more = msg->msg_flags & MSG_MORE;
+ if (call->tx_total_len != -1) {
+ if (len > call->tx_total_len)
+ return -EMSGSIZE;
+ if (!more && len != call->tx_total_len)
+ return -EMSGSIZE;
+ }
+
skb = call->tx_pending;
call->tx_pending = NULL;
rxrpc_see_skb(skb, rxrpc_skb_tx_seen);
@@ -299,6 +307,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
sp->remain -= copy;
skb->mark += copy;
copied += copy;
+ if (call->tx_total_len != -1)
+ call->tx_total_len -= copy;
}
/* check for the far side aborting the call or a network error
@@ -436,6 +446,14 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
return -EINVAL;
break;
+ case RXRPC_TX_LENGTH:
+ if (p->tx_total_len != -1 || len != sizeof(__s64))
+ return -EINVAL;
+ p->tx_total_len = *(__s64 *)CMSG_DATA(cmsg);
+ if (p->tx_total_len < 0)
+ return -EINVAL;
+ break;
+
default:
return -EINVAL;
}
@@ -443,6 +461,8 @@ static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
if (!got_user_ID)
return -EINVAL;
+ if (p->tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA)
+ return -EINVAL;
_leave(" = 0");
return 0;
}
@@ -481,7 +501,8 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
cp.exclusive = rx->exclusive | p->exclusive;
cp.upgrade = p->upgrade;
cp.service_id = srx->srx_service;
- call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID, GFP_KERNEL);
+ call = rxrpc_new_client_call(rx, &cp, srx, p->user_call_ID,
+ p->tx_total_len, GFP_KERNEL);
/* The socket is now unlocked */
_leave(" = %p\n", call);
@@ -501,6 +522,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
int ret;
struct rxrpc_send_params p = {
+ .tx_total_len = -1,
.user_call_ID = 0,
.abort_code = 0,
.command = RXRPC_CMD_SEND_DATA,
@@ -555,6 +577,15 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
ret = -ERESTARTSYS;
goto error_put;
}
+
+ if (p.tx_total_len != -1) {
+ ret = -EINVAL;
+ if (call->tx_total_len != -1 ||
+ call->tx_pending ||
+ call->tx_top != 0)
+ goto error_put;
+ call->tx_total_len = p.tx_total_len;
+ }
}
state = READ_ONCE(call->state);
@@ -672,5 +703,24 @@ bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
mutex_unlock(&call->user_mutex);
return aborted;
}
-
EXPORT_SYMBOL(rxrpc_kernel_abort_call);
+
+/**
+ * rxrpc_kernel_set_tx_length - Set the total Tx length on a call
+ * @sock: The socket the call is on
+ * @call: The call to be informed
+ * @tx_total_len: The amount of data to be transmitted for this call
+ *
+ * Allow a kernel service to set the total transmit length on a call. This
+ * allows buffer-to-packet encrypt-and-copy to be performed.
+ *
+ * This function is primarily for use for setting the reply length since the
+ * request length can be set when beginning the call.
+ */
+void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call,
+ s64 tx_total_len)
+{
+ WARN_ON(call->tx_total_len != -1);
+ call->tx_total_len = tx_total_len;
+}
+EXPORT_SYMBOL(rxrpc_kernel_set_tx_length);
^ permalink raw reply related
* Re: [PATCH V2 1/3] Documentation: devicetree: add multiple cpu port DSA binding
From: Florian Fainelli @ 2017-06-07 21:35 UTC (permalink / raw)
To: Rob Herring
Cc: John Crispin, Andrew Lunn, Vivien Didelot, David S . Miller,
Sean Wang, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170607211002.ubljfplyexjb6dyl@rob-hp-laptop>
On 06/07/2017 02:10 PM, Rob Herring wrote:
> On Tue, May 30, 2017 at 02:32:29PM -0700, Florian Fainelli wrote:
>> On 05/30/2017 03:44 AM, John Crispin wrote:
>>> Extend the DSA binding documentation, adding the new property required
>>> when there is more than one CPU port attached to the switch.
>>>
>>> Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
>>> Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
>>> Signed-off-by: John Crispin <john-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>
>>> ---
>>> Documentation/devicetree/bindings/net/dsa/dsa.txt | 61 ++++++++++++++++++++++-
>>> 1 file changed, 60 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
>>> index cfe8f64eca4f..c164eb38ccc5 100644
>>> --- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
>>> +++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
>>> @@ -55,6 +55,11 @@ A user port has the following optional property:
>>> - label : Describes the label associated with this port, which
>>> will become the netdev name.
>>>
>>> +- cpu : Option for non "cpu"/"dsa" ports. A phandle to a
>>> + "cpu" port, which will be used for passing packets
>>> + from this port to the host. If not present, the first
>>> + "cpu" port will be used.
>>
>> So this option essentially allow us to "partition" the switch between
>> vectors of ports and their upstream/CPU port.
>
> Could this be more generic? This is basically saying route all packets
> on this port to another port. Maybe there's some usecase to route to
> non-cpu ports?
Yes, we absolutely want it to be more generic. The "problem" is that
before an user has a chance to come in and type some commands that
reconfigure the switch, there is a default state in which we need to
assume one particular CPU/management port is going to be used to receive
traffic. This can be pushed as a driver decision as to which of the
multiple CPU ports is the most suitable IMHO.
>
>> While using Device Tree is an obvious choice for making the initial
>> partitioning, it seems like we are missing a configuration mechanism
>> whereby we can properly assign ports to a specific upstream CPU port.
>
> What determines how things are routed/partitioned? If it is purely user
> choice then I don't think this should be in DT.
Right now we don't have any mechanism, and statically doing this from
Device Tree is too inflexible. I have been working on a parallel path
where we use the bridge (which is already accelerated when there is a
switch) in order to define groups of ports, the idea would be do to e.g:
brctl addbr br-lan
brctl addbr br-lan eth0
brctl addbr br-lan lan1
...
brctl addbr br-lan lan4
brctl addbr br-wan
brctl addbr br-wan eth1
brctl addbr br-wan wan
Assuming that lan1-lan4 are your LAN ports, and wan is your WAN port and
you have two CPU ports.
Until we configure these bridges though, we would be in the same state
that we currently are, which is that traffic is only possible between
lan1 <-> eth0, lan2 <-> eth0 and so on (every port is isolated from each
other).
--
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
* Re: [PATCH V2 1/3] Documentation: devicetree: add multiple cpu port DSA binding
From: Andrew Lunn @ 2017-06-07 21:42 UTC (permalink / raw)
To: Rob Herring
Cc: Florian Fainelli, John Crispin, Vivien Didelot, David S . Miller,
Sean Wang, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
devicetree-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <20170607211002.ubljfplyexjb6dyl@rob-hp-laptop>
On Wed, Jun 07, 2017 at 04:10:02PM -0500, Rob Herring wrote:
> On Tue, May 30, 2017 at 02:32:29PM -0700, Florian Fainelli wrote:
> > On 05/30/2017 03:44 AM, John Crispin wrote:
> > > Extend the DSA binding documentation, adding the new property required
> > > when there is more than one CPU port attached to the switch.
> > >
> > > Cc: Rob Herring <robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
> > > Cc: devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> > > Signed-off-by: John Crispin <john-Pj+rj9U5foFAfugRpC6u6w@public.gmane.org>
> > > ---
> > > Documentation/devicetree/bindings/net/dsa/dsa.txt | 61 ++++++++++++++++++++++-
> > > 1 file changed, 60 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/Documentation/devicetree/bindings/net/dsa/dsa.txt b/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > > index cfe8f64eca4f..c164eb38ccc5 100644
> > > --- a/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > > +++ b/Documentation/devicetree/bindings/net/dsa/dsa.txt
> > > @@ -55,6 +55,11 @@ A user port has the following optional property:
> > > - label : Describes the label associated with this port, which
> > > will become the netdev name.
> > >
> > > +- cpu : Option for non "cpu"/"dsa" ports. A phandle to a
> > > + "cpu" port, which will be used for passing packets
> > > + from this port to the host. If not present, the first
> > > + "cpu" port will be used.
> >
> > So this option essentially allow us to "partition" the switch between
> > vectors of ports and their upstream/CPU port.
>
> Could this be more generic? This is basically saying route all packets
> on this port to another port.
Hi Rob
No, it is not saying that.
The CPU port of the switch is special. It is used by the switch for
frames it does not know what to do with. e.g, it has not learned the
destination MAC address, it is an IGMP management packet, etc. Or the
MAC address is that of the CPU, or the CPU needs to bridge it out
another interface, e.g. a L2 VPN. The switch will add an additional
header indicating what the ingress port was, and pass it to the CPU
via this port.
There is a presentation Florian, Vivien and I made at netdev 2.1
earlier this year which talks about this.
If you want to mirror all packets from one port to another, you can
use tc and the mirror action.
> > While using Device Tree is an obvious choice for making the initial
> > partitioning, it seems like we are missing a configuration mechanism
> > whereby we can properly assign ports to a specific upstream CPU port.
>
> What determines how things are routed/partitioned? If it is purely user
> choice then I don't think this should be in DT.
> > Let's move the actual discussion into patch 2 in order not to pollute
> > the DT maintainers' inbox.
We are aiming to load balance traffic to/from the CPU and the switch.
The ports of a switch can very in characteristics. Sometimes two are
able to do 10Gbps, while others are just 1Gbps. So it would make sense
to give those higher speed ports a bigger fraction of the available
CPU bandwidth, etc.
This binding gives us the option to start with a sensible default for
a typical application of the hardware. For something like a WiFi box,
this is probably sufficient. However, there is also a lot of usage of
DSA in industrial application, and more flexibility is needed. For
that we probably need a user API of some sort which allows the
defaults in the device tree to be modified to a specific user case.
Andrew
--
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
* (unknown),
From: agar2000 @ 2017-06-07 21:54 UTC (permalink / raw)
To: netdev
[-- Attachment #1: 99372.zip --]
[-- Type: application/zip, Size: 3195 bytes --]
^ permalink raw reply
* [PATCH net-next v2 0/5] net: dsa: add cross-chip VLAN support
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
The current code in DSA does not support cross-chip VLAN. This means
that in a multi-chip environment such as this one (similar to ZII Rev B)
[CPU].................... (mdio)
(eth0) | : : :
_|_____ _______ _______
[__sw0__]--[__sw1__]--[__sw2__]
| | | | | | | | |
v v v v v v v v v
p1 p2 p3 p4 p5 p6 p7 p8 p9
adding a VLAN to p9 won't be enough to reach the CPU, until at least one
port of sw0 and sw1 join the VLAN as well and become aware of the VID.
This patchset makes the DSA core program the VLAN on the CPU and DSA
links itself, which brings seamlessly cross-chip VLAN support to DSA.
With this series applied*, the hardware VLAN tables of a 3-switch setup
look like this after adding a VLAN to only one port of the end switch:
# cat /sys/class/net/br0/bridge/default_pvid
42
# cat /sys/kernel/debug/mv88e6xxx/sw{0,1,2}/vtu
# ip link set up master br0 dev lan6
# cat /sys/kernel/debug/mv88e6xxx/sw{0,1,2}/vtu
VID FID SID 0 1 2 3 4 5 6
42 1 0 x x x x x = =
VID FID SID 0 1 2 3 4 5 6
42 1 0 x x x x x = =
VID FID SID 0 1 2 3 4 5 6 7 8 9
42 1 0 u x x x x x x x x =
('x' is excluded, 'u' is untagged, '=' is unmodified DSA and CPU ports.)
Completely removing a VLAN entry (which is currently the responsibility
of drivers anyway) is not supported yet since it requires some caching.
(*) the output is shown from this out-of-tree debugfs patch:
https://github.com/vivien/linux/commit/7b61a684b9d6b6a499135a587c7f62a1fddceb8b.patch
Changes in v2:
- canonical incrementation (port++ instead of ++port)
- check CPU and DSA ports before purging a VLAN
- add Reviewed-by tags
Vivien Didelot (5):
net: dsa: mv88e6xxx: define membership on VLAN add
net: dsa: check VLAN capability of every switch
net: dsa: add CPU and DSA ports as VLAN members
net: dsa: mv88e6xxx: exclude all ports in new VLAN
net: dsa: mv88e6xxx: do not skip ports on VLAN del
drivers/net/dsa/mv88e6xxx/chip.c | 27 ++++++++++++++-------------
net/dsa/switch.c | 30 ++++++++++++++++++++----------
2 files changed, 34 insertions(+), 23 deletions(-)
--
2.13.1
^ permalink raw reply
* [PATCH net-next v2 3/5] net: dsa: add CPU and DSA ports as VLAN members
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <20170607221217.2323-1-vivien.didelot@savoirfairelinux.com>
In a multi-chip switch fabric, it is currently the responsibility of the
driver to add the CPU or DSA (interconnecting chips together) ports as
members of a new VLAN entry. This makes the drivers more complicated.
We want the DSA drivers to be stupid and the DSA core being the one
responsible for caring about the abstracted switch logic and topology.
Make the DSA core program the CPU and DSA ports as part of the VLAN.
This makes all chips of the data path to be aware of VIDs spanning the
the whole fabric and thus, seamlessly add support for cross-chip VLAN.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
net/dsa/switch.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index f235ae1e9777..f1029a8d0e20 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -166,6 +166,9 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
bitmap_zero(members, ds->num_ports);
if (ds->index == info->sw_index)
set_bit(info->port, members);
+ for (port = 0; port < ds->num_ports; port++)
+ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port))
+ set_bit(port, members);
if (switchdev_trans_ph_prepare(trans)) {
if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
--
2.13.1
^ permalink raw reply related
* [PATCH net-next v2 4/5] net: dsa: mv88e6xxx: exclude all ports in new VLAN
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <20170607221217.2323-1-vivien.didelot@savoirfairelinux.com>
Now that the DSA core adds the CPU and DSA ports itself to the new VLAN
entry, there is no need to include them as members of this VLAN when
initializing a new VTU entry.
As of now, initialize a new VTU entry with all ports excluded.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 962b4e873bf9..41202b1d6d7f 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1159,11 +1159,10 @@ static int mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid,
entry->valid = true;
entry->vid = vid;
- /* Include only CPU and DSA ports */
+ /* Exclude all ports */
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i)
- entry->member[i] = dsa_is_normal_port(chip->ds, i) ?
- GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER :
- GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;
+ entry->member[i] =
+ GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER;
return mv88e6xxx_atu_new(chip, &entry->fid);
}
--
2.13.1
^ permalink raw reply related
* [PATCH net-next v2 5/5] net: dsa: mv88e6xxx: do not skip ports on VLAN del
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <20170607221217.2323-1-vivien.didelot@savoirfairelinux.com>
The mv88e6xxx driver currently tries to be smart and remove by itself a
VLAN entry from the VTU when the driven switch sees no user ports as
members of the VLAN.
This is bad in a multi-chip switch fabric, since a chip in between
others may have no bridge port members, but still needs to be aware of
the VID in order to correctly pass frames in the data path.
Now that the DSA core explicitly manages DSA and CPU ports, do not skip
them when checking remaining VLAN members.
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 41202b1d6d7f..0534eb706caa 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1325,7 +1325,6 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
int port, u16 vid)
{
- struct dsa_switch *ds = chip->ds;
struct mv88e6xxx_vtu_entry vlan;
int i, err;
@@ -1342,9 +1341,6 @@ static int _mv88e6xxx_port_vlan_del(struct mv88e6xxx_chip *chip,
/* keep the VLAN unless all ports are excluded */
vlan.valid = false;
for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
- if (dsa_is_cpu_port(ds, i) || dsa_is_dsa_port(ds, i))
- continue;
-
if (vlan.member[i] != GLOBAL_VTU_DATA_MEMBER_TAG_NON_MEMBER) {
vlan.valid = true;
break;
--
2.13.1
^ permalink raw reply related
* [PATCH net-next v2 1/5] net: dsa: mv88e6xxx: define membership on VLAN add
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <20170607221217.2323-1-vivien.didelot@savoirfairelinux.com>
Define the target port membership of the VLAN entry in
mv88e6xxx_port_vlan_add where ds is scoped.
Allow the DSA core to call later the port_vlan_add operation for CPU or
DSA ports, by using the Unmodified membership for these ports, as in the
current behavior.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
drivers/net/dsa/mv88e6xxx/chip.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 44c87027623b..962b4e873bf9 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1274,7 +1274,7 @@ mv88e6xxx_port_vlan_prepare(struct dsa_switch *ds, int port,
}
static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
- u16 vid, bool untagged)
+ u16 vid, u8 member)
{
struct mv88e6xxx_vtu_entry vlan;
int err;
@@ -1283,9 +1283,7 @@ static int _mv88e6xxx_port_vlan_add(struct mv88e6xxx_chip *chip, int port,
if (err)
return err;
- vlan.member[port] = untagged ?
- GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED :
- GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
+ vlan.member[port] = member;
return mv88e6xxx_vtu_loadpurge(chip, &vlan);
}
@@ -1297,15 +1295,23 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port,
struct mv88e6xxx_chip *chip = ds->priv;
bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
+ u8 member;
u16 vid;
if (!chip->info->max_vid)
return;
+ if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
+ member = GLOBAL_VTU_DATA_MEMBER_TAG_UNMODIFIED;
+ else if (untagged)
+ member = GLOBAL_VTU_DATA_MEMBER_TAG_UNTAGGED;
+ else
+ member = GLOBAL_VTU_DATA_MEMBER_TAG_TAGGED;
+
mutex_lock(&chip->reg_lock);
for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid)
- if (_mv88e6xxx_port_vlan_add(chip, port, vid, untagged))
+ if (_mv88e6xxx_port_vlan_add(chip, port, vid, member))
netdev_err(ds->ports[port].netdev,
"failed to add VLAN %d%c\n",
vid, untagged ? 'u' : 't');
--
2.13.1
^ permalink raw reply related
* [PATCH net-next v2 2/5] net: dsa: check VLAN capability of every switch
From: Vivien Didelot @ 2017-06-07 22:12 UTC (permalink / raw)
To: netdev
Cc: linux-kernel, kernel, David S. Miller, Florian Fainelli,
Andrew Lunn, Vivien Didelot
In-Reply-To: <20170607221217.2323-1-vivien.didelot@savoirfairelinux.com>
Now that the VLAN object is propagated to every switch chip of the
switch fabric, we can easily ensure that they all support the required
VLAN operations before modifying an entry on a single switch.
To achieve that, remove the condition skipping other target switches,
and add a bitmap of VLAN members, eventually containing the target port,
if we are programming the switch target.
This will allow us to easily add other VLAN members, such as the DSA or
CPU ports (to introduce cross-chip VLAN support) or the other port
members if we want to reduce hardware accesses later.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
---
net/dsa/switch.c | 27 +++++++++++++++++----------
1 file changed, 17 insertions(+), 10 deletions(-)
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index d8e5c311ee7c..f235ae1e9777 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -159,19 +159,27 @@ static int dsa_switch_vlan_add(struct dsa_switch *ds,
{
const struct switchdev_obj_port_vlan *vlan = info->vlan;
struct switchdev_trans *trans = info->trans;
+ DECLARE_BITMAP(members, ds->num_ports);
+ int port, err;
- /* Do not care yet about other switch chips of the fabric */
- if (ds->index != info->sw_index)
- return 0;
+ /* Build a mask of VLAN members */
+ bitmap_zero(members, ds->num_ports);
+ if (ds->index == info->sw_index)
+ set_bit(info->port, members);
if (switchdev_trans_ph_prepare(trans)) {
if (!ds->ops->port_vlan_prepare || !ds->ops->port_vlan_add)
return -EOPNOTSUPP;
- return ds->ops->port_vlan_prepare(ds, info->port, vlan, trans);
+ for_each_set_bit(port, members, ds->num_ports) {
+ err = ds->ops->port_vlan_prepare(ds, port, vlan, trans);
+ if (err)
+ return err;
+ }
}
- ds->ops->port_vlan_add(ds, info->port, vlan, trans);
+ for_each_set_bit(port, members, ds->num_ports)
+ ds->ops->port_vlan_add(ds, port, vlan, trans);
return 0;
}
@@ -181,14 +189,13 @@ static int dsa_switch_vlan_del(struct dsa_switch *ds,
{
const struct switchdev_obj_port_vlan *vlan = info->vlan;
- /* Do not care yet about other switch chips of the fabric */
- if (ds->index != info->sw_index)
- return 0;
-
if (!ds->ops->port_vlan_del)
return -EOPNOTSUPP;
- return ds->ops->port_vlan_del(ds, info->port, vlan);
+ if (ds->index == info->sw_index)
+ return ds->ops->port_vlan_del(ds, info->port, vlan);
+
+ return 0;
}
static int dsa_switch_event(struct notifier_block *nb,
--
2.13.1
^ permalink raw reply related
* [PATCH] net: wireless: intel: iwlwifi: dvm: fix tid mask
From: Seraphime Kirkovski @ 2017-06-07 22:33 UTC (permalink / raw)
To: luca
Cc: Seraphime Kirkovski, Johannes Berg, Emmanuel Grumbach,
Luca Coelho, Intel Linux Wireless, Kalle Valo,
open list:INTEL WIRELESS WIFI LINK (iwlwifi),
open list:NETWORKING DRIVERS, open list
Currently the tid mask covers the first 4 bits of iwlagn_tx_resp::ra_tid,
which gives 16 possible values for tid.
This is problematic because IWL_MAX_TID_COUNT is 8, so indexing
iwl_priv::tid_data can go very wrong.
With UBSAN I can it happening while establishing the first connection
after module load.
[ 272.143440] UBSAN: Undefined behaviour in drivers/net/wireless/intel/iwlwifi/dvm/tx.c:777:32
[ 272.143447] index 8 is out of range for type 'iwl_tid_data [8]'
[ 272.143457] CPU: 0 PID: 4605 Comm: irq/32-iwlwifi Not tainted 4.12.0-dirty #2
[ 272.143460] Hardware name: Hewlett-Packard HP EliteBook 2560p/162B, BIOS 68SSU Ver. F.02 07/26/2011
[ 272.143462] Call Trace:
[ 272.143472] dump_stack+0x9c/0x10b
[ 272.143477] ? _atomic_dec_and_lock+0x285/0x285
[ 272.143486] ubsan_epilogue+0xd/0x4e
[ 272.143493] __ubsan_handle_out_of_bounds+0xef/0x118
[ 272.143498] ? __ubsan_handle_shift_out_of_bounds+0x221/0x221
[ 272.143519] ? iwl_trans_pcie_reclaim+0x153/0xc90 [iwlwifi]
[ 272.143539] iwlagn_check_ratid_empty+0x337/0x410 [iwldvm]
[ 272.143556] ? iwl_hcmd_names_cmp+0x2f/0x60 [iwlwifi]
[ 272.143571] iwlagn_rx_reply_tx+0x8a4/0x1820 [iwldvm]
Signed-off-by: Seraphime Kirkovski <kirkseraph@gmail.com>
---
I'm currently running this patch on my machines and I have wifi.
The patch presumes а cleanup patch, I sent yesterday:
https://www.spinics.net/lists/kernel/msg2526314.html
drivers/net/wireless/intel/iwlwifi/dvm/commands.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
index 37d2ba5ae852..e5994df9ea4c 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/commands.h
@@ -1448,7 +1448,7 @@ struct agg_tx_status {
*/
/* refer to ra_tid */
#define IWLAGN_TX_RES_TID_POS 0
-#define IWLAGN_TX_RES_TID_MSK 0x0f
+#define IWLAGN_TX_RES_TID_MSK 0x07
#define IWLAGN_TX_RES_RA_POS 4
#define IWLAGN_TX_RES_RA_MSK 0xf0
--
2.11.0
^ 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