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_ciExample Usage 112f08c3bdfSopenharmony_ci+++++++++++++ 113f08c3bdfSopenharmony_ci[source,c] 114f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci#include <sys/socket.h> 117f08c3bdfSopenharmony_ci#include <netinet/in.h> 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci#include "tst_test.h" 120f08c3bdfSopenharmony_ci#include "tst_safe_net.h" 121f08c3bdfSopenharmony_ci#include "tst_net.h" 122f08c3bdfSopenharmony_ci 123f08c3bdfSopenharmony_cistatic int sockfd = -1; 124f08c3bdfSopenharmony_ci 125f08c3bdfSopenharmony_cistatic void setup(void) 126f08c3bdfSopenharmony_ci{ 127f08c3bdfSopenharmony_ci struct sockaddr_in addr; 128f08c3bdfSopenharmony_ci 129f08c3bdfSopenharmony_ci tst_init_sockaddr_inet_bin(&addr, INADDR_ANY, 0); 130f08c3bdfSopenharmony_ci sockfd = SAFE_SOCKET(AF_INET, SOCK_STREAM, 0); 131f08c3bdfSopenharmony_ci SAFE_SETSOCKOPT_INT(sockfd, SOL_SOCKET, SO_SNDBUF, 4096); 132f08c3bdfSopenharmony_ci SAFE_BIND(sockfd, (struct sockaddr *)&addr, sizeof(addr)); 133f08c3bdfSopenharmony_ci SAFE_LISTEN(sockfd, 8); 134f08c3bdfSopenharmony_ci} 135f08c3bdfSopenharmony_ci 136f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci2 Configuring network devices 139f08c3bdfSopenharmony_ci----------------------------- 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci+#include "tst_netdevice.h"+ 142f08c3bdfSopenharmony_ci 143f08c3bdfSopenharmony_ciWhen opening a localhost socket isn't enough and the test needs special device 144f08c3bdfSopenharmony_cior routing configuration, the netdevice library can create the required network 145f08c3bdfSopenharmony_cisetup without calling external programs. Internally, the netdevice functions 146f08c3bdfSopenharmony_ciuse a rtnetlink socket to communicate with the kernel. 147f08c3bdfSopenharmony_ci 148f08c3bdfSopenharmony_ciAll of these functions will call +tst_brk()+ on failure, unless stated 149f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup 150f08c3bdfSopenharmony_cistage. 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci2.1 Network device management 153f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 154f08c3bdfSopenharmony_ci 155f08c3bdfSopenharmony_ci- +int NETDEV_INDEX_BY_NAME(const char *ifname)+ – Returns the device index for 156f08c3bdfSopenharmony_ci the given device name, or -1 on error. 157f08c3bdfSopenharmony_ci 158f08c3bdfSopenharmony_ci- +int NETDEV_SET_STATE(const char *ifname, int up)+ – Enable or disable a 159f08c3bdfSopenharmony_ci network device +ifname+. Returns 0 on success, -1 on error. 160f08c3bdfSopenharmony_ci 161f08c3bdfSopenharmony_ci- +int CREATE_VETH_PAIR(const char *ifname1, const char *ifname2)+ – Creates a 162f08c3bdfSopenharmony_ci connected pair of virtual network devices with given device names. Returns 1 163f08c3bdfSopenharmony_ci on success, 0 on error. Add +"CONFIG_VETH"+ to +test.needs_kconfigs+ if your 164f08c3bdfSopenharmony_ci test calls this function. 165f08c3bdfSopenharmony_ci 166f08c3bdfSopenharmony_ci- +int NETDEV_ADD_DEVICE(const char *ifname, const char *devtype)+ - Creates 167f08c3bdfSopenharmony_ci a new network device named +ifname+ of specified device type. Returns 1 on 168f08c3bdfSopenharmony_ci success, 0 on error. 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_DEVICE(const char *ifname)+ – Removes network device 171f08c3bdfSopenharmony_ci +ifname+. Returns 1 on success, 0 on error. 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci2.2 Network address management 174f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 175f08c3bdfSopenharmony_ci 176f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS(const char \*ifname, unsigned int family, const void 177f08c3bdfSopenharmony_ci *address, unsigned int prefix, size_t addrlen, unsigned int flags)+ – Adds 178f08c3bdfSopenharmony_ci new address to network device +ifname+. This is a low-level function which 179f08c3bdfSopenharmony_ci allows setting any type of address. You must specify the protocol +family+, 180f08c3bdfSopenharmony_ci address length in bytes (+addrlen+) and network prefix length (+prefix+). The 181f08c3bdfSopenharmony_ci +address+ itself must be in binary representation in network byte order. You 182f08c3bdfSopenharmony_ci can also pass rtnetlink flags from the +IFA_F_*+ group. Returns 1 on success, 183f08c3bdfSopenharmony_ci 0 on error. 184f08c3bdfSopenharmony_ci 185f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ADDRESS_INET(const char *ifname, in_addr_t address, unsigned 186f08c3bdfSopenharmony_ci int prefix, unsigned int flags)+ – Adds new IPv4 address to network device 187f08c3bdfSopenharmony_ci +ifname+. Parameters have the same meaning as in +NETDEV_ADD_ADDRESS()+. 188f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. 189f08c3bdfSopenharmony_ci 190f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS(const char *ifname, unsigned int family, const 191f08c3bdfSopenharmony_ci void *address, size_t addrlen)+ – Removes the specified address from network 192f08c3bdfSopenharmony_ci device +ifname+. Parameters have the same meaning as in 193f08c3bdfSopenharmony_ci +NETDEV_ADD_ADDRESS()+. Returns 1 on success, 0 on error. 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ADDRESS_INET(const char *ifname, in_addr_t address)+ – 196f08c3bdfSopenharmony_ci Removes specified IPv4 +address+ (in network byte order) from network device 197f08c3bdfSopenharmony_ci +ifname+. Returns 1 on success, 0 on error. 198f08c3bdfSopenharmony_ci 199f08c3bdfSopenharmony_ci2.3 Network namespace device assignment 200f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_ciWARNING: Moving a network device to another namespace will erase previous 203f08c3bdfSopenharmony_ci configuration. Move the device to the correct namespace first, then 204f08c3bdfSopenharmony_ci configure it. 205f08c3bdfSopenharmony_ci 206f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_FD(const char *ifname, int nsfd)+ – Moves network 207f08c3bdfSopenharmony_ci device +ifname+ to network namespace designated by open file descriptor 208f08c3bdfSopenharmony_ci +nsfd+. Returns 1 on success, 0 on error. 209f08c3bdfSopenharmony_ci 210f08c3bdfSopenharmony_ci- +int NETDEV_CHANGE_NS_PID(const char *ifname, pid_t nspid)+ – Moves network 211f08c3bdfSopenharmony_ci device +ifname+ to the network namespace currently used by process +nspid+. 212f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. 213f08c3bdfSopenharmony_ci 214f08c3bdfSopenharmony_ci2.4 Routing table management 215f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 216f08c3bdfSopenharmony_ci 217f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE(const char *ifname, unsigned int family, const void 218f08c3bdfSopenharmony_ci *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr, 219f08c3bdfSopenharmony_ci unsigned int dstprefix, size_t dstlen, const void *gateway, size_t 220f08c3bdfSopenharmony_ci gatewaylen)+ – Adds new route to the main routing table. This is a low-level 221f08c3bdfSopenharmony_ci function which allows creating routes for any protocol. You must specify the 222f08c3bdfSopenharmony_ci protocol +family+ and either network device name +ifname+ or +gateway+ 223f08c3bdfSopenharmony_ci address. Both packet source address +srcaddr+ and destination address 224f08c3bdfSopenharmony_ci +dstaddr+ are optional. You must also specify the corresponding length 225f08c3bdfSopenharmony_ci and prefix argument for any address which is not +NULL+. All addresses must 226f08c3bdfSopenharmony_ci be in binary representation in network byte order. Returns 1 on success, 227f08c3bdfSopenharmony_ci 0 on error. 228f08c3bdfSopenharmony_ci 229f08c3bdfSopenharmony_ci- +int NETDEV_ADD_ROUTE_INET(const char *ifname, in_addr_t srcaddr, unsigned 230f08c3bdfSopenharmony_ci int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t 231f08c3bdfSopenharmony_ci gateway)+ – Adds new IPv4 route to the main routing table. Parameters have 232f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE()+. If you do not want to set 233f08c3bdfSopenharmony_ci explicit +gateway+ address, set it to 0. If the routing rule should ignore 234f08c3bdfSopenharmony_ci the source or destination address, set the corresponding prefix argument 235f08c3bdfSopenharmony_ci to 0. Returns 1 on success, 0 on error. 236f08c3bdfSopenharmony_ci 237f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE(const char *ifname, unsigned int family, const void 238f08c3bdfSopenharmony_ci *srcaddr, unsigned int srcprefix, size_t srclen, const void *dstaddr, 239f08c3bdfSopenharmony_ci unsigned int dstprefix, size_t dstlen, const void *gateway, size_t 240f08c3bdfSopenharmony_ci gatewaylen)+ – Removes a route from the main routing table. Parameters have 241f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE()+. Returns 1 on success, 0 on 242f08c3bdfSopenharmony_ci error. 243f08c3bdfSopenharmony_ci 244f08c3bdfSopenharmony_ci- +int NETDEV_REMOVE_ROUTE_INET(const char *ifname, in_addr_t srcaddr, 245f08c3bdfSopenharmony_ci unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix, in_addr_t 246f08c3bdfSopenharmony_ci gateway)+ – Removes IPv4 route from the main routing table. Parameters have 247f08c3bdfSopenharmony_ci the same meaning as in +NETDEV_ADD_ROUTE_INET()+. Returns 1 on success, 248f08c3bdfSopenharmony_ci 0 on error. 249f08c3bdfSopenharmony_ci 250f08c3bdfSopenharmony_ciExample Usage 251f08c3bdfSopenharmony_ci+++++++++++++ 252f08c3bdfSopenharmony_ci[source,c] 253f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 254f08c3bdfSopenharmony_ci#include <arpa/inet.h> 255f08c3bdfSopenharmony_ci#include <linux/if_addr.h> 256f08c3bdfSopenharmony_ci#include "tst_test.h" 257f08c3bdfSopenharmony_ci#include "tst_netdevice.h" 258f08c3bdfSopenharmony_ci 259f08c3bdfSopenharmony_ci... 260f08c3bdfSopenharmony_ci 261f08c3bdfSopenharmony_cistatic void setup(void) 262f08c3bdfSopenharmony_ci{ 263f08c3bdfSopenharmony_ci CREATE_VETH_PAIR("ltp_veth1", "ltp_veth2"); 264f08c3bdfSopenharmony_ci NETDEV_ADD_ADDRESS_INET("ltp_veth2", htonl(DSTADDR), NETMASK, 265f08c3bdfSopenharmony_ci IFA_F_NOPREFIXROUTE); 266f08c3bdfSopenharmony_ci NETDEV_SET_STATE("ltp_veth2", 1); 267f08c3bdfSopenharmony_ci NETDEV_ADD_ROUTE_INET("ltp_veth2", 0, 0, htonl(SRCNET), NETMASK, 0); 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_ci NETDEV_ADD_ADDRESS_INET("ltp_veth1", htonl(SRCADDR), NETMASK, 270f08c3bdfSopenharmony_ci IFA_F_NOPREFIXROUTE); 271f08c3bdfSopenharmony_ci NETDEV_SET_STATE("ltp_veth1", 1); 272f08c3bdfSopenharmony_ci NETDEV_ADD_ROUTE_INET("ltp_veth1", 0, 0, htonl(DSTNET), NETMASK, 0); 273f08c3bdfSopenharmony_ci ... 274f08c3bdfSopenharmony_ci} 275f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 276f08c3bdfSopenharmony_ci 277f08c3bdfSopenharmony_ci3 rtnetlink API 278f08c3bdfSopenharmony_ci--------------- 279f08c3bdfSopenharmony_ci 280f08c3bdfSopenharmony_ci+#include "tst_rtnetlink.h"+ 281f08c3bdfSopenharmony_ci 282f08c3bdfSopenharmony_ciThe rtnetlink library provides helper functions for constructing and sending 283f08c3bdfSopenharmony_ciarbitrary messages and parsing kernel responses. 284f08c3bdfSopenharmony_ci 285f08c3bdfSopenharmony_ciAll of the functions below will call +tst_brk()+ on failure, unless stated 286f08c3bdfSopenharmony_ciotherwise. Error values described below are returned only during test cleanup 287f08c3bdfSopenharmony_cistage. 288f08c3bdfSopenharmony_ci 289f08c3bdfSopenharmony_ci3.1 Data structures 290f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~ 291f08c3bdfSopenharmony_ci 292f08c3bdfSopenharmony_ci[source,c] 293f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 294f08c3bdfSopenharmony_cistruct tst_rtnl_context; 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_cistruct tst_rtnl_attr_list { 297f08c3bdfSopenharmony_ci unsigned short type; 298f08c3bdfSopenharmony_ci const void *data; 299f08c3bdfSopenharmony_ci ssize_t len; 300f08c3bdfSopenharmony_ci const struct tst_rtnl_attr_list *sublist; 301f08c3bdfSopenharmony_ci}; 302f08c3bdfSopenharmony_ci 303f08c3bdfSopenharmony_cistruct tst_rtnl_message { 304f08c3bdfSopenharmony_ci struct nlmsghdr *header; 305f08c3bdfSopenharmony_ci struct nlmsgerr *err; 306f08c3bdfSopenharmony_ci void *payload; 307f08c3bdfSopenharmony_ci size_t payload_size; 308f08c3bdfSopenharmony_ci}; 309f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 310f08c3bdfSopenharmony_ci 311f08c3bdfSopenharmony_ci+struct tst_rtnl_context+ is an opaque rtnetlink socket with buffer for 312f08c3bdfSopenharmony_ciconstructing and sending arbitrary messages using the functions described 313f08c3bdfSopenharmony_cibelow. Create a new context using +RTNL_CREATE_CONTEXT()+, then free it using 314f08c3bdfSopenharmony_ci+RTNL_DESTROY_CONTEXT()+ when you're done with it. 315f08c3bdfSopenharmony_ci 316f08c3bdfSopenharmony_ci+struct tst_rtnl_attr_list+ is a helper structure for defining complex 317f08c3bdfSopenharmony_cirtnetlink message attribute payloads, including nested attribute lists. Every 318f08c3bdfSopenharmony_cilist and sublist defined using this structure is terminated by item with 319f08c3bdfSopenharmony_cinegative +len+. 320f08c3bdfSopenharmony_ci 321f08c3bdfSopenharmony_ci- +type+ is the attribute type that will be stored in +struct rtattr.rta_type+. 322f08c3bdfSopenharmony_ci 323f08c3bdfSopenharmony_ci- +data+ contains arbitrary attribute payload. 324f08c3bdfSopenharmony_ci 325f08c3bdfSopenharmony_ci- +len+ contains length of the +data+ attribute in bytes. If +data+ is +NULL+, 326f08c3bdfSopenharmony_ci set +len+ to 0. The last item in a list or sublist must have negative length. 327f08c3bdfSopenharmony_ci 328f08c3bdfSopenharmony_ci- +sublist+ contains a nested attribute list which will be appended after 329f08c3bdfSopenharmony_ci +data+ as part of the attribute payload. +struct rtattr.rta_len+ will be 330f08c3bdfSopenharmony_ci calculated automatically with proper alignment, do _not_ add the sublist size 331f08c3bdfSopenharmony_ci to the +len+ field. If you do not want to add nested attributes, set 332f08c3bdfSopenharmony_ci +sublist+ to +NULL+. 333f08c3bdfSopenharmony_ci 334f08c3bdfSopenharmony_ci+struct tst_rtnl_message+ is a structure holding partially parsed rtnetlink 335f08c3bdfSopenharmony_cimessages received from the kernel. +RTNL_RECV()+ returns an array of these 336f08c3bdfSopenharmony_cistructures with the last item having +NULL+ in the +header+ field. Call 337f08c3bdfSopenharmony_ci+RTNL_FREE_MESSAGE()+ to free a message list returned by +RTNL_RECV()+. 338f08c3bdfSopenharmony_ci 339f08c3bdfSopenharmony_ci- +header+ is the netlink header structure of the message. +NULL+ in the header 340f08c3bdfSopenharmony_ci field terminates a list of messages. 341f08c3bdfSopenharmony_ci 342f08c3bdfSopenharmony_ci- +err+ points to the payload of +NLMSG_ERROR+ messages. It is set to +NULL+ 343f08c3bdfSopenharmony_ci for all other message types. 344f08c3bdfSopenharmony_ci 345f08c3bdfSopenharmony_ci- +payload+ is a pointer to message data. 346f08c3bdfSopenharmony_ci 347f08c3bdfSopenharmony_ci- +payload_size+ is the length of +payload+ data in bytes. 348f08c3bdfSopenharmony_ci 349f08c3bdfSopenharmony_ci3.2 Sending and receiving messages 350f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 351f08c3bdfSopenharmony_ci 352f08c3bdfSopenharmony_ci- +struct tst_rtnl_context *RTNL_CREATE_CONTEXT(void)+ – Creates a new 353f08c3bdfSopenharmony_ci rtnetlink communication context for use with the functions described below. 354f08c3bdfSopenharmony_ci Returns +NULL+ on error. 355f08c3bdfSopenharmony_ci 356f08c3bdfSopenharmony_ci- +void RTNL_FREE_MESSAGE(struct tst_rtnl_message *msg)+ – Frees an array of 357f08c3bdfSopenharmony_ci messages returned by +RTNL_RECV()+. 358f08c3bdfSopenharmony_ci 359f08c3bdfSopenharmony_ci- +void RTNL_DESTROY_CONTEXT(struct tst_rtnl_context *ctx)+ – Closes a 360f08c3bdfSopenharmony_ci communication context created by +RTNL_CREATE_CONTEXT()+. 361f08c3bdfSopenharmony_ci 362f08c3bdfSopenharmony_ci- +int RTNL_SEND(struct tst_rtnl_context *ctx)+ – Sends all messages waiting 363f08c3bdfSopenharmony_ci in +ctx+ buffer to the kernel. If there are multiple messages to send, a new 364f08c3bdfSopenharmony_ci +NLMSG_DONE+ message will be added automatically. Returns the number of 365f08c3bdfSopenharmony_ci bytes sent on success. Return 0 or negative value on error. 366f08c3bdfSopenharmony_ci 367f08c3bdfSopenharmony_ci- +int RTNL_SEND_VALIDATE(struct tst_rtnl_context *ctx)+ – Sends all messages 368f08c3bdfSopenharmony_ci just like +RTNL_SEND()+, then receives the response from the kernel and 369f08c3bdfSopenharmony_ci validates results of requests sent with the +NLM_F_ACK+ flag. This function 370f08c3bdfSopenharmony_ci calls +tst_brk()+ as usual if communication fails but it will return error 371f08c3bdfSopenharmony_ci status without terminating the test if one of the received messages contains 372f08c3bdfSopenharmony_ci error code. See +RTNL_CHECK_ACKS()+ below for explanation of the return 373f08c3bdfSopenharmony_ci value. 374f08c3bdfSopenharmony_ci 375f08c3bdfSopenharmony_ci- +int RTNL_WAIT(struct tst_rtnl_context *ctx)+ – Waits until data becomes 376f08c3bdfSopenharmony_ci available to read from the rtnetlink socket (timeout: 1 second). Returns 1 377f08c3bdfSopenharmony_ci if there is data to read, 0 on timeout or -1 on error. 378f08c3bdfSopenharmony_ci 379f08c3bdfSopenharmony_ci- +struct tst_rtnl_message *RTNL_RECV(struct tst_rtnl_context *ctx)+ – Receives 380f08c3bdfSopenharmony_ci rtnetlink messages from the kernel. The messages are received in non-blocking 381f08c3bdfSopenharmony_ci mode so calling +RTNL_WAIT()+ first is recommended. Returns an array of 382f08c3bdfSopenharmony_ci partially parsed messages terminated by an item with +NULL+ in the +header+ 383f08c3bdfSopenharmony_ci field. On error or when there are no messages to receive, returns +NULL+. 384f08c3bdfSopenharmony_ci Call +RTNL_FREE_MESSAGE()+ to free the returned data. 385f08c3bdfSopenharmony_ci 386f08c3bdfSopenharmony_ci- +int RTNL_CHECK_ACKS(struct tst_rtnl_context *ctx, struct tst_rtnl_message 387f08c3bdfSopenharmony_ci *response)+ – Validate results of requests sent with the +NLM_F_ACK+ flag. 388f08c3bdfSopenharmony_ci Do not call +RTNL_ADD_MESSAGE()+ between +RTNL_SEND()+ and 389f08c3bdfSopenharmony_ci +RTNL_CHECK_ACKS()+ because it will reset the state of +ctx+ and prevent 390f08c3bdfSopenharmony_ci result validation. Returns 1 if all messages sent with the +NLM_F_ACK+ flag 391f08c3bdfSopenharmony_ci have a corresponding message in +response+ and the error code is 0. If any 392f08c3bdfSopenharmony_ci of the expected response messages is missing, this function will call 393f08c3bdfSopenharmony_ci +tst_brk()+ (or return 0 during test cleanup phase). If any of the response 394f08c3bdfSopenharmony_ci messages has non-zero error code, this function will return 0 and store the 395f08c3bdfSopenharmony_ci first non-zero error code in global variable +tst_rtnl_errno+ (sign-flipped 396f08c3bdfSopenharmony_ci just like regular libc +errno+). 397f08c3bdfSopenharmony_ci 398f08c3bdfSopenharmony_ci3.3 Creating messages 399f08c3bdfSopenharmony_ci~~~~~~~~~~~~~~~~~~~~~ 400f08c3bdfSopenharmony_ci 401f08c3bdfSopenharmony_ci- +int RTNL_ADD_MESSAGE(struct tst_rtnl_context *ctx, const struct nlmsghdr 402f08c3bdfSopenharmony_ci *header, const void *payload, size_t payload_size)+ – Adds new rtnetlink 403f08c3bdfSopenharmony_ci message to +ctx+ buffer. You need to provide message +header+ and optional 404f08c3bdfSopenharmony_ci +payload+. +payload_size+ is the size of +payload+ data in bytes. If you 405f08c3bdfSopenharmony_ci don't want to add any payload data, set +payload+ to +NULL+ and 406f08c3bdfSopenharmony_ci +payload_size+ to 0. This function will automatically fill the +nlmsg_len+, 407f08c3bdfSopenharmony_ci +nlmsg_seq+ and +nlmsg_pid+ fields of the new message header. You don't need 408f08c3bdfSopenharmony_ci to set those. It'll also automatically add +NLM_F_MULTI+ flag when needed. 409f08c3bdfSopenharmony_ci Returns 1 on success, 0 on error. Note that the first call of 410f08c3bdfSopenharmony_ci +RTNL_ADD_MESSAGE()+ after +RTNL_SEND()+ will reset the state of +ctx+ 411f08c3bdfSopenharmony_ci and +RTNL_CHECK_ACKS()+ will not work correctly until the next +RTNL_SEND()+. 412f08c3bdfSopenharmony_ci 413f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR(struct tst_rtnl_context *ctx, unsigned short type, const 414f08c3bdfSopenharmony_ci void *data, unsigned short len)+ – Adds new attribute to the last message 415f08c3bdfSopenharmony_ci in +ctx+ buffer. See +RTNL_ADD_MESSAGE()+. You need to provide attribute 416f08c3bdfSopenharmony_ci +type+ which will be stored in +struct rtattr.rta_type+, optional payload 417f08c3bdfSopenharmony_ci +data+ and payload size +len+ in bytes. If you don't want to add any payload, 418f08c3bdfSopenharmony_ci set +data+ to +NULL+ and +len+ to 0. Returns 1 on success, 0 on error. 419f08c3bdfSopenharmony_ci 420f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_STRING(struct tst_rtnl_context *ctx, unsigned short type, 421f08c3bdfSopenharmony_ci const char *data)+ – Adds new string attribute to the last message in +ctx+ 422f08c3bdfSopenharmony_ci buffer. Parameters and return value are the same as for +RTNL_ADD_ATTR()+, 423f08c3bdfSopenharmony_ci except the payload length is calculated using +strlen()+. 424f08c3bdfSopenharmony_ci 425f08c3bdfSopenharmony_ci- +int RTNL_ADD_ATTR_LIST(struct tst_rtnl_context *ctx, const struct 426f08c3bdfSopenharmony_ci tst_rtnl_attr_list *list)+ – Adds a list of attributes to the last message 427f08c3bdfSopenharmony_ci in +ctx+ buffer. See description of +struct tst_rtnl_attr_list+ and 428f08c3bdfSopenharmony_ci +RTNL_ADD_MESSAGE()+ above. Returns the number of added attributes on 429f08c3bdfSopenharmony_ci success (nested attributes are not counted), -1 on error. 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ciExample Usage 432f08c3bdfSopenharmony_ci+++++++++++++ 433f08c3bdfSopenharmony_ci[source,c] 434f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 435f08c3bdfSopenharmony_ci#include <asm/types.h> 436f08c3bdfSopenharmony_ci#include <linux/netlink.h> 437f08c3bdfSopenharmony_ci#include <linux/rtnetlink.h> 438f08c3bdfSopenharmony_ci#include <sys/socket.h> 439f08c3bdfSopenharmony_ci#include <netinet/in.h> 440f08c3bdfSopenharmony_ci#include <arpa/inet.h> 441f08c3bdfSopenharmony_ci 442f08c3bdfSopenharmony_ci#include "tst_test.h" 443f08c3bdfSopenharmony_ci#include "tst_rtnetlink.h" 444f08c3bdfSopenharmony_ci#include "tst_netdevice.h" 445f08c3bdfSopenharmony_ci 446f08c3bdfSopenharmony_ci... 447f08c3bdfSopenharmony_ci 448f08c3bdfSopenharmony_civoid setup(void) 449f08c3bdfSopenharmony_ci{ 450f08c3bdfSopenharmony_ci struct tst_rtnl_context *ctx; 451f08c3bdfSopenharmony_ci int index, ret; 452f08c3bdfSopenharmony_ci in_addr_t addr; 453f08c3bdfSopenharmony_ci 454f08c3bdfSopenharmony_ci struct nlmsghdr header = { 455f08c3bdfSopenharmony_ci .nlmsg_type = RTM_NEWADDR, 456f08c3bdfSopenharmony_ci .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_CREATE | 457f08c3bdfSopenharmony_ci NLM_F_EXCL 458f08c3bdfSopenharmony_ci }; 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci struct ifaddrmsg info = { 461f08c3bdfSopenharmony_ci .ifa_family = AF_INET, 462f08c3bdfSopenharmony_ci .ifa_prefixlen = 24 463f08c3bdfSopenharmony_ci }; 464f08c3bdfSopenharmony_ci 465f08c3bdfSopenharmony_ci index = NETDEV_INDEX_BY_NAME("ltp_veth1"); 466f08c3bdfSopenharmony_ci info.ifa_index = index; 467f08c3bdfSopenharmony_ci 468f08c3bdfSopenharmony_ci ctx = RTNL_CREATE_CONTEXT(); 469f08c3bdfSopenharmony_ci RTNL_ADD_MESSAGE(ctx, &header, &info, sizeof(info)); 470f08c3bdfSopenharmony_ci addr = inet_addr("192.168.123.45"); 471f08c3bdfSopenharmony_ci RTNL_ADD_ATTR(ctx, IFA_LOCAL, &addr, sizeof(addr)); 472f08c3bdfSopenharmony_ci ret = RTNL_SEND_VALIDATE(ctx); 473f08c3bdfSopenharmony_ci RTNL_DESTROY_CONTEXT(ctx); 474f08c3bdfSopenharmony_ci 475f08c3bdfSopenharmony_ci if (!ret) { 476f08c3bdfSopenharmony_ci tst_brk(TBROK, "Failed to set ltp_veth1 address"); 477f08c3bdfSopenharmony_ci } 478f08c3bdfSopenharmony_ci} 479f08c3bdfSopenharmony_ci------------------------------------------------------------------------------- 480