Skip to content

Commit 0e631ee

Browse files
dhowellsdavem330
authored andcommitted
rxrpc: Fix DATA Tx to disable nofrag for UDP on AF_INET6 socket
Fix the DATA packet transmission to disable nofrag for UDPv4 on an AF_INET6 socket as well as UDPv6 when trying to transmit fragmentably. Without this, packets filled to the normal size used by the kernel AFS client of 1412 bytes be rejected by udp_sendmsg() with EMSGSIZE immediately. The ->sk_error_report() notification hook is called, but rxrpc doesn't generate a trace for it. This is a temporary fix; a more permanent solution needs to involve changing the size of the packets being filled in accordance with the MTU, which isn't currently done in AF_RXRPC. The reason for not doing so was that, barring the last packet in an rx jumbo packet, jumbos can only be assembled out of 1412-byte packets - and the plan was to construct jumbos on the fly at transmission time. Also, there's no point turning on IPV6_MTU_DISCOVER, since IPv6 has to engage in this anyway since fragmentation is only done by the sender. We can then condense the switch-statement in rxrpc_send_data_packet(). Fixes: 75b54cb ("rxrpc: Add IPv6 support") Signed-off-by: David Howells <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 68dac3e commit 0e631ee

File tree

2 files changed

+12
-41
lines changed

2 files changed

+12
-41
lines changed

net/rxrpc/local_object.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,6 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
165165
goto error;
166166
}
167167

168-
/* we want to set the don't fragment bit */
169-
opt = IPV6_PMTUDISC_DO;
170-
ret = kernel_setsockopt(local->socket, SOL_IPV6, IPV6_MTU_DISCOVER,
171-
(char *) &opt, sizeof(opt));
172-
if (ret < 0) {
173-
_debug("setsockopt failed");
174-
goto error;
175-
}
176-
177168
/* Fall through and set IPv4 options too otherwise we don't get
178169
* errors from IPv4 packets sent through the IPv6 socket.
179170
*/

net/rxrpc/output.c

Lines changed: 12 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -474,41 +474,21 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
474474
skb->tstamp = ktime_get_real();
475475

476476
switch (conn->params.local->srx.transport.family) {
477+
case AF_INET6:
477478
case AF_INET:
478479
opt = IP_PMTUDISC_DONT;
479-
ret = kernel_setsockopt(conn->params.local->socket,
480-
SOL_IP, IP_MTU_DISCOVER,
481-
(char *)&opt, sizeof(opt));
482-
if (ret == 0) {
483-
ret = kernel_sendmsg(conn->params.local->socket, &msg,
484-
iov, 2, len);
485-
conn->params.peer->last_tx_at = ktime_get_seconds();
486-
487-
opt = IP_PMTUDISC_DO;
488-
kernel_setsockopt(conn->params.local->socket, SOL_IP,
489-
IP_MTU_DISCOVER,
490-
(char *)&opt, sizeof(opt));
491-
}
492-
break;
493-
494-
#ifdef CONFIG_AF_RXRPC_IPV6
495-
case AF_INET6:
496-
opt = IPV6_PMTUDISC_DONT;
497-
ret = kernel_setsockopt(conn->params.local->socket,
498-
SOL_IPV6, IPV6_MTU_DISCOVER,
499-
(char *)&opt, sizeof(opt));
500-
if (ret == 0) {
501-
ret = kernel_sendmsg(conn->params.local->socket, &msg,
502-
iov, 2, len);
503-
conn->params.peer->last_tx_at = ktime_get_seconds();
504-
505-
opt = IPV6_PMTUDISC_DO;
506-
kernel_setsockopt(conn->params.local->socket,
507-
SOL_IPV6, IPV6_MTU_DISCOVER,
508-
(char *)&opt, sizeof(opt));
509-
}
480+
kernel_setsockopt(conn->params.local->socket,
481+
SOL_IP, IP_MTU_DISCOVER,
482+
(char *)&opt, sizeof(opt));
483+
ret = kernel_sendmsg(conn->params.local->socket, &msg,
484+
iov, 2, len);
485+
conn->params.peer->last_tx_at = ktime_get_seconds();
486+
487+
opt = IP_PMTUDISC_DO;
488+
kernel_setsockopt(conn->params.local->socket,
489+
SOL_IP, IP_MTU_DISCOVER,
490+
(char *)&opt, sizeof(opt));
510491
break;
511-
#endif
512492

513493
default:
514494
BUG();

0 commit comments

Comments
 (0)