summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2011-07-14 12:48:00 +0200
committerThomas Graf <tgraf@suug.ch>2011-07-14 12:48:00 +0200
commit63548f5664e0e149f5e51219ad6f582f985e3c42 (patch)
treebcb04f5d3beac0aaa887a6cd75ef791faefdfae4
parent21d52eabba00089e3319575616a429fb75309cb7 (diff)
downloadlibnl-63548f5664e0e149f5e51219ad6f582f985e3c42.tar.gz
documentation updatesHEADmaster
-rw-r--r--doc/Doxyfile.in2
-rw-r--r--doc/Makefile.am24
-rw-r--r--doc/core.txt2
-rw-r--r--doc/index.txt16
-rw-r--r--doc/route.txt720
-rw-r--r--doc/src/examples/NLA_PUT.c15
-rw-r--r--doc/src/examples/msg_constr_attr.c51
-rw-r--r--doc/src/examples/msg_parse_attr.c50
-rw-r--r--doc/src/examples/my_parse.c11
-rw-r--r--doc/src/examples/nl_cb_set.c14
-rw-r--r--doc/src/examples/nl_send_simple.c11
-rw-r--r--doc/src/examples/nla_flag.c7
-rw-r--r--doc/src/examples/nla_for_each_attr.c11
-rw-r--r--doc/src/examples/nla_nest_start.c16
-rw-r--r--doc/src/examples/nla_ok.c10
-rw-r--r--doc/src/examples/nla_parse_nested.c12
-rw-r--r--doc/src/examples/nla_put.c14
-rw-r--r--doc/src/examples/nlmsg_for_each.c7
-rw-r--r--doc/src/examples/nlmsg_parse.c29
-rw-r--r--doc/src/examples/nlmsg_put.c31
-rw-r--r--doc/src/examples/sk_group_example.c43
-rw-r--r--doc/src/genl.c10
-rw-r--r--doc/src/nf.c10
-rw-r--r--doc/src/route.c10
-rw-r--r--doc/src/toc.c7
-rw-r--r--lib/msg.c6
-rw-r--r--lib/route/cls.c2
-rw-r--r--lib/route/tc.c1
28 files changed, 758 insertions, 384 deletions
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 <tgraf@suug.ch>
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 <tgraf@suug.ch>
+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 <tgraf@suug.ch>
+////
+
+Netlink Routing Library
+=======================
+Thomas Graf <tgraf@suug.ch>
+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 <netlink/route/tc.h>
+#include <netlink/route/qdisc.h>
+
+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 <<tc_stats, Accessing Statistics>> 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 <netlink/route/tc.h>
+
+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 <netlink/route/qdisc.h>
+
+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 <netlink/route/qdisc.h>
+
+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 <<tc_attr, traffic control
+object attributes>>.
+
+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 <netlink/route/qdisc.h>
+
+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 <netlink/msg.h>
-#include <netlink/attr.h>
-
-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 <netlink/msg.h>
-
-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 <netlink/handlers.h>
-
-/* 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 <netlink/netlink.h>
-
-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 <netlink/attr.h>
-
-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 <netlink/msg.h>
-#include <netlink/attr.h>
-
-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 <netlink/msg.h>
-
-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 <netlink/msg.h>
-#include <netlink/attr.h>
-
-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 <netlink/msg.h>
-
-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 <netlink/netlink.h>
-#include <netlink/socket.h>
-#include <netlink/msg.h>
-
-/*
- * 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