Skip to content

Commit b3e5fd6

Browse files
kmaloordavem330
authored andcommitted
selftests: mptcp: capture netlink events
This change adds to self-testing support for the MPTCP netlink interface by capturing various MPTCP netlink events (and all their metadata) associated with connections, subflows and address announcements. It is used in self-testing scripts that exercise MPTCP netlink commands to precisely validate those operations by examining the dispatched MPTCP netlink events in response to those commands. Acked-by: Paolo Abeni <[email protected]> Signed-off-by: Kishen Maloor <[email protected]> Signed-off-by: Mat Martineau <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 57cc361 commit b3e5fd6

File tree

1 file changed

+157
-7
lines changed

1 file changed

+157
-7
lines changed

tools/testing/selftests/net/mptcp/pm_nl_ctl.c

Lines changed: 157 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
#ifndef MPTCP_PM_NAME
2323
#define MPTCP_PM_NAME "mptcp_pm"
2424
#endif
25+
#ifndef MPTCP_PM_EVENTS
26+
#define MPTCP_PM_EVENTS "mptcp_pm_events"
27+
#endif
2528

2629
static void syntax(char *argv[])
2730
{
@@ -37,6 +40,7 @@ static void syntax(char *argv[])
3740
fprintf(stderr, "\tflush\n");
3841
fprintf(stderr, "\tdump\n");
3942
fprintf(stderr, "\tlimits [<rcv addr max> <subflow max>]\n");
43+
fprintf(stderr, "\tevents\n");
4044
exit(0);
4145
}
4246

@@ -88,6 +92,108 @@ static void nl_error(struct nlmsghdr *nh)
8892
}
8993
}
9094

