Merge branch 'lift-udp_segment-restriction-for-egress-via-device-w-o-csum-offload'
Jakub Sitnicki says: ==================== Lift UDP_SEGMENT restriction for egress via device w/o csum offload This is a follow-up to an earlier question [1] if we can make UDP GSO work with any egress device, even those with no checksum offload capability. That's the default setup for TUN/TAP. Because there is a change in behavior - sendmsg() does no longer return EIO error - I'm submitting through net-next tree, rather than net, as per Willem's advice. [1] https://lore.kernel.org/netdev/87jzqsld6q.fsf@cloudflare.com/ v1: https://lore.kernel.org/r/20240622-linux-udpgso-v1-0-d2344157ab2a@cloudflare.com ==================== Link: https://patch.msgid.link/20240626-linux-udpgso-v2-0-422dfcbd6b48@cloudflare.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
db2dede28d
@ -938,8 +938,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
|
||||
dst_xfrm(skb_dst(skb))) {
|
||||
if (is_udplite || dst_xfrm(skb_dst(skb))) {
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -357,6 +357,14 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
|
||||
else
|
||||
uh->check = gso_make_checksum(seg, ~check) ? : CSUM_MANGLED_0;
|
||||
|
||||
/* On the TX path, CHECKSUM_NONE and CHECKSUM_UNNECESSARY have the same
|
||||
* meaning. However, check for bad offloads in the GSO stack expects the
|
||||
* latter, if the checksum was calculated in software. To vouch for the
|
||||
* segment skbs we actually need to set it on the gso_skb.
|
||||
*/
|
||||
if (gso_skb->ip_summed == CHECKSUM_NONE)
|
||||
gso_skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
|
||||
/* update refcount for the packet */
|
||||
if (copy_dtor) {
|
||||
int delta = sum_truesize - gso_skb->truesize;
|
||||
|
@ -1257,8 +1257,7 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
|
||||
dst_xfrm(skb_dst(skb))) {
|
||||
if (is_udplite || dst_xfrm(skb_dst(skb))) {
|
||||
kfree_skb(skb);
|
||||
return -EIO;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@ static bool cfg_do_ipv6;
|
||||
static bool cfg_do_connected;
|
||||
static bool cfg_do_connectionless;
|
||||
static bool cfg_do_msgmore;
|
||||
static bool cfg_do_recv = true;
|
||||
static bool cfg_do_setsockopt;
|
||||
static int cfg_specific_test_id = -1;
|
||||
|
||||
@ -414,6 +415,9 @@ static void run_one(struct testcase *test, int fdt, int fdr,
|
||||
if (!sent)
|
||||
return;
|
||||
|
||||
if (!cfg_do_recv)
|
||||
return;
|
||||
|
||||
if (test->gso_len)
|
||||
mss = test->gso_len;
|
||||
else
|
||||
@ -464,8 +468,10 @@ static void run_test(struct sockaddr *addr, socklen_t alen)
|
||||
if (fdr == -1)
|
||||
error(1, errno, "socket r");
|
||||
|
||||
if (bind(fdr, addr, alen))
|
||||
error(1, errno, "bind");
|
||||
if (cfg_do_recv) {
|
||||
if (bind(fdr, addr, alen))
|
||||
error(1, errno, "bind");
|
||||
}
|
||||
|
||||
/* Have tests fail quickly instead of hang */
|
||||
if (setsockopt(fdr, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)))
|
||||
@ -524,7 +530,7 @@ static void parse_opts(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
|
||||
while ((c = getopt(argc, argv, "46cCmst:")) != -1) {
|
||||
while ((c = getopt(argc, argv, "46cCmRst:")) != -1) {
|
||||
switch (c) {
|
||||
case '4':
|
||||
cfg_do_ipv4 = true;
|
||||
@ -541,6 +547,9 @@ static void parse_opts(int argc, char **argv)
|
||||
case 'm':
|
||||
cfg_do_msgmore = true;
|
||||
break;
|
||||
case 'R':
|
||||
cfg_do_recv = false;
|
||||
break;
|
||||
case 's':
|
||||
cfg_do_setsockopt = true;
|
||||
break;
|
||||
|
@ -27,6 +27,31 @@ test_route_mtu() {
|
||||
ip route add local fd00::1/128 table local dev lo mtu 1500
|
||||
}
|
||||
|
||||
setup_dummy_sink() {
|
||||
ip link add name sink mtu 1500 type dummy
|
||||
ip addr add dev sink 10.0.0.0/24
|
||||
ip addr add dev sink fd00::2/64 nodad
|
||||
ip link set dev sink up
|
||||
}
|
||||
|
||||
test_hw_gso_hw_csum() {
|
||||
setup_dummy_sink
|
||||
ethtool -K sink tx-checksum-ip-generic on >/dev/null
|
||||
ethtool -K sink tx-udp-segmentation on >/dev/null
|
||||
}
|
||||
|
||||
test_sw_gso_hw_csum() {
|
||||
setup_dummy_sink
|
||||
ethtool -K sink tx-checksum-ip-generic on >/dev/null
|
||||
ethtool -K sink tx-udp-segmentation off >/dev/null
|
||||
}
|
||||
|
||||
test_sw_gso_sw_csum() {
|
||||
setup_dummy_sink
|
||||
ethtool -K sink tx-checksum-ip-generic off >/dev/null
|
||||
ethtool -K sink tx-udp-segmentation off >/dev/null
|
||||
}
|
||||
|
||||
if [ "$#" -gt 0 ]; then
|
||||
"$1"
|
||||
shift 2 # pop "test_*" arg and "--" delimiter
|
||||
@ -56,3 +81,21 @@ echo "ipv4 msg_more"
|
||||
|
||||
echo "ipv6 msg_more"
|
||||
./in_netns.sh "$0" test_dev_mtu -- ./udpgso -6 -C -m
|
||||
|
||||
echo "ipv4 hw-gso hw-csum"
|
||||
./in_netns.sh "$0" test_hw_gso_hw_csum -- ./udpgso -4 -C -R
|
||||
|
||||
echo "ipv6 hw-gso hw-csum"
|
||||
./in_netns.sh "$0" test_hw_gso_hw_csum -- ./udpgso -6 -C -R
|
||||
|
||||
echo "ipv4 sw-gso hw-csum"
|
||||
./in_netns.sh "$0" test_sw_gso_hw_csum -- ./udpgso -4 -C -R
|
||||
|
||||
echo "ipv6 sw-gso hw-csum"
|
||||
./in_netns.sh "$0" test_sw_gso_hw_csum -- ./udpgso -6 -C -R
|
||||
|
||||
echo "ipv4 sw-gso sw-csum"
|
||||
./in_netns.sh "$0" test_sw_gso_sw_csum -- ./udpgso -4 -C -R
|
||||
|
||||
echo "ipv6 sw-gso sw-csum"
|
||||
./in_netns.sh "$0" test_sw_gso_sw_csum -- ./udpgso -6 -C -R
|
||||
|
Loading…
x
Reference in New Issue
Block a user