diff options
Diffstat (limited to 'lib/tst_netdevice.c')
-rw-r--r-- | lib/tst_netdevice.c | 213 |
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); +} |