95+
static int capture_events(int fd, int event_group)
96+
{
97+
u_int8_t buffer[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
98+
NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024];
99+
struct genlmsghdr *ghdr;
100+
struct rtattr *attrs;
101+
struct nlmsghdr *nh;
102+
int ret = 0;
103+
int res_len;
104+
int msg_len;
105+
fd_set rfds;
106+
107+
if (setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
108+
&event_group, sizeof(event_group)) < 0)
109+
error(1, errno, "could not join the " MPTCP_PM_EVENTS " mcast group");
110+
111+
do {
112+
FD_ZERO(&rfds);
113+
FD_SET(fd, &rfds);
114+
res_len = NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
115+
NLMSG_ALIGN(sizeof(struct genlmsghdr)) + 1024;
116+
117+
ret = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
118+
119+
if (ret < 0)
120+
error(1, ret, "error in select() on NL socket");
121+
122+
res_len = recv(fd, buffer, res_len, 0);
123+
if (res_len < 0)
124+
error(1, res_len, "error on recv() from NL socket");
125+
126+
nh = (struct nlmsghdr *)buffer;
127+
128+
for (; NLMSG_OK(nh, res_len); nh = NLMSG_NEXT(nh, res_len)) {
129+
if (nh->nlmsg_type == NLMSG_ERROR)
130+
error(1, NLMSG_ERROR, "received invalid NL message");
131+
132+
ghdr = (struct genlmsghdr *)NLMSG_DATA(nh);
133+
134+
if (ghdr->cmd == 0)
135+
continue;
136+
137+
fprintf(stderr, "type:%d", ghdr->cmd);
138+
139+
msg_len = nh->nlmsg_len - NLMSG_LENGTH(GENL_HDRLEN);
140+
141+
attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
142+
while (RTA_OK(attrs, msg_len)) {
143+
if (attrs->rta_type == MPTCP_ATTR_TOKEN)
144+
fprintf(stderr, ",token:%u", *(__u32 *)RTA_DATA(attrs));
145+
else if (attrs->rta_type == MPTCP_ATTR_FAMILY)
146+
fprintf(stderr, ",family:%u", *(__u16 *)RTA_DATA(attrs));
147+
else if (attrs->rta_type == MPTCP_ATTR_LOC_ID)
148+
fprintf(stderr, ",loc_id:%u", *(__u8 *)RTA_DATA(attrs));
149+
else if (attrs->rta_type == MPTCP_ATTR_REM_ID)
150+
fprintf(stderr, ",rem_id:%u", *(__u8 *)RTA_DATA(attrs));
151+
else if (attrs->rta_type == MPTCP_ATTR_SADDR4) {
152+
u_int32_t saddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
153+
154+
fprintf(stderr, ",saddr4:%u.%u.%u.%u", saddr4 >> 24,
155+
(saddr4 >> 16) & 0xFF, (saddr4 >> 8) & 0xFF,
156+
(saddr4 & 0xFF));
157+
} else if (attrs->rta_type == MPTCP_ATTR_SADDR6) {
158+
char buf[INET6_ADDRSTRLEN];
159+
160+
if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
161+
sizeof(buf)) != NULL)
162+
fprintf(stderr, ",saddr6:%s", buf);
163+
} else if (attrs->rta_type == MPTCP_ATTR_DADDR4) {
164+
u_int32_t daddr4 = ntohl(*(__u32 *)RTA_DATA(attrs));
165+
166+
fprintf(stderr, ",daddr4:%u.%u.%u.%u", daddr4 >> 24,
167+
(daddr4 >> 16) & 0xFF, (daddr4 >> 8) & 0xFF,
168+
(daddr4 & 0xFF));
169+
} else if (attrs->rta_type == MPTCP_ATTR_DADDR6) {
170+
char buf[INET6_ADDRSTRLEN];
171+
172+
if (inet_ntop(AF_INET6, RTA_DATA(attrs), buf,
173+
sizeof(buf)) != NULL)
174+
fprintf(stderr, ",daddr6:%s", buf);
175+
} else if (attrs->rta_type == MPTCP_ATTR_SPORT)
176+
fprintf(stderr, ",sport:%u",
177+
ntohs(*(__u16 *)RTA_DATA(attrs)));
178+
else if (attrs->rta_type == MPTCP_ATTR_DPORT)
179+
fprintf(stderr, ",dport:%u",
180+
ntohs(*(__u16 *)RTA_DATA(attrs)));
181+
else if (attrs->rta_type == MPTCP_ATTR_BACKUP)
182+
fprintf(stderr, ",backup:%u", *(__u8 *)RTA_DATA(attrs));
183+
else if (attrs->rta_type == MPTCP_ATTR_ERROR)
184+
fprintf(stderr, ",error:%u", *(__u8 *)RTA_DATA(attrs));
185+
else if (attrs->rta_type == MPTCP_ATTR_SERVER_SIDE)
186+
fprintf(stderr, ",server_side:%u", *(__u8 *)RTA_DATA(attrs));
187+
188+
attrs = RTA_NEXT(attrs, msg_len);
189+
}
190+
}
191+
fprintf(stderr, "\n");
192+
} while (1);
193+
194+
return 0;
195+
}
196+
91197
/* do a netlink command and, if max > 0, fetch the reply */
92198
static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
93199
{
@@ -121,11 +227,18 @@ static int do_nl_req(int fd, struct nlmsghdr *nh, int len, int max)
121227
return ret;
122228
}
123229

