From 63548f5664e0e149f5e51219ad6f582f985e3c42 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Jul 2011 12:48:00 +0200 Subject: documentation updates --- doc/Doxyfile.in | 2 +- doc/Makefile.am | 24 +- doc/core.txt | 2 + doc/index.txt | 16 + doc/route.txt | 720 +++++++++++++++++++++++++++++++++++ doc/src/examples/NLA_PUT.c | 15 - doc/src/examples/msg_constr_attr.c | 51 --- doc/src/examples/msg_parse_attr.c | 50 --- doc/src/examples/my_parse.c | 11 - doc/src/examples/nl_cb_set.c | 14 - doc/src/examples/nl_send_simple.c | 11 - doc/src/examples/nla_flag.c | 7 - doc/src/examples/nla_for_each_attr.c | 11 - doc/src/examples/nla_nest_start.c | 16 - doc/src/examples/nla_ok.c | 10 - doc/src/examples/nla_parse_nested.c | 12 - doc/src/examples/nla_put.c | 14 - doc/src/examples/nlmsg_for_each.c | 7 - doc/src/examples/nlmsg_parse.c | 29 -- doc/src/examples/nlmsg_put.c | 31 -- doc/src/examples/sk_group_example.c | 43 --- doc/src/genl.c | 10 - doc/src/nf.c | 10 - doc/src/route.c | 10 - doc/src/toc.c | 7 +- lib/msg.c | 6 - lib/route/cls.c | 2 + lib/route/tc.c | 1 - 28 files changed, 758 insertions(+), 384 deletions(-) create mode 100644 doc/index.txt create mode 100644 doc/route.txt delete mode 100644 doc/src/examples/NLA_PUT.c delete mode 100644 doc/src/examples/msg_constr_attr.c delete mode 100644 doc/src/examples/msg_parse_attr.c delete mode 100644 doc/src/examples/my_parse.c delete mode 100644 doc/src/examples/nl_cb_set.c delete mode 100644 doc/src/examples/nl_send_simple.c delete mode 100644 doc/src/examples/nla_flag.c delete mode 100644 doc/src/examples/nla_for_each_attr.c delete mode 100644 doc/src/examples/nla_nest_start.c delete mode 100644 doc/src/examples/nla_ok.c delete mode 100644 doc/src/examples/nla_parse_nested.c delete mode 100644 doc/src/examples/nla_put.c delete mode 100644 doc/src/examples/nlmsg_for_each.c delete mode 100644 doc/src/examples/nlmsg_parse.c delete mode 100644 doc/src/examples/nlmsg_put.c delete mode 100644 doc/src/examples/sk_group_example.c delete mode 100644 doc/src/genl.c delete mode 100644 doc/src/nf.c delete mode 100644 doc/src/route.c diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in index 9bfb711..ed78bfe 100644 --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -642,7 +642,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = src/examples +EXAMPLE_PATH = src # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/doc/Makefile.am b/doc/Makefile.am index 0dd044b..dc52163 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,17 +1,25 @@ # -*- Makefile -*- -.PHONY: gendoc +.PHONY: gendoc api_refs asciidoc -ASCIIDOCOPTS=-n -a pygments -a toc -a language=c -a icons \ +ASCIIDOCOPTS=-a pygments -a language=c -a icons \ -a imagesdir="images/" \ -a stylesdir="${abs_srcdir}/stylesheets/" -gendoc: +%.html: %.txt + asciidoc $(ASCIIDOCOPTS) $< + ./doxygen-link.py libnl.dict $@ > doxygen-link.tmp + mv doxygen-link.tmp $@ + +asciidoc: core.html route.html index.html link.html + +api_ref: doxygen Doxyfile; ./gen-tags.sh | ./tags2dict.sh > libnl.dict - asciidoc $(ASCIIDOCOPTS) core.txt - ./doxygen-link.py libnl.dict core.html > core.tmp.html - mv core.tmp.html core.html -distclean-local: - rm -f api/* libnl.tags *.html; +gendoc: + $(MAKE) api_ref + $(MAKE) asciidoc + +clean-local: + rm -f api/* libnl.dict *.html; diff --git a/doc/core.txt b/doc/core.txt index 7ae3081..22b0e1c 100644 --- a/doc/core.txt +++ b/doc/core.txt @@ -8,6 +8,8 @@ Netlink Core Library ==================== Thomas Graf 3.0, March 30 2011: +:toc: +:numbered: == Introduction diff --git a/doc/index.txt b/doc/index.txt new file mode 100644 index 0000000..c59be0e --- /dev/null +++ b/doc/index.txt @@ -0,0 +1,16 @@ +libnl +===== +Thomas Graf +3.0, April 12 2011: + +== Table of Contents +=== Libraries + - link:core.html[Core Library] + - link:route.html[Routing Family] + +=== Tools + - link:link.html[Link Utility] + +=== Python Packages + - netlink.core + - netlink.route.link diff --git a/doc/route.txt b/doc/route.txt new file mode 100644 index 0000000..4c184e9 --- /dev/null +++ b/doc/route.txt @@ -0,0 +1,720 @@ +//// + vim.syntax: asciidoc + + Copyright (c) 2011 Thomas Graf +//// + +Netlink Routing Library +======================= +Thomas Graf +3.0, March 23 2011: +:toc: +:icons: +:numbered: + + +== Introduction + +== Introduction to the Library + +== Addresses + +== Links / Interfaces + +== Neighbouring + +== Routing + +== Traffic Control + +The traffic control architecture allows the queueing and +prioritization of packets before they are enqueued to the network +driver. To a limited degree it is also possible to take control of +network traffic as it enters the network stack. + +The architecture consists of three different types of modules: + +- *Queueing disciplines (qdisc)* provide a mechanism to enqueue packets + in different forms. They may be used to implement fair queueing, + prioritization of differentiated services, enforce bandwidth + limitations, or even to simulate network behaviour such as packet + loss and packet delay. Qdiscs can be classful in which case they + allow traffic classes described in the next paragraph to be attached + to them. + +- *Traffic classes (class)* are supported by several qdiscs to build + a tree structure for different types of traffic. Each class may be + assigned its own set of attributes such as bandwidth limits or + queueing priorities. Some qdiscs even allow borrowing of bandwidth + between classes. + +- *Classifiers (cls)* are used to decide which qdisc/class the packet + should be enqueued to. Different types of classifiers exists, + ranging from classification based on protocol header values to + classification based on packet priority or firewall marks. + Additionally most classifiers support *extended matches (ematch)* + which allow extending classifiers by a set of matcher modules, and + *actions* which allow classifiers to take actions such as mangling, + mirroring, or even rerouting of packets. + +.Default Qdisc + +The default qdisc used on all network devices is `pfifo_fast`. +Network devices which do not require a transmit queue such as the +loopback device do not have a default qdisc attached. The `pfifo_fast` +qdisc provides three bands to prioritize interactive traffic over bulk +traffic. Classification is based on the packet priority (diffserv). + +image:qdisc_default.png["Default Qdisc"] + +.Multiqueue Default Qdisc + +If the network device provides multiple transmit queues the `mq` +qdisc is used by default. It will automatically create a separate +class for each transmit queue available and will also replace +the single per device tx lock with a per queue lock. + +image:qdisc_mq.png["Multiqueue default Qdisc"] + +.Example of a customized classful qdisc setup + +The following figure illustrates a possible combination of different +queueing and classification modules to implement quality of service +needs. + +image:tc_overview.png["Classful Qdisc diagram"] + +=== Traffic Control Object + +Each type traffic control module (qdisc, class, classifier) is +represented by its own structure. All of them are based on the traffic +control object represented by `struct rtnl_tc` which itself is based +on the generic object `struct nl_object` to make it cacheable. The +traffic control object contains all attributes, implementation details +and statistics that are shared by all of the traffic control object +types. + +image:tc_obj.png["struct rtnl_tc hierarchy"] + +It is not possible to allocate a `struct rtnl_tc` object, instead the +actual tc object types must be allocated directly using +`rtnl_qdisc_alloc()`, `rtnl_class_alloc()`, `rtnl_cls_alloc()` and +then casted to `struct rtnl_tc` using the `TC_CAST()` macro. + +.Usage Example: Allocation, Casting, Freeing +[source,c] +----- +#include +#include + +struct rtnl_qdisc *qdisc; + +/* Allocation of a qdisc object */ +qdisc = rtnl_qdisc_alloc(); + +/* Cast the qdisc to a tc object using TC_CAST() to use rtnl_tc_ functions. */ +rtnl_tc_set_mpu(TC_CAST(qdisc), 64); + +/* Free the qdisc object */ +rtnl_qdisc_put(qdisc); +----- + +[[tc_attr]] +==== Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Handle:: +The handle uniquely identifies a tc object and is used to refer +to other tc objects when constructing tc trees. +| +[source,c] +----- +void rtnl_tc_set_handle(struct rtnl_tc *tc, uint32_t handle); +uint32_t rtnl_tc_get_handle(struct rtnl_tc *tc); +----- +| +IfIndex:: +The interface index specifies the network device the traffic object +is attached to. The function `rtnl_tc_set_link()` should be preferred +when setting the interface index. It stores the reference to the link +object in the tc object and allows retrieving the `mtu` and `linktype` +automatically. +| +[source,c] +----- +void rtnl_tc_set_ifindex(struct rtnl_tc *tc, int ifindex); +void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link); +int rtnl_tc_get_ifindex(struct rtnl_tc *tc); +----- +| +LinkType:: +The link type specifies the kind of link that is used by the network +device (e.g. ethernet, ATM, ...). It is derived automatically when +the network device is specified with `rtnl_tc_set_link()`. +The default fallback is `ARPHRD_ETHER` (ethernet). +| +[source,c] +----- +void rtnl_tc_set_linktype(struct rtnl_tc *tc, uint32_t type); +uint32_t rtnl_tc_get_linktype(struct rtnl_tc *tc); +----- +| +Kind:: +The kind character string specifies the type of qdisc, class, +classifier. Setting the kind results in the module specific +structure being allocated. Therefore it is imperative to call +`rtnl_tc_set_kind()` before using any type specific API functions +such as `rtnl_htb_set_rate()`. +| +[source,c] +----- +int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind); +char *rtnl_tc_get_kind(struct rtnl_tc *tc); +----- +| +MPU:: +The Minimum Packet Unit specifies the minimum packet size which will +be transmitted +ever be seen by this traffic control object. This value is used for +rate calculations. Not all object implementations will make use of +this value. The default value is 0. +| +[source,c] +----- +void rtnl_tc_set_mpu(struct rtnl_tc *tc, uint32_t mpu); +uint32_t rtnl_tc_get_mpu(struct rtnl_tc *tc); +----- +| +MTU:: +The Maximum Transmission Unit specifies the maximum packet size which +will be transmitted. The value is derived from the link specified +with `rtnl_tc_set_link()` if not overwritten with `rtnl_tc_set_mtu()`. +If no link and MTU is specified, the value defaults to 1500 +(ethernet). +| +[source,c] +----- +void rtnl_tc_set_mtu(struct rtnl_tc *tc, uint32_t mtu); +uint32_t rtnl_tc_get_mtu(struct rtnl_tc *tc); +----- +| +Overhead:: +The overhead specifies the additional overhead per packet caused by +the network layer. This value can be used to correct packet size +calculations if the packet size on the wire does not match the packet +size seen by the kernel. The default value is 0. +| +[source,c] +----- +void rtnl_tc_set_overhead(struct rtnl_tc *tc, uint32_t overhead); +uint32_t rtnl_tc_get_overhead(struct rtnl_tc *tc); +----- +| +Parent:: +Specifies the parent traffic control object. The parent is identifier +by its handle. Special values are: +- `TC_H_ROOT`: attach tc object directly to network device (root + qdisc, root classifier) +- `TC_H_INGRESS`: same as `TC_H_ROOT` but on the ingress side of the + network stack. +| +[source,c] +----- +void rtnl_tc_set_parent(struct rtnl_tc *tc, uint32_t parent); +uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc); +----- +| +Statistics:: +Generic statistics, see <> for +additional information. +| +[source,c] +----- +uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id); +----- +|==================================================================== + +[[tc_stats]] +==== Accessing Statistics + +The traffic control object holds a set of generic statistics. Not all +traffic control modules will make use of all of these statistics. Some +modules may provide additional statistics via their own APIs. + +.Statistic identifiers `(enum rtnl_tc_stat)` +[cols="m,,", options="header", frame="topbot"] +|==================================================================== +| ID | Type | Description +| RTNL_TC_PACKETS | Counter | Total # of packets transmitted +| RTNL_TC_BYTES | Counter | Total # of bytes transmitted +| RTNL_TC_RATE_BPS | Rate | Current bytes/s rate +| RTNL_TC_RATE_PPS | Rate | Current packets/s rate +| RTNL_TC_QLEN | Rate | Current length of the queue +| RTNL_TC_BACKLOG | Rate | # of packets currently backloged +| RTNL_TC_DROPS | Counter | # of packets dropped +| RTNL_TC_REQUEUES | Counter | # of packets requeued +| RTNL_TC_OVERLIMITS | Counter | # of packets that exceeded the limit +|==================================================================== + +NOTE: `RTNL_TC_RATE_BPS` and `RTNL_TC_RATE_PPS` only return meaningful + values if a rate estimator has been configured. + +.Usage Example: Retrieving tc statistics +[source,c] +------- +#include + +uint64_t drops, qlen; + +drops = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_DROPS); +qlen = rtnl_tc_get_stat(TC_CAST(qdisc), RTNL_TC_QLEN); +------- + +==== Rate Table Calculations + +[[tc_qdisc]] +=== Queueing Discipline (qdisc) + +.Classless Qdisc + +The queueing discipline (qdisc) is used to implement fair queueing, +priorization or rate control. It provides a _enqueue()_ and +_dequeue()_ operation. Whenever a network packet leaves the networking +stack over a network device, be it a physical or virtual device, it +will be enqueued to a qdisc unless the device is queueless. The +_enqueue()_ operation is followed by an immediate call to _dequeue()_ +for the same qdisc to eventually retrieve a packet which can be +scheduled for transmission by the driver. Additionally, the networking +stack runs a watchdog which polls the qdisc regularly to dequeue and +send packets even if no new packets are being enqueued. + +This additional watchdog is required due to the fact that qdiscs may +hold on to packets and not return any packets upon _dequeue()_ in +order to enforce bandwidth restrictions. + +image:classless_qdisc_nbands.png[alt="Multiband Qdisc", float="right"] + +The figure illustrates a trivial example of a classless qdisc +consisting of three bands (queues). Use of multiple bands is a common +technique in qdiscs to implement fair queueing between flows or +prioritize differentiated services. + +Classless qdiscs can be regarded as a blackbox, their inner workings +can only be steered using the configuration parameters provided by the +qdisc. There is no way of taking influence on the structure of its +internal queues itself. + +.Classful Qdisc + +Classful qdiscs allow for the queueing structure and classification +process to be created by the user. + +image:classful_qdisc.png["Classful Qdisc"] + +The figure above shows a classful qdisc with a classifier attached to +it which will make the decision whether to enqueue a packet to traffic +class +1:1+ or +1:2+. Unlike with classless qdiscs, classful qdiscs +allow the classification process and the structure of the queues to be +defined by the user. This allows for complex traffic class rules to +be applied. + +.List of Qdisc Implementations +[options="header", frame="topbot", cols="2,1^,8"] +|====================================================================== +| Qdisc | Classful | Description +| ATM | Yes | FIXME +| Blackhole | No | This qdisc will drop all packets passed to it. +| CBQ | Yes | +The CBQ (Class Based Queueing) is a classful qdisc which allows +creating traffic classes and enforce bandwidth limitations for each +class. +| DRR | Yes | +The DRR (Deficit Round Robin) scheduler is a classful qdisc +impelemting fair queueing. Each class is assigned a quantum specyfing +the maximum number of bytes that can be served per round. Unused +quantum at the end of the round is carried over to the next round. +| DSMARK | Yes | FIXME +| FIFO | No | FIXME +| GRED | No | FIXME +| HFSC | Yes | FIXME +| HTB | Yes | FIXME +| mq | Yes | FIXME +| multiq | Yes | FIXME +| netem | No | FIXME +| Prio | Yes | FIXME +| RED | Yes | FIXME +| SFQ | Yes | FIXME +| TBF | Yes | FIXME +| teql | No | FIXME +|====================================================================== + + +.QDisc API Overview +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Allocation / Freeing:: +| +[source,c] +----- +struct rtnl_qdisc *rtnl_qdisc_alloc(void); +void rtnl_qdisc_put(struct rtnl_qdisc *qdisc); +----- +| +Addition:: +| +[source,c] +----- +int rtnl_qdisc_build_add_request(struct rtnl_qdisc *qdisc, int flags, + struct nl_msg **result); +int rtnl_qdisc_add(struct nl_sock *sock, struct rtnl_qdisc *qdisc, + int flags); +----- +| +Modification:: +| +[source,c] +----- +int rtnl_qdisc_build_change_request(struct rtnl_qdisc *old, + struct rtnl_qdisc *new, + struct nl_msg **result); +int rtnl_qdisc_change(struct nl_sock *sock, struct rtnl_qdisc *old, + struct rtnl_qdisc *new); +----- +| +Deletion:: +| +[source,c] +----- +int rtnl_qdisc_build_delete_request(struct rtnl_qdisc *qdisc, + struct nl_msg **result); +int rtnl_qdisc_delete(struct nl_sock *sock, struct rtnl_qdisc *qdisc); +----- +| +Cache:: +| +[source,c] +----- +int rtnl_qdisc_alloc_cache(struct nl_sock *sock, + struct nl_cache **cache); +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int, uint32_t); + +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *, int, uint32_t); +----- +|==================================================================== + +[[qdisc_get]] +==== Retrieving Qdisc Configuration + +The function rtnl_qdisc_alloc_cache() is used to retrieve the current +qdisc configuration in the kernel. It will construct a +RTM_GETQDISC+ +netlink message, requesting the complete list of qdiscs configured in +the kernel. + +[source,c] +------- +#include + +struct nl_cache *all_qdiscs; + +if (rtnl_link_alloc_cache(sock, &all_qdiscs) < 0) + /* error while retrieving qdisc cfg */ +------- + +The cache can be accessed using the following functions: + +- Search qdisc with matching ifindex and handle: ++ +[source,c] +-------- +struct rtnl_qdisc *rtnl_qdisc_get(struct nl_cache *cache, int ifindex, uint32_t handle); +-------- +- Search qdisc with matching ifindex and parent: ++ +[source,c] +-------- +struct rtnl_qdisc *rtnl_qdisc_get_by_parent(struct nl_cache *cache, int ifindex , uint32_t parent); +-------- +- Or any of the generic cache functions (e.g. nl_cache_search(), nl_cache_dump(), etc.) + +.Example: Search and print qdisc +[source,c] +------- +struct rtnl_qdisc *qdisc; +int ifindex; + +ifindex = rtnl_link_get_ifindex(eth0_obj); + +/* search for qdisc on eth0 with handle 1:0 */ +if (!(qdisc = rtnl_qdisc_get(all_qdiscs, ifindex, TC_HANDLE(1, 0)))) + /* no such qdisc found */ + +nl_object_dump(OBJ_CAST(qdisc), NULL); + +rtnl_qdisc_put(qdisc); +------- + +[[qdisc_add]] +==== Adding a Qdisc + +In order to add a new qdisc to the kernel, a qdisc object needs to be +allocated. It will hold all attributes of the new qdisc. + +[source,c] +----- +#include + +struct rtnl_qdisc *qdisc; + +if (!(qdisc = rtnl_qdisc_alloc())) + /* OOM error */ +----- + +The next step is to specify all generic qdisc attributes using the tc +object interface described in the section <>. + +The following attributes must be specified: +- IfIndex +- Parent +- Kind + +[source,c] +----- +/* Attach qdisc to device eth0 */ +rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj); + +/* Make this the root qdisc */ +rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + +/* Set qdisc identifier to 1:0, if left unspecified, a handle will be generated by the kernel. */ +rtnl_tc_set_handle(TC_CAST(qdisc), TC_HANDLE(1, 0)); + +/* Make this a HTB qdisc */ +rtnl_tc_set_kind(TC_CAST(qdisc), "htb"); +----- + +After specyfing the qdisc kind (rtnl_tc_set_kind()) the qdisc type +specific interface can be used to set attributes which are specific +to the respective qdisc implementations: + +[source,c] +------ +/* HTB feature: Make unclassified packets go to traffic class 1:5 */ +rtnl_htb_set_defcls(qdisc, TC_HANDLE(1, 5)); +------ + +Finally, the qdisc is ready to be added and can be passed on to the +function rntl_qdisc_add() which takes care of constructing a netlink +message requesting the addition of the new qdisc, sends the message to +the kernel and waits for the response by the kernel. The function +returns 0 if the qdisc has been added or updated successfully or a +negative error code if an error occured. + +CAUTION: The kernel operation for updating and adding a qdisc is the + same. Therefore when calling rtnl_qdisc_add() any existing + qdisc with matching handle will be updated unless the flag + NLM_F_EXCL is specified. + +The following flags may be specified: +[horizontal] +NLM_F_CREATE:: Create qdisc if it does not exist, otherwise + -NLE_OBJ_NOTFOUND is returned. +NLM_F_REPLACE:: If another qdisc is already attached to the same + parent and their handles mismatch, replace the qdisc + instead of returning -EEXIST. +NLM_F_EXCL:: Return -NLE_EXISTS if a qdisc with matching handles + exists already. + +WARNING: The function rtnl_qdisc_add() requires administrator + privileges. + +[source,c] +------ +/* Submit request to kernel and wait for response */ +err = rtnl_qdisc_add(sock, qdisc, NLM_F_CREATE); + +/* Return the qdisc object to free memory resources */ +rtnl_qdisc_put(qdisc); + +if (err < 0) { + fprintf(stderr, "Unable to add qdisc: %s\n", nl_geterror(err)); + return err; +} +------ + +==== Deleting a qdisc + +[source,c] +------ +#include + +struct rtnl_qdisc *qdisc; + +qdisc = rtnl_qdisc_alloc(); + +rtnl_tc_set_link(TC_CAST(qdisc), eth0_obj); +rtnl_tc_set_parent(TC_CAST(qdisc), TC_H_ROOT); + +rtnl_qdisc_delete(sock, qdisc) + +rtnl_qdisc_put(qdisc); +------ + +WARNING: The function rtnl_qdisc_delete() requires administrator + privileges. + + +[[qdisc_htb]] +==== HTB - Hierarchical Token Bucket + +.HTB Qdisc Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Default Class:: +The default class is the fallback class to which all traffic which +remained unclassified is directed to. If no default class or an +invalid default class is specified, packets are transmitted directly +to the next layer (direct transmissions). +| +[source,c] +----- +uint32_t rtnl_htb_get_defcls(struct rtnl_qdisc *qdisc); +int rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls); +----- +| +Rate to Quantum (r2q):: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_rate2quantum(struct rtnl_qdisc *qdisc); +int rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum); +----- +|==================================================================== + + +.HTB Class Attributes + +[cols="a,a", options="header", frame="topbot"] +|==================================================================== +| Attribute | C Interface +| +Priority:: +| +[source,c] +----- +uint32_t rtnl_htb_get_prio(struct rtnl_class *class); +int rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio); +----- +| +Rate:: +The rate (bytes/s) specifies the maximum bandwidth an invidivual class +can use without borrowing. The rate of a class should always be greater +or erqual than the rate of its children. +| +[source,c] +----- +uint32_t rtnl_htb_get_rate(struct rtnl_class *class); +int rtnl_htb_set_rate(struct rtnl_class *class, uint32_t ceil); +----- +| +Ceil Rate:: +The ceil rate specifies the maximum bandwidth an invidivual class +can use. This includes bandwidth that is being borrowed from other +classes. Ceil defaults to the class rate implying that by default +the class will not borrow. The ceil rate of a class should always +be greater or erqual than the ceil rate of its children. +| +[source,c] +----- +uint32_t rtnl_htb_get_ceil(struct rtnl_class *class); +int rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil); +----- +| +Burst:: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_rbuffer(struct rtnl_class *class); +int rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t burst); +----- +| +Ceil Burst:: +TODO +| +[source,c] +----- +uint32_t rtnl_htb_get_bbuffer(struct rtnl_class *class); +int rtnl_htb_set_bbuffer(struct rtnl_class *class, uint32_t burst); +----- +| +Quantum:: +TODO +| +[source,c] +----- +int rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum); +----- +|==================================================================== + +extern int rtnl_htb_set_cbuffer(struct rtnl_class *, uint32_t); + + + + +[[tc_class]] +=== Class + +[options="header", cols="s,a,a,a,a"] +|======================================================================= +| | UNSPEC | TC_H_ROOT | 0:pY | pX:pY +| UNSPEC 3+^| +[horizontal] +qdisc =:: root-qdisc +class =:: root-qdisc:0 +| +[horizontal] +qdisc =:: pX:0 +class =:: pX:0 +| 0:hY 3+^| +[horizontal] +qdisc =:: root-qdisc +class =:: root-qdisc:hY +| +[horizontal] +qdisc =:: pX:0 +class =:: pX:hY +| hX:hY 3+^| +[horizontal] +qdisc =:: hX: +class =:: hX:hY +| +if pX != hX + return -EINVAL +[horizontal] +qdisc =:: hX: +class =:: hX:hY +|======================================================================= + +[[tc_cls]] +=== Classifier (cls) + +[[tc_classid_mngt]] +=== ClassID Management + +[[tc_pktloc]] +=== Packet Location Aliasing (pktloc) + +[[tc_api]] +=== Traffic Control Module API + + diff --git a/doc/src/examples/NLA_PUT.c b/doc/src/examples/NLA_PUT.c deleted file mode 100644 index c3afb47..0000000 --- a/doc/src/examples/NLA_PUT.c +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include - -void construct_attrs(struct nl_msg *msg) -{ - NLA_PUT_STRING(msg, MY_ATTR_FOO1, "some text"); - NLA_PUT_U32(msg, MY_ATTR_FOO1, 0x1010); - NLA_PUT_FLAG(msg, MY_ATTR_FOO3, 1); - - return 0; - -nla_put_failure: - /* NLA_PUT* macros jump here in case of an error */ - return -EMSGSIZE; -} diff --git a/doc/src/examples/msg_constr_attr.c b/doc/src/examples/msg_constr_attr.c deleted file mode 100644 index bfa00fe..0000000 --- a/doc/src/examples/msg_constr_attr.c +++ /dev/null @@ -1,51 +0,0 @@ -struct nl_msg *build_msg(int ifindex, struct nl_addr *lladdr, int mtu) -{ - struct nl_msg *msg; - struct nlattr *info, *vlan; - struct ifinfomsg ifi = { - .ifi_family = AF_INET, - .ifi_index = ifindex, - }; - - /* Allocate a default sized netlink message */ - if (!(msg = nlmsg_alloc_simple(RTM_SETLINK, 0))) - return NULL; - - /* Append the protocol specific header (struct ifinfomsg)*/ - if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0) - goto nla_put_failure - - /* Append a 32 bit integer attribute to carry the MTU */ - NLA_PUT_U32(msg, IFLA_MTU, mtu); - - /* Append a unspecific attribute to carry the link layer address */ - NLA_PUT_ADDR(msg, IFLA_ADDRESS, lladdr); - - /* Append a container for nested attributes to carry link information */ - if (!(info = nla_nest_start(msg, IFLA_LINKINFO))) - goto nla_put_failure; - - /* Put a string attribute into the container */ - NLA_PUT_STRING(msg, IFLA_INFO_KIND, "vlan"); - - /* - * Append another container inside the open container to carry - * vlan specific attributes - */ - if (!(vlan = nla_nest_start(msg, IFLA_INFO_DATA))) - goto nla_put_failure; - - /* add vlan specific info attributes here... */ - - /* Finish nesting the vlan attributes and close the second container. */ - nla_nest_end(msg, vlan); - - /* Finish nesting the link info attribute and close the first container. */ - nla_nest_end(msg, info); - - return msg; - -nla_put_failure: - nlmsg_free(msg); - return NULL; -} diff --git a/doc/src/examples/msg_parse_attr.c b/doc/src/examples/msg_parse_attr.c deleted file mode 100644 index 6e275e9..0000000 --- a/doc/src/examples/msg_parse_attr.c +++ /dev/null @@ -1,50 +0,0 @@ -int parse_message(struct nlmsghdr *hdr) -{ - /* - * The policy defines two attributes: a 32 bit integer and a container - * for nested attributes. - */ - struct nla_policy attr_policy[] = { - [ATTR_FOO] = { .type = NLA_U32 }, - [ATTR_BAR] = { .type = NLA_NESTED }, - }; - struct nlattr *attrs[ATTR_MAX+1]; - int err; - - /* - * The nlmsg_parse() function will make sure that the message contains - * enough payload to hold the header (struct my_hdr), validates any - * attributes attached to the messages and stores a pointer to each - * attribute in the attrs[] array accessable by attribute type. - */ - if ((err = nlmsg_parse(hdr, sizeof(struct my_hdr), attrs, ATTR_MAX, - attr_policy)) < 0) - goto errout; - - if (attrs[ATTR_FOO]) { - /* - * It is safe to directly access the attribute payload without - * any further checks since nlmsg_parse() enforced the policy. - */ - uint32_t foo = nla_get_u32(attrs[ATTR_FOO]); - } - - if (attrs[ATTR_BAR]) { - struct *nested[NESTED_MAX+1]; - - /* - * Attributes nested in a container can be parsed the same way - * as top level attributes. - */ - err = nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_BAR], - nested_policy); - if (err < 0) - goto errout; - - // Process nested attributes here. - } - - err = 0; -errout: - return err; -} diff --git a/doc/src/examples/my_parse.c b/doc/src/examples/my_parse.c deleted file mode 100644 index c1ff637..0000000 --- a/doc/src/examples/my_parse.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -void my_parse(void *stream, int length) -{ - struct nlmsghdr *hdr = stream; - - while (nlmsg_ok(hdr, length)) { - // Parse message here - hdr = nlmsg_next(hdr, &length); - } -} diff --git a/doc/src/examples/nl_cb_set.c b/doc/src/examples/nl_cb_set.c deleted file mode 100644 index 4fbaefc..0000000 --- a/doc/src/examples/nl_cb_set.c +++ /dev/null @@ -1,14 +0,0 @@ -#include - -/* Allocate a callback set and initialize it to the verbose default set */ -struct nl_cb *cb = nl_cb_alloc(NL_CB_VERBOSE); - -/* Modify the set to call my_func() for all valid messages */ -nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); - -/* - * Set the error message handler to the verbose default implementation - * and direct it to print all errors to the given file descriptor. - */ -FILE *file = fopen(...); -nl_cb_err(cb, NL_CB_VERBOSE, NULL, file); diff --git a/doc/src/examples/nl_send_simple.c b/doc/src/examples/nl_send_simple.c deleted file mode 100644 index afbed7a..0000000 --- a/doc/src/examples/nl_send_simple.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -struct nl_sock *sk; -struct rtgenmsg rt_hdr = { - .rtgen_family = AF_UNSPEC, -}; - -sk = nl_socket_alloc(); -nl_connect(sk, NETLINK_ROUTE); - -nl_send_simple(sock, RTM_GETLINK, NLM_F_DUMP, &rt_hdr, sizeof(rt_hdr)); diff --git a/doc/src/examples/nla_flag.c b/doc/src/examples/nla_flag.c deleted file mode 100644 index dc3d0f9..0000000 --- a/doc/src/examples/nla_flag.c +++ /dev/null @@ -1,7 +0,0 @@ -/* nla_put_flag() appends a zero sized attribute to the message. */ -nla_put_flag(msg, ATTR_FLAG); - - -/* There is no need for a receival function, the presence is the value. */ -if (attrs[ATTR_FLAG]) - /* flag is present */ diff --git a/doc/src/examples/nla_for_each_attr.c b/doc/src/examples/nla_for_each_attr.c deleted file mode 100644 index 9d81835..0000000 --- a/doc/src/examples/nla_for_each_attr.c +++ /dev/null @@ -1,11 +0,0 @@ -#include - -struct nalttr *nla; -int rem; - -nla_for_each_attr(nla, attrstream, streamlen, rem) { - /* validate & parse attribute */ -} - -if (rem > 0) - /* unparsed attribute data */ diff --git a/doc/src/examples/nla_nest_start.c b/doc/src/examples/nla_nest_start.c deleted file mode 100644 index 51cd616..0000000 --- a/doc/src/examples/nla_nest_start.c +++ /dev/null @@ -1,16 +0,0 @@ -int put_opts(struct nl_msg *msg) -{ - struct nlattr *opts; - - if (!(opts = nla_nest_start(msg, ATTR_OPTS))) - goto nla_put_failure; - - NLA_PUT_U32(msg, NESTED_FOO, 123); - NLA_PUT_STRING(msg, NESTED_BAR, "some text"); - - nla_nest_end(msg, opts); - return 0; - -nla_put_failure: - return -EMSGSIZE; -} diff --git a/doc/src/examples/nla_ok.c b/doc/src/examples/nla_ok.c deleted file mode 100644 index 4485a96..0000000 --- a/doc/src/examples/nla_ok.c +++ /dev/null @@ -1,10 +0,0 @@ -#include -#include - -struct nlattr *hdr = nlmsg_attrdata(msg, 0); -int remaining = nlmsg_attrlen(msg, 0); - -while (nla_ok(hdr, remaining)) { - /* parse attribute here */ - hdr = nla_next(hdr, &remaining); -}; diff --git a/doc/src/examples/nla_parse_nested.c b/doc/src/examples/nla_parse_nested.c deleted file mode 100644 index 563bfc8..0000000 --- a/doc/src/examples/nla_parse_nested.c +++ /dev/null @@ -1,12 +0,0 @@ -if (attrs[ATTR_OPTS]) { - struct nlattr *nested[NESTED_MAX+1]; - struct nla_policy nested_policy[] = { - [NESTED_FOO] = { .type = NLA_U32 }, - }; - - if (nla_parse_nested(nested, NESTED_MAX, attrs[ATTR_OPTS], nested_policy) < 0) - /* error */ - - if (nested[NESTED_FOO]) - uint32_t val = nla_get_u32(nested[NESTED_FOO]); -} diff --git a/doc/src/examples/nla_put.c b/doc/src/examples/nla_put.c deleted file mode 100644 index 0683fa5..0000000 --- a/doc/src/examples/nla_put.c +++ /dev/null @@ -1,14 +0,0 @@ -struct my_attr_struct { - uint32_t a; - uint32_t b; -}; - -int my_put(struct nl_msg *msg) -{ - struct my_attr_struct obj = { - .a = 10, - .b = 20, - }; - - return nla_put(msg, ATTR_MY_STRUCT, sizeof(obj), &obj); -} diff --git a/doc/src/examples/nlmsg_for_each.c b/doc/src/examples/nlmsg_for_each.c deleted file mode 100644 index ae2ee66..0000000 --- a/doc/src/examples/nlmsg_for_each.c +++ /dev/null @@ -1,7 +0,0 @@ -#include - -struct nlmsghdr *hdr; - -nlmsg_for_each(hdr, stream, length) { - /* do something with message */ -} diff --git a/doc/src/examples/nlmsg_parse.c b/doc/src/examples/nlmsg_parse.c deleted file mode 100644 index ac6acb3..0000000 --- a/doc/src/examples/nlmsg_parse.c +++ /dev/null @@ -1,29 +0,0 @@ -#include -#include - -enum { - MY_ATTR_FOO = 1, - MY_ATTR_BAR, - __MY_ATTR_MAX, -}; - -#define MY_ATTR_MAX (__MY_ATTR_MAX - 1) - -static struct nla_policy my_policy[MY_ATTR_MAX+1] = { - [MY_ATTR_FOO] = { .type = NLA_U32 }, - [MY_ATTR_BAR] = { .type = NLA_STRING, - .maxlen = 16 }, -}; - -void parse_msg(struct nlmsghdr *nlh) -{ - struct nlattr *attrs[MY_ATTR_MAX+1]; - - if (nlmsg_parse(nlh, 0, attrs, MY_ATTR_MAX, my_policy) < 0) - /* error */ - - if (attrs[MY_ATTR_FOO]) { - /* MY_ATTR_FOO is present in message */ - printf("value: %u\n", nla_get_u32(attrs[MY_ATTR_FOO])); - } -} diff --git a/doc/src/examples/nlmsg_put.c b/doc/src/examples/nlmsg_put.c deleted file mode 100644 index 5e609c6..0000000 --- a/doc/src/examples/nlmsg_put.c +++ /dev/null @@ -1,31 +0,0 @@ -#include - -struct nlmsghdr *hdr; -struct nl_msg *msg; -struct myhdr { - uint32_t foo1, foo2; -} hdr = { 10, 20 }; - -/* Allocate a message with the default maximum message size */ -msg = nlmsg_alloc(); - -/* - * Add header with message type MY_MSGTYPE, the flag NLM_F_CREATE, - * let library fill port and sequence number, and reserve room for - * struct myhdr - */ -hdr = nlmsg_put(msg, NL_AUTO_PORT, NL_AUTO_SEQ, MY_MSGTYPE, sizeof(hdr), NLM_F_CREATE); - -/* Copy own header into newly reserved payload section */ -memcpy(nlmsg_data(hdr), &hdr, sizeof(hdr)); - -/* - * The message will now look like this: - * +-------------------+- - -+----------------+- - -+ - * | struct nlmsghdr | Pad | struct myhdr | Pad | - * +-------------------+-----+----------------+- - -+ - * nlh -^ / \ - * +--------+---------+ - * | foo1 | foo2 | - * +--------+---------+ - */ diff --git a/doc/src/examples/sk_group_example.c b/doc/src/examples/sk_group_example.c deleted file mode 100644 index f948e18..0000000 --- a/doc/src/examples/sk_group_example.c +++ /dev/null @@ -1,43 +0,0 @@ -#include -#include -#include - -/* - * This function will be called for each valid netlink message received - * in nl_recvmsgs_default() - */ -static int my_func(struct nl_msg *msg, void *arg) -{ - return 0; -} - -struct nl_sock *sk; - -/* Allocate a new socket */ -sk = nl_socket_alloc(); - -/* - * Notifications do not use sequence numbers, disable sequence number - * checking. - */ -nl_socket_disable_seq_check(sk); - -/* - * Define a callback function, which will be called for each notification - * received - */ -nl_socket_modify_cb(sk, NL_CB_VALID, NL_CB_CUSTOM, my_func, NULL); - -/* Connect to routing netlink protocol */ -nl_connect(sk, NETLINK_ROUTE); - -/* Subscribe to link notifications group */ -nl_socket_add_memberships(sk, RTNLGRP_LINK); - -/* - * Start receiving messages. The function nl_recvmsgs_default() will block - * until one or more netlink messages (notification) are received which - * will be passed on to my_func(). - */ -while (1) - nl_recvmsgs_default(sock); diff --git a/doc/src/genl.c b/doc/src/genl.c deleted file mode 100644 index 8585c62..0000000 --- a/doc/src/genl.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page genl_doc Generic Netlink Library (-lnl-genl) - -\section genl_intro Introduction - -*/ diff --git a/doc/src/nf.c b/doc/src/nf.c deleted file mode 100644 index 006500d..0000000 --- a/doc/src/nf.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page nf_doc Netfilter Netlink Library (-lnl-nf) - -\section nf_intro Introduction - -*/ diff --git a/doc/src/route.c b/doc/src/route.c deleted file mode 100644 index 2c042db..0000000 --- a/doc/src/route.c +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \cond skip - * vim:syntax=doxygen - * \endcond - -\page route_doc Routing Netlink Library (-lnl-route) - -\section route_intro Introduction - -*/ diff --git a/doc/src/toc.c b/doc/src/toc.c index c33727c..ba7e07a 100644 --- a/doc/src/toc.c +++ b/doc/src/toc.c @@ -13,7 +13,7 @@ provide APIs on different levels of abstraction. The core library libnl.so provides a fundamental set of functions to deal with sockets, construct messages, and send/receive those messages. Additional high level interfaces for several individual netlink protocols are provided in separate -libraries (e.g. \ref route_doc "nl-route.so", \ref genl_doc "nl-genl.so", ...). +libraries (e.g. "nl-route.so", "nl-genl.so", ...). The library is designed to ensure that all components are optional, i.e. even though the core library provides a caching system which allows to @@ -28,11 +28,6 @@ version is used with a considerably older kernel. \section main_toc Table of Contents -- \subpage core_doc "1. Netlink Core Library (-lnl)" -- \subpage route_doc "2. Routing Netlink Library (-lnl-route)" -- \subpage genl_doc "3. Generic Netlink Library (-lnl-genl)" -- \subpage nf_doc "4. Netfilter Netlink Library (-lnl-nf)" - \section main_trees GIT Trees \subsection tree_dev Development Tree diff --git a/lib/msg.c b/lib/msg.c index 62f0911..ee2922c 100644 --- a/lib/msg.c +++ b/lib/msg.c @@ -181,8 +181,6 @@ static void __init init_msg_size(void) * Calculates size of netlink message based on payload length. * @arg payload Length of payload * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return size of netlink message without padding. */ int nlmsg_size(int payload) @@ -201,8 +199,6 @@ int nlmsg_msg_size(int payload) * * This function is idential to nlmsg_size() + nlmsg_padlen(). * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return Size of netlink message including padding. */ int nlmsg_total_size(int payload) @@ -218,8 +214,6 @@ int nlmsg_total_size(int payload) * the end of the message to ensure that the next netlink message header begins * properly aligned to NLMSG_ALIGNTO. * - * See \ref core_msg_fmt_align for more information on alignment. - * * @return Number of bytes of padding needed. */ int nlmsg_padlen(int payload) diff --git a/lib/route/cls.c b/lib/route/cls.c index aa79b09..fb2e9be 100644 --- a/lib/route/cls.c +++ b/lib/route/cls.c @@ -237,6 +237,7 @@ int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags) /** * Build netlink message requesting the deletion of a classifier * @arg cls Classifier to delete + * @arg flags Additional netlink message flags * @arg result Pointer to store resulting netlink message * * The behaviour of this function is identical to rtnl_cls_delete() with @@ -264,6 +265,7 @@ int rtnl_cls_build_delete_request(struct rtnl_cls *cls, int flags, * Delete classifier * @arg sk Netlink socket * @arg cls Classifier to delete + * @arg flags Additional netlink message flags * * Builds a \c RTM_DELTFILTER netlink message requesting the deletion * of a classifier and sends the message to the kernel. diff --git a/lib/route/tc.c b/lib/route/tc.c index 7bd4728..6826a05 100644 --- a/lib/route/tc.c +++ b/lib/route/tc.c @@ -307,7 +307,6 @@ void rtnl_tc_set_link(struct rtnl_tc *tc, struct rtnl_link *link) /** * Get link of traffic control object * @arg tc traffic control object - * @arg link link object * * Returns the link of a traffic control object. The link is only * returned if it has been set before via rtnl_tc_set_link() or -- cgit v1.2.1