1f08c3bdfSopenharmony_ciLTP C Test Network API 2f08c3bdfSopenharmony_ci====================== 3f08c3bdfSopenharmony_ci 4f08c3bdfSopenharmony_ciNOTE: See also 5f08c3bdfSopenharmony_ci https://github.com/linux-test-project/ltp/wiki/Test-Writing-Guidelines[Test Writing Guidelines], 6f08c3bdfSopenharmony_ci https://github.com/linux-test-project/ltp/wiki/C-Test-Case-Tutorial[C Test Case Tutorial], 7f08c3bdfSopenharmony_ci https://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API], 8f08c3bdfSopenharmony_ci https://github.com/linux-test-project/ltp/wiki/Shell-Test-API[Shell Test API]. 9f08c3bdfSopenharmony_ci 10f08c3bdfSopenharmony_ciLTP library includes helper functions for configuring sockets and setting up 11f08c3bdfSopenharmony_cinetwork devices. 12f08c3bdfSopenharmony_ci 13f08c3bdfSopenharmony_ci1 Configuring sockets 14f08c3bdfSopenharmony_ci--------------------- 15f08c3bdfSopenharmony_ci 16f08c3bdfSopenharmony_ci1.1 Safe syscall variants 17f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~ 18f08c3bdfSopenharmony_ci 19f08c3bdfSopenharmony_ci+#include "tst_safe_net.h"+ 20f08c3bdfSopenharmony_ci 21f08c3bdfSopenharmony_ciMost common standard syscalls and libc functions for configuring sockets have a 22f08c3bdfSopenharmony_ci"safe" variant in LTP library which will call +tst_brk()+ if the underlying 23f08c3bdfSopenharmony_cisystem function fails. See 24f08c3bdfSopenharmony_cihttps://github.com/linux-test-project/ltp/wiki/C-Test-API[C Test API]. The 25f08c3bdfSopenharmony_cisafe function names are in uppercase with the +SAFE_+ prefix (e.g. the safe 26f08c3bdfSopenharmony_civariant of +socket()+ is called +SAFE_SOCKET()+). For most safe functions, the 27f08c3bdfSopenharmony_ciparameters and return type are identical to the standard system function: 28f08c3bdfSopenharmony_ci 29f08c3bdfSopenharmony_ci- +SAFE_SOCKET()+ 30f08c3bdfSopenharmony_ci- +SAFE_SOCKETPAIR()+ 31f08c3bdfSopenharmony_ci- +SAFE_GETSOCKOPT()+ 32f08c3bdfSopenharmony_ci- +SAFE_SETSOCKOPT()+ 33f08c3bdfSopenharmony_ci- +SAFE_BIND()+ 34f08c3bdfSopenharmony_ci- +SAFE_LISTEN()+ 35f08c3bdfSopenharmony_ci- +SAFE_ACCEPT()+ 36f08c3bdfSopenharmony_ci- +SAFE_CONNECT()+ 37f08c3bdfSopenharmony_ci- +SAFE_GETSOCKNAME()+ 38f08c3bdfSopenharmony_ci- +SAFE_GETHOSTNAME()+ 39f08c3bdfSopenharmony_ci- +SAFE_GETADDRINFO()+ 40f08c3bdfSopenharmony_ci 41f08c3bdfSopenharmony_ciA few safe functions have extra parameters for quick return value validation. 42f08c3bdfSopenharmony_ciThe ellipsis (+...+) represents the standard parameters of the underlying system 43f08c3bdfSopenharmony_cifunction: 44f08c3bdfSopenharmony_ci 45f08c3bdfSopenharmony_ci* +SAFE_SEND(char strict, ...)+ 46f08c3bdfSopenharmony_ci* +SAFE_SENDTO(char strict, ...)+ 47f08c3bdfSopenharmony_ci** If +strict+ is non-zero, the return value must be equal to the data length 48f08c3bdfSopenharmony_ci argument. Otherwise the test will fail and exit. 49f08c3bdfSopenharmony_ci 50f08c3bdfSopenharmony_ci* +SAFE_SENDMSG(size_t msg_len, ...)+ 51f08c3bdfSopenharmony_ci* +SAFE_RECV(size_t msg_len, ...)+ 52f08c3bdfSopenharmony_ci* +SAFE_RECVMSG(size_t msg_len, ...)+ 53f08c3bdfSopenharmony_ci** If +msg_len+ is non-zero, the return value must be equal to the +msg_len+ 54f08c3bdfSopenharmony_ci argument. Otherwise the test will fail and exit. 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_ciThere are also some custom functions for simpler configuration and queries: 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_ci- +int SAFE_SETSOCKOPT_INT(int sockfd, int level, int optname, int value)+ – 59f08c3bdfSopenharmony_ci Simple setsockopt() variant for passing integers by value. 60f08c3bdfSopenharmony_ci 61f08c3bdfSopenharmony_ci- +int TST_GETSOCKPORT(int sockfd)+ – Get port number (in host byte order) of a 62f08c3bdfSopenharmony_ci bound socket. 63f08c3bdfSopenharmony_ci 64f08c3bdfSopenharmony_ci- +unsigned short TST_GET_UNUSED_PORT(int family, int type)+ – Get a random 65f08c3bdfSopenharmony_ci port number (in network byte order) which is currently closed for the given 66f08c3bdfSopenharmony_ci socket family and type. Note that another application may open the port while 67f08c3bdfSopenharmony_ci the test is still running. The test user is responsible for setting up test 68f08c3bdfSopenharmony_ci environment without such interference. 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ci1.2 Address conversion functions 71f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 72f08c3bdfSopenharmony_ci 73f08c3bdfSopenharmony_ci+#include "tst_net.h"+ 74f08c3bdfSopenharmony_ci 75f08c3bdfSopenharmony_ciLTP library also provides helper functions for quick initialization of socket 76f08c3bdfSopenharmony_ciaddress structures: 77f08c3bdfSopenharmony_ci 78f08c3bdfSopenharmony_ci- +void tst_get_in_addr(const char *ip_str, struct in_addr *ip)+ – Convert 79f08c3bdfSopenharmony_ci human-readable IPv4 address string +ip_str+ to binary representation in 80f08c3bdfSopenharmony_ci network byte order. The converted value will be stored in the second argument. 81f08c3bdfSopenharmony_ci 82f08c3bdfSopenharmony_ci- +void tst_get_in6_addr(const char *ip_str, struct in6_addr *ip6)+ – Convert 83f08c3bdfSopenharmony_ci human-readable IPv6 address string +ip_str+ to binary representation in 84f08c3bdfSopenharmony_ci network byte order. The converted value will be stored in the second argument. 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci- +socklen_t tst_get_connect_address(int sock, struct sockaddr_storage *addr)+ – 87f08c3bdfSopenharmony_ci Find the address which can be used to send data to bound socket +sock+ from 88f08c3bdfSopenharmony_ci another socket. The address will be stored in the second argument. This 89f08c3bdfSopenharmony_ci function automatically converts wildcard bind address to localhost. Returns 90f08c3bdfSopenharmony_ci size of the address in bytes. 91f08c3bdfSopenharmony_ci 92f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet(struct sockaddr_in *sa, const char *ip_str, 93f08c3bdfSopenharmony_ci uint16_t port)+ – Initialize socket address structure +sa+ using 94f08c3bdfSopenharmony_ci human-readable IPv4 address +ip_str+ and port number +port+ in host byte 95f08c3bdfSopenharmony_ci order. 96f08c3bdfSopenharmony_ci 97f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet_bin(struct sockaddr_in *sa, uint32_t ip_val, 98f08c3bdfSopenharmony_ci uint16_t port)+ – Initialize socket address structure +sa+ using binary IPv4 99f08c3bdfSopenharmony_ci address +ip_val+ and port number +port+, both in host byte order. 100f08c3bdfSopenharmony_ci 101f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet6(struct sockaddr_in6 *sa, const char *ip_str, 102f08c3bdfSopenharmony_ci uint16_t port)+ – Initialize socket address structure +sa+ using 103f08c3bdfSopenharmony_ci human-readable IPv6 address +ip_str+ and port number +port+ in host byte 104f08c3bdfSopenharmony_ci order. 105f08c3bdfSopenharmony_ci 106f08c3bdfSopenharmony_ci- +void tst_init_sockaddr_inet6_bin(struct sockaddr_in6 *sa, const struct 107f08c3bdfSopenharmony_ci in6_addr *ip_val, uint16_t port)+ – Initialize socket address structure +sa+ 108f08c3bdfSopenharmony_ci using binary IPv6 address +ip_val+ and port number +port+, both in host byte 109f08c3bdfSopenharmony_ci order. 110f08c3bdfSopenharmony_ci 111f08c3bdfSopenharmony_ci.Example Usage 112f08c3bdfSopenharmony_ci[source,c] 113f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 114f08c3bdfSopenharmony_ci 115f08c3bdfSopenharmony_ci#include <sys/socket.h> 116f08c3bdfSopenharmony_ci#include <netinet/in.h> 117f08c3bdfSopenharmony_ci 118f08c3bdfSopenharmony_ci#include "tst_test.h" 119f08c3bdfSopenharmony_ci#include "tst_safe_net.h" 120f08c3bdfSopenharmony_ci#include "tst_net.h" 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_cistatic int sockfd = -1; 123f08c3bdfSopenharmony_ci 124f08c3bdfSopenharmony_cistatic void setup(void) 125f08c3bdfSopenharmony_ci{ 126f08c3bdfSopenharmony_ci struct sockaddr_in addr; 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_ci tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0); 129f08c3bdfSopenharmony_ci sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 130f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096); 131f08c3bdfSopenharmony_ci SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 132f08c3bdfSopenharmony_ci SAFE_LISTEN(sockfd, 8); 133f08c3bdfSopenharmony_ci} 134f08c3bdfSopenharmony_ci 135f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci2 Configuring network devices 138f08c3bdfSopenharmony_ci----------------------------- 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_ci+#include "tst_netdevice.h"+ 141f08c3bdfSopenharmony_ci 142f08c3bdfSopenharmony_ciWhen opening a localhost socket isn't enough and the test needs special device 143f08c3bdfSopenharmony_cior routing configuration, the netdevice library can create the required network 144f08c3bdfSopenharmony_cisetup without calling external programs. Internally, the netdevice functions 145f08c3bdfSopenharmony_ciuse a rtnetlink socket to communicate with the kernel. 146f08c3bdfSopenharmony_ci 147f08c3bdfSopenharmony_ciAll of these functions will call +tst_brk()+ on failure, unless stated 148f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup 149f08c3bdfSopenharmony_cistage. 150f08c3bdfSopenharmony_ci 151f08c3bdfSopenharmony_ci2.1 Network device management 152f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 153f08c3bdfSopenharmony_ci 154f08c3bdfSopenharmony_ci- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ – Returns the device index for 155f08c3bdfSopenharmony_ci the given device name, or -1 on error. 156f08c3bdfSopenharmony_ci 157f08c3bdfSopenharmony_ci- +int NETDEV_SET_STATE(const char *ifname, int up)+ – Enable or disable a 158f08c3bdfSopenharmony_ci network device +ifname+. Returns 0 on success, -1 on error. 159f08c3bdfSopenharmony_ci 160f08c3bdfSopenharmony_ci- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ – Creates a 161f08c3bdfSopenharmony_ci connected pair of virtual network devices with given device names. Returns 1 162f08c3bdfSopenharmony_ci on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your 163f08c3bdfSopenharmony_ci test calls this function. 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_ci- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates 166f08c3bdfSopenharmony_ci a new network device named +ifname+ of specified device type. Returns 1 on 167f08c3bdfSopenharmony_ci success, 0 on error. 168f08c3bdfSopenharmony_ci 169f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ – Removes network device 170f08c3bdfSopenharmony_ci +ifname+. Returns 1 on success, 0 on error. 171f08c3bdfSopenharmony_ci 172f08c3bdfSopenharmony_ci2.2 Network address management 173f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void 176f08c3bdfSopenharmony_ci *address, unsigned int prefix, size_t addrlen, unsigned int flags)+ – Adds 177f08c3bdfSopenharmony_ci new address to network device +ifname+. This is a low-level function which 178f08c3bdfSopenharmony_ci allows setting any type of address. You must specify the protocol +family+, 179f08c3bdfSopenharmony_ci address length in bytes (+addrlen+) and network prefix length (+prefix+). The 180f08c3bdfSopenharmony_ci +address+ itself must be in binary representation in network byte order. You 181f08c3bdfSopenharmony_ci can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success, 182f08c3bdfSopenharmony_ci 0 on error. 183f08c3bdfSopenharmony_ci 184f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned 185f08c3bdfSopenharmony_ci int prefix, unsigned int flags)+ – Adds new IPv4 address to network device 186f08c3bdfSopenharmony_ci +ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+. 187f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. 188f08c3bdfSopenharmony_ci 189f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const 190f08c3bdfSopenharmony_ci void *address, size_t addrlen)+ – Removes the specified address from network 191f08c3bdfSopenharmony_ci device +ifname+. Parameters have the same meaning as in 192f08c3bdfSopenharmony_ci +NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error. 193f08c3bdfSopenharmony_ci 194f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+ – 195f08c3bdfSopenharmony_ci Removes specified IPv4 +address+ (in network byte order) from network device 196f08c3bdfSopenharmony_ci +ifname+. Returns 1 on success, 0 on error. 197f08c3bdfSopenharmony_ci 198f08c3bdfSopenharmony_ci2.3 Network namespace device assignment 199f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 200f08c3bdfSopenharmony_ci 201f08c3bdfSopenharmony_ciWARNING: Moving a network device to another namespace will erase previous 202f08c3bdfSopenharmony_ci configuration. Move the device to the correct namespace first, then 203f08c3bdfSopenharmony_ci configure it. 204f08c3bdfSopenharmony_ci 205f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ – Moves network 206f08c3bdfSopenharmony_ci device +ifname+ to network namespace designated by open file descriptor 207f08c3bdfSopenharmony_ci +nsfd+. Returns 1 on success, 0 on error. 208f08c3bdfSopenharmony_ci 209f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ – Moves network 210f08c3bdfSopenharmony_ci device +ifname+ to the network namespace currently used by process +nspid+. 211f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. 212f08c3bdfSopenharmony_ci 213f08c3bdfSopenharmony_ci2.4 Routing table management 214f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 215f08c3bdfSopenharmony_ci 216f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void 217f08c3bdfSopenharmony_ci *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr, 218f08c3bdfSopenharmony_ci unsigned int dstprefix, size_t dstlen, const void *gateway, size_t 219f08c3bdfSopenharmony_ci gatewaylen)+ – Adds new route to the main routing table. This is a low-level 220f08c3bdfSopenharmony_ci function which allows creating routes for any protocol. You must specify the 221f08c3bdfSopenharmony_ci protocol +family+ and either network device name +ifname+ or +gateway+ 222f08c3bdfSopenharmony_ci address. Both packet source address +srcaddr+ and destination address 223f08c3bdfSopenharmony_ci +dstaddr+ are optional. You must also specify the corresponding length 224f08c3bdfSopenharmony_ci and prefix argument for any address which is not +NULL+. All addresses must 225f08c3bdfSopenharmony_ci be in binary representation in network byte order. Returns 1 on success, 226f08c3bdfSopenharmony_ci 0 on error. 227f08c3bdfSopenharmony_ci 228f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned 229f08c3bdfSopenharmony_ci int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t 230f08c3bdfSopenharmony_ci gateway)+ – Adds new IPv4 route to the main routing table. Parameters have 231f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set 232f08c3bdfSopenharmony_ci explicit +gateway+ address, set it to 0. If the routing rule should ignore 233f08c3bdfSopenharmony_ci the source or destination address, set the corresponding prefix argument 234f08c3bdfSopenharmony_ci to 0. Returns 1 on success, 0 on error. 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void 237f08c3bdfSopenharmony_ci *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr, 238f08c3bdfSopenharmony_ci unsigned int dstprefix, size_t dstlen, const void *gateway, size_t 239f08c3bdfSopenharmony_ci gatewaylen)+ – Removes a route from the main routing table. Parameters have 240f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on 241f08c3bdfSopenharmony_ci error. 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr, 244f08c3bdfSopenharmony_ci unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t 245f08c3bdfSopenharmony_ci gateway)+ – Removes IPv4 route from the main routing table. Parameters have 246f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success, 247f08c3bdfSopenharmony_ci 0 on error. 248f08c3bdfSopenharmony_ci 249f08c3bdfSopenharmony_ci.Example Usage 250f08c3bdfSopenharmony_ci[source,c] 251f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 252f08c3bdfSopenharmony_ci#include <arpa/inet.h> 253f08c3bdfSopenharmony_ci#include <linux/if_addr.h> 254f08c3bdfSopenharmony_ci#include "tst_test.h" 255f08c3bdfSopenharmony_ci#include "tst_netdevice.h" 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_ci... 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_cistatic void setup(void) 260f08c3bdfSopenharmony_ci{ 261f08c3bdfSopenharmony_ci CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2"); 262f08c3bdfSopenharmony_ci NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK, 263f08c3bdfSopenharmony_ci IFA_F_NOPREFIXROUTE); 264f08c3bdfSopenharmony_ci NETDEV_SET_STATE("ltp_veth2", 1); 265f08c3bdfSopenharmony_ci NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0); 266f08c3bdfSopenharmony_ci 267f08c3bdfSopenharmony_ci NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK, 268f08c3bdfSopenharmony_ci IFA_F_NOPREFIXROUTE); 269f08c3bdfSopenharmony_ci NETDEV_SET_STATE("ltp_veth1", 1); 270f08c3bdfSopenharmony_ci NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0); 271f08c3bdfSopenharmony_ci ... 272f08c3bdfSopenharmony_ci} 273f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 274f08c3bdfSopenharmony_ci 275f08c3bdfSopenharmony_ci3 rtnetlink API 276f08c3bdfSopenharmony_ci--------------- 277f08c3bdfSopenharmony_ci 278f08c3bdfSopenharmony_ci+#include "tst_rtnetlink.h"+ 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ciThe rtnetlink library provides helper functions for constructing and sending 281f08c3bdfSopenharmony_ciarbitrary messages and parsing kernel responses. 282f08c3bdfSopenharmony_ci 283f08c3bdfSopenharmony_ciAll of the functions below will call +tst_brk()+ on failure, unless stated 284f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup 285f08c3bdfSopenharmony_cistage. 286f08c3bdfSopenharmony_ci 287f08c3bdfSopenharmony_ci3.1 Data structures 288f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~ 289f08c3bdfSopenharmony_ci 290f08c3bdfSopenharmony_ci[source,c] 291f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 292f08c3bdfSopenharmony_cistruct tst_rtnl_context; 293f08c3bdfSopenharmony_ci 294f08c3bdfSopenharmony_cistruct tst_rtnl_attr_list { 295f08c3bdfSopenharmony_ci unsigned short type; 296f08c3bdfSopenharmony_ci const void *data; 297f08c3bdfSopenharmony_ci ssize_t len; 298f08c3bdfSopenharmony_ci const struct tst_rtnl_attr_list *sublist; 299f08c3bdfSopenharmony_ci}; 300f08c3bdfSopenharmony_ci 301f08c3bdfSopenharmony_cistruct tst_rtnl_message { 302f08c3bdfSopenharmony_ci struct nlmsghdr *header; 303f08c3bdfSopenharmony_ci struct nlmsgerr *err; 304f08c3bdfSopenharmony_ci void *payload; 305f08c3bdfSopenharmony_ci size_t payload_size; 306f08c3bdfSopenharmony_ci}; 307f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 308f08c3bdfSopenharmony_ci 309f08c3bdfSopenharmony_ci+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for 310f08c3bdfSopenharmony_ciconstructing and sending arbitrary messages using the functions described 311f08c3bdfSopenharmony_cibelow. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using 312f08c3bdfSopenharmony_ci+RTNL_DESTROY_CONTEXT()+ when you're done with it. 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci+struct tst_rtnl_attr_list+ is a helper structure for defining complex 315f08c3bdfSopenharmony_cirtnetlink message attribute payloads, including nested attribute lists. Every 316f08c3bdfSopenharmony_cilist and sublist defined using this structure is terminated by item with 317f08c3bdfSopenharmony_cinegative +len+. 318f08c3bdfSopenharmony_ci 319f08c3bdfSopenharmony_ci- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+. 320f08c3bdfSopenharmony_ci 321f08c3bdfSopenharmony_ci- +data+ contains arbitrary attribute payload. 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+, 324f08c3bdfSopenharmony_ci set +len+ to 0. The last item in a list or sublist must have negative length. 325f08c3bdfSopenharmony_ci 326f08c3bdfSopenharmony_ci- +sublist+ contains a nested attribute list which will be appended after 327f08c3bdfSopenharmony_ci +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be 328f08c3bdfSopenharmony_ci calculated automatically with proper alignment, do _not_ add the sublist size 329f08c3bdfSopenharmony_ci to the +len+ field. If you do not want to add nested attributes, set 330f08c3bdfSopenharmony_ci +sublist+ to +NULL+. 331f08c3bdfSopenharmony_ci 332f08c3bdfSopenharmony_ci+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink 333f08c3bdfSopenharmony_cimessages received from the kernel. +RTNL_RECV()+ returns an array of these 334f08c3bdfSopenharmony_cistructures with the last item having +NULL+ in the +header+ field. Call 335f08c3bdfSopenharmony_ci+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+. 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ci- +header+ is the netlink header structure of the message. +NULL+ in the header 338f08c3bdfSopenharmony_ci field terminates a list of messages. 339f08c3bdfSopenharmony_ci 340f08c3bdfSopenharmony_ci- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+ 341f08c3bdfSopenharmony_ci for all other message types. 342f08c3bdfSopenharmony_ci 343f08c3bdfSopenharmony_ci- +payload+ is a pointer to message data. 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_ci- +payload_size+ is the length of +payload+ data in bytes. 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci3.2 Sending and receiving messages 348f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 349f08c3bdfSopenharmony_ci 350f08c3bdfSopenharmony_ci- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new 351f08c3bdfSopenharmony_ci rtnetlink communication context for use with the functions described below. 352f08c3bdfSopenharmony_ci Returns +NULL+ on error. 353f08c3bdfSopenharmony_ci 354f08c3bdfSopenharmony_ci- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of 355f08c3bdfSopenharmony_ci messages returned by +RTNL_RECV()+. 356f08c3bdfSopenharmony_ci 357f08c3bdfSopenharmony_ci- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a 358f08c3bdfSopenharmony_ci communication context created by +RTNL_CREATE_CONTEXT()+. 359f08c3bdfSopenharmony_ci 360f08c3bdfSopenharmony_ci- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting 361f08c3bdfSopenharmony_ci in +ctx+ buffer to the kernel. If there are multiple messages to send, a new 362f08c3bdfSopenharmony_ci +NLMSG_DONE+ message will be added automatically. Returns the number of 363f08c3bdfSopenharmony_ci bytes sent on success. Return 0 or negative value on error. 364f08c3bdfSopenharmony_ci 365f08c3bdfSopenharmony_ci- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages 366f08c3bdfSopenharmony_ci just like +RTNL_SEND()+, then receives the response from the kernel and 367f08c3bdfSopenharmony_ci validates results of requests sent with the +NLM_F_ACK+ flag. This function 368f08c3bdfSopenharmony_ci calls +tst_brk()+ as usual if communication fails but it will return error 369f08c3bdfSopenharmony_ci status without terminating the test if one of the received messages contains 370f08c3bdfSopenharmony_ci error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return 371f08c3bdfSopenharmony_ci value. 372f08c3bdfSopenharmony_ci 373f08c3bdfSopenharmony_ci- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes 374f08c3bdfSopenharmony_ci available to read from the rtnetlink socket (timeout: 1 second). Returns 1 375f08c3bdfSopenharmony_ci if there is data to read, 0 on timeout or -1 on error. 376f08c3bdfSopenharmony_ci 377f08c3bdfSopenharmony_ci- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives 378f08c3bdfSopenharmony_ci rtnetlink messages from the kernel. The messages are received in non-blocking 379f08c3bdfSopenharmony_ci mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of 380f08c3bdfSopenharmony_ci partially parsed messages terminated by an item with +NULL+ in the +header+ 381f08c3bdfSopenharmony_ci field. On error or when there are no messages to receive, returns +NULL+. 382f08c3bdfSopenharmony_ci Call +RTNL_FREE_MESSAGE()+ to free the returned data. 383f08c3bdfSopenharmony_ci 384f08c3bdfSopenharmony_ci- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message 385f08c3bdfSopenharmony_ci *response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag. 386f08c3bdfSopenharmony_ci Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and 387f08c3bdfSopenharmony_ci +RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent 388f08c3bdfSopenharmony_ci result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag 389f08c3bdfSopenharmony_ci have a corresponding message in +response+ and the error code is 0. If any 390f08c3bdfSopenharmony_ci of the expected response messages is missing, this function will call 391f08c3bdfSopenharmony_ci +tst_brk()+ (or return 0 during test cleanup phase). If any of the response 392f08c3bdfSopenharmony_ci messages has non-zero error code, this function will return 0 and store the 393f08c3bdfSopenharmony_ci first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped 394f08c3bdfSopenharmony_ci just like regular libc +errno+). 395f08c3bdfSopenharmony_ci 396f08c3bdfSopenharmony_ci3.3 Creating messages 397f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~ 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr 400f08c3bdfSopenharmony_ci *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink 401f08c3bdfSopenharmony_ci message to +ctx+ buffer. You need to provide message +header+ and optional 402f08c3bdfSopenharmony_ci +payload+. +payload_size+ is the size of +payload+ data in bytes. If you 403f08c3bdfSopenharmony_ci don't want to add any payload data, set +payload+ to +NULL+ and 404f08c3bdfSopenharmony_ci +payload_size+ to 0. This function will automatically fill the +nlmsg_len+, 405f08c3bdfSopenharmony_ci +nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need 406f08c3bdfSopenharmony_ci to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed. 407f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. Note that the first call of 408f08c3bdfSopenharmony_ci +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+ 409f08c3bdfSopenharmony_ci and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+. 410f08c3bdfSopenharmony_ci 411f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const 412f08c3bdfSopenharmony_ci void *data, unsigned short len)+ – Adds new attribute to the last message 413f08c3bdfSopenharmony_ci in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute 414f08c3bdfSopenharmony_ci +type+ which will be stored in +struct rtattr.rta_type+, optional payload 415f08c3bdfSopenharmony_ci +data+ and payload size +len+ in bytes. If you don't want to add any payload, 416f08c3bdfSopenharmony_ci set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error. 417f08c3bdfSopenharmony_ci 418f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type, 419f08c3bdfSopenharmony_ci const char *data)+ – Adds new string attribute to the last message in +ctx+ 420f08c3bdfSopenharmony_ci buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+, 421f08c3bdfSopenharmony_ci except the payload length is calculated using +strlen()+. 422f08c3bdfSopenharmony_ci 423f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct 424f08c3bdfSopenharmony_ci tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message 425f08c3bdfSopenharmony_ci in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and 426f08c3bdfSopenharmony_ci +RTNL_ADD_MESSAGE()+ above. Returns the number of added attributes on 427f08c3bdfSopenharmony_ci success (nested attributes are not counted), -1 on error. 428f08c3bdfSopenharmony_ci 429f08c3bdfSopenharmony_ci.Example Usage 430f08c3bdfSopenharmony_ci[source,c] 431f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 432f08c3bdfSopenharmony_ci#include <asm/types.h> 433f08c3bdfSopenharmony_ci#include <linux/netlink.h> 434f08c3bdfSopenharmony_ci#include <linux/rtnetlink.h> 435f08c3bdfSopenharmony_ci#include <sys/socket.h> 436f08c3bdfSopenharmony_ci#include <netinet/in.h> 437f08c3bdfSopenharmony_ci#include <arpa/inet.h> 438f08c3bdfSopenharmony_ci 439f08c3bdfSopenharmony_ci#include "tst_test.h" 440f08c3bdfSopenharmony_ci#include "tst_rtnetlink.h" 441f08c3bdfSopenharmony_ci#include "tst_netdevice.h" 442f08c3bdfSopenharmony_ci 443f08c3bdfSopenharmony_ci... 444f08c3bdfSopenharmony_ci 445f08c3bdfSopenharmony_civoid setup(void) 446f08c3bdfSopenharmony_ci{ 447f08c3bdfSopenharmony_ci struct tst_rtnl_context *ctx; 448f08c3bdfSopenharmony_ci int index, ret; 449f08c3bdfSopenharmony_ci in_addr_t addr; 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ci struct nlmsghdr header = { 452f08c3bdfSopenharmony_ci .nlmsg_type = RTM_NEWADDR, 453f08c3bdfSopenharmony_ci .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | 454f08c3bdfSopenharmony_ci NLM_F_EXCL 455f08c3bdfSopenharmony_ci }; 456f08c3bdfSopenharmony_ci 457f08c3bdfSopenharmony_ci struct ifaddrmsg info = { 458f08c3bdfSopenharmony_ci .ifa_family = AF_INET, 459f08c3bdfSopenharmony_ci .ifa_prefixlen = 24 460f08c3bdfSopenharmony_ci }; 461f08c3bdfSopenharmony_ci 462f08c3bdfSopenharmony_ci index = NETDEV_INDEX_BY_NAME("ltp_veth1"); 463f08c3bdfSopenharmony_ci info.ifa_index = index; 464f08c3bdfSopenharmony_ci 465f08c3bdfSopenharmony_ci ctx = RTNL_CREATE_CONTEXT(); 466f08c3bdfSopenharmony_ci RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info)); 467f08c3bdfSopenharmony_ci addr = inet_addr("192.168.123.45"); 468f08c3bdfSopenharmony_ci RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr)); 469f08c3bdfSopenharmony_ci ret = RTNL_SEND_VALIDATE(ctx); 470f08c3bdfSopenharmony_ci RTNL_DESTROY_CONTEXT(ctx); 471f08c3bdfSopenharmony_ci 472f08c3bdfSopenharmony_ci if (!ret) { 473f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to set ltp_veth1 address"); 474f08c3bdfSopenharmony_ci } 475f08c3bdfSopenharmony_ci} 476f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 477