xref: /aosp_15_r20/external/libnl/doc/route.txt (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
1////
2	vim.syntax: asciidoc
3
4	Copyright (c) 2011 Thomas Graf <[email protected]>
5////
6
7Routing Family Netlink Library (libnl-route)
8============================================
9Thomas Graf <[email protected]>
103.1, Aug 11 2011:
11
12== Introduction
13
14This library provides APIs to the kernel interfaces of the routing family.
15
16
17NOTE: Work in progress.
18
19== Addresses
20
21[[route_link]]
22== Links (Network Devices)
23
24The link configuration interface is part of the +NETLINK_ROUTE+ protocol
25family and implements the following netlink message types:
26
27- View and modify the configuration of physical and virtual network devices.
28- Create and delete virtual network devices (e.g. dummy devices, VLAN devices,
29  tun devices, bridging devices, ...)
30- View and modify per link network configuration settings (e.g.
31  +net.ipv6.conf.eth0.accept_ra+, +net.ipv4.conf.eth1.forwarding+, ...)
32
33.Naming Convention (network device, link, interface)
34
35In networking several terms are commonly used to refer to network devices.
36While they have distinct meanings they have been used interchangeably in
37the past. Within the Linux kernel, the term _network device_ or _netdev_ is
38commonly used In user space the term _network interface_ is very common.
39The routing netlink protocol uses the term _link_ and so does the _iproute2_
40utility and most routing daemons.
41
42=== Netlink Protocol
43
44This section describes the protocol semantics of the netlink based link
45configuration interface. The following messages are defined:
46
47[options="header", cols="1,2,2"]
48|==============================================================================
49| Message Type   | User -> Kernel                    | Kernel -> User
50| +RTM_NEWLINK+  | Create or update virtual network device
51| Reply to +RTM_GETLINK+ request or notification of link added or updated
52| +RTM_DELLINK+  | Delete virtual network device
53| Notification of link deleted or disappeared
54| +RTM_GETLINK+  | Retrieve link configuration and statistics |
55| +RTM_SETLINK+  | Modify link configuration |
56|==============================================================================
57
58See link:core.html#core_msg_types[Netlink Library - Message Types] for more
59information on common semantics of these message types.
60
61==== Link Message Format
62
63All netlink link messages share a common header (+struct ifinfomsg+) which
64is appended after the netlink header (+struct nlmsghdr+).
65
66image:ifinfomsg.png["Link Message Header"]
67
68The meaning of each field may differ depending on the message type. A
69+struct ifinfomsg+ is defined in +<linux/rtnetlink.h>+ to represent the
70header.
71
72Address Family (8bit)::
73The address family is usually set to +AF_UNSPEC+ but may be specified in
74+RTM_GETLINK+ requests to limit the returned links to a specific address
75family.
76
77Link Layer Type (16bit)::
78Currently only used in kernel->user messages to report the link layer type
79of a link. The value corresponds to the +ARPHRD_*+ defines found in
80+<linux/if_arp.h>+. Translation from/to strings can be done using the
81functions nl_llproto2str()/nl_str2llproto().
82
83Link Index (32bit)::
84Carries the interface index and is used to identify existing links.
85
86Flags (32bit)::
87In kernel->user messages the value of this field represents the current
88state of the link flags. In user->kernel messages this field is used to
89change flags or set the initial flag state of new links. Note that in order
90to change a flag, the flag must also be set in the _Flags Change Mask_ field.
91
92Flags Change Mask (32bit)::
93The primary use of this field is to specify a mask of flags that should be
94changed based on the value of the _Flags_ field. A special meaning is given
95to this field when present in link notifications, see TODO.
96
97Attributes (variable)::
98All link message types may carry netlink attributes. They are defined in the
99header file <linux/if_link.h> and share the prefix +IFLA_+.
100
101==== Link Message Types
102
103.RTM_GETLINK (user->kernel)
104
105Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and return
106a single +RTM_NEWLINK+ message containing the link configuration and statistics
107or a netlink error message if no such link was found.
108
109*Parameters:*
110
111* *Address family*
112** If the address family is set to +PF_BRIDGE+, only bridging devices will be
113   returned.
114** If the address family is set to +PF_INET6+, only ipv6 enabled devices will
115   be returned.
116
117*Flags:*
118
119* +NLM_F_DUMP+ If set, all links will be returned in form of a multipart
120  message.
121
122*Returns:*
123
124* +EINVAL+ if neither interface nor link name are set
125* +ENODEV+ if no link was found
126* +ENOBUFS+ if allocation failed
127
128.RTM_NEWLINK (user->kernel)
129
130Creates a new or updates an existing link. Only virtual links may be created
131but all links may be updated.
132
133*Flags:*
134
135- +NLM_F_CREATE+ Create link if it does not exist
136- +NLM_F_EXCL+ Return +EEXIST+ if link already exists
137
138*Returns:*
139
140- +EINVAL+ malformed message or invalid configuration parameters
141- +EAFNOSUPPORT+ if an address family specific configuration (+IFLA_AF_SPEC+)
142  is not supported.
143- +EOPNOTSUPP+ if the link does not support modification of parameters
144- +EEXIST+ if +NLM_F_EXCL+ was set and the link exists alraedy
145- +ENODEV+ if the link does not exist and +NLM_F_CREATE+ is not set
146
147.RTM_NEWLINK (kernel->user)
148
149This message type is used in reply to a +RTM_GETLINK+ request and carries
150the configuration and statistics of a link. If multiple links need to
151be sent, the messages will be sent in form of a multipart message.
152
153The message type is also used for notifications sent by the kernel to the
154multicast group +RTNLGRP_LINK+ to inform about various link events. It is
155therefore recommended to always use a separate link socket for link
156notifications in order to separate between the two message types.
157
158TODO: document how to detect different notifications
159
160.RTM_DELLINK (user->kernel)
161
162Lookup link by 1. interface index or 2. link name (+IFLA_IFNAME+) and delete
163the virtual link.
164
165*Returns:*
166
167* +EINVAL+ if neither interface nor link name are set
168* +ENODEV+ if no link was found
169* +ENOTSUPP+ if the operation is not supported (not a virtual link)
170
171.RTM_DELLINK (kernel->user)
172
173Notification sent by the kernel to the multicast group +RTNLGRP_LINK+ when
174
175a. a network device was unregistered (change == ~0)
176b. a bridging device was deleted (address family will be +PF_BRIDGE+)
177
178=== Get / List
179
180[[link_list]]
181==== Get list of links
182
183To retrieve the list of links in the kernel, allocate a new link cache
184using +rtnl_link_alloc_cache()+ to hold the links. It will automatically
185construct and send a +RTM_GETLINK+ message requesting a dump of all links
186from the kernel and feed the returned +RTM_NEWLINK+ to the internal link
187message parser which adds the returned links to the cache.
188
189[source,c]
190-----
191#include <netlink/route/link.h>
192
193int rtnl_link_alloc_cache(struct nl_sock *sk, int family, struct nl_cache **result)
194-----
195
196The cache will contain link objects (+struct rtnl_link+, see <<link_object>>)
197and can be accessed using the standard cache functions. By setting the
198+family+ parameter to an address family other than +AF_UNSPEC+, the resulting
199cache will only contain links supporting the specified address family.
200
201The following direct search functions are provided to search by interface
202index and by link name:
203
204[source,c]
205-----
206#include <netlink/route/link.h>
207
208struct rtnl_link *rtnl_link_get(struct nl_cache *cache, int ifindex);
209struct rtnl_link *rtnl_link_get_by_name(struct nl_cache *cache, const char *name);
210-----
211
212.Example: Link Cache
213
214[source,c]
215-----
216struct nl_cache *cache;
217struct rtnl_link *link;
218
219if (rtnl_link_alloc_cache(sock, AF_UNSPEC, &cache)) < 0)
220	/* error */
221
222if (!(link = rtnl_link_get_by_name(cache, "eth1")))
223	/* link does not exist */
224
225/* do something with link */
226
227rtnl_link_put(link);
228nl_cache_put(cache);
229-----
230
231[[link_direct_lookup]]
232==== Lookup Single Link (Direct Lookup)
233
234If only a single link is of interest, the link can be looked up directly
235without the use of a link cache using the function +rtnl_link_get_kernel()+.
236
237[source,c]
238-----
239#include <netlink/route/link.h>
240
241int rtnl_link_get_kernel(struct nl_sock *sk, int ifindex, const char *name, struct rtnl_link **result);
242-----
243
244It will construct and send a +RTM_GETLINK+ request using the parameters
245provided and wait for a +RTM_NEWLINK+ or netlink error message sent in
246return. If the link exists, the link is returned as link object
247(see <<link_object>>).
248
249.Example: Direct link lookup
250[source,c]
251-----
252struct rtnl_link *link;
253
254if (rtnl_link_get_kernel(sock, 0, "eth1", &link) < 0)
255	/* error */
256
257/* do something with link */
258
259rtnl_link_put(link);
260-----
261
262NOTE: While using this function can save a substantial amount of bandwidth
263      on the netlink socket, the result will not be cached, subsequent calls
264      to rtnl_link_get_kernel() will always trigger sending a +RTM_GETLINK+
265      request.
266
267[[link_translate_ifindex]]
268==== Translating interface index to link name
269
270Applications which require to translate interface index to a link name or
271vice versa may use the following functions to do so. Both functions require
272a filled link cache to work with.
273
274[source,c]
275-----
276char *rtnl_link_i2name (struct nl_cache *cache, int ifindex, char *dst, size_t len);
277int rtnl_link_name2i (struct nl_cache *cache, const char *name);
278-----
279
280=== Add / Modify
281
282Several types of virtual link can be added on the fly using the function
283+rtnl_link_add()+.
284
285[source,c]
286-----
287#include <netlink/route/link.h>
288
289int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags);
290-----
291
292=== Delete
293
294The deletion of virtual links such as VLAN devices or dummy devices is done
295using the function +rtnl_link_delete()+. The link passed on to the function
296can be a link from a link cache or it can be construct with the minimal
297attributes needed to identify the link.
298
299[source,c]
300-----
301#include <netlink/route/link.h>
302
303int rtnl_link_delete(struct nl_sock *sk, const struct rtnl_link *link);
304-----
305
306The function will construct and send a +RTM_DELLINK+ request message and
307returns any errors returned by the kernel.
308
309.Example: Delete link by name
310[source,c]
311-----
312struct rtnl_link *link;
313
314if (!(link = rtnl_link_alloc()))
315	/* error */
316
317rtnl_link_set_name(link, "my_vlan");
318
319if (rtnl_link_delete(sock, link) < 0)
320	/* error */
321
322rtnl_link_put(link);
323-----
324
325[[link_object]]
326=== Link Object
327
328A link is represented by the structure +struct rtnl_link+. Instances may be
329created with the function +rtnl_link_alloc()+ or via a link cache (see
330<<link_list>>) and are freed again using the function +rtnl_link_put()+.
331
332[source,c]
333-----
334#include <netlink/route/link.h>
335
336struct rtnl_link *rtnl_link_alloc(void);
337void rtnl_link_put(struct rtnl_link *link);
338-----
339
340[[link_attr_name]]
341==== Name
342The name serves as unique, human readable description of the link. By
343default, links are named based on their type and then enumerated, e.g.
344eth0, eth1, ethn but they may be renamed at any time.
345
346Kernels >= 2.6.11 support identification by link name.
347
348[source,c]
349-----
350#include <netlink/route/link.h>
351
352void rtnl_link_set_name(struct rtnl_link *link, const char *name);
353char *rtnl_link_get_name(struct rtnl_link *link);
354-----
355
356*Accepted link name format:* +[^ /]*+ (maximum length: 15 characters)
357
358[[link_attr_ifindex]]
359==== Interface Index (Identifier)
360The interface index is an integer uniquely identifying a link. If present
361in any link message, it will be used to identify an existing link.
362
363[source,c]
364-----
365#include <netlink/route/link.h>
366
367void rtnl_link_set_ifindex(struct rtnl_link *link, int ifindex);
368int rtnl_link_get_ifindex(struct rtnl_link *link);
369-----
370
371[[link_attr_group]]
372==== Group
373Each link can be assigned a numeric group identifier to group a bunch of links
374together and apply a set of changes to a group instead of just a single link.
375
376
377[source,c]
378-----
379#include <netlink/route/link.h>
380
381void rtnl_link_set_group(struct rtnl_link *link, uint32_t group);
382uint32_t rtnl_link_get_group(struct rtnl_link *link);
383-----
384
385[[link_attr_address]]
386==== Link Layer Address
387The link layer address (e.g. MAC address).
388
389[source,c]
390-----
391#include <netlink/route/link.h>
392
393void rtnl_link_set_addr(struct rtnl_link *link, struct nl_addr *addr);
394struct nl_addr *rtnl_link_get_addr(struct rtnl_link *link);
395-----
396
397[[link_attr_broadcast]]
398==== Broadcast Address
399The link layer broadcast address
400
401[source,c]
402-----
403#include <netlink/route/link.h>
404
405void rtnl_link_set_broadcast(struct rtnl_link *link, struct nl_addr *addr);
406struct nl_addr *rtnl_link_get_broadcast(struct rtnl_link *link);
407-----
408
409[[link_attr_mtu]]
410==== MTU (Maximum Transmission Unit)
411The maximum transmission unit specifies the maximum packet size a network
412device can transmit or receive. This value may be lower than the capability
413of the physical network device.
414
415[source,c]
416-----
417#include <netlink/route/link.h>
418
419void rtnl_link_set_mtu(struct rtnl_link *link, unsigned int mtu);
420unsigned int rtnl_link_get_mtu(struct rtnl_link *link);
421-----
422
423[[link_attr_flags]]
424==== Flags
425The flags of a link enable or disable various link features or inform about
426the state of the link.
427
428[source,c]
429-----
430#include <netlink/route/link.h>
431
432void rtnl_link_set_flags(struct rtnl_link *link, unsigned int flags);
433void rtnl_link_unset_flags(struct rtnl_link *link, unsigned int flags);
434unsigned int rtnl_link_get_flags(struct rtnl_link *link);
435-----
436
437[options="compact"]
438[horizontal]
439IFF_UP::           Link is up (administratively)
440IFF_RUNNING::      Link is up and carrier is OK (RFC2863 OPER_UP)
441IFF_LOWER_UP::     Link layer is operational
442IFF_DORMANT::      Driver signals dormant
443IFF_BROADCAST::    Link supports broadcasting
444IFF_MULTICAST::    Link supports multicasting
445IFF_ALLMULTI::     Link supports multicast routing
446IFF_DEBUG::        Tell driver to do debugging (currently unused)
447IFF_LOOPBACK::     Link loopback network
448IFF_POINTOPOINT::  Point-to-point link
449IFF_NOARP::        ARP is not supported
450IFF_PROMISC::      Status of promiscuous mode
451IFF_MASTER::       Master of a load balancer (bonding)
452IFF_SLAVE::        Slave to a master link
453IFF_PORTSEL::      Driver supports setting media type (only used by ARM ethernet)
454IFF_AUTOMEDIA::    Link selects port automatically (only used by ARM ethernet)
455IFF_ECHO::         Echo sent packets (testing feature, CAN only)
456IFF_DYNAMIC::      Unused (BSD compatibility)
457IFF_NOTRAILERS::   Unused (BSD compatibility)
458
459To translate a link flag to a link flag name or vice versa:
460
461[source,c]
462-----
463#include <netlink/route/link.h>
464
465char *rtnl_link_flags2str(int flags, char *buf, size_t size);
466int rtnl_link_str2flags(const char *flag_name);
467-----
468
469[[link_attr_txqlen]]
470==== Transmission Queue Length
471
472The transmission queue holds packets before packets are delivered to
473the driver for transmission. It is usually specified in number of
474packets but the unit may be specific to the link type.
475
476[source,c]
477-----
478#include <netlink/route/link.h>
479
480void rtnl_link_set_txqlen(struct rtnl_link *link, unsigned int txqlen);
481unsigned int rtnl_link_get_txqlen(struct rtnl_link *link);
482-----
483
484[[link_attr_operstate]]
485==== Operational Status
486The operational status has been introduced to provide extended information
487on the link status. Traditionally the link state has been described using
488the link flags +IFF_UP, IFF_RUNNING, IFF_LOWER_UP+, and +IFF_DORMANT+ which
489was no longer sufficient for some link types.
490
491[source,c]
492-----
493#include <netlink/route/link.h>
494
495void rtnl_link_set_operstate(struct rtnl_link *link, uint8_t state);
496uint8_t rtnl_link_get_operstate(struct rtnl_link *link);
497-----
498
499[options="compact"]
500[horizontal]
501IF_OPER_UNKNOWN::          Unknown state
502IF_OPER_NOTPRESENT::       Link not present
503IF_OPER_DOWN::             Link down
504IF_OPER_LOWERLAYERDOWN::   L1 down
505IF_OPER_TESTING::          Testing
506IF_OPER_DORMANT::          Dormant
507IF_OPER_UP::               Link up
508
509Translation of operational status code to string and vice versa:
510
511[source,c]
512-----
513#include <netlink/route/link.h>
514
515char *rtnl_link_operstate2str(uint8_t state, char *buf, size_t size);
516int rtnl_link_str2operstate(const char *name);
517-----
518
519[[link_attr_mode]]
520==== Mode
521Currently known link modes are:
522
523[options="compact"]
524[horizontal]
525IF_LINK_MODE_DEFAULT::   Default link mode
526IF_LINK_MODE_DORMANT::   Limit upward transition to dormant
527
528[source,c]
529-----
530#include <netlink/route/link.h>
531
532void rtnl_link_set_linkmode(struct rtnl_link *link, uint8_t mode);
533uint8_t rtnl_link_get_linkmode(struct rtnl_link *link);
534-----
535
536Translation of link mode to string and vice versa:
537
538[source,c]
539-----
540char *rtnl_link_mode2str(uint8_t mode, char *buf, size_t len);
541uint8_t rtnl_link_str2mode(const char *name);
542-----
543
544[[link_attr_alias]]
545==== IfAlias
546Alternative name for the link, primarly used for SNMP IfAlias.
547
548[source,c]
549-----
550#include <netlink/route/link.h>
551
552const char *rtnl_link_get_ifalias(struct rtnl_link *link);
553void rtnl_link_set_ifalias(struct rtnl_link *link, const char *alias);
554-----
555
556*Length limit:* 256
557
558[[link_attr_arptype]]
559==== Hardware Type
560
561[source,c]
562-----
563#include <netlink/route/link.h>
564#include <linux/if_arp.h>
565
566void rtnl_link_set_arptype(struct rtnl_link *link, unsigned int arptype);
567unsigned int rtnl_link_get_arptype(struct rtnl_link *link);
568----
569
570Translation of hardware type to character string and vice versa:
571
572[source,c]
573-----
574#include <netlink/utils.h>
575
576char *nl_llproto2str(int arptype, char *buf, size_t len);
577int nl_str2llproto(const char *name);
578-----
579
580[[link_attr_qdisc]]
581==== Qdisc
582The name of the queueing discipline used by the link is of informational
583nature only. It is a read-only attribute provided by the kernel and cannot
584be modified. The set function is provided solely for the purpose of creating
585link objects to be used for comparison.
586
587For more information on how to modify the qdisc of a link, see section
588<<route_tc>>.
589
590[source,c]
591-----
592#include <netlink/route/link.h>
593
594void rtnl_link_set_qdisc(struct rtnl_link *link, const char *name);
595char *rtnl_link_get_qdisc(struct rtnl_link *link);
596-----
597
598[[link_attr_promiscuity]]
599==== Promiscuity
600The number of subsystem currently depending on the link being promiscuous mode.
601A value of 0 indicates that the link is not in promiscuous mode. It is a
602read-only attribute provided by the kernel and cannot be modified. The set
603function is provided solely for the purpose of creating link objects to be
604used for comparison.
605
606[source,c]
607-----
608#include <netlink/route/link.h>
609
610void rtnl_link_set_promiscuity(struct rtnl_link *link, uint32_t count);
611uint32_t rtnl_link_get_promiscuity(struct rtnl_link *link);
612-----
613
614[[link_num_rxtx_queues]]
615==== RX/TX Queues
616The number of RX/TX queues the link provides. The attribute is writable but
617will only be considered when creating a new network device via netlink.
618
619[source,c]
620-----
621#include <netlink/route/link.h>
622
623void rtnl_link_set_num_tx_queues(struct rtnl_link *link, uint32_t nqueues);
624uint32_t rtnl_link_get_num_tx_queues(struct rtnl_link *link);
625
626void rtnl_link_set_num_rx_queues(struct rtnl_link *link, uint32_t nqueues);
627uint32_t rtnl_link_get_num_rx_queues(struct rtnl_link *link);
628-----
629
630[[link_attr_weight]]
631==== Weight
632This attribute is unused and obsoleted in all recent kernels.
633
634
635[[link_modules]]
636=== Modules
637
638[[link_bonding]]
639==== Bonding
640
641.Example: Add bonding link
642[source,c]
643-----
644#include <netlink/route/link.h>
645
646struct rtnl_link *link;
647
648link = rtnl_link_bond_alloc();
649rtnl_link_set_name(link, "my_bond");
650
651/* requires admin privileges */
652if (rtnl_link_add(sk, link, NLM_F_CREATE) < 0)
653	/* error */
654
655rtnl_link_put(link);
656-----
657
658[[link_vlan]]
659==== VLAN
660
661[source,c]
662-----
663extern char *		rtnl_link_vlan_flags2str(int, char *, size_t);
664extern int		rtnl_link_vlan_str2flags(const char *);
665
666extern int		rtnl_link_vlan_set_id(struct rtnl_link *, int);
667extern int		rtnl_link_vlan_get_id(struct rtnl_link *);
668
669extern int		rtnl_link_vlan_set_flags(struct rtnl_link *,
670						 unsigned int);
671extern int		rtnl_link_vlan_unset_flags(struct rtnl_link *,
672						   unsigned int);
673extern unsigned int	rtnl_link_vlan_get_flags(struct rtnl_link *);
674
675extern int		rtnl_link_vlan_set_ingress_map(struct rtnl_link *,
676						       int, uint32_t);
677extern uint32_t *	rtnl_link_vlan_get_ingress_map(struct rtnl_link *);
678
679extern int		rtnl_link_vlan_set_egress_map(struct rtnl_link *,
680						      uint32_t, int);
681extern struct vlan_map *rtnl_link_vlan_get_egress_map(struct rtnl_link *,
682						      int *);
683-----
684
685.Example: Add a VLAN device
686[source,c]
687-----
688struct rtnl_link *link;
689int master_index;
690
691/* lookup interface index of eth0 */
692if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
693	/* error */
694
695/* allocate new link object of type vlan */
696link = rtnl_link_vlan_alloc();
697
698/* set eth0 to be our master device */
699rtnl_link_set_link(link, master_index);
700
701rtnl_link_vlan_set_id(link, 10);
702
703if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
704	/* error */
705
706rtnl_link_put(link);
707-----
708
709[[link_macvlan]]
710==== MACVLAN
711
712[source,c]
713-----
714extern struct rtnl_link *rtnl_link_macvlan_alloc(void);
715
716extern int		rtnl_link_is_macvlan(struct rtnl_link *);
717
718extern char *		rtnl_link_macvlan_mode2str(int, char *, size_t);
719extern int		rtnl_link_macvlan_str2mode(const char *);
720
721extern char *		rtnl_link_macvlan_flags2str(int, char *, size_t);
722extern int		rtnl_link_macvlan_str2flags(const char *);
723
724extern int		rtnl_link_macvlan_set_mode(struct rtnl_link *,
725			                           uint32_t);
726extern uint32_t		rtnl_link_macvlan_get_mode(struct rtnl_link *);
727
728extern int		rtnl_link_macvlan_set_flags(struct rtnl_link *,
729						 uint16_t);
730extern int		rtnl_link_macvlan_unset_flags(struct rtnl_link *,
731						   uint16_t);
732extern uint16_t		rtnl_link_macvlan_get_flags(struct rtnl_link *);
733-----
734
735.Example: Add a MACVLAN device
736[source,c]
737-----
738struct rtnl_link *link;
739int master_index;
740struct nl_addr* addr;
741
742/* lookup interface index of eth0 */
743if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
744	/* error */
745
746/* allocate new link object of type macvlan */
747link = rtnl_link_macvlan_alloc();
748
749/* set eth0 to be our master device */
750rtnl_link_set_link(link, master_index);
751
752/* set address of virtual interface */
753addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN);
754rtnl_link_set_addr(link, addr);
755nl_addr_put(addr);
756
757/* set mode of virtual interface */
758rtnl_link_macvlan_set_mode(link, rtnl_link_macvlan_str2mode("bridge"));
759
760if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
761	/* error */
762
763rtnl_link_put(link);
764-----
765
766[[link_macvtap]]
767==== MACVTAP
768
769[source,c]
770-----
771extern struct rtnl_link *rtnl_link_macvtap_alloc(void);
772
773extern int		rtnl_link_is_macvtap(struct rtnl_link *);
774
775extern char *		rtnl_link_macvtap_mode2str(int, char *, size_t);
776extern int		rtnl_link_macvtap_str2mode(const char *);
777
778extern char *		rtnl_link_macvtap_flags2str(int, char *, size_t);
779extern int		rtnl_link_macvtap_str2flags(const char *);
780
781extern int		rtnl_link_macvtap_set_mode(struct rtnl_link *,
782			                           uint32_t);
783extern uint32_t		rtnl_link_macvtap_get_mode(struct rtnl_link *);
784
785extern int		rtnl_link_macvtap_set_flags(struct rtnl_link *,
786			                            uint16_t);
787extern int		rtnl_link_macvtap_unset_flags(struct rtnl_link *,
788			                              uint16_t);
789extern uint16_t		rtnl_link_macvtap_get_flags(struct rtnl_link *);
790-----
791
792.Example: Add a MACVTAP device
793[source,c]
794-----
795struct rtnl_link *link;
796int master_index;
797struct nl_addr* addr;
798
799/* lookup interface index of eth0 */
800if (!(master_index = rtnl_link_name2i(link_cache, "eth0")))
801	/* error */
802
803/* allocate new link object of type macvtap */
804link = rtnl_link_macvtap_alloc();
805
806/* set eth0 to be our master device */
807rtnl_link_set_link(link, master_index);
808
809/* set address of virtual interface */
810addr = nl_addr_build(AF_LLC, ether_aton("00:11:22:33:44:55"), ETH_ALEN);
811rtnl_link_set_addr(link, addr);
812nl_addr_put(addr);
813
814/* set mode of virtual interface */
815rtnl_link_macvtap_set_mode(link, rtnl_link_macvtap_str2mode("bridge"));
816
817if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
818	/* error */
819
820rtnl_link_put(link);
821-----
822
823[[link_vxlan]]
824==== VXLAN
825
826[source,c]
827-----
828extern struct rtnl_link *rtnl_link_vxlan_alloc(void);
829
830extern int	rtnl_link_is_vxlan(struct rtnl_link *);
831
832extern int	rtnl_link_vxlan_set_id(struct rtnl_link *, uint32_t);
833extern int	rtnl_link_vxlan_get_id(struct rtnl_link *, uint32_t *);
834
835extern int	rtnl_link_vxlan_set_group(struct rtnl_link *, struct nl_addr *);
836extern int	rtnl_link_vxlan_get_group(struct rtnl_link *, struct nl_addr **);
837
838extern int	rtnl_link_vxlan_set_link(struct rtnl_link *, uint32_t);
839extern int	rtnl_link_vxlan_get_link(struct rtnl_link *, uint32_t *);
840
841extern int	rtnl_link_vxlan_set_local(struct rtnl_link *, struct nl_addr *);
842extern int	rtnl_link_vxlan_get_local(struct rtnl_link *, struct nl_addr **);
843
844extern int	rtnl_link_vxlan_set_ttl(struct rtnl_link *, uint8_t);
845extern int	rtnl_link_vxlan_get_ttl(struct rtnl_link *);
846
847extern int	rtnl_link_vxlan_set_tos(struct rtnl_link *, uint8_t);
848extern int	rtnl_link_vxlan_get_tos(struct rtnl_link *);
849
850extern int	rtnl_link_vxlan_set_learning(struct rtnl_link *, uint8_t);
851extern int	rtnl_link_vxlan_get_learning(struct rtnl_link *);
852extern int	rtnl_link_vxlan_enable_learning(struct rtnl_link *);
853extern int	rtnl_link_vxlan_disable_learning(struct rtnl_link *);
854
855extern int	rtnl_link_vxlan_set_ageing(struct rtnl_link *, uint32_t);
856extern int	rtnl_link_vxlan_get_ageing(struct rtnl_link *, uint32_t *);
857
858extern int	rtnl_link_vxlan_set_limit(struct rtnl_link *, uint32_t);
859extern int	rtnl_link_vxlan_get_limit(struct rtnl_link *, uint32_t *);
860
861extern int	rtnl_link_vxlan_set_port_range(struct rtnl_link *,
862					       struct ifla_vxlan_port_range *);
863extern int	rtnl_link_vxlan_get_port_range(struct rtnl_link *,
864					       struct ifla_vxlan_port_range *);
865
866extern int	rtnl_link_vxlan_set_proxy(struct rtnl_link *, uint8_t);
867extern int	rtnl_link_vxlan_get_proxy(struct rtnl_link *);
868extern int	rtnl_link_vxlan_enable_proxy(struct rtnl_link *);
869extern int	rtnl_link_vxlan_disable_proxy(struct rtnl_link *);
870
871extern int	rtnl_link_vxlan_set_rsc(struct rtnl_link *, uint8_t);
872extern int	rtnl_link_vxlan_get_rsc(struct rtnl_link *);
873extern int	rtnl_link_vxlan_enable_rsc(struct rtnl_link *);
874extern int	rtnl_link_vxlan_disable_rsc(struct rtnl_link *);
875
876extern int	rtnl_link_vxlan_set_l2miss(struct rtnl_link *, uint8_t);
877extern int	rtnl_link_vxlan_get_l2miss(struct rtnl_link *);
878extern int	rtnl_link_vxlan_enable_l2miss(struct rtnl_link *);
879extern int	rtnl_link_vxlan_disable_l2miss(struct rtnl_link *);
880
881extern int	rtnl_link_vxlan_set_l3miss(struct rtnl_link *, uint8_t);
882extern int	rtnl_link_vxlan_get_l3miss(struct rtnl_link *);
883extern int	rtnl_link_vxlan_enable_l3miss(struct rtnl_link *);
884extern int	rtnl_link_vxlan_disable_l3miss(struct rtnl_link *);
885-----
886
887.Example: Add a VXLAN device
888[source,c]
889-----
890struct rtnl_link *link;
891struct nl_addr* addr;
892
893/* allocate new link object of type vxlan */
894link = rtnl_link_vxlan_alloc();
895
896/* set interface name */
897rtnl_link_set_name(link, "vxlan128");
898
899/* set VXLAN network identifier */
900if ((err = rtnl_link_vxlan_set_id(link, 128)) < 0)
901	/* error */
902
903/* set multicast address to join */
904if ((err = nl_addr_parse("239.0.0.1", AF_INET, &addr)) < 0)
905	/* error */
906
907if ((err = rtnl_link_set_group(link, addr)) < 0)
908	/* error */
909
910nl_addr_put(addr);
911
912if ((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
913	/* error */
914
915rtnl_link_put(link);
916-----
917
918[[link_ipip]]
919==== IPIP
920
921[source,c]
922-----
923extern struct rtnl_link *rtnl_link_ipip_alloc(void);
924extern int rtnl_link_ipip_add(struct nl_sock *sk, const char *name);
925
926extern int rtnl_link_ipip_set_link(struct rtnl_link *link,  uint32_t index);
927extern uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link);
928
929extern int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr);
930extern uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link);
931
932extern int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr);
933extern uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link);
934
935extern int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl);
936extern uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link);
937
938extern int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos);
939extern uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link);
940
941extern int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
942extern uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link);
943
944extern int rtnl_link_ipip_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
945extern int rtnl_link_ipip_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
946
947-----
948
949.Example: Add an ipip tunnel device
950[source,c]
951-----
952struct rtnl_link *link
953struct in_addr addr
954
955/* allocate new link object of type ipip */
956if(!(link = rtnl_link_ipip_alloc()))
957        /* error */
958
959/* set ipip tunnel name */
960if ((err = rtnl_link_set_name(link, "ipip-tun")) < 0)
961         /* error */
962
963/* set link index  */
964if ((err = rtnl_link_ipip_set_link(link, if_index)) < 0)
965        /* error */
966
967/* set local address */
968inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
969if ((err = rtnl_link_ipip_set_local(link, addr.s_addr)) < 0)
970        /* error */
971
972/* set remote address */
973inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
974if ((err = rtnl_link_ipip_set_remote(link, addr.s_addr)) < 0)
975        /* error */
976
977/* set tunnel ttl  */
978if ((err = rtnl_link_ipip_set_ttl(link, 64)) < 0)
979        /* error */
980
981if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
982        /* error */
983
984rtnl_link_put(link);
985-----
986
987[[link_ipgre]]
988==== IPGRE
989
990[source,c]
991-----
992extern struct rtnl_link *rtnl_link_ipgre_alloc(void);
993extern int rtnl_link_ipgre_add(struct nl_sock *sk, const char *name);
994
995extern int rtnl_link_ipgre_set_link(struct rtnl_link *link,  uint32_t index);
996extern uint32_t rtnl_link_ipgre_get_link(struct rtnl_link *link);
997
998extern int rtnl_link_ipgre_set_iflags(struct rtnl_link *link, uint16_t iflags);
999extern uint16_t rtnl_link_get_iflags(struct rtnl_link *link);
1000
1001extern int rtnl_link_ipgre_set_oflags(struct rtnl_link *link, uint16_t oflags);
1002extern uint16_t rtnl_link_get_oflags(struct rtnl_link *link);
1003
1004extern int rtnl_link_ipgre_set_ikey(struct rtnl_link *link, uint32_t ikey);
1005extern uint32_t rtnl_link_get_ikey(struct rtnl_link *link);
1006
1007extern int rtnl_link_ipgre_set_okey(struct rtnl_link *link, uint32_t okey);
1008extern uint32_t rtnl_link_get_okey(struct rtnl_link *link)
1009
1010extern int rtnl_link_ipgre_set_local(struct rtnl_link *link, uint32_t addr);
1011extern uint32_t rtnl_link_ipgre_get_local(struct rtnl_link *link);
1012
1013extern int rtnl_link_ipgre_set_remote(struct rtnl_link *link, uint32_t addr);
1014extern uint32_t rtnl_link_ipgre_get_remote(struct rtnl_link *link);
1015
1016extern int rtnl_link_ipgre_set_ttl(struct rtnl_link *link, uint8_t ttl);
1017extern uint8_t rtnl_link_ipgre_get_ttl(struct rtnl_link *link);
1018
1019extern int rtnl_link_ipgre_set_tos(struct rtnl_link *link, uint8_t tos);
1020extern uint8_t rtnl_link_ipgre_get_tos(struct rtnl_link *link);
1021
1022extern int rtnl_link_ipgre_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
1023extern uint8_t rtnl_link_ipgre_get_pmtudisc(struct rtnl_link *link);
1024
1025extern int rtnl_link_ipgre_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1026extern int rtnl_link_ipgre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1027
1028-----
1029
1030.Example: Add an ipgre tunnel device
1031[source,c]
1032-----
1033struct rtnl_link *link
1034struct in_addr addr
1035
1036/* allocate new link object of type ipgre */
1037if(!(link = rtnl_link_ipgre_alloc()))
1038	/* error */
1039
1040/* set ipgre tunnel name */
1041if ((err = rtnl_link_set_name(link, "ipgre-tun")) < 0)
1042	/* error */
1043
1044/* set link index  */
1045if ((err = rtnl_link_ipgre_set_link(link, if_index)) < 0)
1046	/* error */
1047
1048/* set local address */
1049inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
1050if ((err = rtnl_link_ipgre_set_local(link, addr.s_addr)) < 0)
1051	/* error */
1052
1053/* set remote address */
1054inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
1055if ((err = rtnl_link_ipgre_set_remote(link, addr.s_addr)) < 0)
1056	/* error */
1057
1058/* set tunnel ttl  */
1059if ((err = rtnl_link_ipgre_set_ttl(link, 64)) < 0)
1060	/* error */
1061
1062if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
1063	/* error */
1064
1065rtnl_link_put(link);
1066-----
1067
1068[[link_sit]]
1069==== SIT
1070
1071[source,c]
1072-----
1073extern struct rtnl_link *rtnl_link_sit_alloc(void);
1074extern int rtnl_link_sit_add(struct nl_sock *sk, const char *name);
1075
1076extern int rtnl_link_sit_set_link(struct rtnl_link *link,  uint32_t index);
1077extern uint32_t rtnl_link_sit_get_link(struct rtnl_link *link);
1078
1079extern int rtnl_link_sit_set_iflags(struct rtnl_link *link, uint16_t iflags);
1080extern uint16_t rtnl_link_get_iflags(struct rtnl_link *link);
1081
1082extern int rtnl_link_sit_set_oflags(struct rtnl_link *link, uint16_t oflags);
1083extern uint16_t rtnl_link_get_oflags(struct rtnl_link *link);
1084
1085extern int rtnl_link_sit_set_ikey(struct rtnl_link *link, uint32_t ikey);
1086extern uint32_t rtnl_link_get_ikey(struct rtnl_link *link);
1087
1088extern int rtnl_link_sit_set_okey(struct rtnl_link *link, uint32_t okey);
1089extern uint32_t rtnl_link_get_okey(struct rtnl_link *link)
1090
1091extern int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr);
1092extern uint32_t rtnl_link_sit_get_local(struct rtnl_link *link);
1093
1094extern int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr);
1095extern uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link);
1096
1097extern int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl);
1098extern uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link);
1099
1100extern int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos);
1101extern uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link);
1102
1103extern int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc);
1104extern uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link);
1105
1106extern int rtnl_link_sit_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1107extern int rtnl_link_sit_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1108
1109-----
1110
1111.Example: Add a sit tunnel device
1112[source,c]
1113-----
1114struct rtnl_link *link
1115struct in_addr addr
1116
1117/* allocate new link object of type sit */
1118if(!(link = rtnl_link_sit_alloc()))
1119	/* error */
1120
1121/* set sit tunnel name */
1122if ((err = rtnl_link_set_name(link, "sit-tun")) < 0)
1123	/* error */
1124
1125/* set link index  */
1126if ((err = rtnl_link_sit_set_link(link, if_index)) < 0)
1127	/* error */
1128
1129/* set local address */
1130inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
1131if ((err = rtnl_link_sit_set_local(link, addr.s_addr)) < 0)
1132	/* error */
1133
1134/* set remote address */
1135inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
1136if ((err = rtnl_link_sit_set_remote(link, addr.s_addr)) < 0)
1137	/* error */
1138
1139/* set tunnel ttl  */
1140if ((err = rtnl_link_sit_set_ttl(link, 64)) < 0)
1141	/* error */
1142
1143if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
1144        /* error */
1145
1146rtnl_link_put(link);
1147-----
1148
1149
1150[[link_ipvti]]
1151==== IPVTI
1152
1153[source,c]
1154-----
1155extern struct rtnl_link *rtnl_link_ipvti_alloc(void);
1156extern int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name);
1157
1158extern int rtnl_link_ipvti_set_link(struct rtnl_link *link,  uint32_t index);
1159extern uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link);
1160
1161extern int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey);
1162extern uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link);
1163
1164extern int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey);
1165extern uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
1166
1167extern int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr);
1168extern uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link);
1169
1170extern int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t addr);
1171extern uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link);
1172
1173extern int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1174extern int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1175
1176-----
1177
1178.Example: Add an ipvti tunnel device
1179[source,c]
1180-----
1181struct rtnl_link *link
1182struct in_addr addr
1183
1184/* allocate new link object of type ipvti */
1185if(!(link = rtnl_link_ipvti_alloc()))
1186	/* error */
1187
1188/* set ipvti tunnel name */
1189if ((err = rtnl_link_set_name(link, "ipvti-tun")) < 0)
1190	/* error */
1191
1192/* set link index  */
1193if ((err = rtnl_link_ipvti_set_link(link, if_index)) < 0)
1194	/* error */
1195
1196/* set local address */
1197inet_pton(AF_INET, "192.168.254.12", &addr.s_addr);
1198if ((err = rtnl_link_ipvti_set_local(link, addr.s_addr)) < 0)
1199	/* error */
1200
1201/* set remote address */
1202inet_pton(AF_INET, "192.168.254.13", &addr.s_addr
1203if ((err = rtnl_link_ipvti_set_remote(link, addr.s_addr)) < 0)
1204	/* error */
1205
1206if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
1207	/* error */
1208
1209rtnl_link_put(link);
1210-----
1211
1212[[link_ip6tnl]]
1213==== IP6TNL
1214
1215[source,c]
1216-----
1217extern struct rtnl_link *rtnl_link_ip6_tnl_alloc(void);
1218extern int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name);
1219
1220extern int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link,  uint32_t index);
1221extern uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link);
1222
1223extern int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *);
1224extern int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *);
1225
1226extern int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *);
1227extern int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *);
1228
1229extern int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl);
1230extern uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link);
1231
1232extern int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos);
1233extern uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link);
1234
1235extern int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit);
1236extern uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link);
1237
1238extern int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags);
1239extern uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link);
1240
1241extern uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link);
1242extern int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo);
1243
1244extern int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto);
1245extern uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link);
1246
1247extern int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1248extern int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1249
1250-----
1251
1252.Example: Add an ip6tnl tunnel device
1253[source,c]
1254-----
1255struct rtnl_link *link
1256struct in6_addr addr
1257
1258link = rtnl_link_ip6_tnl_alloc();
1259
1260rtnl_link_set_name(link, "ip6tnl-tun");
1261rtnl_link_ip6_tnl_set_link(link, if_index);
1262
1263inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr);
1264rtnl_link_ip6_tnl_set_local(link, &addr);
1265
1266inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr);
1267rtnl_link_ip6_tnl_set_remote(link, &addr);
1268
1269rtnl_link_add(sk, link, NLM_F_CREATE);
1270rtnl_link_put(link);
1271
1272-----
1273
1274[[link_ip6gre]]
1275==== IP6GRE
1276
1277[source,c]
1278----
1279extern int rtnl_link_is_ip6gre(struct rtnl_link *link);
1280
1281extern struct rtnl_link *rtnl_link_ip6gre_alloc(void);
1282extern int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name);
1283
1284extern int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index);
1285extern int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index);
1286
1287extern int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags);
1288extern int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags);
1289
1290extern int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags);
1291extern int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags);
1292
1293extern int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey);
1294extern int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey);
1295
1296extern int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey);
1297extern int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey);
1298
1299extern int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local);
1300extern int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local);
1301
1302extern int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote);
1303extern int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote);
1304
1305extern int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl);
1306extern int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl);
1307
1308extern int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit);
1309extern int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit);
1310
1311extern int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo);
1312extern int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo);
1313
1314extern int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags);
1315extern int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags);
1316
1317extern int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1318extern int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1319
1320----
1321
1322.Example: Add an ip6gre tunnel device
1323[source,c]
1324----
1325struct rtnl_link *link
1326struct in6_addr addr
1327
1328link = rtnl_link_ip6gre_alloc();
1329
1330rtnl_link_set_name(link, "ip6gre-tun");
1331rtnl_link_ip6gre_set_link(link, if_index);
1332
1333inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr);
1334rtnl_link_ip6gre_set_local(link, &addr);
1335
1336inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr);
1337rtnl_link_ip6gre_set_remote(link, &addr);
1338
1339rtnl_link_add(sk, link, NLM_F_CREATE);
1340rtnl_link_put(link);
1341
1342-----
1343
1344[[link_ip6vti]]
1345==== IP6VTI
1346
1347[source,c]
1348----
1349int rtnl_link_is_ip6vti(struct rtnl_link *link);
1350
1351extern struct rtnl_link *rtnl_link_ip6vti_alloc(void);
1352extern int rtnl_link_ip6vti_add(struct nl_sock *sk, const char *name);
1353
1354extern int rtnl_link_ip6vti_set_link(struct rtnl_link *link, uint32_t index);
1355extern int rtnl_link_ip6vti_get_link(struct rtnl_link *link, uint32_t *index);
1356
1357extern int rtnl_link_ip6vti_set_ikey(struct rtnl_link *link, uint32_t ikey);
1358extern int rtnl_link_ip6vti_get_ikey(struct rtnl_link *link, uint32_t *ikey);
1359
1360extern int rtnl_link_ip6vti_set_okey(struct rtnl_link *link, uint32_t okey);
1361extern int rtnl_link_ip6vti_get_okey(struct rtnl_link *link, uint32_t *okey);
1362
1363extern int rtnl_link_ip6vti_set_local(struct rtnl_link *link, struct in6_addr *local);
1364extern int rtnl_link_ip6vti_get_local(struct rtnl_link *link, struct in6_addr *remote);
1365
1366extern int rtnl_link_ip6vti_set_remote(struct rtnl_link *link, struct in6_addr *remote);
1367extern int rtnl_link_ip6vti_get_remote(struct rtnl_link *link, struct in6_addr *remote);
1368
1369extern int rtnl_link_ip6vti_set_fwmark(struct rtnl_link *link, uint32_t fwmark);
1370extern int rtnl_link_ip6vti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark);
1371
1372----
1373
1374.Example: Add an ip6vti tunnel device
1375[source,c]
1376----
1377struct rtnl_link *link
1378struct in6_addr addr
1379
1380link = rtnl_link_ip6vti_alloc();
1381
1382rtnl_link_set_name(link, "ip6vti-tun");
1383rtnl_link_ip6vti_set_link(link, if_index);
1384
1385inet_pton(AF_INET6, "2607:f0d0:1002:51::4", &addr);
1386rtnl_link_ip6vti_set_local(link, &addr);
1387
1388inet_pton(AF_INET6, "2607:f0d0:1002:52::5", &addr);
1389rtnl_link_ip6vti_set_remote(link, &addr);
1390
1391rtnl_link_add(sk, link, NLM_F_CREATE);
1392rtnl_link_put(link);
1393
1394-----
1395
1396[[link_xfrmi]]
1397==== XFRMI
1398
1399[source,c]
1400-----
1401extern struct rtnl_link *rtnl_link_xfrmi_alloc(void);
1402
1403extern int rtnl_link_xfrmi_set_link(struct rtnl_link *link,  uint32_t index);
1404extern uint32_t rtnl_link_xfrmi_get_link(struct rtnl_link *link);
1405
1406extern int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id);
1407extern uint32_t rtnl_link_xfrmi_get_if_id(struct rtnl_link *link);
1408
1409-----
1410
1411.Example: Add a xfrmi device
1412[source,c]
1413-----
1414struct rtnl_link *link
1415struct in_addr addr
1416
1417/* allocate new link object of type xfrmi */
1418if(!(link = rtnl_link_xfrmi_alloc()))
1419	/* error */
1420
1421/* set xfrmi name */
1422if ((err = rtnl_link_set_name(link, "ipsec0")) < 0)
1423	/* error */
1424
1425/* set link index  */
1426if ((err = rtnl_link_xfrmi_set_link(link, if_index)) < 0)
1427	/* error */
1428
1429/* set if_id */
1430if ((err = rtnl_link_xfrmi_set_if_id(link, 16)) < 0)
1431	/* error */
1432
1433if((err = rtnl_link_add(sk, link, NLM_F_CREATE)) < 0)
1434	/* error */
1435
1436rtnl_link_put(link);
1437-----
1438
1439== Neighbouring
1440
1441== Routing
1442
1443[[route_tc]]
1444== Traffic Control
1445
1446The traffic control architecture allows the queueing and
1447prioritization of packets before they are enqueued to the network
1448driver. To a limited degree it is also possible to take control of
1449network traffic as it enters the network stack.
1450
1451The architecture consists of three different types of modules:
1452
1453- *Queueing disciplines (qdisc)* provide a mechanism to enqueue packets
1454  in different forms. They may be used to implement fair queueing,
1455  prioritization of differentiated services, enforce bandwidth
1456  limitations, or even to simulate network behaviour such as packet
1457  loss and packet delay. Qdiscs can be classful in which case they
1458  allow traffic classes described in the next paragraph to be attached
1459  to them.
1460
1461- *Traffic classes (class)* are supported by several qdiscs to build
1462  a tree structure for different types of traffic. Each class may be
1463  assigned its own set of attributes such as bandwidth limits or
1464  queueing priorities. Some qdiscs even allow borrowing of bandwidth
1465  between classes.
1466
1467- *Classifiers (cls)* are used to decide which qdisc/class the packet
1468  should be enqueued to. Different types of classifiers exists,
1469  ranging from classification based on protocol header values to
1470  classification based on packet priority or firewall marks.
1471  Additionally most classifiers support *extended matches (ematch)*
1472  which allow extending classifiers by a set of matcher modules, and
1473  *actions* which allow classifiers to take actions such as mangling,
1474  mirroring, or even rerouting of packets.
1475
1476.Default Qdisc
1477
1478The default qdisc used on all network devices is `pfifo_fast`.
1479Network devices which do not require a transmit queue such as the
1480loopback device do not have a default qdisc attached. The `pfifo_fast`
1481qdisc provides three bands to prioritize interactive traffic over bulk
1482traffic. Classification is based on the packet priority (diffserv).
1483
1484image:qdisc_default.png["Default Qdisc"]
1485
1486.Multiqueue Default Qdisc
1487
1488If the network device provides multiple transmit queues the `mq`
1489qdisc is used by default. It will automatically create a separate
1490class for each transmit queue available and will also replace
1491the single per device tx lock with a per queue lock.
1492
1493image:qdisc_mq.png["Multiqueue default Qdisc"]
1494
1495.Example of a customized classful qdisc setup
1496
1497The following figure illustrates a possible combination of different
1498queueing and classification modules to implement quality of service
1499needs.
1500
1501image:tc_overview.png["Classful Qdisc diagram"]
1502
1503=== Traffic Control Object
1504
1505Each type traffic control module (qdisc, class, classifier) is
1506represented by its own structure. All of them are based on the traffic
1507control object represented by `struct rtnl_tc` which itself is based
1508on the generic object `struct nl_object` to make it cacheable. The
1509traffic control object contains all attributes, implementation details
1510and statistics that are shared by all of the traffic control object
1511types.
1512
1513image:tc_obj.png["struct rtnl_tc hierarchy"]
1514
1515It is not possible to allocate a `struct rtnl_tc` object, instead the
1516actual tc object types must be allocated directly using
1517`rtnl_qdisc_alloc()`, `rtnl_class_alloc()`, `rtnl_cls_alloc()` and
1518then casted to `struct rtnl_tc` using the `TC_CAST()` macro.
1519
1520.Usage Example: Allocation, Casting, Freeing
1521[source,c]
1522-----
1523#include <netlink/route/tc.h>
1524#include <netlink/route/qdisc.h>
1525
1526struct rtnl_qdisc *qdisc;
1527
1528/* Allocation of a qdisc object */
1529qdisc = rtnl_qdisc_alloc();
1530
1531/* Cast the qdisc to a tc object using TC_CAST() to use rtnl_tc_ functions. */
1532rtnl_tc_set_mpu(TC_CAST(qdisc), 64);
1533
1534/* Free the qdisc object */
1535rtnl_qdisc_put(qdisc);
1536-----
1537
1538[[tc_attr]]
1539==== Attributes
1540
1541Handle::
1542The handle uniquely identifies a tc object and is used to refer
1543to other tc objects when constructing tc trees.
1544+
1545[source,c]
1546-----
1547void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t handle);
1548uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc);
1549-----
1550
1551Interface Index::
1552The interface index specifies the network device the traffic object
1553is attached to. The function `rtnl_tc_set_link()` should be preferred
1554when setting the interface index. It stores the reference to the link
1555object in the tc object and allows retrieving the `mtu` and `linktype`
1556automatically.
1557+
1558[source,c]
1559-----
1560void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex);
1561void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link);
1562int rtnl_tc_get_ifindex(struct rtnl_tc *tc);
1563-----
1564
1565Link Type::
1566The link type specifies the kind of link that is used by the network
1567device (e.g. ethernet, ATM, ...). It is derived automatically when
1568the network device is specified with `rtnl_tc_set_link()`.
1569The default fallback is `ARPHRD_ETHER` (ethernet).
1570+
1571[source,c]
1572-----
1573void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type);
1574uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc);
1575-----
1576
1577Kind::
1578The kind character string specifies the type of qdisc, class,
1579classifier. Setting the kind results in the module specific
1580structure being allocated. Therefore it is imperative to call
1581`rtnl_tc_set_kind()` before using any type specific API functions
1582such as `rtnl_htb_set_rate()`.
1583+
1584[source,c]
1585-----
1586int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind);
1587char *rtnl_tc_get_kind(struct rtnl_tc *tc);
1588-----
1589
1590MPU::
1591The Minimum Packet Unit specifies the minimum packet size which will
1592be transmitted
1593ever be seen by this traffic control object. This value is used for
1594rate calculations. Not all object implementations will make use of
1595this value. The default value is 0.
1596+
1597[source,c]
1598-----
1599void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu);
1600uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc);
1601-----
1602
1603MTU::
1604The Maximum Transmission Unit specifies the maximum packet size which
1605will be transmitted. The value is derived from the link specified
1606with `rtnl_tc_set_link()` if not overwritten with `rtnl_tc_set_mtu()`.
1607If no link and MTU is specified, the value defaults to 1500
1608(ethernet).
1609+
1610[source,c]
1611-----
1612void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu);
1613uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc);
1614-----
1615
1616Overhead::
1617The overhead specifies the additional overhead per packet caused by
1618the network layer. This value can be used to correct packet size
1619calculations if the packet size on the wire does not match the packet
1620size seen by the kernel. The default value is 0.
1621+
1622[source,c]
1623-----
1624void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead);
1625uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc);
1626-----
1627
1628Parent::
1629Specifies the parent traffic control object. The parent is identified
1630by its handle. Special values are:
1631- `TC_H_ROOT`: attach tc object directly to network device (root
1632  qdisc, root classifier)
1633- `TC_H_INGRESS`: same as `TC_H_ROOT` but on the ingress side of the
1634  network stack.
1635+
1636[source,c]
1637-----
1638void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent);
1639uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc);
1640-----
1641
1642Statistics::
1643Generic statistics, see <<tc_stats>> for additional information.
1644+
1645[source,c]
1646-----
1647uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id);
1648-----
1649
1650[[tc_stats]]
1651==== Accessing Statistics
1652
1653The traffic control object holds a set of generic statistics. Not all
1654traffic control modules will make use of all of these statistics. Some
1655modules may provide additional statistics via their own APIs.
1656
1657.Statistic identifiers `(enum rtnl_tc_stat)`
1658[cols="m,,", options="header", frame="topbot"]
1659|====================================================================
1660| ID                 | Type    | Description
1661| RTNL_TC_PACKETS    | Counter | Total # of packets transmitted
1662| RTNL_TC_BYTES      | Counter | Total # of bytes transmitted
1663| RTNL_TC_RATE_BPS   | Rate    | Current bytes/s rate
1664| RTNL_TC_RATE_PPS   | Rate    | Current packets/s rate
1665| RTNL_TC_QLEN       | Rate    | Current length of the queue
1666| RTNL_TC_BACKLOG    | Rate    | # of packets currently backlogged
1667| RTNL_TC_DROPS      | Counter | # of packets dropped
1668| RTNL_TC_REQUEUES   | Counter | # of packets requeued
1669| RTNL_TC_OVERLIMITS | Counter | # of packets that exceeded the limit
1670|====================================================================
1671
1672NOTE: `RTNL_TC_RATE_BPS` and `RTNL_TC_RATE_PPS` only return meaningful
1673      values if a rate estimator has been configured.
1674
1675.Usage Example: Retrieving tc statistics
1676[source,c]
1677-------
1678#include <netlink/route/tc.h>
1679
1680uint64_t drops, qlen;
1681
1682drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS);
1683qlen  = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_QLEN);
1684-------
1685
1686==== Rate Table Calculations
1687TODO
1688
1689[[tc_qdisc]]
1690=== Queueing Discipline (qdisc)
1691
1692.Classless Qdisc
1693
1694The queueing discipline (qdisc) is used to implement fair queueing,
1695prioritization or rate control. It provides a _enqueue()_ and
1696_dequeue()_ operation. Whenever a network packet leaves the networking
1697stack over a network device, be it a physical or virtual device, it
1698will be enqueued to a qdisc unless the device is queueless. The
1699_enqueue()_ operation is followed by an immediate call to _dequeue()_
1700for the same qdisc to eventually retrieve a packet which can be
1701scheduled for transmission by the driver. Additionally, the networking
1702stack runs a watchdog which polls the qdisc regularly to dequeue and
1703send packets even if no new packets are being enqueued.
1704
1705This additional watchdog is required due to the fact that qdiscs may
1706hold on to packets and not return any packets upon _dequeue()_ in
1707order to enforce bandwidth restrictions.
1708
1709image:classless_qdisc_nbands.png[alt="Multiband Qdisc", float="right"]
1710
1711The figure illustrates a trivial example of a classless qdisc
1712consisting of three bands (queues). Use of multiple bands is a common
1713technique in qdiscs to implement fair queueing between flows or
1714prioritize differentiated services.
1715
1716Classless qdiscs can be regarded as a blackbox, their inner workings
1717can only be steered using the configuration parameters provided by the
1718qdisc. There is no way of taking influence on the structure of its
1719internal queues itself.
1720
1721.Classful Qdisc
1722
1723Classful qdiscs allow for the queueing structure and classification
1724process to be created by the user.
1725
1726image:classful_qdisc.png["Classful Qdisc"]
1727
1728The figure above shows a classful qdisc with a classifier attached to
1729it which will make the decision whether to enqueue a packet to traffic
1730class +1:1+ or +1:2+. Unlike with classless qdiscs, classful qdiscs
1731allow the classification process and the structure of the queues to be
1732defined by the user. This allows for complex traffic class rules to
1733be applied.
1734
1735.List of Qdisc Implementations
1736[options="header", frame="topbot", cols="2,1^,8"]
1737|======================================================================
1738| Qdisc     | Classful | Description
1739| ATM       | Yes      | FIXME
1740| Blackhole | No       | This qdisc will drop all packets passed to it.
1741| CBQ       | Yes      |
1742The CBQ (Class Based Queueing) is a classful qdisc which allows
1743creating traffic classes and enforce bandwidth limitations for each
1744class.
1745| DRR       | Yes      |
1746The DRR (Deficit Round Robin) scheduler is a classful qdisc
1747implementing fair queueing. Each class is assigned a quantum specifying
1748the maximum number of bytes that can be served per round.  Unused
1749quantum at the end of the round is carried over to the next round.
1750| DSMARK   | Yes       | FIXME
1751| FIFO     | No        | FIXME
1752| GRED     | No        | FIXME
1753| HFSC     | Yes       | FIXME
1754| HTB      | Yes       | FIXME
1755| mq       | Yes       | FIXME
1756| multiq   | Yes       | FIXME
1757| netem    | No        | FIXME
1758| Prio     | Yes       | FIXME
1759| RED      | Yes       | FIXME
1760| SFQ      | Yes       | FIXME
1761| TBF      | Yes       | FIXME
1762| teql     | No        | FIXME
1763|======================================================================
1764
1765
1766.QDisc API Overview
1767[cols="a,a", options="header", frame="topbot"]
1768|====================================================================
1769| Attribute | C Interface
1770|
1771Allocation / Freeing::
1772|
1773[source,c]
1774-----
1775struct rtnl_qdisc *rtnl_qdisc_alloc(void);
1776void rtnl_qdisc_put(struct rtnl_qdisc *qdisc);
1777-----
1778|
1779Addition::
1780|
1781[source,c]
1782-----
1783int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags,
1784				 struct nl_msg **result);
1785int rtnl_qdisc_add(struct nl_sock *sock, struct rtnl_qdisc *qdisc,
1786                   int flags);
1787-----
1788|
1789Modification::
1790|
1791[source,c]
1792-----
1793int rtnl_qdisc_build_change_request(struct rtnl_qdisc *old,
1794				    struct rtnl_qdisc *new,
1795				    struct nl_msg **result);
1796int rtnl_qdisc_change(struct nl_sock *sock, struct rtnl_qdisc *old,
1797		      struct rtnl_qdisc *new);
1798-----
1799|
1800Deletion::
1801|
1802[source,c]
1803-----
1804int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc,
1805				    struct nl_msg **result);
1806int rtnl_qdisc_delete(struct nl_sock *sock, struct rtnl_qdisc *qdisc);
1807-----
1808|
1809Cache::
1810|
1811[source,c]
1812-----
1813int rtnl_qdisc_alloc_cache(struct nl_sock *sock,
1814			   struct nl_cache **cache);
1815struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int, uint32_t);
1816
1817struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t);
1818-----
1819|====================================================================
1820
1821[[qdisc_get]]
1822==== Retrieving Qdisc Configuration
1823
1824The function rtnl_qdisc_alloc_cache() is used to retrieve the current
1825qdisc configuration in the kernel. It will construct a +RTM_GETQDISC+
1826netlink message, requesting the complete list of qdiscs configured in
1827the kernel.
1828
1829[source,c]
1830-------
1831#include <netlink/route/qdisc.h>
1832
1833struct nl_cache *all_qdiscs;
1834
1835if (rtnl_link_alloc_cache(sock, &all_qdiscs) < 0)
1836	/* error while retrieving qdisc cfg */
1837-------
1838
1839The cache can be accessed using the following functions:
1840
1841- Search qdisc with matching ifindex and handle:
1842+
1843[source,c]
1844--------
1845struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, uint32_t handle);
1846--------
1847- Search qdisc with matching ifindex and parent:
1848+
1849[source,c]
1850--------
1851struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, int ifindex , uint32_t parent);
1852--------
1853- Or any of the generic cache functions (e.g. nl_cache_search(), nl_cache_dump(), etc.)
1854
1855.Example: Search and print qdisc
1856[source,c]
1857-------
1858struct rtnl_qdisc *qdisc;
1859int ifindex;
1860
1861ifindex = rtnl_link_get_ifindex(eth0_obj);
1862
1863/* search for qdisc on eth0 with handle 1:0 */
1864if (!(qdisc = rtnl_qdisc_get(all_qdiscs, ifindex, TC_HANDLE(1, 0))))
1865	/* no such qdisc found */
1866
1867nl_object_dump(OBJ_CAST(qdisc), NULL);
1868
1869rtnl_qdisc_put(qdisc);
1870-------
1871
1872[[qdisc_add]]
1873==== Adding a Qdisc
1874
1875In order to add a new qdisc to the kernel, a qdisc object needs to be
1876allocated. It will hold all attributes of the new qdisc.
1877
1878[source,c]
1879-----
1880#include <netlink/route/qdisc.h>
1881
1882struct rtnl_qdisc *qdisc;
1883
1884if (!(qdisc = rtnl_qdisc_alloc()))
1885	/* OOM error */
1886-----
1887
1888The next step is to specify all generic qdisc attributes using the tc
1889object interface described in the section <<tc_attr>>.
1890
1891The following attributes must be specified:
1892- IfIndex
1893- Parent
1894- Kind
1895
1896[source,c]
1897-----
1898/* Attach qdisc to device eth0 */
1899rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj);
1900
1901/* Make this the root qdisc */
1902rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
1903
1904/* Set qdisc identifier to 1:0, if left unspecified, a handle will be generated by the kernel. */
1905rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1, 0));
1906
1907/* Make this a HTB qdisc */
1908rtnl_tc_set_kind(TC_CAST(qdisc), "htb");
1909-----
1910
1911After specifying the qdisc kind (rtnl_tc_set_kind()) the qdisc type
1912specific interface can be used to set attributes which are specific
1913to the respective qdisc implementations:
1914
1915[source,c]
1916------
1917/* HTB feature: Make unclassified packets go to traffic class 1:5 */
1918rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, 5));
1919------
1920
1921Finally, the qdisc is ready to be added and can be passed on to the
1922function rntl_qdisc_add() which takes care of constructing a netlink
1923message requesting the addition of the new qdisc, sends the message to
1924the kernel and waits for the response by the kernel. The function
1925returns 0 if the qdisc has been added or updated successfully or a
1926negative error code if an error occured.
1927
1928CAUTION: The kernel operation for updating and adding a qdisc is the
1929         same. Therefore when calling rtnl_qdisc_add() any existing
1930         qdisc with matching handle will be updated unless the flag
1931         NLM_F_EXCL is specified.
1932
1933The following flags may be specified:
1934[horizontal]
1935NLM_F_CREATE::  Create qdisc if it does not exist, otherwise
1936                -NLE_OBJ_NOTFOUND is returned.
1937NLM_F_REPLACE:: If another qdisc is already attached to the same
1938                parent and their handles mismatch, replace the qdisc
1939                instead of returning -EEXIST.
1940NLM_F_EXCL::    Return -NLE_EXISTS if a qdisc with matching handles
1941                exists already.
1942
1943WARNING: The function rtnl_qdisc_add() requires administrator
1944         privileges.
1945
1946[source,c]
1947------
1948/* Submit request to kernel and wait for response */
1949err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE);
1950
1951/* Return the qdisc object to free memory resources */
1952rtnl_qdisc_put(qdisc);
1953
1954if (err < 0) {
1955	fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err));
1956	return err;
1957}
1958------
1959
1960==== Deleting a qdisc
1961
1962[source,c]
1963------
1964#include <netlink/route/qdisc.h>
1965
1966struct rtnl_qdisc *qdisc;
1967
1968qdisc = rtnl_qdisc_alloc();
1969
1970rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj);
1971rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT);
1972
1973rtnl_qdisc_delete(sock, qdisc)
1974
1975rtnl_qdisc_put(qdisc);
1976------
1977
1978WARNING: The function rtnl_qdisc_delete() requires administrator
1979         privileges.
1980
1981
1982[[qdisc_htb]]
1983==== HTB - Hierarchical Token Bucket
1984
1985.HTB Qdisc Attributes
1986
1987Default Class::
1988The default class is the fallback class to which all traffic which
1989remained unclassified is directed to. If no default class or an
1990invalid default class is specified, packets are transmitted directly
1991to the next layer (direct transmissions).
1992+
1993[source,c]
1994-----
1995uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc);
1996int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls);
1997-----
1998
1999Rate to Quantum (r2q)::
2000TODO
2001+
2002[source,c]
2003-----
2004uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc);
2005int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum);
2006-----
2007
2008
2009.HTB Class Attributes
2010
2011Priority::
2012+
2013[source,c]
2014-----
2015uint32_t rtnl_htb_get_prio(struct rtnl_class *class);
2016int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio);
2017-----
2018
2019Rate::
2020The rate (bytes/s) specifies the maximum bandwidth an individual class
2021can use without borrowing. The rate of a class should always be greater
2022or erqual than the rate of its children.
2023+
2024[source,c]
2025-----
2026uint32_t rtnl_htb_get_rate(struct rtnl_class *class);
2027int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil);
2028-----
2029
2030Ceil Rate::
2031The ceil rate specifies the maximum bandwidth an individual class
2032can use. This includes bandwidth that is being borrowed from other
2033classes. Ceil defaults to the class rate implying that by default
2034the class will not borrow. The ceil rate of a class should always
2035be greater or erqual than the ceil rate of its children.
2036+
2037[source,c]
2038-----
2039uint32_t rtnl_htb_get_ceil(struct rtnl_class *class);
2040int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil);
2041-----
2042
2043Burst::
2044TODO
2045+
2046[source,c]
2047-----
2048uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class);
2049int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t burst);
2050-----
2051
2052Ceil Burst::
2053TODO
2054+
2055[source,c]
2056-----
2057uint32_t rtnl_htb_get_cbuffer(struct rtnl_class *);
2058int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t);
2059-----
2060
2061Quantum::
2062TODO
2063+
2064[source,c]
2065-----
2066uint32_t rtnl_htb_get_quantum(struct rtnl_class *class);
2067int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum);
2068-----
2069
2070
2071[[tc_class]]
2072=== Class
2073
2074[options="header", cols="s,a,a,a,a"]
2075|=======================================================================
2076|        | UNSPEC             | TC_H_ROOT          | 0:pY  | pX:pY
2077| UNSPEC 3+^|
2078[horizontal]
2079qdisc =:: root-qdisc
2080class =:: root-qdisc:0
2081|
2082[horizontal]
2083qdisc =:: pX:0
2084class =:: pX:0
2085| 0:hY 3+^|
2086[horizontal]
2087qdisc =:: root-qdisc
2088class =:: root-qdisc:hY
2089|
2090[horizontal]
2091qdisc =:: pX:0
2092class =:: pX:hY
2093| hX:hY 3+^|
2094[horizontal]
2095qdisc =:: hX:
2096class =:: hX:hY
2097|
2098if pX != hX
2099    return -EINVAL
2100[horizontal]
2101qdisc =:: hX:
2102class =:: hX:hY
2103|=======================================================================
2104
2105[[tc_cls]]
2106=== Classifier (cls)
2107
2108TODO
2109
2110[[tc_classid_mngt]]
2111=== ClassID Management
2112
2113TODO
2114
2115[[tc_pktloc]]
2116=== Packet Location Aliasing (pktloc)
2117
2118TODO
2119
2120[[tc_api]]
2121=== Traffic Control Module API
2122
2123TODO
2124