Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'follow-up-on-deduplicate-cookie-logic'

Willem de Bruijn says:

====================
follow-up on deduplicate cookie logic

1/3: I came across a leftover from cookie deduplication, due to UDP
having two code paths: lockless fast path and locked cork path.

3/3: Even though the leftover was in the fast path, this prompted me
to complete coverage to the cork path.

2/3: That uncovered a subtle API inconsistency in how dontfrag is
configured. It should not be possible to switch DF mid datagram.
====================

Link: https://patch.msgid.link/20250307033620.411611-1-willemdebruijn.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+32 -15
+1
include/linux/ipv6.h
··· 207 207 struct ipv6_txoptions *opt; 208 208 u8 hop_limit; 209 209 u8 tclass; 210 + u8 dontfrag:1; 210 211 }; 211 212 212 213 /* struct ipv6_pinfo - ipv6 private area */
+5 -6
net/ipv6/ip6_output.c
··· 1386 1386 } 1387 1387 v6_cork->hop_limit = ipc6->hlimit; 1388 1388 v6_cork->tclass = ipc6->tclass; 1389 + v6_cork->dontfrag = ipc6->dontfrag; 1389 1390 if (rt->dst.flags & DST_XFRM_TUNNEL) 1390 1391 mtu = READ_ONCE(np->pmtudisc) >= IPV6_PMTUDISC_PROBE ? 1391 1392 READ_ONCE(rt->dst.dev->mtu) : dst_mtu(&rt->dst); ··· 1422 1421 int getfrag(void *from, char *to, int offset, 1423 1422 int len, int odd, struct sk_buff *skb), 1424 1423 void *from, size_t length, int transhdrlen, 1425 - unsigned int flags, struct ipcm6_cookie *ipc6) 1424 + unsigned int flags) 1426 1425 { 1427 1426 struct sk_buff *skb, *skb_prev = NULL; 1428 1427 struct inet_cork *cork = &cork_full->base; ··· 1476 1475 if (headersize + transhdrlen > mtu) 1477 1476 goto emsgsize; 1478 1477 1479 - if (cork->length + length > mtu - headersize && ipc6->dontfrag && 1478 + if (cork->length + length > mtu - headersize && v6_cork->dontfrag && 1480 1479 (sk->sk_protocol == IPPROTO_UDP || 1481 1480 sk->sk_protocol == IPPROTO_ICMPV6 || 1482 1481 sk->sk_protocol == IPPROTO_RAW)) { ··· 1856 1855 1857 1856 return __ip6_append_data(sk, &sk->sk_write_queue, &inet->cork, 1858 1857 &np->cork, sk_page_frag(sk), getfrag, 1859 - from, length, transhdrlen, flags, ipc6); 1858 + from, length, transhdrlen, flags); 1860 1859 } 1861 1860 EXPORT_SYMBOL_GPL(ip6_append_data); 1862 1861 ··· 2055 2054 ip6_cork_release(cork, &v6_cork); 2056 2055 return ERR_PTR(err); 2057 2056 } 2058 - if (ipc6->dontfrag < 0) 2059 - ipc6->dontfrag = inet6_test_bit(DONTFRAG, sk); 2060 2057 2061 2058 err = __ip6_append_data(sk, &queue, cork, &v6_cork, 2062 2059 &current->task_frag, getfrag, from, 2063 2060 length + exthdrlen, transhdrlen + exthdrlen, 2064 - flags, ipc6); 2061 + flags); 2065 2062 if (err) { 2066 2063 __ip6_flush_pending_frames(sk, &queue, cork, &v6_cork); 2067 2064 return ERR_PTR(err);
+7 -4
tools/testing/selftests/net/cmsg_ip.sh
··· 50 50 # IPV6_DONTFRAG 51 51 for ovr in setsock cmsg both diff; do 52 52 for df in 0 1; do 53 - for p in u i r; do 53 + for p in u U i r; do 54 54 [ $p == "u" ] && prot=UDP 55 + [ $p == "U" ] && prot=UDP 55 56 [ $p == "i" ] && prot=ICMP 56 57 [ $p == "r" ] && prot=RAW 57 58 ··· 82 81 ip $IPVER -netns $NS route add table 300 prohibit any 83 82 84 83 for ovr in setsock cmsg both diff; do 85 - for p in u i r; do 84 + for p in u U i r; do 86 85 [ $p == "u" ] && prot=UDP 86 + [ $p == "U" ] && prot=UDP 87 87 [ $p == "i" ] && prot=ICMP 88 88 [ $p == "r" ] && prot=RAW 89 89 ··· 136 134 local -r LIM=4 137 135 138 136 for ovr in setsock cmsg both diff; do 139 - for p in u i r; do 137 + for p in u U i r; do 140 138 [ $p == "u" ] && prot=UDP 139 + [ $p == "U" ] && prot=UDP 141 140 [ $p == "i" ] && prot=ICMP 142 141 [ $p == "r" ] && prot=RAW 143 142 ··· 169 166 test_ttl_hoplimit -6 $TGT6 hlim 170 167 171 168 # IPV6 exthdr 172 - for p in u i r; do 169 + for p in u U i r; do 173 170 # Very basic "does it crash" test 174 171 for h in h d r; do 175 172 $NSEXE ./cmsg_sender -p $p -6 -H $h $TGT6 1234
+19 -5
tools/testing/selftests/net/cmsg_sender.c
··· 33 33 ERN_RECVERR, 34 34 ERN_CMSG_RD, 35 35 ERN_CMSG_RCV, 36 + ERN_SEND_MORE, 36 37 }; 37 38 38 39 struct option_cmsg_u32 { ··· 47 46 const char *service; 48 47 unsigned int size; 49 48 unsigned int num_pkt; 49 + bool msg_more; 50 50 struct { 51 51 unsigned int mark; 52 52 unsigned int dontfrag; ··· 96 94 "\t\t-S send() size\n" 97 95 "\t\t-4/-6 Force IPv4 / IPv6 only\n" 98 96 "\t\t-p prot Socket protocol\n" 99 - "\t\t (u = UDP (default); i = ICMP; r = RAW)\n" 97 + "\t\t (u = UDP (default); i = ICMP; r = RAW;\n" 98 + "\t\t U = UDP with MSG_MORE)\n" 100 99 "\n" 101 100 "\t\t-m val Set SO_MARK with given value\n" 102 101 "\t\t-M val Set SO_MARK via setsockopt\n" ··· 112 109 "\t\t-l val Set TTL/HOPLIMIT via cmsg\n" 113 110 "\t\t-L val Set TTL/HOPLIMIT via setsockopt\n" 114 111 "\t\t-H type Add an IPv6 header option\n" 115 - "\t\t (h = HOP; d = DST; r = RTDST)" 116 - ""); 112 + "\t\t (h = HOP; d = DST; r = RTDST)\n" 113 + "\n"); 117 114 exit(ERN_HELP); 118 115 } 119 116 ··· 136 133 opt.sock.family = AF_INET6; 137 134 break; 138 135 case 'p': 139 - if (*optarg == 'u' || *optarg == 'U') { 136 + if (*optarg == 'u') { 140 137 opt.sock.proto = IPPROTO_UDP; 138 + } else if (*optarg == 'U') { 139 + opt.sock.proto = IPPROTO_UDP; 140 + opt.msg_more = true; 141 141 } else if (*optarg == 'i' || *optarg == 'I') { 142 142 opt.sock.proto = IPPROTO_ICMP; 143 143 } else if (*optarg == 'r') { ··· 537 531 cs_write_cmsg(fd, &msg, cbuf, sizeof(cbuf)); 538 532 539 533 for (i = 0; i < opt.num_pkt; i++) { 540 - err = sendmsg(fd, &msg, 0); 534 + err = sendmsg(fd, &msg, opt.msg_more ? MSG_MORE : 0); 541 535 if (err < 0) { 542 536 if (!opt.silent_send) 543 537 fprintf(stderr, "send failed: %s\n", strerror(errno)); ··· 547 541 fprintf(stderr, "short send\n"); 548 542 err = ERN_SEND_SHORT; 549 543 goto err_out; 544 + } 545 + if (opt.msg_more) { 546 + err = write(fd, NULL, 0); 547 + if (err < 0) { 548 + fprintf(stderr, "send more: %s\n", strerror(errno)); 549 + err = ERN_SEND_MORE; 550 + goto err_out; 551 + } 550 552 } 551 553 } 552 554 err = ERN_SUCCESS;