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.

selftests: af_unix: validate SO_PEEK_OFF advancement and reset

Extend the so_peek_off selftest to ensure the socket peek offset is handled
correctly after both MSG_PEEK and actual data consumption.

Verify that the peek offset advances by the same amount as the number of
bytes read when performing a read with MSG_PEEK.

After exercising SO_PEEK_OFF via MSG_PEEK, drain the receive queue with a
non-peek recv() and verify that it can receive all the content in the
buffer and SO_PEEK_OFF returns back to 0.

The verification after actual data consumption was suggested by Miao Wang
when the original so_peek_off selftest was introduced.

Link: https://lore.kernel.org/all/7B657CC7-B5CA-46D2-8A4B-8AB5FB83C6DA@gmail.com/
Suggested-by: Miao Wang <shankerwangmiao@gmail.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Signed-off-by: Soichiro Ueda <the.latticeheart@gmail.com>
Link: https://patch.msgid.link/20260310072832.127848-1-the.latticeheart@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Soichiro Ueda and committed by
Jakub Kicinski
34c0378b 482aac8b

+46
+46
tools/testing/selftests/net/af_unix/so_peek_off.c
··· 76 76 ASSERT_STREQ(str, buf); \ 77 77 } while (0) 78 78 79 + #define peekoffeq(fd, expected) \ 80 + do { \ 81 + socklen_t optlen = sizeof(int); \ 82 + int off = -1; \ 83 + int ret; \ 84 + \ 85 + ret = getsockopt(fd, SOL_SOCKET, SO_PEEK_OFF, \ 86 + &off, &optlen); \ 87 + ASSERT_EQ(0, ret); \ 88 + ASSERT_EQ((socklen_t)sizeof(off), optlen); \ 89 + ASSERT_EQ(expected, off); \ 90 + } while (0) 91 + 79 92 #define async \ 80 93 for (pid_t pid = (pid = fork(), \ 81 94 pid < 0 ? \ ··· 104 91 sendeq(self->fd[0], "aaaabbbb", 0); 105 92 106 93 recveq(self->fd[1], "aaaa", 4, MSG_PEEK); 94 + peekoffeq(self->fd[1], 4); 107 95 recveq(self->fd[1], "bbbb", 100, MSG_PEEK); 96 + peekoffeq(self->fd[1], 8); 97 + 98 + recveq(self->fd[1], "aaaabbbb", 8, 0); 99 + peekoffeq(self->fd[1], 0); 108 100 } 109 101 110 102 TEST_F(so_peek_off, two_chunks) ··· 118 100 sendeq(self->fd[0], "bbbb", 0); 119 101 120 102 recveq(self->fd[1], "aaaa", 4, MSG_PEEK); 103 + peekoffeq(self->fd[1], 4); 121 104 recveq(self->fd[1], "bbbb", 100, MSG_PEEK); 105 + peekoffeq(self->fd[1], 8); 106 + 107 + recveq(self->fd[1], "aaaa", 4, 0); 108 + recveq(self->fd[1], "bbbb", 4, 0); 109 + peekoffeq(self->fd[1], 0); 122 110 } 123 111 124 112 TEST_F(so_peek_off, two_chunks_blocking) ··· 135 111 } 136 112 137 113 recveq(self->fd[1], "aaaa", 4, MSG_PEEK); 114 + peekoffeq(self->fd[1], 4); 138 115 139 116 async { 140 117 usleep(1000); ··· 144 119 145 120 /* goto again; -> goto redo; in unix_stream_read_generic(). */ 146 121 recveq(self->fd[1], "bbbb", 100, MSG_PEEK); 122 + peekoffeq(self->fd[1], 8); 123 + 124 + recveq(self->fd[1], "aaaa", 4, 0); 125 + recveq(self->fd[1], "bbbb", 4, 0); 126 + peekoffeq(self->fd[1], 0); 147 127 } 148 128 149 129 TEST_F(so_peek_off, two_chunks_overlap) 150 130 { 151 131 sendeq(self->fd[0], "aaaa", 0); 152 132 recveq(self->fd[1], "aa", 2, MSG_PEEK); 133 + peekoffeq(self->fd[1], 2); 153 134 154 135 sendeq(self->fd[0], "bbbb", 0); 155 136 156 137 if (variant->type == SOCK_STREAM) { 157 138 /* SOCK_STREAM tries to fill the buffer. */ 158 139 recveq(self->fd[1], "aabb", 4, MSG_PEEK); 140 + peekoffeq(self->fd[1], 6); 159 141 recveq(self->fd[1], "bb", 100, MSG_PEEK); 142 + peekoffeq(self->fd[1], 8); 160 143 } else { 161 144 /* SOCK_DGRAM and SOCK_SEQPACKET returns at the skb boundary. */ 162 145 recveq(self->fd[1], "aa", 100, MSG_PEEK); 146 + peekoffeq(self->fd[1], 4); 163 147 recveq(self->fd[1], "bbbb", 100, MSG_PEEK); 148 + peekoffeq(self->fd[1], 8); 164 149 } 150 + 151 + recveq(self->fd[1], "aaaa", 4, 0); 152 + recveq(self->fd[1], "bbbb", 4, 0); 153 + peekoffeq(self->fd[1], 0); 165 154 } 166 155 167 156 TEST_F(so_peek_off, two_chunks_overlap_blocking) ··· 186 147 } 187 148 188 149 recveq(self->fd[1], "aa", 2, MSG_PEEK); 150 + peekoffeq(self->fd[1], 2); 189 151 190 152 async { 191 153 usleep(1000); ··· 195 155 196 156 /* Even SOCK_STREAM does not wait if at least one byte is read. */ 197 157 recveq(self->fd[1], "aa", 100, MSG_PEEK); 158 + peekoffeq(self->fd[1], 4); 198 159 199 160 recveq(self->fd[1], "bbbb", 100, MSG_PEEK); 161 + peekoffeq(self->fd[1], 8); 162 + 163 + recveq(self->fd[1], "aaaa", 4, 0); 164 + recveq(self->fd[1], "bbbb", 4, 0); 165 + peekoffeq(self->fd[1], 0); 200 166 } 201 167 202 168 TEST_HARNESS_MAIN