124-
static int genl_parse_getfamily(struct nlmsghdr *nlh)
230+
static int genl_parse_getfamily(struct nlmsghdr *nlh, int *pm_family,
231+
int *events_mcast_grp)
125232
{
126233
struct genlmsghdr *ghdr = NLMSG_DATA(nlh);
127234
int len = nlh->nlmsg_len;
128235
struct rtattr *attrs;
236+
struct rtattr *grps;
237+
struct rtattr *grp;
238+
int got_events_grp;
239+
int got_family;
240+
int grps_len;
241+
int grp_len;
129242

130243
if (nlh->nlmsg_type != GENL_ID_CTRL)
131244
error(1, errno, "Not a controller message, len=%d type=0x%x\n",
@@ -140,17 +253,50 @@ static int genl_parse_getfamily(struct nlmsghdr *nlh)
140253
error(1, errno, "Unknown controller command %d\n", ghdr->cmd);
141254

142255
attrs = (struct rtattr *) ((char *) ghdr + GENL_HDRLEN);
256+
got_family = 0;
257+
got_events_grp = 0;
258+
143259
while (RTA_OK(attrs, len)) {
144-
if (attrs->rta_type == CTRL_ATTR_FAMILY_ID)
145-
return *(__u16 *)RTA_DATA(attrs);
260+
if (attrs->rta_type == CTRL_ATTR_FAMILY_ID) {
261+
*pm_family = *(__u16 *)RTA_DATA(attrs);
262+
got_family = 1;
263+
} else if (attrs->rta_type == CTRL_ATTR_MCAST_GROUPS) {
264+
grps = RTA_DATA(attrs);
265+
grps_len = RTA_PAYLOAD(attrs);
266+
267+
while (RTA_OK(grps, grps_len)) {
268+
grp = RTA_DATA(grps);
269+
grp_len = RTA_PAYLOAD(grps);
270+
got_events_grp = 0;
271+
272+
while (RTA_OK(grp, grp_len)) {
273+
if (grp->rta_type == CTRL_ATTR_MCAST_GRP_ID)
274+
*events_mcast_grp = *(__u32 *)RTA_DATA(grp);
275+
else if (grp->rta_type == CTRL_ATTR_MCAST_GRP_NAME &&
276+
!strcmp(RTA_DATA(grp), MPTCP_PM_EVENTS))
277+
got_events_grp = 1;
278+
279+
grp = RTA_NEXT(grp, grp_len);
280+
}
281+
282+
if (got_events_grp)
283+
break;
284+
285+
grps = RTA_NEXT(grps, grps_len);
286+
}
287+
}
288+
289+
if (got_family && got_events_grp)
290+
return 0;
291+
146292
attrs = RTA_NEXT(attrs, len);
147293
}
148294

149295
error(1, errno, "can't find CTRL_ATTR_FAMILY_ID attr");
150296
return -1;
151297
}
152298

153-
static int resolve_mptcp_pm_netlink(int fd)
299+
static int resolve_mptcp_pm_netlink(int fd, int *pm_family, int *events_mcast_grp)
154300
{
155301
char data[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
156302
NLMSG_ALIGN(sizeof(struct genlmsghdr)) +
@@ -172,7 +318,7 @@ static int resolve_mptcp_pm_netlink(int fd)
172318
off += NLMSG_ALIGN(rta->rta_len);
173319

174320
do_nl_req(fd, nh, off, sizeof(data));
175-
return genl_parse_getfamily((void *)data);
321+
return genl_parse_getfamily((void *)data, pm_family, events_mcast_grp);
176322
}
177323

178324
int dsf(int fd, int pm_family, int argc, char *argv[])
@@ -1192,7 +1338,9 @@ int set_flags(int fd, int pm_family, int argc, char *argv[])
11921338

11931339
int main(int argc, char *argv[])
11941340
{
1195-
int fd, pm_family;
1341+
int events_mcast_grp;
1342+
int pm_family;
1343+
int fd;
11961344

11971345
if (argc < 2)
11981346
syntax(argv);
@@ -1201,7 +1349,7 @@ int main(int argc, char *argv[])
12011349
if (fd == -1)
12021350
error(1, errno, "socket netlink");
12031351

1204-
pm_family = resolve_mptcp_pm_netlink(fd);
1352+
resolve_mptcp_pm_netlink(fd, &pm_family, &events_mcast_grp);
12051353

12061354
if (!strcmp(argv[1], "add"))
12071355
return add_addr(fd, pm_family, argc, argv);
@@ -1225,6 +1373,8 @@ int main(int argc, char *argv[])
12251373
return get_set_limits(fd, pm_family, argc, argv);
12261374
else if (!strcmp(argv[1], "set"))
12271375
return set_flags(fd, pm_family, argc, argv);
1376+
else if (!strcmp(argv[1], "events"))
1377+
return capture_events(fd, events_mcast_grp);
12281378

12291379
fprintf(stderr, "unknown sub-command: %s", argv[1]);
12301380
syntax(argv);

0 commit comments

Comments
 (0)