Lely core libraries 2.3.4
if.h
Go to the documentation of this file.
1
22#ifndef LELY_IO2_INTERN_LINUX_IF_H_
23#define LELY_IO2_INTERN_LINUX_IF_H_
24
25#include "io.h"
26
27#ifdef __linux__
28
29#include "rtnl.h"
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35static int io_if_get_txqlen(
36 unsigned short ifi_type, int ifi_index, __u32 *ptxqlen);
37static int io_if_set_txqlen(
38 unsigned short ifi_type, int ifi_index, __u32 txqlen);
39static int io_if_get_txqlen_parse(struct nlmsghdr *nlh, size_t len, void *arg);
40
41static inline int
42io_if_get_txqlen(unsigned short ifi_type, int ifi_index, __u32 *ptxqlen)
43{
44 int errsv = 0;
45
46 struct rtnl_handle rth = { -1, 0, 0 };
47 if (rtnl_open(&rth) == -1) {
48 errsv = errno;
49 goto error_rtnl_open;
50 }
51
52 if (rtnl_send_getlink_request(&rth, AF_UNSPEC, ifi_type, ifi_index)
53 == -1) {
54 errsv = errno;
55 goto error_rtnl_send_getlink_request;
56 }
57
58 struct {
59 unsigned short ifi_type;
60 unsigned int ifi_flags;
61 __u32 txqlen;
62 } arg = { ifi_type, 0, 0 };
63 if (rtnl_recv_type(&rth, RTM_NEWLINK, &io_if_get_txqlen_parse, &arg)
64 == -1) {
65 errsv = errno;
66 goto error_rtnl_recv_type;
67 }
68
69 if (ptxqlen)
70 *ptxqlen = arg.txqlen;
71
72 rtnl_close(&rth);
73 return 0;
74
75error_rtnl_recv_type:
76error_rtnl_send_getlink_request:
77 rtnl_close(&rth);
78error_rtnl_open:
79 errno = errsv;
80 return -1;
81}
82
83static inline int
84io_if_set_txqlen(unsigned short ifi_type, int ifi_index, __u32 txqlen)
85{
86 int errsv = 0;
87
88 struct rtnl_handle rth = { -1, 0, 0 };
89 if (rtnl_open(&rth) == -1) {
90 errsv = errno;
91 goto error_rtnl_open;
92 }
93
94 if (rtnl_send_getlink_request(&rth, AF_UNSPEC, ifi_type, ifi_index)
95 == -1) {
96 errsv = errno;
97 goto error_rtnl_send_getlink_request;
98 }
99
100 struct {
101 unsigned short ifi_type;
102 unsigned int ifi_flags;
103 __u32 txqlen;
104 } arg = { ifi_type, 0, 0 };
105 if (rtnl_recv_type(&rth, RTM_NEWLINK, &io_if_get_txqlen_parse, &arg)
106 == -1) {
107 errsv = errno;
108 goto error_rtnl_recv_type;
109 }
110
111 if (arg.txqlen < txqlen) {
112 char buf[8];
113 struct rtattr *rta = (struct rtattr *)buf;
114 *rta = (struct rtattr){ .rta_len = RTA_LENGTH(sizeof(__u32)),
115 .rta_type = IFLA_TXQLEN };
116 *(__u32 *)RTA_DATA(rta) = txqlen;
117
118 // clang-format off
119 if (rtnl_send_newlink_request(&rth, AF_UNSPEC, ifi_type,
120 ifi_index, arg.ifi_flags, rta,
121 RTA_ALIGN(rta->rta_len)) == -1) {
122 // clang-format on
123 errsv = errno;
124 goto error_rtnl_send_newlink_request;
125 }
126
127 if (rtnl_recv_ack(&rth) == -1) {
128 errsv = errno;
129 goto error_rtnl_recv_ack;
130 }
131 }
132
133 rtnl_close(&rth);
134 return 0;
135
136error_rtnl_recv_ack:
137error_rtnl_send_newlink_request:
138error_rtnl_recv_type:
139error_rtnl_send_getlink_request:
140 rtnl_close(&rth);
141error_rtnl_open:
142 errno = errsv;
143 return -1;
144}
145
146static inline int
147io_if_get_txqlen_parse(struct nlmsghdr *nlh, size_t len, void *arg_)
148{
149 assert(nlh);
150 assert(NLMSG_OK(nlh, len));
151 assert(nlh->nlmsg_type == RTM_NEWLINK);
152 struct {
153 unsigned short ifi_type;
154 unsigned int ifi_flags;
155 __u32 txqlen;
156 } *arg = arg_;
157 assert(arg);
158
159 struct ifinfomsg *ifi = NLMSG_DATA(nlh);
160 if (ifi->ifi_type != arg->ifi_type) {
161 errno = ENODEV;
162 return -1;
163 }
164
165 arg->ifi_flags = ifi->ifi_flags;
166
167 struct rtattr *rta =
168 rta_find(IFLA_RTA(ifi), IFLA_PAYLOAD(nlh), IFLA_TXQLEN);
169 if (!rta || RTA_PAYLOAD(rta) < sizeof(__u32)) {
170 errno = EOPNOTSUPP;
171 return -1;
172 }
173
174 arg->txqlen = *(__u32 *)RTA_DATA(rta);
175
176 return 0;
177}
178
179#ifdef __cplusplus
180}
181#endif
182
183#endif // __linux__
184
185#endif // !LELY_IO2_INTERN_LINUX_IF_H_
This is the internal header file of the rtnetlink functions.
This is the internal header file of the Windows-specific I/O declarations.