Thread (6 messages) 6 messages, 2 authors, 2014-01-17

[PATCH RFC 1/2] can: Limit default size of CAN_RAW socket send queue

From: Michal Sojka <hidden>
Date: 2014-01-16 20:06:55
Subsystem: can network drivers, can network layer, the rest · Maintainers: Marc Kleine-Budde, Vincent Mailhol, Oliver Hartkopp, Linus Torvalds

This fixes the infamous ENOBUFS problem, which appears when an
application sends CAN frames faster than they leave the system.

Packets for sending can be queued at three places: socket, queueing
discipline and device driver. Only the socket queue is able to block
the sender; other queues are non-blocking. Since the size of the qdisc
queue was set by default to 10 packets, this queue was full much
earlier than the socket queue and this resulted in ENOBUFS error.

This patch limits the default size of the socket send queue to
approximately 3 CAN frames and increases the size of the qdisc queue
to 100 frames. This setting allows for at least 33 CAN_RAW sockets to
be used simultaneously in the system without getting ENOBUFS errors.

Note that the size of the socket queue is only approximate, because it
is counted in bytes and the realy allocated memory (skb->truesize) can
be bigger than what is reported by SKB_TRUESIZE(). For example, on my
32 bit PowerPC system, SKB_TRUESIZE() = 408, but skb->truesize = 448.

Open issues:
- Will this work with CANFD?
- What about other AF_CAN protocols?

Signed-off-by: Michal Sojka <redacted>
---
 drivers/net/can/dev.c | 2 +-
 net/can/raw.c         | 4 ++++
 2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
index 1870c47..a0bce83 100644
--- a/drivers/net/can/dev.c
+++ b/drivers/net/can/dev.c
@@ -492,7 +492,7 @@ static void can_setup(struct net_device *dev)
 	dev->mtu = CAN_MTU;
 	dev->hard_header_len = 0;
 	dev->addr_len = 0;
-	dev->tx_queue_len = 10;
+	dev->tx_queue_len = 100;
 
 	/* New-style flags. */
 	dev->flags = IFF_NOARP;
diff --git a/net/can/raw.c b/net/can/raw.c
index fdda5f6..4ad0bb2 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -291,6 +291,10 @@ static int raw_init(struct sock *sk)
 {
 	struct raw_sock *ro = raw_sk(sk);
 
+	/* allow at most 3 frames to wait for transmission in socket queue */
+	sk->sk_sndbuf = 3 * SKB_TRUESIZE(sizeof(struct can_frame) +
+					 sizeof(struct can_skb_priv));
+
 	ro->bound            = 0;
 	ro->ifindex          = 0;
 
-- 
1.8.5.2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help