1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2021 Linux Test Project
4 */
5
6 #include <asm/types.h>
7 #include <linux/veth.h>
8 #include <sys/socket.h>
9 #include <net/if.h>
10 #include <linux/pkt_sched.h>
11 #include "lapi/rtnetlink.h"
12
13 #define TST_NO_DEFAULT_MAIN
14 #include "tst_test.h"
15 #include "tst_rtnetlink.h"
16 #include "tst_netdevice.h"
17
create_request(const char * file,const int lineno,unsigned int type,unsigned int flags,const void * payload,size_t psize)18 static struct tst_rtnl_context *create_request(const char *file,
19 const int lineno, unsigned int type, unsigned int flags,
20 const void *payload, size_t psize)
21 {
22 struct tst_rtnl_context *ctx;
23 struct nlmsghdr header = {
24 .nlmsg_type = type,
25 .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags,
26 };
27
28 ctx = tst_rtnl_create_context(file, lineno);
29
30 if (!ctx)
31 return NULL;
32
33 if (!tst_rtnl_add_message(file, lineno, ctx, &header, payload, psize)) {
34 tst_rtnl_destroy_context(file, lineno, ctx);
35 return NULL;
36 }
37
38 return ctx;
39 }
40
tst_netdev_index_by_name(const char * file,const int lineno,const char * ifname)41 int tst_netdev_index_by_name(const char *file, const int lineno,
42 const char *ifname)
43 {
44 struct ifreq ifr;
45 int sock, ret;
46
47 if (strlen(ifname) >= IFNAMSIZ) {
48 tst_brk_(file, lineno, TBROK,
49 "Network device name \"%s\" too long", ifname);
50 return -1;
51 }
52
53 sock = safe_socket(file, lineno, NULL, AF_INET, SOCK_DGRAM, 0);
54
55 if (sock < 0)
56 return -1;
57
58 strcpy(ifr.ifr_name, ifname);
59 ret = SAFE_IOCTL_(file, lineno, sock, SIOCGIFINDEX, &ifr);
60 safe_close(file, lineno, NULL, sock);
61
62 return ret ? -1 : ifr.ifr_ifindex;
63 }
64
tst_netdev_set_state(const char * file,const int lineno,const char * ifname,int up)65 int tst_netdev_set_state(const char *file, const int lineno,
66 const char *ifname, int up)
67 {
68 struct ifreq ifr;
69 int sock, ret;
70
71 if (strlen(ifname) >= IFNAMSIZ) {
72 tst_brk_(file, lineno, TBROK,
73 "Network device name \"%s\" too long", ifname);
74 return -1;
75 }
76
77 sock = safe_socket(file, lineno, NULL, AF_INET, SOCK_DGRAM, 0);
78
79 if (sock < 0)
80 return -1;
81
82 strcpy(ifr.ifr_name, ifname);
83 ret = SAFE_IOCTL_(file, lineno, sock, SIOCGIFFLAGS, &ifr);
84
85 if (ret) {
86 safe_close(file, lineno, NULL, sock);
87 return ret;
88 }
89
90 if (up)
91 ifr.ifr_flags |= IFF_UP;
92 else
93 ifr.ifr_flags &= ~IFF_UP;
94
95 ret = SAFE_IOCTL_(file, lineno, sock, SIOCSIFFLAGS, &ifr);
96 safe_close(file, lineno, NULL, sock);
97
98 return ret;
99 }
100
tst_create_veth_pair(const char * file,const int lineno,int strict,const char * ifname1,const char * ifname2)101 int tst_create_veth_pair(const char *file, const int lineno, int strict,
102 const char *ifname1, const char *ifname2)
103 {
104 int ret;
105 struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
106 struct tst_rtnl_context *ctx;
107 struct tst_rtnl_attr_list peerinfo[] = {
108 {IFLA_IFNAME, ifname2, strlen(ifname2) + 1, NULL},
109 {0, NULL, -1, NULL}
110 };
111 struct tst_rtnl_attr_list peerdata[] = {
112 {VETH_INFO_PEER, &info, sizeof(info), peerinfo},
113 {0, NULL, -1, NULL}
114 };
115 struct tst_rtnl_attr_list attrs[] = {
116 {IFLA_IFNAME, ifname1, strlen(ifname1) + 1, NULL},
117 {IFLA_LINKINFO, NULL, 0, (const struct tst_rtnl_attr_list[]){
118 {IFLA_INFO_KIND, "veth", 4, NULL},
119 {IFLA_INFO_DATA, NULL, 0, peerdata},
120 {0, NULL, -1, NULL}
121 }},
122 {0, NULL, -1, NULL}
123 };
124
125 if (strlen(ifname1) >= IFNAMSIZ) {
126 tst_brk_(file, lineno, TBROK,
127 "Network device name \"%s\" too long", ifname1);
128 return 0;
129 }
130
131 if (strlen(ifname2) >= IFNAMSIZ) {
132 tst_brk_(file, lineno, TBROK,
133 "Network device name \"%s\" too long", ifname2);
134 return 0;
135 }
136
137 ctx = create_request(file, lineno, RTM_NEWLINK,
138 NLM_F_CREATE | NLM_F_EXCL, &info, sizeof(info));
139
140 if (!ctx)
141 return 0;
142
143 if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
144 tst_rtnl_destroy_context(file, lineno, ctx);
145 return 0;
146 }
147
148 ret = tst_rtnl_send_validate(file, lineno, ctx);
149 tst_rtnl_destroy_context(file, lineno, ctx);
150
151 if (strict && !ret) {
152 tst_brk_(file, lineno, TBROK,
153 "Failed to create veth interfaces %s+%s: %s", ifname1,
154 ifname2, tst_strerrno(tst_rtnl_errno));
155 }
156
157 return ret;
158 }
159
tst_netdev_add_device(const char * file,const int lineno,int strict,const char * ifname,const char * devtype)160 int tst_netdev_add_device(const char *file, const int lineno, int strict,
161 const char *ifname, const char *devtype)
162 {
163 int ret;
164 struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
165 struct tst_rtnl_context *ctx;
166 struct tst_rtnl_attr_list attrs[] = {
167 {IFLA_IFNAME, ifname, strlen(ifname) + 1, NULL},
168 {IFLA_LINKINFO, NULL, 0, (const struct tst_rtnl_attr_list[]){
169 {IFLA_INFO_KIND, devtype, strlen(devtype), NULL},
170 {0, NULL, -1, NULL}
171 }},
172 {0, NULL, -1, NULL}
173 };
174
175 if (strlen(ifname) >= IFNAMSIZ) {
176 tst_brk_(file, lineno, TBROK,
177 "Network device name \"%s\" too long", ifname);
178 return 0;
179 }
180
181 ctx = create_request(file, lineno, RTM_NEWLINK,
182 NLM_F_CREATE | NLM_F_EXCL, &info, sizeof(info));
183
184 if (!ctx)
185 return 0;
186
187 if (tst_rtnl_add_attr_list(file, lineno, ctx, attrs) != 2) {
188 tst_rtnl_destroy_context(file, lineno, ctx);
189 return 0;
190 }
191
192 ret = tst_rtnl_send_validate(file, lineno, ctx);
193 tst_rtnl_destroy_context(file, lineno, ctx);
194
195 if (strict && !ret) {
196 tst_brk_(file, lineno, TBROK,
197 "Failed to create %s device %s: %s", devtype, ifname,
198 tst_strerrno(tst_rtnl_errno));
199 }
200
201 return ret;
202 }
203
tst_netdev_remove_device(const char * file,const int lineno,int strict,const char * ifname)204 int tst_netdev_remove_device(const char *file, const int lineno, int strict,
205 const char *ifname)
206 {
207 struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
208 struct tst_rtnl_context *ctx;
209 int ret;
210
211 if (strlen(ifname) >= IFNAMSIZ) {
212 tst_brk_(file, lineno, TBROK,
213 "Network device name \"%s\" too long", ifname);
214 return 0;
215 }
216
217 ctx = create_request(file, lineno, RTM_DELLINK, 0, &info, sizeof(info));
218
219 if (!ctx)
220 return 0;
221
222 if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
223 tst_rtnl_destroy_context(file, lineno, ctx);
224 return 0;
225 }
226
227 ret = tst_rtnl_send_validate(file, lineno, ctx);
228 tst_rtnl_destroy_context(file, lineno, ctx);
229
230 if (strict && !ret) {
231 tst_brk_(file, lineno, TBROK,
232 "Failed to remove netdevice %s: %s", ifname,
233 tst_strerrno(tst_rtnl_errno));
234 }
235
236 return ret;
237 }
238
modify_address(const char * file,const int lineno,int strict,unsigned int action,unsigned int nl_flags,const char * ifname,unsigned int family,const void * address,unsigned int prefix,size_t addrlen,uint32_t addr_flags)239 static int modify_address(const char *file, const int lineno, int strict,
240 unsigned int action, unsigned int nl_flags, const char *ifname,
241 unsigned int family, const void *address, unsigned int prefix,
242 size_t addrlen, uint32_t addr_flags)
243 {
244 struct tst_rtnl_context *ctx;
245 int index, ret;
246 struct ifaddrmsg info = {
247 .ifa_family = family,
248 .ifa_prefixlen = prefix
249 };
250
251 index = tst_netdev_index_by_name(file, lineno, ifname);
252
253 if (index < 0) {
254 tst_brk_(file, lineno, TBROK, "Interface %s not found", ifname);
255 return 0;
256 }
257
258 info.ifa_index = index;
259 ctx = create_request(file, lineno, action, nl_flags, &info,
260 sizeof(info));
261
262 if (!ctx)
263 return 0;
264
265 if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_FLAGS, &addr_flags,
266 sizeof(uint32_t))) {
267 tst_rtnl_destroy_context(file, lineno, ctx);
268 return 0;
269 }
270
271 if (!tst_rtnl_add_attr(file, lineno, ctx, IFA_LOCAL, address,
272 addrlen)) {
273 tst_rtnl_destroy_context(file, lineno, ctx);
274 return 0;
275 }
276
277 ret = tst_rtnl_send_validate(file, lineno, ctx);
278 tst_rtnl_destroy_context(file, lineno, ctx);
279
280 if (strict && !ret) {
281 tst_brk_(file, lineno, TBROK,
282 "Failed to modify %s network address: %s", ifname,
283 tst_strerrno(tst_rtnl_errno));
284 }
285
286 return ret;
287 }
288
tst_netdev_add_address(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * address,unsigned int prefix,size_t addrlen,unsigned int flags)289 int tst_netdev_add_address(const char *file, const int lineno, int strict,
290 const char *ifname, unsigned int family, const void *address,
291 unsigned int prefix, size_t addrlen, unsigned int flags)
292 {
293 return modify_address(file, lineno, strict, RTM_NEWADDR,
294 NLM_F_CREATE | NLM_F_EXCL, ifname, family, address, prefix,
295 addrlen, flags);
296 }
297
tst_netdev_add_address_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t address,unsigned int prefix,unsigned int flags)298 int tst_netdev_add_address_inet(const char *file, const int lineno, int strict,
299 const char *ifname, in_addr_t address, unsigned int prefix,
300 unsigned int flags)
301 {
302 return tst_netdev_add_address(file, lineno, strict, ifname, AF_INET,
303 &address, prefix, sizeof(address), flags);
304 }
305
tst_netdev_remove_address(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * address,size_t addrlen)306 int tst_netdev_remove_address(const char *file, const int lineno, int strict,
307 const char *ifname, unsigned int family, const void *address,
308 size_t addrlen)
309 {
310 return modify_address(file, lineno, strict, RTM_DELADDR, 0, ifname,
311 family, address, 0, addrlen, 0);
312 }
313
tst_netdev_remove_address_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t address)314 int tst_netdev_remove_address_inet(const char *file, const int lineno,
315 int strict, const char *ifname, in_addr_t address)
316 {
317 return tst_netdev_remove_address(file, lineno, strict, ifname, AF_INET,
318 &address, sizeof(address));
319 }
320
change_ns(const char * file,const int lineno,int strict,const char * ifname,unsigned short attr,uint32_t value)321 static int change_ns(const char *file, const int lineno, int strict,
322 const char *ifname, unsigned short attr, uint32_t value)
323 {
324 struct ifinfomsg info = { .ifi_family = AF_UNSPEC };
325 struct tst_rtnl_context *ctx;
326 int ret;
327
328 if (strlen(ifname) >= IFNAMSIZ) {
329 tst_brk_(file, lineno, TBROK,
330 "Network device name \"%s\" too long", ifname);
331 return 0;
332 }
333
334 ctx = create_request(file, lineno, RTM_NEWLINK, 0, &info, sizeof(info));
335
336 if (!ctx)
337 return 0;
338
339 if (!tst_rtnl_add_attr_string(file, lineno, ctx, IFLA_IFNAME, ifname)) {
340 tst_rtnl_destroy_context(file, lineno, ctx);
341 return 0;
342 }
343
344 if (!tst_rtnl_add_attr(file, lineno, ctx, attr, &value,
345 sizeof(uint32_t))) {
346 tst_rtnl_destroy_context(file, lineno, ctx);
347 return 0;
348 }
349
350 ret = tst_rtnl_send_validate(file, lineno, ctx);
351 tst_rtnl_destroy_context(file, lineno, ctx);
352
353 if (strict && !ret) {
354 tst_brk_(file, lineno, TBROK,
355 "Failed to move %s to another namespace: %s", ifname,
356 tst_strerrno(tst_rtnl_errno));
357 }
358
359 return ret;
360 }
361
tst_netdev_change_ns_fd(const char * file,const int lineno,int strict,const char * ifname,int nsfd)362 int tst_netdev_change_ns_fd(const char *file, const int lineno, int strict,
363 const char *ifname, int nsfd)
364 {
365 return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_FD, nsfd);
366 }
367
tst_netdev_change_ns_pid(const char * file,const int lineno,int strict,const char * ifname,pid_t nspid)368 int tst_netdev_change_ns_pid(const char *file, const int lineno, int strict,
369 const char *ifname, pid_t nspid)
370 {
371 return change_ns(file, lineno, strict, ifname, IFLA_NET_NS_PID, nspid);
372 }
373
modify_route(const char * file,const int lineno,int strict,unsigned int action,unsigned int flags,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)374 static int modify_route(const char *file, const int lineno, int strict,
375 unsigned int action, unsigned int flags, const char *ifname,
376 unsigned int family, const void *srcaddr, unsigned int srcprefix,
377 size_t srclen, const void *dstaddr, unsigned int dstprefix,
378 size_t dstlen, const void *gateway, size_t gatewaylen)
379 {
380 struct tst_rtnl_context *ctx;
381 int ret;
382 int32_t index;
383 struct rtmsg info = {
384 .rtm_family = family,
385 .rtm_dst_len = dstprefix,
386 .rtm_src_len = srcprefix,
387 .rtm_table = RT_TABLE_MAIN,
388 .rtm_protocol = RTPROT_STATIC,
389 .rtm_type = RTN_UNICAST
390 };
391
392 if (!ifname && !gateway) {
393 tst_brk_(file, lineno, TBROK,
394 "Interface name or gateway address required");
395 return 0;
396 }
397
398 if (ifname && strlen(ifname) >= IFNAMSIZ) {
399 tst_brk_(file, lineno, TBROK,
400 "Network device name \"%s\" too long", ifname);
401 return 0;
402 }
403
404 if (ifname) {
405 index = tst_netdev_index_by_name(file, lineno, ifname);
406
407 if (index < 0)
408 return 0;
409 }
410
411 if (action == RTM_DELROUTE)
412 info.rtm_scope = RT_SCOPE_NOWHERE;
413 else
414 info.rtm_scope = RT_SCOPE_UNIVERSE;
415
416 ctx = create_request(file, lineno, action, flags, &info, sizeof(info));
417
418 if (!ctx)
419 return 0;
420
421 if (srcaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_SRC, srcaddr,
422 srclen)) {
423 tst_rtnl_destroy_context(file, lineno, ctx);
424 return 0;
425 }
426
427 if (dstaddr && !tst_rtnl_add_attr(file, lineno, ctx, RTA_DST, dstaddr,
428 dstlen)) {
429 tst_rtnl_destroy_context(file, lineno, ctx);
430 return 0;
431 }
432
433 if (gateway && !tst_rtnl_add_attr(file, lineno, ctx, RTA_GATEWAY,
434 gateway, gatewaylen)) {
435 tst_rtnl_destroy_context(file, lineno, ctx);
436 return 0;
437 }
438
439 if (ifname && !tst_rtnl_add_attr(file, lineno, ctx, RTA_OIF, &index,
440 sizeof(index))) {
441 tst_rtnl_destroy_context(file, lineno, ctx);
442 return 0;
443 }
444
445 ret = tst_rtnl_send_validate(file, lineno, ctx);
446 tst_rtnl_destroy_context(file, lineno, ctx);
447
448 if (strict && !ret) {
449 tst_brk_(file, lineno, TBROK,
450 "Failed to modify network route: %s",
451 tst_strerrno(tst_rtnl_errno));
452 }
453
454 return ret;
455 }
456
modify_route_inet(const char * file,const int lineno,int strict,unsigned int action,unsigned int flags,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)457 static int modify_route_inet(const char *file, const int lineno, int strict,
458 unsigned int action, unsigned int flags, const char *ifname,
459 in_addr_t srcaddr, unsigned int srcprefix, in_addr_t dstaddr,
460 unsigned int dstprefix, in_addr_t gateway)
461 {
462 void *src = NULL, *dst = NULL, *gw = NULL;
463 size_t srclen = 0, dstlen = 0, gwlen = 0;
464
465 if (srcprefix) {
466 src = &srcaddr;
467 srclen = sizeof(srcaddr);
468 }
469
470 if (dstprefix) {
471 dst = &dstaddr;
472 dstlen = sizeof(dstaddr);
473 }
474
475 if (gateway) {
476 gw = &gateway;
477 gwlen = sizeof(gateway);
478 }
479
480 return modify_route(file, lineno, strict, action, flags, ifname,
481 AF_INET, src, srcprefix, srclen, dst, dstprefix, dstlen, gw,
482 gwlen);
483 }
484
tst_netdev_add_route(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)485 int tst_netdev_add_route(const char *file, const int lineno, int strict,
486 const char *ifname, unsigned int family, const void *srcaddr,
487 unsigned int srcprefix, size_t srclen, const void *dstaddr,
488 unsigned int dstprefix, size_t dstlen, const void *gateway,
489 size_t gatewaylen)
490 {
491 return modify_route(file, lineno, strict, RTM_NEWROUTE,
492 NLM_F_CREATE | NLM_F_EXCL, ifname, family, srcaddr, srcprefix,
493 srclen, dstaddr, dstprefix, dstlen, gateway, gatewaylen);
494 }
495
tst_netdev_add_route_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)496 int tst_netdev_add_route_inet(const char *file, const int lineno, int strict,
497 const char *ifname, in_addr_t srcaddr, unsigned int srcprefix,
498 in_addr_t dstaddr, unsigned int dstprefix, in_addr_t gateway)
499 {
500 return modify_route_inet(file, lineno, strict, RTM_NEWROUTE,
501 NLM_F_CREATE | NLM_F_EXCL, ifname, srcaddr, srcprefix, dstaddr,
502 dstprefix, gateway);
503 }
504
tst_netdev_remove_route(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,const void * srcaddr,unsigned int srcprefix,size_t srclen,const void * dstaddr,unsigned int dstprefix,size_t dstlen,const void * gateway,size_t gatewaylen)505 int tst_netdev_remove_route(const char *file, const int lineno, int strict,
506 const char *ifname, unsigned int family, const void *srcaddr,
507 unsigned int srcprefix, size_t srclen, const void *dstaddr,
508 unsigned int dstprefix, size_t dstlen, const void *gateway,
509 size_t gatewaylen)
510 {
511 return modify_route(file, lineno, strict, RTM_DELROUTE, 0, ifname,
512 family, srcaddr, srcprefix, srclen, dstaddr, dstprefix, dstlen,
513 gateway, gatewaylen);
514 }
515
tst_netdev_remove_route_inet(const char * file,const int lineno,int strict,const char * ifname,in_addr_t srcaddr,unsigned int srcprefix,in_addr_t dstaddr,unsigned int dstprefix,in_addr_t gateway)516 int tst_netdev_remove_route_inet(const char *file, const int lineno,
517 int strict, const char *ifname, in_addr_t srcaddr,
518 unsigned int srcprefix, in_addr_t dstaddr, unsigned int dstprefix,
519 in_addr_t gateway)
520 {
521 return modify_route_inet(file, lineno, strict, RTM_DELROUTE, 0, ifname,
522 srcaddr, srcprefix, dstaddr, dstprefix, gateway);
523 }
524
modify_qdisc(const char * file,const int lineno,int strict,const char * object,unsigned int action,unsigned int nl_flags,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,unsigned int info,const char * qd_kind,const struct tst_rtnl_attr_list * config)525 static int modify_qdisc(const char *file, const int lineno, int strict,
526 const char *object, unsigned int action, unsigned int nl_flags,
527 const char *ifname, unsigned int family, unsigned int parent,
528 unsigned int handle, unsigned int info, const char *qd_kind,
529 const struct tst_rtnl_attr_list *config)
530 {
531 struct tst_rtnl_context *ctx;
532 int ret;
533 struct tcmsg msg = {
534 .tcm_family = family,
535 .tcm_handle = handle,
536 .tcm_parent = parent,
537 .tcm_info = info
538 };
539
540 if (!qd_kind) {
541 tst_brk_(file, lineno, TBROK,
542 "Queueing discipline name required");
543 return 0;
544 }
545
546 if (ifname) {
547 msg.tcm_ifindex = tst_netdev_index_by_name(file, lineno,
548 ifname);
549
550 if (msg.tcm_ifindex < 0) {
551 tst_brk_(file, lineno, TBROK, "Interface %s not found",
552 ifname);
553 return 0;
554 }
555 }
556
557 ctx = create_request(file, lineno, action, nl_flags, &msg, sizeof(msg));
558
559 if (!ctx)
560 return 0;
561
562 if (!tst_rtnl_add_attr_string(file, lineno, ctx, TCA_KIND, qd_kind)) {
563 tst_rtnl_destroy_context(file, lineno, ctx);
564 return 0;
565 }
566
567 if (config && !tst_rtnl_add_attr_list(file, lineno, ctx, config)) {
568 tst_rtnl_destroy_context(file, lineno, ctx);
569 return 0;
570 }
571
572 ret = tst_rtnl_send_validate(file, lineno, ctx);
573 tst_rtnl_destroy_context(file, lineno, ctx);
574
575 if (strict && !ret) {
576 tst_brk_(file, lineno, TBROK,
577 "Failed to modify %s: %s", object,
578 tst_strerrno(tst_rtnl_errno));
579 }
580
581 return ret;
582 }
583
tst_netdev_add_qdisc(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,const char * qd_kind,const struct tst_rtnl_attr_list * config)584 int tst_netdev_add_qdisc(const char *file, const int lineno, int strict,
585 const char *ifname, unsigned int family, unsigned int parent,
586 unsigned int handle, const char *qd_kind,
587 const struct tst_rtnl_attr_list *config)
588 {
589 return modify_qdisc(file, lineno, strict, "queueing discipline",
590 RTM_NEWQDISC, NLM_F_CREATE | NLM_F_EXCL, ifname, family,
591 parent, handle, 0, qd_kind, config);
592 }
593
tst_netdev_remove_qdisc(const char * file,const int lineno,int strict,const char * ifname,unsigned int family,unsigned int parent,unsigned int handle,const char * qd_kind)594 int tst_netdev_remove_qdisc(const char *file, const int lineno, int strict,
595 const char *ifname, unsigned int family, unsigned int parent,
596 unsigned int handle, const char *qd_kind)
597 {
598 return modify_qdisc(file, lineno, strict, "queueing discipline",
599 RTM_DELQDISC, 0, ifname, family, parent, handle, 0, qd_kind,
600 NULL);
601 }
602
tst_netdev_add_traffic_class(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,const char * qd_kind,const struct tst_rtnl_attr_list * config)603 int tst_netdev_add_traffic_class(const char *file, const int lineno,
604 int strict, const char *ifname, unsigned int parent,
605 unsigned int handle, const char *qd_kind,
606 const struct tst_rtnl_attr_list *config)
607 {
608 return modify_qdisc(file, lineno, strict, "traffic class",
609 RTM_NEWTCLASS, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
610 parent, handle, 0, qd_kind, config);
611 }
612
tst_netdev_remove_traffic_class(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,const char * qd_kind)613 int tst_netdev_remove_traffic_class(const char *file, const int lineno,
614 int strict, const char *ifname, unsigned int parent,
615 unsigned int handle, const char *qd_kind)
616 {
617 return modify_qdisc(file, lineno, strict, "traffic class",
618 RTM_DELTCLASS, 0, ifname, AF_UNSPEC, parent, handle, 0,
619 qd_kind, NULL);
620 }
621
tst_netdev_add_traffic_filter(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,unsigned int protocol,unsigned int priority,const char * f_kind,const struct tst_rtnl_attr_list * config)622 int tst_netdev_add_traffic_filter(const char *file, const int lineno,
623 int strict, const char *ifname, unsigned int parent,
624 unsigned int handle, unsigned int protocol, unsigned int priority,
625 const char *f_kind, const struct tst_rtnl_attr_list *config)
626 {
627 return modify_qdisc(file, lineno, strict, "traffic filter",
628 RTM_NEWTFILTER, NLM_F_CREATE | NLM_F_EXCL, ifname, AF_UNSPEC,
629 parent, handle, TC_H_MAKE(priority << 16, htons(protocol)),
630 f_kind, config);
631 }
632
tst_netdev_remove_traffic_filter(const char * file,const int lineno,int strict,const char * ifname,unsigned int parent,unsigned int handle,unsigned int protocol,unsigned int priority,const char * f_kind)633 int tst_netdev_remove_traffic_filter(const char *file, const int lineno,
634 int strict, const char *ifname, unsigned int parent,
635 unsigned int handle, unsigned int protocol, unsigned int priority,
636 const char *f_kind)
637 {
638 return modify_qdisc(file, lineno, strict, "traffic filter",
639 RTM_DELTFILTER, 0, ifname, AF_UNSPEC, parent, handle,
640 TC_H_MAKE(priority << 16, htons(protocol)), f_kind, NULL);
641 }
642