aboutsummaryrefslogtreecommitdiff
path: root/include/tst_rtnetlink.h
blob: 6a0c53df4f5eaea516bcd3bcb409d74f4a0373cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright (c) 2021 Linux Test Project
 */

#ifndef TST_RTNETLINK_H
#define TST_RTNETLINK_H

struct tst_rtnl_context;

struct tst_rtnl_attr_list {
	unsigned short type;
	const void *data;
	ssize_t len;
	const struct tst_rtnl_attr_list *sublist;
};

struct tst_rtnl_message {
	struct nlmsghdr *header;
	struct nlmsgerr *err;
	void *payload;
	size_t payload_size;
};

extern int tst_rtnl_errno;

/* Open a netlink socket */
struct tst_rtnl_context *tst_rtnl_create_context(const char *file,
	const int lineno);
#define RTNL_CREATE_CONTEXT() tst_rtnl_create_context(__FILE__, __LINE__)

/* Free a tst_rtnl_message array returned by tst_rtnl_recv() */
void tst_rtnl_free_message(struct tst_rtnl_message *msg);
#define RTNL_FREE_MESSAGE tst_rtnl_free_message

/* Close netlink socket */
void tst_rtnl_destroy_context(const char *file, const int lineno,
	struct tst_rtnl_context *ctx);
#define RTNL_DESTROY_CONTEXT(ctx) \
	tst_rtnl_destroy_context(__FILE__, __LINE__, (ctx))

/* Send all messages in given buffer */
int tst_rtnl_send(const char *file, const int lineno,
	struct tst_rtnl_context *ctx);
#define RTNL_SEND(ctx) tst_rtnl_send(__FILE__, __LINE__, (ctx))

/* Send all messages in given buffer and validate kernel response */
int tst_rtnl_send_validate(const char *file, const int lineno,
	struct tst_rtnl_context *ctx);
#define RTNL_SEND_VALIDATE(ctx) \
	tst_rtnl_send_validate(__FILE__, __LINE__, (ctx))

/* Wait until data is available for reading from the netlink socket */
int tst_rtnl_wait(struct tst_rtnl_context *ctx);
#define RTNL_WAIT tst_rtnl_wait

/*
 * Read from netlink socket and return an array of partially parsed messages.
 * header == NULL indicates end of array.
 */
struct tst_rtnl_message *tst_rtnl_recv(const char *file, const int lineno,
	struct tst_rtnl_context *ctx);
#define RTNL_RECV(ctx) tst_rtnl_recv(__FILE__, __LINE__, (ctx))

/* Add new message to buffer */
int tst_rtnl_add_message(const char *file, const int lineno,
	struct tst_rtnl_context *ctx, const struct nlmsghdr *header,
	const void *payload, size_t payload_size);
#define RTNL_ADD_MESSAGE(ctx, header, payload, psize) \
	tst_rtnl_add_message(__FILE__, __LINE__, (ctx), (header), (payload), \
		(psize))

/* Add arbitrary attribute to last message */
int tst_rtnl_add_attr(const char *file, const int lineno,
	struct tst_rtnl_context *ctx, unsigned short type, const void *data,
	unsigned short len);
#define RTNL_ADD_ATTR(ctx, type, data, len) \
	tst_rtnl_add_attr(__FILE__, __LINE__, (ctx), (type), (data), (len))

/* Add string attribute to last message */
int tst_rtnl_add_attr_string(const char *file, const int lineno,
	struct tst_rtnl_context *ctx, unsigned short type, const char *data);
#define RTNL_ADD_ATTR_STRING(ctx, type, data) \
	tst_rtnl_add_attr_string(__FILE__, __LINE__, (ctx), (type), (data))

/*
 * Add list of arbitrary attributes to last message. The list is terminated
 * by attribute with negative length. Nested sublists are supported.
 */
int tst_rtnl_add_attr_list(const char *file, const int lineno,
	struct tst_rtnl_context *ctx, const struct tst_rtnl_attr_list *list);
#define RTNL_ADD_ATTR_LIST(ctx, list) \
	tst_rtnl_add_attr_list(__FILE__, __LINE__, (ctx), (list))

/* Check that all sent messages with NLM_F_ACK flag have been acked without
 * error. Usage:
 *
 * tst_rtnl_send(ctx);
 * tst_rtnl_wait(ctx);
 * response = tst_rtnl_recv(ctx);
 * if (!tst_rtnl_check_acks(ctx, response)) { ... }
 * tst_rtnl_free_message(response);
 */
int tst_rtnl_check_acks(const char *file, const int lineno,
	struct tst_rtnl_context *ctx, struct tst_rtnl_message *response);
#define RTNL_CHECK_ACKS(ctx, response) \
	tst_rtnl_context(__FILE__, __LINE__, (ctx), (response))

#endif /* TST_RTNETLINK_H */