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
32 extern "C" {
33 #endif
34 
35 static int io_if_get_txqlen(
36  unsigned short ifi_type, int ifi_index, __u32 *ptxqlen);
37 static int io_if_set_txqlen(
38  unsigned short ifi_type, int ifi_index, __u32 txqlen);
39 static int io_if_get_txqlen_parse(struct nlmsghdr *nlh, size_t len, void *arg);
40 
41 static inline int
42 io_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 
75 error_rtnl_recv_type:
76 error_rtnl_send_getlink_request:
77  rtnl_close(&rth);
78 error_rtnl_open:
79  errno = errsv;
80  return -1;
81 }
82 
83 static inline int
84 io_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 
136 error_rtnl_recv_ack:
137 error_rtnl_send_newlink_request:
138 error_rtnl_recv_type:
139 error_rtnl_send_getlink_request:
140  rtnl_close(&rth);
141 error_rtnl_open:
142  errno = errsv;
143  return -1;
144 }
145 
146 static inline int
147 io_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_
rtnl.h
rtnl_handle
Definition: rtnl.h:47
io.h