[LTP] [PATCH v5 2/2] net/route: Add netlink based route change tests
Petr Vorel
pvorel@suse.cz
Wed Apr 29 12:41:29 CEST 2020
Hi Alexey,
> Minor comments below.
Thanks for your review!
> > + for (i = 0; i < num_loops; i++) {
> > + if (iface_len > 1)
> > + tst_res(TINFO, "testing gw: %s, iface: %s",
> > + p_gw->ip_str, p_iface->iface);
> > + else if (gw_len > 1)
> > + tst_res(TINFO, "testing gw: %s", p_gw->ip_str);
> > + else
> > + tst_res(TINFO, "testing dst: %s/%d", p_dst->ip_str, prefix);
> It would be better to avoid printing it on every iteration, especially
> with the large NS_TIMES.
Understand, I thought you wouldn't like it. How about print only on error?
> > +
> > + rtnl_route(p_iface->index, p_dst->ip, gw ? p_gw->ip : NULL,
> > + prefix, RTM_NEWROUTE);
> > + send_udp(p_rhost->ip);
> > + rtnl_route(p_iface->index, p_dst->ip, gw ? p_gw->ip : NULL,
> > + prefix, RTM_DELROUTE);
> > +
> > + if (gw)
> > + p_gw = p_gw->next ?: gw;
> > + p_dst = p_dst->next ?: dst;
> > + p_iface = p_iface->next ?: iface;
> > + p_rhost = p_rhost->next ?: rhost;
> > + }
> > +
> > + tst_res(TPASS, "routes created and deleted");
> > +}
Something like this?
static void print_route_info(int iface, struct sockaddr *dst,
struct sockaddr *gw, int type)
{
char dst_str[INET6_ADDRSTRLEN], gw_str[INET6_ADDRSTRLEN];
tst_sock_addr(dst, sizeof(dst), dst_str, sizeof(dst_str));
if (gw)
tst_sock_addr(gw, sizeof(gw), gw_str, sizeof(gw_str));
tst_res(TINFO, "type: %s, iface: %d, dst: %s, gw: %s",
type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
iface, dst_str, gw ? gw_str : "null");
tst_brk(TBROK, "failed due previous netlink errors");
}
static void rtnl_route(int iface, struct addrinfo *dst, struct addrinfo *gw,
int type)
{
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct rtmsg *rtm;
uint32_t seq, portid;
struct in6_addr dst_in6, gw_in6;
in_addr_t dst_ip, gw_ip;
int ret;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = type;
nlh->nlmsg_flags = NLM_F_ACK;
if (type == RTM_NEWROUTE)
nlh->nlmsg_flags |= NLM_F_REQUEST | NLM_F_CREATE | NLM_F_REPLACE;
nlh->nlmsg_seq = seq = time(NULL);
rtm = mnl_nlmsg_put_extra_header(nlh, sizeof(struct rtmsg));
rtm->rtm_family = family;
rtm->rtm_dst_len = prefix;
rtm->rtm_src_len = 0;
rtm->rtm_tos = 0;
rtm->rtm_protocol = RTPROT_STATIC;
rtm->rtm_table = RT_TABLE_MAIN;
rtm->rtm_type = RTN_UNICAST;
rtm->rtm_scope = gw ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK;
rtm->rtm_flags = 0;
if (is_ipv6) {
dst_in6 = ((struct sockaddr_in6 *)dst->ai_addr)->sin6_addr;
mnl_attr_put(nlh, RTA_DST, sizeof(struct in6_addr), &dst_in6);
} else {
dst_ip = ((struct sockaddr_in *)dst->ai_addr)->sin_addr.s_addr;
mnl_attr_put_u32(nlh, RTA_DST, dst_ip);
}
mnl_attr_put_u32(nlh, RTA_OIF, iface);
if (gw) {
if (is_ipv6) {
gw_in6 = ((struct sockaddr_in6 *)gw->ai_addr)->sin6_addr;
mnl_attr_put(nlh, RTA_GATEWAY, sizeof(struct in6_addr), &gw_in6);
} else {
gw_ip = ((struct sockaddr_in *)gw->ai_addr)->sin_addr.s_addr;
mnl_attr_put_u32(nlh, RTA_GATEWAY, gw_ip);
}
}
nl = mnl_socket_open(NETLINK_ROUTE);
if (nl == NULL) {
tst_res(TFAIL, "mnl_socket_open failed (errno=%d): %s", errno,
strerror(errno));
goto err;
}
if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
tst_res(TFAIL, "mnl_socket_bind failed (errno=%d): %s", errno,
strerror(errno));
goto err;
}
portid = mnl_socket_get_portid(nl);
if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
tst_res(TFAIL, "mnl_socket_sendto failed (errno=%d): %s", errno,
strerror(errno));
goto err;
}
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
if (ret < 0) {
tst_res(TFAIL, "mnl_socket_recvfrom failed (ret=%d, errno=%d): %s",
ret, errno, strerror(errno));
goto err;
}
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
if (ret < 0) {
tst_res(TFAIL, "mnl_cb_run failed (ret=%d, errno=%d): %s", ret,
errno, strerror(errno));
goto err;
}
mnl_socket_close(nl);
return;
err:
print_route_info(iface, dst->ai_addr, gw ? gw->ai_addr: NULL, type);
}
> > +
> > +static struct tst_option options[] = {
> > + {"6", &ipv6_opt, "-6 Use IPv6 (default is IPv4)"},
> > + {"c:", &c_opt, " Num loops (mandatory)"},
> "-c x ...
Fixed.
BTW I also removed prefix parameter from rtnl_route() (it's a global parameter,
family is not passed either).
https://github.com/pevik/ltp/blob/route/c.v5.fixes/testcases/network/stress/route/route-change-netlink.c
+ below is full diff against posted version.
Kind regards,
Petr
diff --git testcases/network/stress/route/route-change-netlink.c testcases/network/stress/route/route-change-netlink.c
index 57ae02a3c..80677f1a4 100644
--- testcases/network/stress/route/route-change-netlink.c
+++ testcases/network/stress/route/route-change-netlink.c
@@ -177,7 +177,22 @@ static void cleanup(void)
mnl_socket_close(nl);
}
-static void rtnl_route(int iface, struct addrinfo *dst, struct addrinfo *gw, uint32_t prefix, int type)
+static void print_route_info(int iface, struct sockaddr *dst,
+ struct sockaddr *gw, int type)
+{
+ char dst_str[INET6_ADDRSTRLEN], gw_str[INET6_ADDRSTRLEN];
+ tst_sock_addr(dst, sizeof(dst), dst_str, sizeof(dst_str));
+ if (gw)
+ tst_sock_addr(gw, sizeof(gw), gw_str, sizeof(gw_str));
+
+ tst_res(TINFO, "type: %s, iface: %d, dst: %s, gw: %s",
+ type == RTM_NEWROUTE ? "RTM_NEWROUTE" : "RTM_DELROUTE",
+ iface, dst_str, gw ? gw_str : "null");
+ tst_brk(TBROK, "failed due previous netlink errors");
+}
+
+static void rtnl_route(int iface, struct addrinfo *dst, struct addrinfo *gw,
+ int type)
{
struct mnl_socket *nl;
char buf[MNL_SOCKET_BUFFER_SIZE];
@@ -229,31 +244,44 @@ static void rtnl_route(int iface, struct addrinfo *dst, struct addrinfo *gw, uin
}
nl = mnl_socket_open(NETLINK_ROUTE);
- if (nl == NULL)
- tst_brk(TBROK, "mnl_socket_open failed (errno=%d): %s", errno,
+ if (nl == NULL) {
+ tst_res(TFAIL, "mnl_socket_open failed (errno=%d): %s", errno,
strerror(errno));
+ goto err;
+ }
- if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0)
- tst_brk(TBROK, "mnl_socket_bind failed (errno=%d): %s", errno,
+ if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) {
+ tst_res(TFAIL, "mnl_socket_bind failed (errno=%d): %s", errno,
strerror(errno));
+ goto err;
+ }
portid = mnl_socket_get_portid(nl);
- if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0)
- tst_brk(TBROK, "mnl_socket_sendto failed (errno=%d): %s", errno,
+ if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) {
+ tst_res(TFAIL, "mnl_socket_sendto failed (errno=%d): %s", errno,
strerror(errno));
+ goto err;
+ }
ret = mnl_socket_recvfrom(nl, buf, sizeof(buf));
- if (ret < 0)
- tst_brk(TBROK, "mnl_socket_recvfrom failed (ret=%d, errno=%d): %s",
+ if (ret < 0) {
+ tst_res(TFAIL, "mnl_socket_recvfrom failed (ret=%d, errno=%d): %s",
ret, errno, strerror(errno));
+ goto err;
+ }
ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL);
- if (ret < 0)
- tst_brk(TBROK, "mnl_cb_run failed (ret=%d, errno=%d): %s", ret,
+ if (ret < 0) {
+ tst_res(TFAIL, "mnl_cb_run failed (ret=%d, errno=%d): %s", ret,
errno, strerror(errno));
+ goto err;
+ }
mnl_socket_close(nl);
+ return;
+err:
+ print_route_info(iface, dst->ai_addr, gw ? gw->ai_addr: NULL, type);
}
static void send_udp(struct addrinfo *rhost_addrinfo)
@@ -274,19 +302,11 @@ static void run(void)
struct iface *p_iface = iface;
for (i = 0; i < num_loops; i++) {
- if (iface_len > 1)
- tst_res(TINFO, "testing gw: %s, iface: %s",
- p_gw->ip_str, p_iface->iface);
- else if (gw_len > 1)
- tst_res(TINFO, "testing gw: %s", p_gw->ip_str);
- else
- tst_res(TINFO, "testing dst: %s/%d", p_dst->ip_str, prefix);
-
rtnl_route(p_iface->index, p_dst->ip, gw ? p_gw->ip : NULL,
- prefix, RTM_NEWROUTE);
+ RTM_NEWROUTE);
send_udp(p_rhost->ip);
rtnl_route(p_iface->index, p_dst->ip, gw ? p_gw->ip : NULL,
- prefix, RTM_DELROUTE);
+ RTM_DELROUTE);
if (gw)
p_gw = p_gw->next ?: gw;
@@ -300,7 +320,7 @@ static void run(void)
static struct tst_option options[] = {
{"6", &ipv6_opt, "-6 Use IPv6 (default is IPv4)"},
- {"c:", &c_opt, " Num loops (mandatory)"},
+ {"c:", &c_opt, "-c x Num loops (mandatory)"},
{"d:", &d_opt, "-d iface Interface to work on (mandatory)"},
{"g:", &g_opt, "-g x Gateway IP"},
{"p:", &p_opt, "-p port Rhost port (mandatory)"},
More information about the ltp
mailing list