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

selftests: mptcp: pm_nl_ctl: always look for errors

If a Netlink command for the MPTCP path-managers is not valid, it is
important to check if there are errors. If yes, they need to be reported
instead of being ignored and exiting without errors.

Now if no replies are expected, an ACK from the kernelspace is asked by
the userspace in order to always expect a reply. We can use the same
buffer that is currently always >1024 bytes. Then we can check if there
is an error (err->error), print it if any and report the error.

After this modification, it is required to mute expected errors in
mptcp_join.sh and pm_netlink.sh selftests:

- when trying to add a bad endpoint, e.g. duplicated
- when trying to set the two limits above the hard limit

Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230730-upstream-net-next-20230728-mptcp-selftests-misc-v1-3-7e9cc530a9cd@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Matthieu Baerts and committed by
Jakub Kicinski
1dc88d24 9466df1a

+26 -15
+1 -1
tools/testing/selftests/net/mptcp/mptcp_join.sh
··· 3452 3452 chk_mptcp_info subflows 1 subflows 1 3453 3453 chk_mptcp_info add_addr_signal 1 add_addr_accepted 1 3454 3454 3455 - pm_nl_add_endpoint $ns2 10.0.2.2 id 33 3455 + pm_nl_add_endpoint $ns2 10.0.2.2 id 33 2>/dev/null 3456 3456 pm_nl_check_endpoint "ID change is prevented" \ 3457 3457 $ns2 10.0.2.2 id 1 flags implicit 3458 3458
+3 -3
tools/testing/selftests/net/mptcp/pm_netlink.sh
··· 99 99 "id 1 flags 10.0.1.1 100 100 id 3 flags signal,backup 10.0.1.3" "dump addrs after del" 101 101 102 - ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 102 + ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.3 2>/dev/null 103 103 check "ip netns exec $ns1 ./pm_nl_ctl get 4" "" "duplicate addr" 104 104 105 105 ip netns exec $ns1 ./pm_nl_ctl add 10.0.1.4 flags signal ··· 127 127 ip netns exec $ns1 ./pm_nl_ctl flush 128 128 check "ip netns exec $ns1 ./pm_nl_ctl dump" "" "flush addrs" 129 129 130 - ip netns exec $ns1 ./pm_nl_ctl limits 9 1 130 + ip netns exec $ns1 ./pm_nl_ctl limits 9 1 2>/dev/null 131 131 check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "rcv addrs above hard limit" 132 132 133 - ip netns exec $ns1 ./pm_nl_ctl limits 1 9 133 + ip netns exec $ns1 ./pm_nl_ctl limits 1 9 2>/dev/null 134 134 check "ip netns exec $ns1 ./pm_nl_ctl limits" "$default_limits" "subflows above hard limit" 135 135 136 136 ip netns exec $ns1 ./pm_nl_ctl limits 8 8
+22 -11
tools/testing/selftests/net/mptcp/pm_nl_ctl.c
··· 66 66 return off; 67 67 } 68 68 69 - static void nl_error(struct nlmsghdr *nh) 69 + static int nl_error(struct nlmsghdr *nh) 70 70 { 71 71 struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(nh); 72 72 int len = nh->nlmsg_len - sizeof(*nh); 73 73 uint32_t off; 74 74 75 - if (len < sizeof(struct nlmsgerr)) 75 + if (len < sizeof(struct nlmsgerr)) { 76 76 error(1, 0, "netlink error message truncated %d min %ld", len, 77 77 sizeof(struct nlmsgerr)); 78 + return -1; 79 + } 78 80 79 - if (!err->error) { 81 + if (err->error) { 80 82 /* check messages from kernel */ 81 83 struct rtattr *attrs = (struct rtattr *)NLMSG_DATA(nh); 84 + 85 + fprintf(stderr, "netlink error %d (%s)\n", 86 + err->error, strerror(-err->error)); 82 87 83 88 while (RTA_OK(attrs, len)) { 84 89 if (attrs->rta_type == NLMSGERR_ATTR_MSG) ··· 96 91 } 97 92 attrs = RTA_NEXT(attrs, len); 98 93 } 99 - } else { 100 - fprintf(stderr, "netlink error %d", err->error); 94 + return -1; 101 95 } 96 + 97 + return 0; 102 98 } 103 99 104 100 static int capture_events(int fd, int event_group) ··· 204 198 return 0; 205 199 } 206 200 207 - /* do a netlink command and, if max > 0, fetch the reply */ 201 + /* do a netlink command and, if max > 0, fetch the reply ; nh's size >1024B */ 208 202 static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max) 209 203 { 210 204 struct sockaddr_nl nladdr = { .nl_family = AF_NETLINK }; ··· 213 207 int rem, ret; 214 208 int err = 0; 215 209 210 + /* If no expected answer, ask for an ACK to look for errors if any */ 211 + if (max == 0) { 212 + nh->nlmsg_flags |= NLM_F_ACK; 213 + max = 1024; 214 + } 215 + 216 216 nh->nlmsg_len = len; 217 217 ret = sendto(fd, data, len, 0, (void *)&nladdr, sizeof(nladdr)); 218 218 if (ret != len) 219 219 error(1, errno, "send netlink: %uB != %uB\n", ret, len); 220 - if (max == 0) 221 - return 0; 222 220 223 221 addr_len = sizeof(nladdr); 224 222 rem = ret = recvfrom(fd, data, max, 0, (void *)&nladdr, &addr_len); ··· 231 221 232 222 /* Beware: the NLMSG_NEXT macro updates the 'rem' argument */ 233 223 for (; NLMSG_OK(nh, rem); nh = NLMSG_NEXT(nh, rem)) { 234 - if (nh->nlmsg_type == NLMSG_ERROR) { 235 - nl_error(nh); 224 + if (nh->nlmsg_type == NLMSG_DONE) 225 + break; 226 + 227 + if (nh->nlmsg_type == NLMSG_ERROR && nl_error(nh)) 236 228 err = 1; 237 - } 238 229 } 239 230 if (err) 240 231 error(1, 0, "bailing out due to netlink error[s]");