1 /* SPDX-License-Identifier: GPL-2.0-or-later 2 * Copyright (c) 2021 Linux Test Project 3 */ 4 5 #ifndef TST_RTNETLINK_H 6 #define TST_RTNETLINK_H 7 8 struct tst_rtnl_context; 9 10 struct tst_rtnl_attr_list { 11 unsigned short type; 12 const void *data; 13 ssize_t len; 14 const struct tst_rtnl_attr_list *sublist; 15 }; 16 17 struct tst_rtnl_message { 18 struct nlmsghdr *header; 19 struct nlmsgerr *err; 20 void *payload; 21 size_t payload_size; 22 }; 23 24 extern int tst_rtnl_errno; 25 26 /* Open a netlink socket */ 27 struct tst_rtnl_context *tst_rtnl_create_context(const char *file, 28 const int lineno); 29 #define RTNL_CREATE_CONTEXT() tst_rtnl_create_context(__FILE__, __LINE__) 30 31 /* Free a tst_rtnl_message array returned by tst_rtnl_recv() */ 32 void tst_rtnl_free_message(struct tst_rtnl_message *msg); 33 #define RTNL_FREE_MESSAGE tst_rtnl_free_message 34 35 /* Close netlink socket */ 36 void tst_rtnl_destroy_context(const char *file, const int lineno, 37 struct tst_rtnl_context *ctx); 38 #define RTNL_DESTROY_CONTEXT(ctx) \ 39 tst_rtnl_destroy_context(__FILE__, __LINE__, (ctx)) 40 41 /* Send all messages in given buffer */ 42 int tst_rtnl_send(const char *file, const int lineno, 43 struct tst_rtnl_context *ctx); 44 #define RTNL_SEND(ctx) tst_rtnl_send(__FILE__, __LINE__, (ctx)) 45 46 /* Send all messages in given buffer and validate kernel response */ 47 int tst_rtnl_send_validate(const char *file, const int lineno, 48 struct tst_rtnl_context *ctx); 49 #define RTNL_SEND_VALIDATE(ctx) \ 50 tst_rtnl_send_validate(__FILE__, __LINE__, (ctx)) 51 52 /* Wait until data is available for reading from the netlink socket */ 53 int tst_rtnl_wait(struct tst_rtnl_context *ctx); 54 #define RTNL_WAIT tst_rtnl_wait 55 56 /* 57 * Read from netlink socket and return an array of partially parsed messages. 58 * header == NULL indicates end of array. 59 */ 60 struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno, 61 struct tst_rtnl_context *ctx); 62 #define RTNL_RECV(ctx) tst_rtnl_recv(__FILE__, __LINE__, (ctx)) 63 64 /* Add new message to buffer */ 65 int tst_rtnl_add_message(const char *file, const int lineno, 66 struct tst_rtnl_context *ctx, const struct nlmsghdr *header, 67 const void *payload, size_t payload_size); 68 #define RTNL_ADD_MESSAGE(ctx, header, payload, psize) \ 69 tst_rtnl_add_message(__FILE__, __LINE__, (ctx), (header), (payload), \ 70 (psize)) 71 72 /* Add arbitrary attribute to last message */ 73 int tst_rtnl_add_attr(const char *file, const int lineno, 74 struct tst_rtnl_context *ctx, unsigned short type, const void *data, 75 unsigned short len); 76 #define RTNL_ADD_ATTR(ctx, type, data, len) \ 77 tst_rtnl_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len)) 78 79 /* Add string attribute to last message */ 80 int tst_rtnl_add_attr_string(const char *file, const int lineno, 81 struct tst_rtnl_context *ctx, unsigned short type, const char *data); 82 #define RTNL_ADD_ATTR_STRING(ctx, type, data) \ 83 tst_rtnl_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data)) 84 85 /* 86 * Add list of arbitrary attributes to last message. The list is terminated 87 * by attribute with negative length. Nested sublists are supported. 88 */ 89 int tst_rtnl_add_attr_list(const char *file, const int lineno, 90 struct tst_rtnl_context *ctx, const struct tst_rtnl_attr_list *list); 91 #define RTNL_ADD_ATTR_LIST(ctx, list) \ 92 tst_rtnl_add_attr_list(__FILE__, __LINE__, (ctx), (list)) 93 94 /* Check that all sent messages with NLM_F_ACK flag have been acked without 95 * error. Usage: 96 * 97 * tst_rtnl_send(ctx); 98 * tst_rtnl_wait(ctx); 99 * response = tst_rtnl_recv(ctx); 100 * if (!tst_rtnl_check_acks(ctx, response)) { ... } 101 * tst_rtnl_free_message(response); 102 */ 103 int tst_rtnl_check_acks(const char *file, const int lineno, 104 struct tst_rtnl_context *ctx, struct tst_rtnl_message *response); 105 #define RTNL_CHECK_ACKS(ctx, response) \ 106 tst_rtnl_context(__FILE__, __LINE__, (ctx), (response)) 107 108 #endif /* TST_RTNETLINK_H */ 109