aboutsummaryrefslogtreecommitdiff
path: root/lib/tst_netdevice.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tst_netdevice.c')
-rw-r--r--lib/tst_netdevice.c213
1 files changed, 170 insertions, 43 deletions
diff --git a/lib/tst_netdevice.c b/lib/tst_netdevice.c
index 4a0442932..dba44c623 100644
--- a/lib/tst_netdevice.c
+++ b/lib/tst_netdevice.c
@@ -7,6 +7,7 @@
#include <linux/veth.h>
#include <sys/socket.h>
#include <net/if.h>
+#include <linux/pkt_sched.h>
#include "lapi/rtnetlink.h"
#define TST_NO_DEFAULT_MAIN
@@ -97,7 +98,7 @@ int tst_netdev_set_state(const char *file, const int lineno,
return ret;
}
-int tst_create_veth_pair(const char *file, const int lineno,
+int tst_create_veth_pair(const char *file, const int lineno, int strict,
const char *ifname1, const char *ifname2)
{
int ret;
@@ -147,7 +148,7 @@ int tst_create_veth_pair(const char *file, const int lineno,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to create veth interfaces %s+%s: %s", ifname1,
ifname2, tst_strerrno(tst_rtnl_errno));
@@ -156,7 +157,7 @@ int tst_create_veth_pair(const char *file, const int lineno,
return ret;
}
-int tst_netdev_add_device(const char *file, const int lineno,
+int tst_netdev_add_device(const char *file, const int lineno, int strict,
const char *ifname, const char *devtype)
{
int ret;
@@ -191,7 +192,7 @@ int tst_netdev_add_device(const char *file, const int lineno,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to create %s device %s: %s", devtype, ifname,
tst_strerrno(tst_rtnl_errno));
@@ -200,7 +201,7 @@ int tst_netdev_add_device(const char *file, const int lineno,
return ret;
}
-int tst_netdev_remove_device(const char *file, const int lineno,
+int tst_netdev_remove_device(const char *file, const int lineno, int strict,
const char *ifname)
{
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
@@ -226,7 +227,7 @@ int tst_netdev_remove_device(const char *file, const int lineno,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to remove netdevice %s: %s", ifname,
tst_strerrno(tst_rtnl_errno));
@@ -235,7 +236,7 @@ int tst_netdev_remove_device(const char *file, const int lineno,
return ret;
}
-static int modify_address(const char *file, const int lineno,
+static int modify_address(const char *file, const int lineno, int strict,
unsigned int action, unsigned int nl_flags, const char *ifname,
unsigned int family, const void *address, unsigned int prefix,
size_t addrlen, uint32_t addr_flags)
@@ -276,7 +277,7 @@ static int modify_address(const char *file, const int lineno,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to modify %s network address: %s", ifname,
tst_strerrno(tst_rtnl_errno));
@@ -285,40 +286,40 @@ static int modify_address(const char *file, const int lineno,
return ret;
}
-int tst_netdev_add_address(const char *file, const int lineno,
+int tst_netdev_add_address(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, const void *address,
unsigned int prefix, size_t addrlen, unsigned int flags)
{
- return modify_address(file, lineno, RTM_NEWADDR,
+ return modify_address(file, lineno, strict, RTM_NEWADDR,
NLM_F_CREATE | NLM_F_EXCL, ifname, family, address, prefix,
addrlen, flags);
}
-int tst_netdev_add_address_inet(const char *file, const int lineno,
+int tst_netdev_add_address_inet(const char *file, const int lineno, int strict,
const char *ifname, in_addr_t address, unsigned int prefix,
unsigned int flags)
{
- return tst_netdev_add_address(file, lineno, ifname, AF_INET,
+ return tst_netdev_add_address(file, lineno, strict, ifname, AF_INET,
&address, prefix, sizeof(address), flags);
}
-int tst_netdev_remove_address(const char *file, const int lineno,
+int tst_netdev_remove_address(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, const void *address,
size_t addrlen)
{
- return modify_address(file, lineno, RTM_DELADDR, 0, ifname, family,
- address, 0, addrlen, 0);
+ return modify_address(file, lineno, strict, RTM_DELADDR, 0, ifname,
+ family, address, 0, addrlen, 0);
}
int tst_netdev_remove_address_inet(const char *file, const int lineno,
- const char *ifname, in_addr_t address)
+ int strict, const char *ifname, in_addr_t address)
{
- return tst_netdev_remove_address(file, lineno, ifname, AF_INET,
+ return tst_netdev_remove_address(file, lineno, strict, ifname, AF_INET,
&address, sizeof(address));
}
-static int change_ns(const char *file, const int lineno, const char *ifname,
- unsigned short attr, uint32_t value)
+static int change_ns(const char *file, const int lineno, int strict,
+ const char *ifname, unsigned short attr, uint32_t value)
{
struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
struct tst_rtnl_context *ctx;
@@ -332,6 +333,9 @@ static int change_ns(const char *file, const int lineno, const char *ifname,
ctx = create_request(file, lineno, RTM_NEWLINK, 0, &info, sizeof(info));
+ if (!ctx)
+ return 0;
+
if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
tst_rtnl_destroy_context(file, lineno, ctx);
return 0;
@@ -346,7 +350,7 @@ static int change_ns(const char *file, const int lineno, const char *ifname,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to move %s to another namespace: %s", ifname,
tst_strerrno(tst_rtnl_errno));
@@ -355,23 +359,23 @@ static int change_ns(const char *file, const int lineno, const char *ifname,
return ret;
}
-int tst_netdev_change_ns_fd(const char *file, const int lineno,
+int tst_netdev_change_ns_fd(const char *file, const int lineno, int strict,
const char *ifname, int nsfd)
{
- return change_ns(file, lineno, ifname, IFLA_NET_NS_FD, nsfd);
+ return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_FD, nsfd);
}
-int tst_netdev_change_ns_pid(const char *file, const int lineno,
+int tst_netdev_change_ns_pid(const char *file, const int lineno, int strict,
const char *ifname, pid_t nspid)
{
- return change_ns(file, lineno, ifname, IFLA_NET_NS_PID, nspid);
+ return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_PID, nspid);
}
-static int modify_route(const char *file, const int lineno, unsigned int action,
- unsigned int flags, const char *ifname, unsigned int family,
- const void *srcaddr, unsigned int srcprefix, size_t srclen,
- const void *dstaddr, unsigned int dstprefix, size_t dstlen,
- const void *gateway, size_t gatewaylen)
+static int modify_route(const char *file, const int lineno, int strict,
+ unsigned int action, unsigned int flags, const char *ifname,
+ unsigned int family, const void *srcaddr, unsigned int srcprefix,
+ size_t srclen, const void *dstaddr, unsigned int dstprefix,
+ size_t dstlen, const void *gateway, size_t gatewaylen)
{
struct tst_rtnl_context *ctx;
int ret;
@@ -411,6 +415,9 @@ static int modify_route(const char *file, const int lineno, unsigned int action,
ctx = create_request(file, lineno, action, flags, &info, sizeof(info));
+ if (!ctx)
+ return 0;
+
if (srcaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_SRC, srcaddr,
srclen)) {
tst_rtnl_destroy_context(file, lineno, ctx);
@@ -438,7 +445,7 @@ static int modify_route(const char *file, const int lineno, unsigned int action,
ret = tst_rtnl_send_validate(file, lineno, ctx);
tst_rtnl_destroy_context(file, lineno, ctx);
- if (!ret) {
+ if (strict && !ret) {
tst_brk_(file, lineno, TBROK,
"Failed to modify network route: %s",
tst_strerrno(tst_rtnl_errno));
@@ -447,7 +454,7 @@ static int modify_route(const char *file, const int lineno, unsigned int action,
return ret;
}
-static int modify_route_inet(const char *file, const int lineno,
+static int modify_route_inet(const char *file, const int lineno, int strict,
unsigned int action, unsigned int flags, const char *ifname,
in_addr_t srcaddr, unsigned int srcprefix, in_addr_t dstaddr,
unsigned int dstprefix, in_addr_t gateway)
@@ -470,45 +477,165 @@ static int modify_route_inet(const char *file, const int lineno,
gwlen = sizeof(gateway);
}
- return modify_route(file, lineno, action, flags, ifname, AF_INET, src,
- srcprefix, srclen, dst, dstprefix, dstlen, gw, gwlen);
+ return modify_route(file, lineno, strict, action, flags, ifname,
+ AF_INET, src, srcprefix, srclen, dst, dstprefix, dstlen, gw,
+ gwlen);
}
-int tst_netdev_add_route(const char *file, const int lineno,
+int tst_netdev_add_route(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, const void *srcaddr,
unsigned int srcprefix, size_t srclen, const void *dstaddr,
unsigned int dstprefix, size_t dstlen, const void *gateway,
size_t gatewaylen)
{
- return modify_route(file, lineno, RTM_NEWROUTE,
+ return modify_route(file, lineno, strict, RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_EXCL, ifname, family, srcaddr, srcprefix,
srclen, dstaddr, dstprefix, dstlen, gateway, gatewaylen);
}
-int tst_netdev_add_route_inet(const char *file, const int lineno,
+int tst_netdev_add_route_inet(const char *file, const int lineno, int strict,
const char *ifname, in_addr_t srcaddr, unsigned int srcprefix,
in_addr_t dstaddr, unsigned int dstprefix, in_addr_t gateway)
{
- return modify_route_inet(file, lineno, RTM_NEWROUTE,
+ return modify_route_inet(file, lineno, strict, RTM_NEWROUTE,
NLM_F_CREATE | NLM_F_EXCL, ifname, srcaddr, srcprefix, dstaddr,
dstprefix, gateway);
}
-int tst_netdev_remove_route(const char *file, const int lineno,
+int tst_netdev_remove_route(const char *file, const int lineno, int strict,
const char *ifname, unsigned int family, const void *srcaddr,
unsigned int srcprefix, size_t srclen, const void *dstaddr,
unsigned int dstprefix, size_t dstlen, const void *gateway,
size_t gatewaylen)
{
- return modify_route(file, lineno, RTM_DELROUTE, 0, ifname, family,
- srcaddr, srcprefix, srclen, dstaddr, dstprefix, dstlen,
+ return modify_route(file, lineno, strict, RTM_DELROUTE, 0, ifname,
+ family, srcaddr, srcprefix, srclen, dstaddr, dstprefix, dstlen,
gateway, gatewaylen);
}
int tst_netdev_remove_route_inet(const char *file, const int lineno,
- const char *ifname, in_addr_t srcaddr, unsigned int srcprefix,
- in_addr_t dstaddr, unsigned int dstprefix, in_addr_t gateway)
+ int strict, const char *ifname, in_addr_t srcaddr,
+ unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix,
+ in_addr_t gateway)
{
- return modify_route_inet(file, lineno, RTM_DELROUTE, 0, ifname,
+ return modify_route_inet(file, lineno, strict, RTM_DELROUTE, 0, ifname,
srcaddr, srcprefix, dstaddr, dstprefix, gateway);
}
+
+static int modify_qdisc(const char *file, const int lineno, int strict,
+ const char *object, unsigned int action, unsigned int nl_flags,
+ const char *ifname, unsigned int family, unsigned int parent,
+ unsigned int handle, unsigned int info, const char *qd_kind,
+ const struct tst_rtnl_attr_list *config)
+{
+ struct tst_rtnl_context *ctx;
+ int ret;
+ struct tcmsg msg = {
+ .tcm_family = family,
+ .tcm_handle = handle,
+ .tcm_parent = parent,
+ .tcm_info = info
+ };
+
+ if (!qd_kind) {
+ tst_brk_(file, lineno, TBROK,
+ "Queueing discipline name required");
+ return 0;
+ }
+
+ if (ifname) {
+ msg.tcm_ifindex = tst_netdev_index_by_name(file, lineno,
+ ifname);
+
+ if (msg.tcm_ifindex < 0) {
+ tst_brk_(file, lineno, TBROK, "Interface %s not found",
+ ifname);
+ return 0;
+ }
+ }
+
+ ctx = create_request(file, lineno, action, nl_flags, &msg, sizeof(msg));
+
+ if (!ctx)
+ return 0;
+
+ if (!tst_rtnl_add_attr_string(file, lineno, ctx, TCA_KIND, qd_kind)) {
+ tst_rtnl_destroy_context(file, lineno, ctx);
+ return 0;
+ }
+
+ if (config && !tst_rtnl_add_attr_list(file, lineno, ctx, config)) {
+ tst_rtnl_destroy_context(file, lineno, ctx);
+ return 0;
+ }
+
+ ret = tst_rtnl_send_validate(file, lineno, ctx);
+ tst_rtnl_destroy_context(file, lineno, ctx);
+
+ if (strict && !ret) {
+ tst_brk_(file, lineno, TBROK,
+ "Failed to modify %s: %s", object,
+ tst_strerrno(tst_rtnl_errno));
+ }
+
+ return ret;
+}
+
+int tst_netdev_add_qdisc(const char *file, const int lineno, int strict,
+ const char *ifname, unsigned int family, unsigned int parent,
+ unsigned int handle, const char *qd_kind,
+ const struct tst_rtnl_attr_list *config)
+{
+ return modify_qdisc(file, lineno, strict, "queueing discipline",
+ RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL, ifname, family,
+ parent, handle, 0, qd_kind, config);
+}
+
+int tst_netdev_remove_qdisc(const char *file, const int lineno, int strict,
+ const char *ifname, unsigned int family, unsigned int parent,
+ unsigned int handle, const char *qd_kind)
+{
+ return modify_qdisc(file, lineno, strict, "queueing discipline",
+ RTM_DELQDISC, 0, ifname, family, parent, handle, 0, qd_kind,
+ NULL);
+}
+
+int tst_netdev_add_traffic_class(const char *file, const int lineno,
+ int strict, const char *ifname, unsigned int parent,
+ unsigned int handle, const char *qd_kind,
+ const struct tst_rtnl_attr_list *config)
+{
+ return modify_qdisc(file, lineno, strict, "traffic class",
+ RTM_NEWTCLASS, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
+ parent, handle, 0, qd_kind, config);
+}
+
+int tst_netdev_remove_traffic_class(const char *file, const int lineno,
+ int strict, const char *ifname, unsigned int parent,
+ unsigned int handle, const char *qd_kind)
+{
+ return modify_qdisc(file, lineno, strict, "traffic class",
+ RTM_DELTCLASS, 0, ifname, AF_UNSPEC, parent, handle, 0,
+ qd_kind, NULL);
+}
+
+int tst_netdev_add_traffic_filter(const char *file, const int lineno,
+ int strict, const char *ifname, unsigned int parent,
+ unsigned int handle, unsigned int protocol, unsigned int priority,
+ const char *f_kind, const struct tst_rtnl_attr_list *config)
+{
+ return modify_qdisc(file, lineno, strict, "traffic filter",
+ RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
+ parent, handle, TC_H_MAKE(priority << 16, htons(protocol)),
+ f_kind, config);
+}
+
+int tst_netdev_remove_traffic_filter(const char *file, const int lineno,
+ int strict, const char *ifname, unsigned int parent,
+ unsigned int handle, unsigned int protocol, unsigned int priority,
+ const char *f_kind)
+{
+ return modify_qdisc(file, lineno, strict, "traffic filter",
+ RTM_DELTFILTER, 0, ifname, AF_UNSPEC, parent, handle,
+ TC_H_MAKE(priority << 16, htons(protocol)), f_kind, NULL);
+}