summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2011-03-21 15:51:52 +0100
committerThomas Graf <tgraf@suug.ch>2011-03-21 15:51:52 +0100
commit8eb5b5532eae985a5f0911dccf2db8cb4e0a5de4 (patch)
tree0fec48d114edbb535bd234f2684acccf81447d13
parent5dc897d5de9f54078221b241e0122713207f5e0c (diff)
downloadlibnl-8eb5b5532eae985a5f0911dccf2db8cb4e0a5de4.tar.gz
Unified TC API
Finally got rid of all the qdisc/class/cls code duplication in the tc module API. The API takes care of allocation/freeing the tc object specific data. I hope I got it right this time.
-rw-r--r--include/Makefile.am4
-rw-r--r--include/netlink-tc.h17
-rw-r--r--include/netlink-types.h18
-rw-r--r--include/netlink/cli/class.h3
-rw-r--r--include/netlink/cli/cls.h15
-rw-r--r--include/netlink/cli/qdisc.h20
-rw-r--r--include/netlink/cli/tc.h18
-rw-r--r--include/netlink/route/class-modules.h73
-rw-r--r--include/netlink/route/class.h2
-rw-r--r--include/netlink/route/classifier-modules.h78
-rw-r--r--include/netlink/route/classifier.h7
-rw-r--r--include/netlink/route/qdisc-modules.h75
-rw-r--r--include/netlink/route/sch/netem.h26
-rw-r--r--include/netlink/route/sch/prio.h4
-rw-r--r--include/netlink/route/sch/sfq.h8
-rw-r--r--include/netlink/route/sch/tbf.h6
-rw-r--r--include/netlink/route/tc-api.h141
-rw-r--r--include/netlink/route/tc.h26
-rw-r--r--lib/Makefile.am7
-rw-r--r--lib/cli/cls/basic.c19
-rw-r--r--lib/cli/cls/cgroup.c19
-rw-r--r--lib/cli/qdisc/bfifo.c18
-rw-r--r--lib/cli/qdisc/blackhole.c17
-rw-r--r--lib/cli/qdisc/htb.c32
-rw-r--r--lib/cli/qdisc/pfifo.c19
-rw-r--r--lib/route/class.c206
-rw-r--r--lib/route/class_api.c102
-rw-r--r--lib/route/class_obj.c240
-rw-r--r--lib/route/cls.c194
-rw-r--r--lib/route/cls/basic.c100
-rw-r--r--lib/route/cls/cgroup.c91
-rw-r--r--lib/route/cls/ematch.c4
-rw-r--r--lib/route/cls/fw.c78
-rw-r--r--lib/route/cls/police.c3
-rw-r--r--lib/route/cls/u32.c95
-rw-r--r--lib/route/cls_api.c103
-rw-r--r--lib/route/cls_obj.c228
-rw-r--r--lib/route/qdisc.c173
-rw-r--r--lib/route/qdisc_api.c98
-rw-r--r--lib/route/qdisc_obj.c229
-rw-r--r--lib/route/sch/blackhole.c19
-rw-r--r--lib/route/sch/cbq.c176
-rw-r--r--lib/route/sch/dsmark.c190
-rw-r--r--lib/route/sch/fifo.c128
-rw-r--r--lib/route/sch/htb.c370
-rw-r--r--lib/route/sch/netem.c306
-rw-r--r--lib/route/sch/prio.c134
-rw-r--r--lib/route/sch/red.c96
-rw-r--r--lib/route/sch/sfq.c145
-rw-r--r--lib/route/sch/tbf.c175
-rw-r--r--lib/route/tc.c567
-rw-r--r--src/lib/class.c10
-rw-r--r--src/lib/cls.c65
-rw-r--r--src/lib/qdisc.c96
-rw-r--r--src/lib/tc.c77
-rw-r--r--src/nl-class-add.c12
-rw-r--r--src/nl-class-delete.c2
-rw-r--r--src/nl-class-list.c2
-rw-r--r--src/nl-cls-add.c15
-rw-r--r--src/nl-cls-delete.c2
-rw-r--r--src/nl-cls-list.c2
-rw-r--r--src/nl-qdisc-add.c12
-rw-r--r--src/nl-qdisc-delete.c2
-rw-r--r--src/nl-qdisc-list.c2
64 files changed, 2142 insertions, 3079 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
index 8815a6e..8824dfe 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -43,20 +43,18 @@ nobase_include_HEADERS = \
netlink/route/sch/sfq.h \
netlink/route/sch/tbf.h \
netlink/route/addr.h \
- netlink/route/class-modules.h \
netlink/route/class.h \
- netlink/route/classifier-modules.h \
netlink/route/classifier.h \
netlink/route/link.h \
netlink/route/neighbour.h \
netlink/route/neightbl.h \
netlink/route/nexthop.h \
- netlink/route/qdisc-modules.h \
netlink/route/qdisc.h \
netlink/route/route.h \
netlink/route/rtnl.h \
netlink/route/rule.h \
netlink/route/tc.h \
+ netlink/route/tc-api.h \
netlink/socket.h \
netlink/types.h \
netlink/utils.h \
diff --git a/include/netlink-tc.h b/include/netlink-tc.h
index 9e4bce9..3e44642 100644
--- a/include/netlink-tc.h
+++ b/include/netlink-tc.h
@@ -36,18 +36,6 @@ extern "C" {
extern int tca_parse(struct nlattr **, int, struct rtnl_tc *,
struct nla_policy *);
-extern int tca_msg_parser(struct nlmsghdr *, struct rtnl_tc *);
-extern void tca_free_data(struct rtnl_tc *);
-extern int tca_clone(struct rtnl_tc *, struct rtnl_tc *);
-extern void tca_dump_line(struct rtnl_tc *, const char *,
- struct nl_dump_params *);
-extern void tca_dump_details(struct rtnl_tc *, struct nl_dump_params *);
-extern void tca_dump_stats(struct rtnl_tc *, struct nl_dump_params *);
-extern int tca_compare(struct nl_object *, struct nl_object *, uint32_t, int);
-
-extern void tca_set_kind(struct rtnl_tc *, const char *);
-
-extern int tca_build_msg(struct rtnl_tc *, int, int, struct nl_msg **);
#define RTNL_TC_RTABLE_SIZE 256
@@ -55,11 +43,6 @@ extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *,
uint32_t *);
-static inline void *tca_priv(struct rtnl_tc *tca)
-{
- return tca->tc_subdata;
-}
-
static inline void *tca_xstats(struct rtnl_tc *tca)
{
return tca->tc_xstats->d_data;
diff --git a/include/netlink-types.h b/include/netlink-types.h
index de17f9a..1cb7c0e 100644
--- a/include/netlink-types.h
+++ b/include/netlink-types.h
@@ -17,6 +17,7 @@
#include <netlink/route/qdisc.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
+#include <netlink/route/tc-api.h>
#define NL_SOCK_BUFSIZE_SET (1<<0)
#define NL_SOCK_PASSCRED (1<<1)
@@ -441,7 +442,7 @@ struct rtnl_tstats
#define TCKINDSIZ 32
-#define NL_TCA_GENERIC(pre) \
+#define NL_TC_GENERIC(pre) \
NLHDR_COMMON \
uint32_t pre ##_family; \
uint32_t pre ##_ifindex; \
@@ -457,31 +458,30 @@ struct rtnl_tstats
uint64_t pre ##_stats[RTNL_TC_STATS_MAX+1]; \
struct nl_data * pre ##_xstats; \
struct nl_data * pre ##_subdata; \
- struct rtnl_link * pre ##_link
+ struct rtnl_link * pre ##_link; \
+ struct rtnl_tc_ops * pre ##_ops; \
+ enum rtnl_tc_type pre ##_type
struct rtnl_tc
{
- NL_TCA_GENERIC(tc);
+ NL_TC_GENERIC(tc);
};
struct rtnl_qdisc
{
- NL_TCA_GENERIC(q);
- struct rtnl_qdisc_ops *q_ops;
+ NL_TC_GENERIC(q);
};
struct rtnl_class
{
- NL_TCA_GENERIC(c);
- struct rtnl_class_ops *c_ops;
+ NL_TC_GENERIC(c);
};
struct rtnl_cls
{
- NL_TCA_GENERIC(c);
+ NL_TC_GENERIC(c);
uint16_t c_prio;
uint16_t c_protocol;
- struct rtnl_cls_ops *c_ops;
};
struct rtnl_u32
diff --git a/include/netlink/cli/class.h b/include/netlink/cli/class.h
index 0141c21..5001e42 100644
--- a/include/netlink/cli/class.h
+++ b/include/netlink/cli/class.h
@@ -13,12 +13,9 @@
#define __NETLINK_CLI_CLASS_H_
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/cli/tc.h>
extern struct rtnl_class *nl_cli_class_alloc(void);
extern struct nl_cache *nl_cli_class_alloc_cache(struct nl_sock *, int);
-extern void nl_cli_class_parse_kind(struct rtnl_class *, char *);
-
#endif
diff --git a/include/netlink/cli/cls.h b/include/netlink/cli/cls.h
index cdcb17e..a2707b8 100644
--- a/include/netlink/cli/cls.h
+++ b/include/netlink/cli/cls.h
@@ -13,27 +13,12 @@
#define __NETLINK_CLI_CLS_H_
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/cli/tc.h>
-struct nl_cli_cls_module
-{
- const char * cm_name;
- struct rtnl_cls_ops * cm_ops;
- int (*cm_parse_argv)(struct rtnl_cls *, int, char **);
- struct nl_list_head cm_list;
-};
-
extern struct rtnl_cls * nl_cli_cls_alloc(void);
extern struct nl_cache * nl_cli_cls_alloc_cache(struct nl_sock *,
int, uint32_t);
-extern void nl_cli_cls_parse_kind(struct rtnl_cls *, char *);
extern void nl_cli_cls_parse_proto(struct rtnl_cls *, char *);
extern struct rtnl_ematch_tree *nl_cli_cls_parse_ematch(struct rtnl_cls *, char *);
-extern struct nl_cli_cls_module *nl_cli_cls_lookup(struct rtnl_cls_ops *);
-extern void nl_cli_cls_register(struct nl_cli_cls_module *);
-extern void nl_cli_cls_unregister(struct nl_cli_cls_module *);
-
-
#endif
diff --git a/include/netlink/cli/qdisc.h b/include/netlink/cli/qdisc.h
index 00c7083..b102da4 100644
--- a/include/netlink/cli/qdisc.h
+++ b/include/netlink/cli/qdisc.h
@@ -6,36 +6,18 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2008-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef __NETLINK_CLI_QDISC_H_
#define __NETLINK_CLI_QDISC_H_
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#define nl_cli_qdisc_alloc_cache(sk) \
nl_cli_alloc_cache((sk), "queueing disciplines", \
rtnl_qdisc_alloc_cache)
-struct nl_cli_qdisc_module
-{
- const char * qm_name;
- struct rtnl_qdisc_ops * qm_ops;
- struct rtnl_class_ops * qm_class_ops;
- void (*qm_parse_qdisc_argv)(struct rtnl_qdisc *, int, char **);
- void (*qm_parse_class_argv)(struct rtnl_class *, int, char **);
- struct nl_list_head qm_list;
-};
-
-extern struct nl_cli_qdisc_module *nl_cli_qdisc_lookup(struct rtnl_qdisc_ops *);
-extern struct nl_cli_qdisc_module *nl_cli_qdisc_lookup_by_class(struct rtnl_class_ops *);
-extern void nl_cli_qdisc_register(struct nl_cli_qdisc_module *);
-extern void nl_cli_qdisc_unregister(struct nl_cli_qdisc_module *);
-
extern struct rtnl_qdisc *nl_cli_qdisc_alloc(void);
-extern void nl_cli_qdisc_parse_kind(struct rtnl_qdisc *, char *);
-
#endif
diff --git a/include/netlink/cli/tc.h b/include/netlink/cli/tc.h
index 82f9a1d..85d2e30 100644
--- a/include/netlink/cli/tc.h
+++ b/include/netlink/cli/tc.h
@@ -6,13 +6,13 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef __NETLINK_CLI_TC_H_
#define __NETLINK_CLI_TC_H_
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
extern void nl_cli_tc_parse_dev(struct rtnl_tc *, struct nl_cache *, char *);
extern void nl_cli_tc_parse_parent(struct rtnl_tc *, char *);
@@ -21,5 +21,19 @@ extern void nl_cli_tc_parse_mtu(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_mpu(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_overhead(struct rtnl_tc *, char *);
extern void nl_cli_tc_parse_linktype(struct rtnl_tc *, char *);
+extern void nl_cli_tc_parse_kind(struct rtnl_tc *, char *);
+
+struct nl_cli_tc_module
+{
+ const char * tm_name;
+ enum rtnl_tc_type tm_type;
+ struct rtnl_tc_ops * tm_ops;
+ void (*tm_parse_argv)(struct rtnl_tc *, int, char **);
+ struct nl_list_head tm_list;
+};
+
+extern struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *);
+extern void nl_cli_tc_register(struct nl_cli_tc_module *);
+extern void nl_cli_tc_unregister(struct nl_cli_tc_module *);
#endif
diff --git a/include/netlink/route/class-modules.h b/include/netlink/route/class-modules.h
deleted file mode 100644
index 74a25c9..0000000
--- a/include/netlink/route/class-modules.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * netlink/route/class-modules.h Class Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_CLASS_MODULES_H_
-#define NETLINK_CLASS_MODULES_H_
-
-#include <netlink/netlink.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Class operations
- * @ingroup class_api
- */
-struct rtnl_class_ops
-{
- /**
- * Kind/Name of class
- */
- char co_kind[32];
-
- /**
- * Dump callbacks
- */
- void (*co_dump[NL_DUMP_MAX+1])(struct rtnl_class *,
- struct nl_dump_params *);
-
- /**
- * Must return the contents supposed to be in TCA_OPTIONS
- */
- struct nl_msg *(*co_get_opts)(struct rtnl_class *);
-
- /**
- * TCA_OPTIONS message parser
- */
- int (*co_msg_parser)(struct rtnl_class *);
-
- /**
- * Called before a class object gets destroyed
- */
- void (*co_free_data)(struct rtnl_class *);
-
- /**
- * Called whenever a class object needs to be cloned
- */
- int (*co_clone)(struct rtnl_class *, struct rtnl_class *);
-
- /**
- * INTERNAL (Do not use)
- */
- struct rtnl_class_ops *co_next;
-};
-
-extern int rtnl_class_register(struct rtnl_class_ops *);
-extern int rtnl_class_unregister(struct rtnl_class_ops *);
-extern struct rtnl_class_ops * rtnl_class_lookup_ops(struct rtnl_class *);
-extern struct rtnl_class_ops * __rtnl_class_lookup_ops(const char *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink/route/class.h b/include/netlink/route/class.h
index 13a25d6..ad3bacf 100644
--- a/include/netlink/route/class.h
+++ b/include/netlink/route/class.h
@@ -22,8 +22,6 @@ extern "C" {
struct rtnl_class;
-extern struct nl_object_ops class_obj_ops;
-
extern struct rtnl_class * rtnl_class_alloc(void);
extern void rtnl_class_put(struct rtnl_class *);
extern int rtnl_class_alloc_cache(struct nl_sock *, int,
diff --git a/include/netlink/route/classifier-modules.h b/include/netlink/route/classifier-modules.h
deleted file mode 100644
index 35cb06e..0000000
--- a/include/netlink/route/classifier-modules.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * netlink/route/classifier-modules.h Classifier Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_CLASS_MODULES_H_
-#define NETLINK_CLASS_MODULES_H_
-
-#include <netlink/netlink.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Classifier operations
- * @ingroup cls_api
- */
-struct rtnl_cls_ops
-{
- /**
- * Name of classifier module
- */
- char co_kind[32];
-
-
- /**
- * Size of private classifier data
- */
- size_t co_size;
-
- /**
- * Dump callbacks
- */
- void (*co_dump[NL_DUMP_MAX+1])(struct rtnl_cls *,
- struct nl_dump_params *);
- /**
- * Must return the contents supposed to be in TCA_OPTIONS
- */
- int (*co_get_opts)(struct rtnl_cls *, struct nl_msg *);
-
- /**
- * TCA_OPTIONS message parser
- */
- int (*co_msg_parser)(struct rtnl_cls *);
-
- /**
- * Called before a class object gets destroyed
- */
- void (*co_free_data)(struct rtnl_cls *);
-
- /**
- * Called whenever a classifier object needs to be cloned
- */
- int (*co_clone)(struct rtnl_cls *, struct rtnl_cls *);
-
- /**
- * INTERNAL (Do not use)
- */
- struct rtnl_cls_ops *co_next;
-};
-
-extern int rtnl_cls_register(struct rtnl_cls_ops *);
-extern int rtnl_cls_unregister(struct rtnl_cls_ops *);
-extern struct rtnl_cls_ops * rtnl_cls_lookup_ops(struct rtnl_cls *);
-extern struct rtnl_cls_ops * __rtnl_cls_lookup_ops(const char *kind);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink/route/classifier.h b/include/netlink/route/classifier.h
index 17c834b..23af837 100644
--- a/include/netlink/route/classifier.h
+++ b/include/netlink/route/classifier.h
@@ -21,8 +21,6 @@
extern "C" {
#endif
-extern struct nl_object_ops cls_obj_ops;
-
extern struct rtnl_cls *rtnl_cls_alloc(void);
extern void rtnl_cls_put(struct rtnl_cls *);
@@ -39,17 +37,12 @@ extern int rtnl_cls_build_delete_request(struct rtnl_cls *, int,
struct nl_msg **);
extern int rtnl_cls_delete(struct nl_sock *, struct rtnl_cls *, int);
-extern int rtnl_cls_set_kind(struct rtnl_cls *, const char *);
-extern struct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *);
-
extern void rtnl_cls_set_prio(struct rtnl_cls *, uint16_t);
extern uint16_t rtnl_cls_get_prio(struct rtnl_cls *);
extern void rtnl_cls_set_protocol(struct rtnl_cls *, uint16_t);
extern uint16_t rtnl_cls_get_protocol(struct rtnl_cls *);
-extern void *rtnl_cls_data(struct rtnl_cls *);
-
#ifdef __cplusplus
}
#endif
diff --git a/include/netlink/route/qdisc-modules.h b/include/netlink/route/qdisc-modules.h
deleted file mode 100644
index 769625e..0000000
--- a/include/netlink/route/qdisc-modules.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * netlink/route/qdisc-modules.h Qdisc Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
- */
-
-#ifndef NETLINK_QDISC_MODULES_H_
-#define NETLINK_QDISC_MODULES_H_
-
-#include <netlink/netlink.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * Qdisc Operations
- * @ingroup qdisc
- */
-struct rtnl_qdisc_ops
-{
- /**
- * Kind/Name of Qdisc
- */
- char qo_kind[32];
-
- /**
- * Dump callbacks
- */
- void (*qo_dump[NL_DUMP_MAX+1])(struct rtnl_qdisc *,
- struct nl_dump_params *);
-
- /**
- * Must return the contents supposed to be in TCA_OPTIONS
- */
- struct nl_msg *(*qo_get_opts)(struct rtnl_qdisc *);
-
- int (*qo_build_msg)(struct rtnl_qdisc *, struct nl_msg *);
-
- /**
- * TCA_OPTIONS message parser
- */
- int (*qo_msg_parser)(struct rtnl_qdisc *);
-
- /**
- * Called before a Qdisc object gets destroyed
- */
- void (*qo_free_data)(struct rtnl_qdisc *);
-
- /**
- * Called whenever a qdisc object needs to be cloned
- */
- int (*qo_clone)(struct rtnl_qdisc *, struct rtnl_qdisc *);
-
- /**
- * INTERNAL (Do not use)
- */
- struct rtnl_qdisc_ops *qo_next;
-};
-
-extern int rtnl_qdisc_register(struct rtnl_qdisc_ops *);
-extern int rtnl_qdisc_unregister(struct rtnl_qdisc_ops *);
-extern struct rtnl_qdisc_ops * rtnl_qdisc_lookup_ops(struct rtnl_qdisc *);
-extern struct rtnl_qdisc_ops * __rtnl_qdisc_lookup_ops(const char *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/include/netlink/route/sch/netem.h b/include/netlink/route/sch/netem.h
index c293777..ce56ee7 100644
--- a/include/netlink/route/sch/netem.h
+++ b/include/netlink/route/sch/netem.h
@@ -18,48 +18,48 @@
extern "C" {
#endif
-extern int rtnl_netem_set_limit(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_limit(struct rtnl_qdisc *);
/* Packet Re-ordering */
-extern int rtnl_netem_set_gap(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_gap(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_gap(struct rtnl_qdisc *);
-extern int rtnl_netem_set_reorder_probability(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_reorder_probability(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *);
-extern int rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *);
/* Corruption */
-extern int rtnl_netem_set_corruption_probability(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_corruption_probability(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_corruption_probability(struct rtnl_qdisc *);
-extern int rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_corruption_correlation(struct rtnl_qdisc *);
/* Packet Loss */
-extern int rtnl_netem_set_loss(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_loss(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_loss(struct rtnl_qdisc *);
-extern int rtnl_netem_set_loss_correlation(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_loss_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *);
/* Packet Duplication */
-extern int rtnl_netem_set_duplicate(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_duplicate(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_duplicate(struct rtnl_qdisc *);
-extern int rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *);
/* Packet Delay */
-extern int rtnl_netem_set_delay(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_delay(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_delay(struct rtnl_qdisc *);
-extern int rtnl_netem_set_jitter(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_jitter(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_jitter(struct rtnl_qdisc *);
-extern int rtnl_netem_set_delay_correlation(struct rtnl_qdisc *, int);
+extern void rtnl_netem_set_delay_correlation(struct rtnl_qdisc *, int);
extern int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *);
/* Delay Distribution */
diff --git a/include/netlink/route/sch/prio.h b/include/netlink/route/sch/prio.h
index ff35b07..f6fdc86 100644
--- a/include/netlink/route/sch/prio.h
+++ b/include/netlink/route/sch/prio.h
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_PRIO_H_
@@ -38,7 +38,7 @@ extern "C" {
/** @} */
-extern int rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *, int);
+extern void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *);
extern int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *, uint8_t[], int);
extern uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *);
diff --git a/include/netlink/route/sch/sfq.h b/include/netlink/route/sch/sfq.h
index 19b3817..7cc0b3e 100644
--- a/include/netlink/route/sch/sfq.h
+++ b/include/netlink/route/sch/sfq.h
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_SFQ_H_
@@ -18,13 +18,13 @@
extern "C" {
#endif
-extern int rtnl_sfq_set_quantum(struct rtnl_qdisc *, int);
+extern void rtnl_sfq_set_quantum(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_quantum(struct rtnl_qdisc *);
-extern int rtnl_sfq_set_limit(struct rtnl_qdisc *, int);
+extern void rtnl_sfq_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_limit(struct rtnl_qdisc *);
-extern int rtnl_sfq_set_perturb(struct rtnl_qdisc *, int);
+extern void rtnl_sfq_set_perturb(struct rtnl_qdisc *, int);
extern int rtnl_sfq_get_perturb(struct rtnl_qdisc *);
extern int rtnl_sfq_get_divisor(struct rtnl_qdisc *);
diff --git a/include/netlink/route/sch/tbf.h b/include/netlink/route/sch/tbf.h
index bb0e3b1..8a2144a 100644
--- a/include/netlink/route/sch/tbf.h
+++ b/include/netlink/route/sch/tbf.h
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_TBF_H_
@@ -19,11 +19,11 @@
extern "C" {
#endif
-extern int rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *, int);
+extern void rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *, int);
extern int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *);
-extern int rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *, int, int, int);
+extern void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *, int, int, int);
extern int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *);
extern int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *);
diff --git a/include/netlink/route/tc-api.h b/include/netlink/route/tc-api.h
new file mode 100644
index 0000000..8ed940a
--- /dev/null
+++ b/include/netlink/route/tc-api.h
@@ -0,0 +1,141 @@
+/*
+ * netlink/route/tc-api.h Traffic Control API
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation version 2.1
+ * of the License.
+ *
+ * Copyright (c) 2011 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_TC_API_H_
+#define NETLINK_TC_API_H_
+
+#include <netlink/netlink.h>
+#include <netlink/msg.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum rtnl_tc_type {
+ RTNL_TC_TYPE_QDISC,
+ RTNL_TC_TYPE_CLASS,
+ RTNL_TC_TYPE_CLS,
+ __RTNL_TC_TYPE_MAX,
+};
+
+#define RTNL_TC_TYPE_MAX (__RTNL_TC_TYPE_MAX - 1)
+
+/**
+ * Traffic control object operations
+ * @ingroup tc
+ *
+ * This structure holds function pointers and settings implementing
+ * the features of each traffic control object implementation.
+ */
+struct rtnl_tc_ops
+{
+ /**
+ * Name of traffic control module
+ */
+ char *to_kind;
+
+ /**
+ * Type of traffic control object
+ */
+ enum rtnl_tc_type to_type;
+
+
+ /**
+ * Size of private data
+ */
+ size_t to_size;
+
+ /**
+ * Dump callbacks
+ */
+ void (*to_dump[NL_DUMP_MAX+1])(struct rtnl_tc *, void *,
+ struct nl_dump_params *);
+ /**
+ * Used to fill the contents of TCA_OPTIONS
+ */
+ int (*to_msg_fill)(struct rtnl_tc *, void *, struct nl_msg *);
+
+ /**
+ * Uesd to to fill tc related messages, unlike with to_msg_fill,
+ * the contents is not encapsulated with a TCA_OPTIONS nested
+ * attribute.
+ */
+ int (*to_msg_fill_raw)(struct rtnl_tc *, void *, struct nl_msg *);
+
+ /**
+ * TCA_OPTIONS message parser
+ */
+ int (*to_msg_parser)(struct rtnl_tc *, void *);
+
+ /**
+ * Called before a tc object is destroyed
+ */
+ void (*to_free_data)(struct rtnl_tc *, void *);
+
+ /**
+ * Called whenever a classifier object needs to be cloned
+ */
+ int (*to_clone)(void *, void *);
+
+ /**
+ * Internal, don't touch
+ */
+ struct nl_list_head to_list;
+};
+
+struct rtnl_tc_type_ops
+{
+ enum rtnl_tc_type tt_type;
+
+ char *tt_dump_prefix;
+
+ /**
+ * Dump callbacks
+ */
+ void (*tt_dump[NL_DUMP_MAX+1])(struct rtnl_tc *,
+ struct nl_dump_params *);
+};
+
+extern int rtnl_tc_msg_parse(struct nlmsghdr *,
+ struct rtnl_tc *);
+extern int rtnl_tc_msg_build(struct rtnl_tc *, int,
+ int, struct nl_msg **);
+
+extern void rtnl_tc_free_data(struct nl_object *);
+extern int rtnl_tc_clone(struct nl_object *,
+ struct nl_object *);
+extern void rtnl_tc_dump_line(struct nl_object *,
+ struct nl_dump_params *);
+extern void rtnl_tc_dump_details(struct nl_object *,
+ struct nl_dump_params *);
+extern void rtnl_tc_dump_stats(struct nl_object *,
+ struct nl_dump_params *);
+extern int rtnl_tc_compare(struct nl_object *,
+ struct nl_object *,
+ uint32_t, int);
+
+extern void * rtnl_tc_data(struct rtnl_tc *);
+
+extern struct rtnl_tc_ops * rtnl_tc_lookup_ops(enum rtnl_tc_type,
+ const char *);
+extern struct rtnl_tc_ops * rtnl_tc_get_ops(struct rtnl_tc *);
+extern int rtnl_tc_register(struct rtnl_tc_ops *);
+extern void rtnl_tc_unregister(struct rtnl_tc_ops *);
+
+extern void rtnl_tc_type_register(struct rtnl_tc_type_ops *);
+extern void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/tc.h b/include/netlink/route/tc.h
index 4ba0e06..17021be 100644
--- a/include/netlink/route/tc.h
+++ b/include/netlink/route/tc.h
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#ifndef NETLINK_TC_H_
@@ -23,12 +23,31 @@
extern "C" {
#endif
+/**
+ * Traffic control object
+ * @ingroup tc
+ */
struct rtnl_tc;
/**
+ * Macro to cast qdisc/class/classifier to tc object
* @ingroup tc
+ *
+ * @code
+ * rtnl_tc_set_mpu(TC_CAST(qdisc), 40);
+ * @endcode
+ */
+#define TC_CAST(ptr) ((struct rtnl_tc *) (ptr))
+
+/**
+ * Traffic control statistical identifier
+ * @ingroup tc
+ *
+ * @code
+ * uint64_t n = rtnl_tc_get_stat(TC_CAST(class), RTNL_TC_PACKETS);
+ * @endcode
*/
-enum rtnl_tc_stats_id {
+enum rtnl_tc_stat {
RTNL_TC_PACKETS, /**< Number of packets seen */
RTNL_TC_BYTES, /**< Total bytes seen */
RTNL_TC_RATE_BPS, /**< Current bits/s (rate estimator) */
@@ -58,8 +77,9 @@ extern void rtnl_tc_set_handle(struct rtnl_tc *, uint32_t);
extern uint32_t rtnl_tc_get_handle(struct rtnl_tc *);
extern void rtnl_tc_set_parent(struct rtnl_tc *, uint32_t);
extern uint32_t rtnl_tc_get_parent(struct rtnl_tc *);
+extern int rtnl_tc_set_kind(struct rtnl_tc *, const char *);
extern char * rtnl_tc_get_kind(struct rtnl_tc *);
-extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, int );
+extern uint64_t rtnl_tc_get_stat(struct rtnl_tc *, enum rtnl_tc_stat);
extern int rtnl_tc_calc_txtime(int, int);
extern int rtnl_tc_calc_bufsize(int, int);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index ccab7ca..25a7ac5 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -43,11 +43,10 @@ route/cls/ematch_syntax.c: route/cls/ematch_syntax.y
libnl_route_la_LIBADD = libnl.la
libnl_route_la_SOURCES = \
- route/addr.c route/class.c route/class_api.c route/class_obj.c \
- route/cls.c route/cls_api.c route/cls_obj.c route/link.c \
+ route/addr.c route/class.c route/cls.c route/link.c \
route/neigh.c route/neightbl.c route/nexthop.c route/qdisc.c \
- route/qdisc_api.c route/qdisc_obj.c route/route.c route/route_obj.c \
- route/route_utils.c route/rtnl.c route/rule.c route/tc.c route/classid.c \
+ route/route.c route/route_obj.c route/route_utils.c route/rtnl.c \
+ route/rule.c route/tc.c route/classid.c \
\
route/cls/fw.c route/cls/police.c route/cls/u32.c route/cls/basic.c \
route/cls/cgroup.c \
diff --git a/lib/cli/cls/basic.c b/lib/cli/cls/basic.c
index 9ec46ef..1939988 100644
--- a/lib/cli/cls/basic.c
+++ b/lib/cli/cls/basic.c
@@ -6,10 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
+#include <netlink/cli/tc.h>
#include <netlink/cli/cls.h>
#include <netlink/route/cls/basic.h>
@@ -29,8 +30,9 @@ static void print_usage(void)
" nl-cls-add --dev=eth0 --parent=q_root basic --target=c_default\n");
}
-static int parse_argv(struct rtnl_cls *cls, int argc, char **argv)
+static void parse_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_cls *cls = (struct rtnl_cls *) tc;
struct rtnl_ematch_tree *tree;
uint32_t target;
int err;
@@ -71,22 +73,21 @@ static int parse_argv(struct rtnl_cls *cls, int argc, char **argv)
break;
}
}
-
- return 0;
}
-static struct nl_cli_cls_module basic_module =
+static struct nl_cli_tc_module basic_module =
{
- .cm_name = "basic",
- .cm_parse_argv = parse_argv,
+ .tm_name = "basic",
+ .tm_type = RTNL_TC_TYPE_CLS,
+ .tm_parse_argv = parse_argv,
};
static void __init basic_init(void)
{
- nl_cli_cls_register(&basic_module);
+ nl_cli_tc_register(&basic_module);
}
static void __exit basic_exit(void)
{
- nl_cli_cls_unregister(&basic_module);
+ nl_cli_tc_unregister(&basic_module);
}
diff --git a/lib/cli/cls/cgroup.c b/lib/cli/cls/cgroup.c
index 41920ea..fae6208 100644
--- a/lib/cli/cls/cgroup.c
+++ b/lib/cli/cls/cgroup.c
@@ -6,10 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
+#include <netlink/cli/tc.h>
#include <netlink/cli/cls.h>
#include <netlink/route/cls/cgroup.h>
@@ -26,8 +27,9 @@ static void print_usage(void)
" nl-cls-add --dev=eth0 --parent=q_root cgroup\n");
}
-static int parse_argv(struct rtnl_cls *cls, int argc, char **argv)
+static void parse_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_cls *cls = (struct rtnl_cls *) tc;
struct rtnl_ematch_tree *tree;
for (;;) {
@@ -53,22 +55,21 @@ static int parse_argv(struct rtnl_cls *cls, int argc, char **argv)
break;
}
}
-
- return 0;
}
-static struct nl_cli_cls_module cgroup_module =
+static struct nl_cli_tc_module cgroup_module =
{
- .cm_name = "cgroup",
- .cm_parse_argv = parse_argv,
+ .tm_name = "cgroup",
+ .tm_type = RTNL_TC_TYPE_CLS,
+ .tm_parse_argv = parse_argv,
};
static void __init cgroup_init(void)
{
- nl_cli_cls_register(&cgroup_module);
+ nl_cli_tc_register(&cgroup_module);
}
static void __exit cgroup_exit(void)
{
- nl_cli_cls_unregister(&cgroup_module);
+ nl_cli_tc_unregister(&cgroup_module);
}
diff --git a/lib/cli/qdisc/bfifo.c b/lib/cli/qdisc/bfifo.c
index 2f74659..710d6c4 100644
--- a/lib/cli/qdisc/bfifo.c
+++ b/lib/cli/qdisc/bfifo.c
@@ -6,11 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
-#include <netlink/cli/qdisc.h>
+#include <netlink/cli/tc.h>
#include <netlink/route/sch/fifo.h>
static void print_usage(void)
@@ -27,8 +27,9 @@ static void print_usage(void)
" nl-qdisc-add --dev=eth1 --parent=root bfifo --limit=4096\n");
}
-static void bfifo_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
+static void bfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
int limit;
for (;;) {
@@ -64,18 +65,19 @@ static void bfifo_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
}
}
-static struct nl_cli_qdisc_module bfifo_module =
+static struct nl_cli_tc_module bfifo_module =
{
- .qm_name = "bfifo",
- .qm_parse_qdisc_argv = bfifo_parse_argv,
+ .tm_name = "bfifo",
+ .tm_type = RTNL_TC_TYPE_QDISC,
+ .tm_parse_argv = bfifo_parse_argv,
};
static void __init bfifo_init(void)
{
- nl_cli_qdisc_register(&bfifo_module);
+ nl_cli_tc_register(&bfifo_module);
}
static void __exit bfifo_exit(void)
{
- nl_cli_qdisc_unregister(&bfifo_module);
+ nl_cli_tc_unregister(&bfifo_module);
}
diff --git a/lib/cli/qdisc/blackhole.c b/lib/cli/qdisc/blackhole.c
index 1eebb32..af9dc6d 100644
--- a/lib/cli/qdisc/blackhole.c
+++ b/lib/cli/qdisc/blackhole.c
@@ -6,11 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
-#include <netlink/cli/qdisc.h>
+#include <netlink/cli/tc.h>
static void print_usage(void)
{
@@ -25,7 +25,7 @@ static void print_usage(void)
" nl-qdisc-add --dev=eth1 --parent=root blackhole\n");
}
-static void blackhole_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
+static void blackhole_parse_argv(struct rtnl_tc *tc, int argc, char **argv)
{
for (;;) {
int c, optidx = 0;
@@ -46,18 +46,19 @@ static void blackhole_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv
}
}
-static struct nl_cli_qdisc_module blackhole_module =
+static struct nl_cli_tc_module blackhole_module =
{
- .qm_name = "blackhole",
- .qm_parse_qdisc_argv = blackhole_parse_argv,
+ .tm_name = "blackhole",
+ .tm_type = RTNL_TC_TYPE_QDISC,
+ .tm_parse_argv = blackhole_parse_argv,
};
static void __init blackhole_init(void)
{
- nl_cli_qdisc_register(&blackhole_module);
+ nl_cli_tc_register(&blackhole_module);
}
static void __exit blackhole_exit(void)
{
- nl_cli_qdisc_unregister(&blackhole_module);
+ nl_cli_tc_unregister(&blackhole_module);
}
diff --git a/lib/cli/qdisc/htb.c b/lib/cli/qdisc/htb.c
index febf429..32ed272 100644
--- a/lib/cli/qdisc/htb.c
+++ b/lib/cli/qdisc/htb.c
@@ -6,11 +6,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
-#include <netlink/cli/qdisc.h>
+#include <netlink/cli/tc.h>
#include <netlink/route/sch/htb.h>
static void print_qdisc_usage(void)
@@ -28,8 +28,10 @@ static void print_qdisc_usage(void)
" nl-qdisc-add --dev=eth1 --parent=root --handle=1: htb --default=10\n");
}
-static void htb_parse_qdisc_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
+static void htb_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
+
for (;;) {
int c, optidx = 0;
enum {
@@ -82,8 +84,9 @@ static void print_class_usage(void)
" nl-class-add --dev=eth1 --parent=1: --classid=1:1 htb --rate=20mbit\n");
}
-static void htb_parse_class_argv(struct rtnl_class *class, int argc, char **argv)
+static void htb_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_class *class = (struct rtnl_class *) tc;
long rate;
for (;;) {
@@ -173,19 +176,28 @@ static void htb_parse_class_argv(struct rtnl_class *class, int argc, char **argv
}
}
-static struct nl_cli_qdisc_module htb_module =
+static struct nl_cli_tc_module htb_qdisc_module =
+{
+ .tm_name = "htb",
+ .tm_type = RTNL_TC_TYPE_QDISC,
+ .tm_parse_argv = htb_parse_qdisc_argv,
+};
+
+static struct nl_cli_tc_module htb_class_module =
{
- .qm_name = "htb",
- .qm_parse_qdisc_argv = htb_parse_qdisc_argv,
- .qm_parse_class_argv = htb_parse_class_argv,
+ .tm_name = "htb",
+ .tm_type = RTNL_TC_TYPE_CLASS,
+ .tm_parse_argv = htb_parse_class_argv,
};
static void __init htb_init(void)
{
- nl_cli_qdisc_register(&htb_module);
+ nl_cli_tc_register(&htb_qdisc_module);
+ nl_cli_tc_register(&htb_class_module);
}
static void __exit htb_exit(void)
{
- nl_cli_qdisc_unregister(&htb_module);
+ nl_cli_tc_unregister(&htb_class_module);
+ nl_cli_tc_unregister(&htb_qdisc_module);
}
diff --git a/lib/cli/qdisc/pfifo.c b/lib/cli/qdisc/pfifo.c
index 38cc97a..946aba6 100644
--- a/lib/cli/qdisc/pfifo.c
+++ b/lib/cli/qdisc/pfifo.c
@@ -7,11 +7,11 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
-#include <netlink/cli/qdisc.h>
+#include <netlink/cli/tc.h>
#include <netlink/route/sch/fifo.h>
static void print_usage(void)
@@ -28,8 +28,10 @@ static void print_usage(void)
" nl-qdisc-add --dev=eth1 --parent=root pfifo --limit=32\n");
}
-static void pfifo_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
+static void pfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv)
{
+ struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
+
for (;;) {
int c, optidx = 0;
enum {
@@ -57,18 +59,19 @@ static void pfifo_parse_argv(struct rtnl_qdisc *qdisc, int argc, char **argv)
}
}
-static struct nl_cli_qdisc_module pfifo_module =
+static struct nl_cli_tc_module pfifo_module =
{
- .qm_name = "pfifo",
- .qm_parse_qdisc_argv = pfifo_parse_argv,
+ .tm_name = "pfifo",
+ .tm_type = RTNL_TC_TYPE_QDISC,
+ .tm_parse_argv = pfifo_parse_argv,
};
static void __init pfifo_init(void)
{
- nl_cli_qdisc_register(&pfifo_module);
+ nl_cli_tc_register(&pfifo_module);
}
static void __exit pfifo_exit(void)
{
- nl_cli_qdisc_unregister(&pfifo_module);
+ nl_cli_tc_unregister(&pfifo_module);
}
diff --git a/lib/route/class.c b/lib/route/class.c
index 9717d20..47356e2 100644
--- a/lib/route/class.c
+++ b/lib/route/class.c
@@ -18,44 +18,42 @@
#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/classifier.h>
#include <netlink/utils.h>
static struct nl_cache_ops rtnl_class_ops;
+static struct nl_object_ops class_obj_ops;
+
+static void class_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p)
+{
+ struct rtnl_class *class = (struct rtnl_class *) tc;
+ char buf[32];
+
+ if (class->c_info)
+ nl_dump(p, "child-qdisc %s ",
+ rtnl_tc_handle2str(class->c_info, buf, sizeof(buf)));
+}
+
static int class_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
- struct nlmsghdr *n, struct nl_parser_param *pp)
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
{
- int err;
struct rtnl_class *class;
- struct rtnl_class_ops *cops;
-
- class = rtnl_class_alloc();
- if (!class) {
- err = -NLE_NOMEM;
- goto errout;
- }
- class->ce_msgtype = n->nlmsg_type;
+ int err;
- err = tca_msg_parser(n, (struct rtnl_tc *) class);
- if (err < 0)
- goto errout_free;
+ if (!(class = rtnl_class_alloc()))
+ return -NLE_NOMEM;
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_msg_parser) {
- err = cops->co_msg_parser(class);
- if (err < 0)
- goto errout_free;
- }
+ if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(class))) < 0)
+ goto errout;
- err = pp->pp_cb((struct nl_object *) class, pp);
-errout_free:
- rtnl_class_put(class);
+ err = pp->pp_cb(OBJ_CAST(class), pp);
errout:
+ rtnl_class_put(class);
+
return err;
}
@@ -78,30 +76,7 @@ static int class_request_update(struct nl_cache *cache, struct nl_sock *sk)
static int class_build(struct rtnl_class *class, int type, int flags,
struct nl_msg **result)
{
- struct rtnl_class_ops *cops;
- int err;
-
- err = tca_build_msg((struct rtnl_tc *) class, type, flags, result);
- if (err < 0)
- return err;
-
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_get_opts) {
- struct nl_msg *opts;
-
- opts = cops->co_get_opts(class);
- if (opts) {
- err = nla_put_nested(*result, TCA_OPTIONS, opts);
- nlmsg_free(opts);
- if (err < 0)
- goto errout;
- }
- }
-
- return 0;
-errout:
- nlmsg_free(*result);
- return err;
+ return rtnl_tc_msg_build(TC_CAST(class), type, flags, result);
}
/**
@@ -214,6 +189,117 @@ int rtnl_class_delete(struct nl_sock *sk, struct rtnl_class *class)
/** @} */
/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct rtnl_class *rtnl_class_alloc(void)
+{
+ struct rtnl_tc *tc;
+
+ tc = TC_CAST(nl_object_alloc(&class_obj_ops));
+ if (tc)
+ tc->tc_type = RTNL_TC_TYPE_CLASS;
+
+ return (struct rtnl_class *) tc;
+}
+
+void rtnl_class_put(struct rtnl_class *class)
+{
+ nl_object_put((struct nl_object *) class);
+}
+
+/** @} */
+
+/**
+ * @name Leaf Qdisc
+ * @{
+ */
+
+/**
+ * Lookup the leaf qdisc of a class
+ * @arg class the parent class
+ * @arg cache a qdisc cache including at laest all qdiscs of the
+ * interface the specified class is attached to
+ * @return The qdisc from the cache or NULL if the class has no leaf qdisc
+ */
+struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class,
+ struct nl_cache *cache)
+{
+ struct rtnl_qdisc *leaf;
+
+ if (!class->c_info)
+ return NULL;
+
+ leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex,
+ class->c_handle);
+ if (!leaf || leaf->q_handle != class->c_info)
+ return NULL;
+
+ return leaf;
+}
+
+/** @} */
+
+
+/**
+ * @name Iterators
+ * @{
+ */
+
+/**
+ * Call a callback for each child of a class
+ * @arg class the parent class
+ * @arg cache a class cache including all classes of the interface
+ * the specified class is attached to
+ * @arg cb callback function
+ * @arg arg argument to be passed to callback function
+ */
+void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ struct rtnl_class *filter;
+
+ filter = rtnl_class_alloc();
+ if (!filter)
+ return;
+
+ rtnl_tc_set_parent(TC_CAST(filter), class->c_handle);
+ rtnl_tc_set_ifindex(TC_CAST(filter), class->c_ifindex);
+ rtnl_tc_set_kind(TC_CAST(filter), class->c_kind);
+
+ nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg);
+ rtnl_class_put(filter);
+}
+
+/**
+ * Call a callback for each classifier attached to the class
+ * @arg class the parent class
+ * @arg cache a filter cache including at least all the filters
+ * attached to the specified class
+ * @arg cb callback function
+ * @arg arg argument to be passed to callback function
+ */
+void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ struct rtnl_cls *filter;
+
+ filter = rtnl_cls_alloc();
+ if (!filter)
+ return;
+
+ rtnl_tc_set_ifindex((struct rtnl_tc *) filter, class->c_ifindex);
+ rtnl_tc_set_parent((struct rtnl_tc *) filter, class->c_parent);
+
+ nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
+ rtnl_cls_put(filter);
+}
+
+/** @} */
+
+
+/**
* @name Cache Management
* @{
*/
@@ -276,6 +362,28 @@ struct rtnl_class *rtnl_class_get(struct nl_cache *cache, int ifindex,
/** @} */
+static struct rtnl_tc_type_ops class_ops = {
+ .tt_type = RTNL_TC_TYPE_CLASS,
+ .tt_dump_prefix = "class",
+ .tt_dump = {
+ [NL_DUMP_DETAILS] = class_dump_details,
+ },
+};
+
+static struct nl_object_ops class_obj_ops = {
+ .oo_name = "route/class",
+ .oo_size = sizeof(struct rtnl_class),
+ .oo_free_data = rtnl_tc_free_data,
+ .oo_clone = rtnl_tc_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = rtnl_tc_dump_line,
+ [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
+ [NL_DUMP_STATS] = rtnl_tc_dump_stats,
+ },
+ .oo_compare = rtnl_tc_compare,
+ .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
+};
+
static struct nl_cache_ops rtnl_class_ops = {
.co_name = "route/class",
.co_hdrsize = sizeof(struct tcmsg),
@@ -293,12 +401,14 @@ static struct nl_cache_ops rtnl_class_ops = {
static void __init class_init(void)
{
+ rtnl_tc_type_register(&class_ops);
nl_cache_mngt_register(&rtnl_class_ops);
}
static void __exit class_exit(void)
{
nl_cache_mngt_unregister(&rtnl_class_ops);
+ rtnl_tc_type_unregister(&class_ops);
}
/** @} */
diff --git a/lib/route/class_api.c b/lib/route/class_api.c
deleted file mode 100644
index 374cf0f..0000000
--- a/lib/route/class_api.c
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * lib/route/class_api.c Queueing Classes Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup class
- * @defgroup class_api Class Modules
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
-#include <netlink/utils.h>
-
-static struct rtnl_class_ops *class_ops_list;
-
-/**
- * @name Module API
- * @{
- */
-
-/**
- * Register a class module
- * @arg cops class module operations
- */
-int rtnl_class_register(struct rtnl_class_ops *cops)
-{
- struct rtnl_class_ops *o, **op;
-
- if (!cops->co_kind[0])
- BUG();
-
- for (op = &class_ops_list; (o = *op) != NULL; op = &o->co_next)
- if (!strcasecmp(cops->co_kind, o->co_kind))
- return -NLE_EXIST;
-
- cops->co_next = NULL;
- *op = cops;
-
- return 0;
-}
-
-/**
- * Unregister a class module
- * @arg cops class module operations
- */
-int rtnl_class_unregister(struct rtnl_class_ops *cops)
-{
- struct rtnl_class_ops *o, **op;
-
- for (op = &class_ops_list; (o = *op) != NULL; op = &o->co_next)
- if (!strcasecmp(cops->co_kind, o->co_kind))
- break;
-
- if (!o)
- return -NLE_OBJ_NOTFOUND;
-
- *op = cops->co_next;
-
- return 0;
-}
-
-struct rtnl_class_ops *__rtnl_class_lookup_ops(const char *kind)
-{
- struct rtnl_class_ops *cops;
-
- for (cops = class_ops_list; cops; cops = cops->co_next)
- if (!strcmp(kind, cops->co_kind))
- return cops;
-
- return NULL;
-}
-
-/**
- * Lookup class operations for a class object
- * @arg class Class object.
- *
- * @return Class operations or NULL if not found.
- */
-struct rtnl_class_ops *rtnl_class_lookup_ops(struct rtnl_class *class)
-{
- if (!class->c_ops)
- class->c_ops = __rtnl_class_lookup_ops(class->c_kind);
-
- return class->c_ops;
-}
-
-
-/** @} */
-
-/** @} */
diff --git a/lib/route/class_obj.c b/lib/route/class_obj.c
deleted file mode 100644
index 097db25..0000000
--- a/lib/route/class_obj.c
+++ /dev/null
@@ -1,240 +0,0 @@
-/*
- * lib/route/class.c Queueing Classes
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup class
- * @defgroup class_obj Class Object
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
-#include <netlink/route/qdisc.h>
-#include <netlink/route/classifier.h>
-#include <netlink/utils.h>
-
-static void class_free_data(struct nl_object *obj)
-{
- struct rtnl_class *class = (struct rtnl_class *) obj;
- struct rtnl_class_ops *cops;
-
- tca_free_data((struct rtnl_tc *) class);
-
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_free_data)
- cops->co_free_data(class);
-}
-
-static int class_clone(struct nl_object *_dst, struct nl_object *_src)
-{
- struct rtnl_class *dst = nl_object_priv(_dst);
- struct rtnl_class *src = nl_object_priv(_src);
- struct rtnl_class_ops *cops;
- int err;
-
- err = tca_clone((struct rtnl_tc *) dst, (struct rtnl_tc *) src);
- if (err < 0)
- goto errout;
-
- cops = rtnl_class_lookup_ops(src);
- if (cops && cops->co_clone)
- err = cops->co_clone(dst, src);
-errout:
- return err;
-}
-
-static void class_dump_line(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_class *class = (struct rtnl_class *) obj;
- struct rtnl_class_ops *cops;
-
- tca_dump_line((struct rtnl_tc *) class, "class", p);
-
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_dump[NL_DUMP_LINE])
- cops->co_dump[NL_DUMP_LINE](class, p);
- nl_dump(p, "\n");
-}
-
-static void class_dump_details(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_class *class = (struct rtnl_class *) obj;
- struct rtnl_class_ops *cops;
-
- class_dump_line(obj, p);
- tca_dump_details((struct rtnl_tc *) class, p);
-
- if (class->c_info) {
- char buf[32];
- nl_dump(p, "child-qdisc %s ",
- rtnl_tc_handle2str(class->c_info, buf, sizeof(buf)));
- }
-
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_dump[NL_DUMP_DETAILS])
- cops->co_dump[NL_DUMP_DETAILS](class, p);
- else if (!class->c_info)
- nl_dump(p, "noop (no leaf qdisc)");
-
- nl_dump(p, "\n");
-}
-
-static void class_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_class *class = (struct rtnl_class *) obj;
- struct rtnl_class_ops *cops;
-
- class_dump_details(obj, p);
- tca_dump_stats((struct rtnl_tc *) class, p);
- nl_dump(p, "\n");
-
- cops = rtnl_class_lookup_ops(class);
- if (cops && cops->co_dump[NL_DUMP_STATS])
- cops->co_dump[NL_DUMP_STATS](class, p);
-}
-
-/**
- * @name Allocation/Freeing
- * @{
- */
-
-struct rtnl_class *rtnl_class_alloc(void)
-{
- return (struct rtnl_class *) nl_object_alloc(&class_obj_ops);
-}
-
-void rtnl_class_put(struct rtnl_class *class)
-{
- nl_object_put((struct nl_object *) class);
-}
-
-/** @} */
-
-/**
- * @name Leaf Qdisc
- * @{
- */
-
-/**
- * Lookup the leaf qdisc of a class
- * @arg class the parent class
- * @arg cache a qdisc cache including at laest all qdiscs of the
- * interface the specified class is attached to
- * @return The qdisc from the cache or NULL if the class has no leaf qdisc
- */
-struct rtnl_qdisc *rtnl_class_leaf_qdisc(struct rtnl_class *class,
- struct nl_cache *cache)
-{
- struct rtnl_qdisc *leaf;
-
- if (!class->c_info)
- return NULL;
-
- leaf = rtnl_qdisc_get_by_parent(cache, class->c_ifindex,
- class->c_handle);
- if (!leaf || leaf->q_handle != class->c_info)
- return NULL;
-
- return leaf;
-}
-
-/** @} */
-
-
-/**
- * @name Iterators
- * @{
- */
-
-/**
- * Call a callback for each child of a class
- * @arg class the parent class
- * @arg cache a class cache including all classes of the interface
- * the specified class is attached to
- * @arg cb callback function
- * @arg arg argument to be passed to callback function
- */
-void rtnl_class_foreach_child(struct rtnl_class *class, struct nl_cache *cache,
- void (*cb)(struct nl_object *, void *), void *arg)
-{
- struct rtnl_class *filter;
-
- filter = rtnl_class_alloc();
- if (!filter)
- return;
-
- rtnl_tc_set_parent((struct rtnl_tc *) filter, class->c_handle);
- rtnl_tc_set_ifindex((struct rtnl_tc *) filter, class->c_ifindex);
- rtnl_class_set_kind(filter, class->c_kind);
-
- nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
- rtnl_class_put(filter);
-}
-
-/**
- * Call a callback for each classifier attached to the class
- * @arg class the parent class
- * @arg cache a filter cache including at least all the filters
- * attached to the specified class
- * @arg cb callback function
- * @arg arg argument to be passed to callback function
- */
-void rtnl_class_foreach_cls(struct rtnl_class *class, struct nl_cache *cache,
- void (*cb)(struct nl_object *, void *), void *arg)
-{
- struct rtnl_cls *filter;
-
- filter = rtnl_cls_alloc();
- if (!filter)
- return;
-
- rtnl_tc_set_ifindex((struct rtnl_tc *) filter, class->c_ifindex);
- rtnl_tc_set_parent((struct rtnl_tc *) filter, class->c_parent);
-
- nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
- rtnl_cls_put(filter);
-}
-
-/** @} */
-
-
-/**
- * @name Attributes
- * @{
- */
-
-void rtnl_class_set_kind(struct rtnl_class *class, const char *name)
-{
- tca_set_kind((struct rtnl_tc *) class, name);
- class->c_ops = __rtnl_class_lookup_ops(name);
-}
-
-/** @} */
-
-struct nl_object_ops class_obj_ops = {
- .oo_name = "route/class",
- .oo_size = sizeof(struct rtnl_class),
- .oo_free_data = class_free_data,
- .oo_clone = class_clone,
- .oo_dump = {
- [NL_DUMP_LINE] = class_dump_line,
- [NL_DUMP_DETAILS] = class_dump_details,
- [NL_DUMP_STATS] = class_dump_stats,
- },
- .oo_compare = tca_compare,
- .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
-};
-
-/** @} */
diff --git a/lib/route/cls.c b/lib/route/cls.c
index 093b030..a041baa 100644
--- a/lib/route/cls.c
+++ b/lib/route/cls.c
@@ -28,66 +28,26 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/link.h>
-static struct nl_cache_ops rtnl_cls_ops;
-
-static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
- struct nlmsghdr *nlh, struct nl_parser_param *pp)
-{
- struct rtnl_cls_ops *cops;
- struct rtnl_cls *cls;
- int err;
+/** @cond SKIP */
+#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
+#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
+/** @endcond */
- cls = rtnl_cls_alloc();
- if (!cls) {
- err = -NLE_NOMEM;
- goto errout;
- }
- cls->ce_msgtype = nlh->nlmsg_type;
-
- err = tca_msg_parser(nlh, (struct rtnl_tc *) cls);
- if (err < 0)
- goto errout_free;
-
- cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
- cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_msg_parser && (err = cops->co_msg_parser(cls)) < 0)
- goto errout_free;
-
- err = pp->pp_cb((struct nl_object *) cls, pp);
-errout_free:
- rtnl_cls_put(cls);
-errout:
- return err;
-}
-
-static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk)
-{
- struct tcmsg tchdr = {
- .tcm_family = AF_UNSPEC,
- .tcm_ifindex = cache->c_iarg1,
- .tcm_parent = cache->c_iarg2,
- };
-
- return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
- sizeof(tchdr));
-}
+static struct nl_object_ops cls_obj_ops;
+static struct nl_cache_ops rtnl_cls_ops;
static int cls_build(struct rtnl_cls *cls, int type, int flags,
struct nl_msg **result)
{
- struct rtnl_cls_ops *cops;
int err, prio, proto;
struct tcmsg *tchdr;
- err = tca_build_msg((struct rtnl_tc *) cls, type, flags, result);
+ err = rtnl_tc_msg_build(TC_CAST(cls), type, flags, result);
if (err < 0)
return err;
@@ -96,27 +56,68 @@ static int cls_build(struct rtnl_cls *cls, int type, int flags,
proto = rtnl_cls_get_protocol(cls);
tchdr->tcm_info = TC_H_MAKE(prio << 16, htons(proto));
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_get_opts) {
- struct nlattr *opts;
+ return 0;
+}
- if (!(opts = nla_nest_start(*result, TCA_OPTIONS))) {
- err = -NLE_NOMEM;
- goto errout;
- }
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
- if ((err = cops->co_get_opts(cls, *result)) < 0)
- goto errout;
+struct rtnl_cls *rtnl_cls_alloc(void)
+{
+ struct rtnl_tc *tc;
- nla_nest_end(*result, opts);
- }
+ tc = TC_CAST(nl_object_alloc(&cls_obj_ops));
+ if (tc)
+ tc->tc_type = RTNL_TC_TYPE_CLS;
- return 0;
-errout:
- nlmsg_free(*result);
- return err;
+ return (struct rtnl_cls *) tc;
+}
+
+void rtnl_cls_put(struct rtnl_cls *cls)
+{
+ nl_object_put((struct nl_object *) cls);
+}
+
+/** @} */
+
+/**
+ * @name Attributes
+ * @{
+ */
+
+void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
+{
+ cls->c_prio = prio;
+ cls->ce_mask |= CLS_ATTR_PRIO;
+}
+
+uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
+{
+ if (cls->ce_mask & CLS_ATTR_PRIO)
+ return cls->c_prio;
+ else
+ return 0;
+}
+
+void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
+{
+ cls->c_protocol = protocol;
+ cls->ce_mask |= CLS_ATTR_PROTOCOL;
+}
+
+uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
+{
+ if (cls->ce_mask & CLS_ATTR_PROTOCOL)
+ return cls->c_protocol;
+ else
+ return ETH_P_ALL;
}
+/** @} */
+
+
/**
* @name Classifier Addition/Modification/Deletion
* @{
@@ -311,6 +312,57 @@ int rtnl_cls_alloc_cache(struct nl_sock *sk, int ifindex, uint32_t parent, st
/** @} */
+static void cls_dump_line(struct rtnl_tc *tc, struct nl_dump_params *p)
+{
+ struct rtnl_cls *cls = (struct rtnl_cls *) tc;
+ char buf[32];
+
+ nl_dump(p, " prio %u protocol %s", cls->c_prio,
+ nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
+}
+
+static int cls_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *nlh, struct nl_parser_param *pp)
+{
+ struct rtnl_cls *cls;
+ int err;
+
+ if (!(cls = rtnl_cls_alloc()))
+ return -NLE_NOMEM;
+
+ if ((err = rtnl_tc_msg_parse(nlh, TC_CAST(cls))) < 0)
+ goto errout;
+
+ cls->c_prio = TC_H_MAJ(cls->c_info) >> 16;
+ cls->c_protocol = ntohs(TC_H_MIN(cls->c_info));
+
+ err = pp->pp_cb(OBJ_CAST(cls), pp);
+errout:
+ rtnl_cls_put(cls);
+
+ return err;
+}
+
+static int cls_request_update(struct nl_cache *cache, struct nl_sock *sk)
+{
+ struct tcmsg tchdr = {
+ .tcm_family = AF_UNSPEC,
+ .tcm_ifindex = cache->c_iarg1,
+ .tcm_parent = cache->c_iarg2,
+ };
+
+ return nl_send_simple(sk, RTM_GETTFILTER, NLM_F_DUMP, &tchdr,
+ sizeof(tchdr));
+}
+
+static struct rtnl_tc_type_ops cls_ops = {
+ .tt_type = RTNL_TC_TYPE_CLS,
+ .tt_dump_prefix = "cls",
+ .tt_dump = {
+ [NL_DUMP_LINE] = cls_dump_line,
+ },
+};
+
static struct nl_cache_ops rtnl_cls_ops = {
.co_name = "route/cls",
.co_hdrsize = sizeof(struct tcmsg),
@@ -326,14 +378,30 @@ static struct nl_cache_ops rtnl_cls_ops = {
.co_obj_ops = &cls_obj_ops,
};
+static struct nl_object_ops cls_obj_ops = {
+ .oo_name = "route/cls",
+ .oo_size = sizeof(struct rtnl_cls),
+ .oo_free_data = rtnl_tc_free_data,
+ .oo_clone = rtnl_tc_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = rtnl_tc_dump_line,
+ [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
+ [NL_DUMP_STATS] = rtnl_tc_dump_stats,
+ },
+ .oo_compare = rtnl_tc_compare,
+ .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
+};
+
static void __init cls_init(void)
{
+ rtnl_tc_type_register(&cls_ops);
nl_cache_mngt_register(&rtnl_cls_ops);
}
static void __exit cls_exit(void)
{
nl_cache_mngt_unregister(&rtnl_cls_ops);
+ rtnl_tc_type_unregister(&cls_ops);
}
/** @} */
diff --git a/lib/route/cls/basic.c b/lib/route/cls/basic.c
index 94f0cf7..9d7710a 100644
--- a/lib/route/cls/basic.c
+++ b/lib/route/cls/basic.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2008-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
* @ingroup cls
- * @defgroup basic Basic Classifier
+ * @defgroup cls_basic Basic Classifier
*
* @par Introduction
* The basic classifier is the simplest form of a classifier. It does
@@ -25,8 +25,8 @@
#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/basic.h>
#include <netlink/route/cls/ematch.h>
@@ -47,50 +47,57 @@ static struct nla_policy basic_policy[TCA_BASIC_MAX+1] = {
[TCA_BASIC_EMATCHES] = { .type = NLA_NESTED },
};
-static int basic_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
+static int basic_clone(void *_dst, void *_src)
{
return -NLE_OPNOTSUPP;
}
-static void basic_free_data(struct rtnl_cls *cls)
+static void basic_free_data(struct rtnl_tc *tc, void *data)
{
- struct rtnl_basic *basic = rtnl_cls_data(cls);
+ struct rtnl_basic *b = data;
- rtnl_ematch_tree_free(basic->b_ematch);
+ if (!b)
+ return;
+
+ rtnl_ematch_tree_free(b->b_ematch);
}
-static int basic_msg_parser(struct rtnl_cls *cls)
+static int basic_msg_parser(struct rtnl_tc *tc, void *data)
{
struct nlattr *tb[TCA_BASIC_MAX + 1];
- struct rtnl_basic *basic = rtnl_cls_data(cls);
+ struct rtnl_basic *b = data;
int err;
- err = tca_parse(tb, TCA_BASIC_MAX, (struct rtnl_tc *) cls, basic_policy);
+ err = tca_parse(tb, TCA_BASIC_MAX, tc, basic_policy);
if (err < 0)
return err;
if (tb[TCA_BASIC_CLASSID]) {
- basic->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
- basic->b_mask |= BASIC_ATTR_TARGET;
+ b->b_target = nla_get_u32(tb[TCA_BASIC_CLASSID]);
+ b->b_mask |= BASIC_ATTR_TARGET;
}
if (tb[TCA_BASIC_EMATCHES]) {
if ((err = rtnl_ematch_parse_attr(tb[TCA_BASIC_EMATCHES],
- &basic->b_ematch)) < 0)
+ &b->b_ematch)) < 0)
return err;
- if (basic->b_ematch)
- basic->b_mask |= BASIC_ATTR_EMATCH;
+ if (b->b_ematch)
+ b->b_mask |= BASIC_ATTR_EMATCH;
}
return 0;
}
-static void basic_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void basic_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b = data;
char buf[32];
+ if (!b)
+ return;
+
if (b->b_mask & BASIC_ATTR_EMATCH)
nl_dump(p, " ematch");
else
@@ -101,9 +108,13 @@ static void basic_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
rtnl_tc_handle2str(b->b_target, buf, sizeof(buf)));
}
-static void basic_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void basic_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b = data;
+
+ if (!b)
+ return;
if (b->b_mask & BASIC_ATTR_EMATCH) {
nl_dump_line(p, " ematch ");
@@ -112,9 +123,13 @@ static void basic_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
nl_dump(p, "no options.\n");
}
-static int basic_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
+static int basic_msg_fill(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b = data;
+
+ if (!b)
+ return 0;
if (!(b->b_mask & BASIC_ATTR_TARGET))
return -NLE_MISSING_ATTR;
@@ -138,7 +153,10 @@ nla_put_failure:
void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b;
+
+ if (!(b = rtnl_tc_data(TC_CAST(cls))))
+ return;
b->b_target = target;
b->b_mask |= BASIC_ATTR_TARGET;
@@ -146,14 +164,20 @@ void rtnl_basic_set_target(struct rtnl_cls *cls, uint32_t target)
uint32_t rtnl_basic_get_target(struct rtnl_cls *cls)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b;
+
+ if (!(b = rtnl_tc_data(TC_CAST(cls))))
+ return 0;
return b->b_target;
}
void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
{
- struct rtnl_basic *b = rtnl_cls_data(cls);
+ struct rtnl_basic *b;
+
+ if (!(b = rtnl_tc_data(TC_CAST(cls))))
+ return;
if (b->b_ematch) {
rtnl_ematch_tree_free(b->b_ematch);
@@ -168,19 +192,25 @@ void rtnl_basic_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
struct rtnl_ematch_tree *rtnl_basic_get_ematch(struct rtnl_cls *cls)
{
- return ((struct rtnl_basic *) rtnl_cls_data(cls))->b_ematch;
+ struct rtnl_basic *b;
+
+ if (!(b = rtnl_tc_data(TC_CAST(cls))))
+ return NULL;
+
+ return b->b_ematch;
}
/** @} */
-static struct rtnl_cls_ops basic_ops = {
- .co_kind = "basic",
- .co_size = sizeof(struct rtnl_basic),
- .co_msg_parser = basic_msg_parser,
- .co_clone = basic_clone,
- .co_free_data = basic_free_data,
- .co_get_opts = basic_get_opts,
- .co_dump = {
+static struct rtnl_tc_ops basic_ops = {
+ .to_kind = "basic",
+ .to_type = RTNL_TC_TYPE_CLS,
+ .to_size = sizeof(struct rtnl_basic),
+ .to_msg_parser = basic_msg_parser,
+ .to_clone = basic_clone,
+ .to_free_data = basic_free_data,
+ .to_msg_fill = basic_msg_fill,
+ .to_dump = {
[NL_DUMP_LINE] = basic_dump_line,
[NL_DUMP_DETAILS] = basic_dump_details,
},
@@ -188,12 +218,12 @@ static struct rtnl_cls_ops basic_ops = {
static void __init basic_init(void)
{
- rtnl_cls_register(&basic_ops);
+ rtnl_tc_register(&basic_ops);
}
static void __exit basic_exit(void)
{
- rtnl_cls_unregister(&basic_ops);
+ rtnl_tc_unregister(&basic_ops);
}
/** @} */
diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c
index 751e385..230863b 100644
--- a/lib/route/cls/cgroup.c
+++ b/lib/route/cls/cgroup.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2009-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2009-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup cls_api
- * @defgroup cgroup Control Groups Classifier
+ * @ingroup cls
+ * @defgroup cls_cgroup Control Groups Classifier
*
* @{
*/
@@ -21,8 +21,8 @@
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/cgroup.h>
#include <netlink/route/cls/ematch.h>
@@ -34,26 +34,28 @@ static struct nla_policy cgroup_policy[TCA_CGROUP_MAX+1] = {
[TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED },
};
-static int cgroup_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
+static int cgroup_clone(void *dst, void *src)
{
return -NLE_OPNOTSUPP;
}
-static void cgroup_free_data(struct rtnl_cls *cls)
+static void cgroup_free_data(struct rtnl_tc *tc, void *data)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = data;
+
+ if (!c)
+ return;
rtnl_ematch_tree_free(c->cg_ematch);
}
-static int cgroup_msg_parser(struct rtnl_cls *cls)
+static int cgroup_msg_parser(struct rtnl_tc *tc, void *data)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
struct nlattr *tb[TCA_CGROUP_MAX + 1];
+ struct rtnl_cgroup *c = data;
int err;
- err = tca_parse(tb, TCA_CGROUP_MAX, (struct rtnl_tc *) cls,
- cgroup_policy);
+ err = tca_parse(tb, TCA_CGROUP_MAX, tc, cgroup_policy);
if (err < 0)
return err;
@@ -73,9 +75,13 @@ static int cgroup_msg_parser(struct rtnl_cls *cls)
return 0;
}
-static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void cgroup_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = data;
+
+ if (!c)
+ return;
if (c->cg_mask & CGROUP_ATTR_EMATCH)
nl_dump(p, " ematch");
@@ -83,22 +89,34 @@ static void cgroup_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
nl_dump(p, " match-all");
}
-static void cgroup_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void cgroup_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = data;
+
+ if (!c)
+ return;
if (c->cg_mask & CGROUP_ATTR_EMATCH) {
nl_dump_line(p, " ematch ");
- rtnl_ematch_tree_dump(c->cg_ematch, p);
+
+ if (c->cg_ematch)
+ rtnl_ematch_tree_dump(c->cg_ematch, p);
+ else
+ nl_dump(p, "<no tree>");
} else
- nl_dump(p, "no options.\n");
+ nl_dump(p, "no options");
}
-static int cgroup_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
+static int cgroup_fill_msg(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c = data;
- if (!(cls->ce_mask & TCA_ATTR_HANDLE))
+ if (!c)
+ BUG();
+
+ if (!(tc->ce_mask & TCA_ATTR_HANDLE))
return -NLE_MISSING_ATTR;
if (c->cg_mask & CGROUP_ATTR_EMATCH)
@@ -116,7 +134,10 @@ static int cgroup_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
{
- struct rtnl_cgroup *c = rtnl_cls_data(cls);
+ struct rtnl_cgroup *c;
+
+ if (!(c = rtnl_tc_data(TC_CAST(cls))))
+ BUG();
if (c->cg_ematch) {
rtnl_ematch_tree_free(c->cg_ematch);
@@ -131,19 +152,25 @@ void rtnl_cgroup_set_ematch(struct rtnl_cls *cls, struct rtnl_ematch_tree *tree)
struct rtnl_ematch_tree *rtnl_cgroup_get_ematch(struct rtnl_cls *cls)
{
- return ((struct rtnl_cgroup *) rtnl_cls_data(cls))->cg_ematch;
+ struct rtnl_cgroup *c;
+
+ if (!(c = rtnl_tc_data(TC_CAST(cls))))
+ BUG();
+
+ return c->cg_ematch;
}
/** @} */
-static struct rtnl_cls_ops cgroup_ops = {
- .co_kind = "cgroup",
- .co_size = sizeof(struct rtnl_cgroup),
- .co_clone = cgroup_clone,
- .co_msg_parser = cgroup_msg_parser,
- .co_free_data = cgroup_free_data,
- .co_get_opts = cgroup_get_opts,
- .co_dump = {
+static struct rtnl_tc_ops cgroup_ops = {
+ .to_kind = "cgroup",
+ .to_type = RTNL_TC_TYPE_CLS,
+ .to_size = sizeof(struct rtnl_cgroup),
+ .to_clone = cgroup_clone,
+ .to_msg_parser = cgroup_msg_parser,
+ .to_free_data = cgroup_free_data,
+ .to_msg_fill = cgroup_fill_msg,
+ .to_dump = {
[NL_DUMP_LINE] = cgroup_dump_line,
[NL_DUMP_DETAILS] = cgroup_dump_details,
},
@@ -151,12 +178,12 @@ static struct rtnl_cls_ops cgroup_ops = {
static void __init cgroup_init(void)
{
- rtnl_cls_register(&cgroup_ops);
+ rtnl_tc_register(&cgroup_ops);
}
static void __exit cgroup_exit(void)
{
- rtnl_cls_unregister(&cgroup_ops);
+ rtnl_tc_unregister(&cgroup_ops);
}
/** @} */
diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c
index e2719c2..8c9c3dd 100644
--- a/lib/route/cls/ematch.c
+++ b/lib/route/cls/ematch.c
@@ -20,7 +20,6 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/cmp.h>
@@ -511,6 +510,9 @@ static void dump_ematch_sequence(struct nl_list_head *head,
void rtnl_ematch_tree_dump(struct rtnl_ematch_tree *tree,
struct nl_dump_params *p)
{
+ if (!tree)
+ BUG();
+
dump_ematch_sequence(&tree->et_list, p);
nl_dump(p, "\n");
}
diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c
index b8055fe..11c9c67 100644
--- a/lib/route/cls/fw.c
+++ b/lib/route/cls/fw.c
@@ -6,14 +6,14 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2006 Petr Gotthard <petr.gotthard@siemens.com>
* Copyright (c) 2006 Siemens AG Oesterreich
*/
/**
- * @ingroup cls_api
- * @defgroup fw Firewall Classifier
+ * @ingroup cls
+ * @defgroup cls_fw Firewall Classifier
*
* @{
*/
@@ -21,8 +21,8 @@
#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/fw.h>
/** @cond SKIP */
@@ -38,13 +38,13 @@ static struct nla_policy fw_policy[TCA_FW_MAX+1] = {
.maxlen = IFNAMSIZ },
};
-static int fw_msg_parser(struct rtnl_cls *cls)
+static int fw_msg_parser(struct rtnl_tc *tc, void *data)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
struct nlattr *tb[TCA_FW_MAX + 1];
+ struct rtnl_fw *f = data;
int err;
- err = tca_parse(tb, TCA_FW_MAX, (struct rtnl_tc *) cls, fw_policy);
+ err = tca_parse(tb, TCA_FW_MAX, tc, fw_policy);
if (err < 0)
return err;
@@ -75,18 +75,17 @@ static int fw_msg_parser(struct rtnl_cls *cls)
return 0;
}
-static void fw_free_data(struct rtnl_cls *cls)
+static void fw_free_data(struct rtnl_tc *tc, void *data)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
+ struct rtnl_fw *f = data;
nl_data_free(f->cf_act);
nl_data_free(f->cf_police);
}
-static int fw_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
+static int fw_clone(void *_dst, void *_src)
{
- struct rtnl_fw *dst = rtnl_cls_data(_dst);
- struct rtnl_fw *src = rtnl_cls_data(_src);
+ struct rtnl_fw *dst = _dst, *src = _src;
if (src->cf_act && !(dst->cf_act = nl_data_clone(src->cf_act)))
return -NLE_NOMEM;
@@ -97,28 +96,35 @@ static int fw_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
return 0;
}
-static void fw_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void fw_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
- char buf[32];
+ struct rtnl_fw *f = data;
+
+ if (f && f->cf_mask & FW_ATTR_CLASSID) {
+ char buf[32];
- if (f->cf_mask & FW_ATTR_CLASSID)
nl_dump(p, " target %s",
rtnl_tc_handle2str(f->cf_classid, buf, sizeof(buf)));
+ }
}
-static void fw_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void fw_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
+ struct rtnl_fw *f = data;
- if (f->cf_mask & FW_ATTR_INDEV)
+ if (f && f->cf_mask & FW_ATTR_INDEV)
nl_dump(p, "indev %s ", f->cf_indev);
}
-static int fw_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
+static int fw_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
-
+ struct rtnl_fw *f = data;
+
+ if (!f)
+ return 0;
+
if (f->cf_mask & FW_ATTR_CLASSID)
NLA_PUT_U32(msg, TCA_FW_CLASSID, f->cf_classid);
@@ -134,7 +140,7 @@ static int fw_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
return 0;
nla_put_failure:
- return -NLE_NOMEM;
+ return -NLE_MSGSIZE;
}
/**
@@ -144,7 +150,10 @@ nla_put_failure:
int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
{
- struct rtnl_fw *f = rtnl_cls_data(cls);
+ struct rtnl_fw *f;
+
+ if (!(f = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
f->cf_classid = classid;
f->cf_mask |= FW_ATTR_CLASSID;
@@ -154,14 +163,15 @@ int rtnl_fw_set_classid(struct rtnl_cls *cls, uint32_t classid)
/** @} */
-static struct rtnl_cls_ops fw_ops = {
- .co_kind = "fw",
- .co_size = sizeof(struct rtnl_fw),
- .co_msg_parser = fw_msg_parser,
- .co_free_data = fw_free_data,
- .co_clone = fw_clone,
- .co_get_opts = fw_get_opts,
- .co_dump = {
+static struct rtnl_tc_ops fw_ops = {
+ .to_kind = "fw",
+ .to_type = RTNL_TC_TYPE_CLS,
+ .to_size = sizeof(struct rtnl_fw),
+ .to_msg_parser = fw_msg_parser,
+ .to_msg_fill = fw_msg_fill,
+ .to_free_data = fw_free_data,
+ .to_clone = fw_clone,
+ .to_dump = {
[NL_DUMP_LINE] = fw_dump_line,
[NL_DUMP_DETAILS] = fw_dump_details,
},
@@ -169,12 +179,12 @@ static struct rtnl_cls_ops fw_ops = {
static void __init fw_init(void)
{
- rtnl_cls_register(&fw_ops);
+ rtnl_tc_register(&fw_ops);
}
static void __exit fw_exit(void)
{
- rtnl_cls_unregister(&fw_ops);
+ rtnl_tc_unregister(&fw_ops);
}
/** @} */
diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c
index f2cd45a..d7ab26b 100644
--- a/lib/route/cls/police.c
+++ b/lib/route/cls/police.c
@@ -13,9 +13,8 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/police.h>
/**
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 38214c9..2016460 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -6,14 +6,14 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2005-2006 Petr Gotthard <petr.gotthard@siemens.com>
* Copyright (c) 2005-2006 Siemens AG Oesterreich
*/
/**
- * @ingroup cls_api
- * @defgroup u32 Universal 32-bit Classifier
+ * @ingroup cls
+ * @defgroup cls_u32 Universal 32-bit Classifier
*
* @{
*/
@@ -23,9 +23,8 @@
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
#include <netlink/route/cls/u32.h>
/** @cond SKIP */
@@ -64,13 +63,13 @@ static struct nla_policy u32_policy[TCA_U32_MAX+1] = {
[TCA_U32_PCNT] = { .minlen = sizeof(struct tc_u32_pcnt) },
};
-static int u32_msg_parser(struct rtnl_cls *cls)
+static int u32_msg_parser(struct rtnl_tc *tc, void *data)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
struct nlattr *tb[TCA_U32_MAX + 1];
int err;
- err = tca_parse(tb, TCA_U32_MAX, (struct rtnl_tc *) cls, u32_policy);
+ err = tca_parse(tb, TCA_U32_MAX, tc, u32_policy);
if (err < 0)
return err;
@@ -151,9 +150,9 @@ errout:
return err;
}
-static void u32_free_data(struct rtnl_cls *cls)
+static void u32_free_data(struct rtnl_tc *tc, void *data)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
nl_data_free(u->cu_selector);
nl_data_free(u->cu_act);
@@ -161,10 +160,9 @@ static void u32_free_data(struct rtnl_cls *cls)
nl_data_free(u->cu_pcnt);
}
-static int u32_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
+static int u32_clone(void *_dst, void *_src)
{
- struct rtnl_u32 *dst = rtnl_cls_data(_dst);
- struct rtnl_u32 *src = rtnl_cls_data(_src);
+ struct rtnl_u32 *dst = _dst, *src = _src;
if (src->cu_selector &&
!(dst->cu_selector = nl_data_clone(src->cu_selector)))
@@ -182,10 +180,14 @@ static int u32_clone(struct rtnl_cls *_dst, struct rtnl_cls *_src)
return 0;
}
-static void u32_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void u32_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
char buf[32];
+
+ if (!u)
+ return;
if (u->cu_mask & U32_ATTR_DIVISOR)
nl_dump(p, " divisor %u", u->cu_divisor);
@@ -195,7 +197,7 @@ static void u32_dump_line(struct rtnl_cls *cls, struct nl_dump_params *p)
}
static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel,
- struct rtnl_cls *cls, struct rtnl_u32 *u)
+ struct rtnl_u32 *u)
{
int i;
struct tc_u32_key *key;
@@ -253,11 +255,15 @@ static void print_selector(struct nl_dump_params *p, struct tc_u32_sel *sel,
}
}
-static void u32_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void u32_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
struct tc_u32_sel *s;
+ if (!u)
+ return;
+
if (!(u->cu_mask & U32_ATTR_SELECTOR)) {
nl_dump(p, "no-selector\n");
return;
@@ -277,7 +283,7 @@ static void u32_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
if (u->cu_mask & U32_ATTR_INDEV)
nl_dump(p, "indev %s ", u->cu_indev);
- print_selector(p, s, cls, u);
+ print_selector(p, s, u);
nl_dump(p, "\n");
#if 0
@@ -289,9 +295,13 @@ static void u32_dump_details(struct rtnl_cls *cls, struct nl_dump_params *p)
#endif
}
-static void u32_dump_stats(struct rtnl_cls *cls, struct nl_dump_params *p)
+static void u32_dump_stats(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
+
+ if (!u)
+ return;
if (u->cu_mask & U32_ATTR_PCNT) {
struct tc_u32_pcnt *pc = u->cu_pcnt->d_data;
@@ -301,9 +311,12 @@ static void u32_dump_stats(struct rtnl_cls *cls, struct nl_dump_params *p)
}
}
-static int u32_get_opts(struct rtnl_cls *cls, struct nl_msg *msg)
+static int u32_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u = data;
+
+ if (!u)
+ return 0;
if (u->cu_mask & U32_ATTR_DIVISOR)
NLA_PUT_U32(msg, TCA_U32_DIVISOR, u->cu_divisor);
@@ -350,7 +363,10 @@ void rtnl_u32_set_handle(struct rtnl_cls *cls, int htid, int hash,
int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid)
{
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u;
+
+ if (!(u = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
u->cu_classid = classid;
u->cu_mask |= U32_ATTR_CLASSID;
@@ -368,7 +384,10 @@ int rtnl_u32_set_classid(struct rtnl_cls *cls, uint32_t classid)
int rtnl_u32_set_flags(struct rtnl_cls *cls, int flags)
{
struct tc_u32_sel *sel;
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u;
+
+ if (!(u = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
sel = u32_selector_alloc(u);
if (!sel)
@@ -398,9 +417,12 @@ int rtnl_u32_add_key(struct rtnl_cls *cls, uint32_t val, uint32_t mask,
int off, int offmask)
{
struct tc_u32_sel *sel;
- struct rtnl_u32 *u = rtnl_cls_data(cls);
+ struct rtnl_u32 *u;
int err;
+ if (!(u = rtnl_tc_data(TC_CAST(cls))))
+ return -NLE_NOMEM;
+
sel = u32_selector_alloc(u);
if (!sel)
return -NLE_NOMEM;
@@ -501,14 +523,15 @@ int rtnl_u32_add_key_in6_addr(struct rtnl_cls *cls, struct in6_addr *addr,
/** @} */
-static struct rtnl_cls_ops u32_ops = {
- .co_kind = "u32",
- .co_size = sizeof(struct rtnl_u32),
- .co_msg_parser = u32_msg_parser,
- .co_free_data = u32_free_data,
- .co_clone = u32_clone,
- .co_get_opts = u32_get_opts,
- .co_dump = {
+static struct rtnl_tc_ops u32_ops = {
+ .to_kind = "u32",
+ .to_type = RTNL_TC_TYPE_CLS,
+ .to_size = sizeof(struct rtnl_u32),
+ .to_msg_parser = u32_msg_parser,
+ .to_free_data = u32_free_data,
+ .to_clone = u32_clone,
+ .to_msg_fill = u32_msg_fill,
+ .to_dump = {
[NL_DUMP_LINE] = u32_dump_line,
[NL_DUMP_DETAILS] = u32_dump_details,
[NL_DUMP_STATS] = u32_dump_stats,
@@ -517,12 +540,12 @@ static struct rtnl_cls_ops u32_ops = {
static void __init u32_init(void)
{
- rtnl_cls_register(&u32_ops);
+ rtnl_tc_register(&u32_ops);
}
static void __exit u32_exit(void)
{
- rtnl_cls_unregister(&u32_ops);
+ rtnl_tc_unregister(&u32_ops);
}
/** @} */
diff --git a/lib/route/cls_api.c b/lib/route/cls_api.c
deleted file mode 100644
index 73f05df..0000000
--- a/lib/route/cls_api.c
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * lib/route/cls_api.c Classifier Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup cls
- * @defgroup cls_api Classifier Modules
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/utils.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
-#include <netlink/route/link.h>
-
-static struct rtnl_cls_ops *cls_ops_list;
-
-/**
- * @name Classifier Module API
- * @{
- */
-
-/**
- * Register a classifier module
- * @arg cops classifier module operations
- */
-int rtnl_cls_register(struct rtnl_cls_ops *cops)
-{
- struct rtnl_cls_ops *o, **op;
-
- if (!cops->co_kind)
- BUG();
-
- for (op = &cls_ops_list; (o = *op) != NULL; op = &o->co_next)
- if (!strcasecmp(cops->co_kind, o->co_kind))
- return -NLE_EXIST;
-
- cops->co_next = NULL;
- *op = cops;
-
- return 0;
-}
-
-/**
- * Unregister a classifier module
- * @arg cops classifier module operations
- */
-int rtnl_cls_unregister(struct rtnl_cls_ops *cops)
-{
- struct rtnl_cls_ops *o, **op;
-
- for (op = &cls_ops_list; (o = *op) != NULL; op = &o->co_next)
- if (!strcasecmp(cops->co_kind, o->co_kind))
- break;
-
- if (!o)
- return -NLE_OBJ_NOTFOUND;
-
- *op = cops->co_next;
-
- return 0;
-}
-
-struct rtnl_cls_ops *__rtnl_cls_lookup_ops(const char *kind)
-{
- struct rtnl_cls_ops *cops;
-
- for (cops = cls_ops_list; cops; cops = cops->co_next)
- if (!strcmp(kind, cops->co_kind))
- return cops;
-
- return NULL;
-}
-
-/**
- * Lookup classifier operations for a classifier object
- * @arg cls Classifier object.
- *
- * @return Classifier operations or NULL if not found.
- */
-struct rtnl_cls_ops *rtnl_cls_lookup_ops(struct rtnl_cls *cls)
-{
- if (!cls->c_ops)
- cls->c_ops = __rtnl_cls_lookup_ops(cls->c_kind);
-
- return cls->c_ops;
-}
-
-
-/** @} */
-
-/** @} */
diff --git a/lib/route/cls_obj.c b/lib/route/cls_obj.c
deleted file mode 100644
index dcf97ed..0000000
--- a/lib/route/cls_obj.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * lib/route/cls_api.c Classifier Object
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup cls
- * @defgroup cls_obj Classifier Object
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/utils.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/classifier.h>
-#include <netlink/route/classifier-modules.h>
-#include <netlink/route/link.h>
-
-/** @cond SKIP */
-#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
-#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
-/** @endcond */
-
-static void cls_free_data(struct nl_object *obj)
-{
- struct rtnl_cls *cls = (struct rtnl_cls *) obj;
- struct rtnl_cls_ops *cops;
-
- tca_free_data((struct rtnl_tc *) cls);
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_free_data)
- cops->co_free_data(cls);
-
- nl_data_free(cls->c_subdata);
-}
-
-static int cls_clone(struct nl_object *_dst, struct nl_object *_src)
-{
- struct rtnl_cls *dst = nl_object_priv(_dst);
- struct rtnl_cls *src = nl_object_priv(_src);
- struct rtnl_cls_ops *cops;
- int err;
-
- err = tca_clone((struct rtnl_tc *) dst, (struct rtnl_tc *) src);
- if (err < 0)
- goto errout;
-
- if (src->c_subdata) {
- if (!(dst->c_subdata = nl_data_clone(src->c_subdata))) {
- err = -NLE_NOMEM;
- goto errout;
- }
- }
-
- cops = rtnl_cls_lookup_ops(src);
- if (cops && cops->co_clone)
- err = cops->co_clone(dst, src);
-errout:
- return err;
-}
-
-static void cls_dump_line(struct nl_object *obj, struct nl_dump_params *p)
-{
- char buf[32];
- struct rtnl_cls *cls = (struct rtnl_cls *) obj;
- struct rtnl_cls_ops *cops;
-
- tca_dump_line((struct rtnl_tc *) cls, "cls", p);
-
- nl_dump(p, " prio %u protocol %s", cls->c_prio,
- nl_ether_proto2str(cls->c_protocol, buf, sizeof(buf)));
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_dump[NL_DUMP_LINE])
- cops->co_dump[NL_DUMP_LINE](cls, p);
- nl_dump(p, "\n");
-}
-
-static void cls_dump_details(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_cls *cls = (struct rtnl_cls *) obj;
- struct rtnl_cls_ops *cops;
-
- cls_dump_line(obj, p);
- tca_dump_details((struct rtnl_tc *) cls, p);
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_dump[NL_DUMP_DETAILS])
- cops->co_dump[NL_DUMP_DETAILS](cls, p);
- else
- nl_dump(p, "no options\n");
-}
-
-static void cls_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_cls *cls = (struct rtnl_cls *) obj;
- struct rtnl_cls_ops *cops;
-
- cls_dump_details(obj, p);
- tca_dump_stats((struct rtnl_tc *) cls, p);
- nl_dump(p, "\n");
-
- cops = rtnl_cls_lookup_ops(cls);
- if (cops && cops->co_dump[NL_DUMP_STATS])
- cops->co_dump[NL_DUMP_STATS](cls, p);
-}
-
-/**
- * @name Allocation/Freeing
- * @{
- */
-
-struct rtnl_cls *rtnl_cls_alloc(void)
-{
- return (struct rtnl_cls *) nl_object_alloc(&cls_obj_ops);
-}
-
-void rtnl_cls_put(struct rtnl_cls *cls)
-{
- nl_object_put((struct nl_object *) cls);
-}
-
-/** @} */
-
-
-/**
- * @name Attributes
- * @{
- */
-
-int rtnl_cls_set_kind(struct rtnl_cls *cls, const char *kind)
-{
- if (cls->ce_mask & TCA_ATTR_KIND)
- return -NLE_EXIST;
-
- tca_set_kind((struct rtnl_tc *) cls, kind);
-
- /* Force allocation of data */
- rtnl_cls_data(cls);
-
- return 0;
-}
-
-struct rtnl_cls_ops *rtnl_cls_get_ops(struct rtnl_cls *cls)
-{
- return cls->c_ops;
-}
-
-void rtnl_cls_set_prio(struct rtnl_cls *cls, uint16_t prio)
-{
- cls->c_prio = prio;
- cls->ce_mask |= CLS_ATTR_PRIO;
-}
-
-uint16_t rtnl_cls_get_prio(struct rtnl_cls *cls)
-{
- if (cls->ce_mask & CLS_ATTR_PRIO)
- return cls->c_prio;
- else
- return 0;
-}
-
-void rtnl_cls_set_protocol(struct rtnl_cls *cls, uint16_t protocol)
-{
- cls->c_protocol = protocol;
- cls->ce_mask |= CLS_ATTR_PROTOCOL;
-}
-
-uint16_t rtnl_cls_get_protocol(struct rtnl_cls *cls)
-{
- if (cls->ce_mask & CLS_ATTR_PROTOCOL)
- return cls->c_protocol;
- else
- return ETH_P_ALL;
-}
-
-void *rtnl_cls_data(struct rtnl_cls *cls)
-{
- if (!cls->c_subdata) {
- struct rtnl_cls_ops *ops = cls->c_ops;
-
- if (!ops) {
- if (!cls->c_kind[0])
- BUG();
-
- ops = __rtnl_cls_lookup_ops(cls->c_kind);
- if (ops == NULL)
- return NULL;
-
- cls->c_ops = ops;
- }
-
- if (!ops->co_size)
- BUG();
-
- if (!(cls->c_subdata = nl_data_alloc(NULL, ops->co_size)))
- return NULL;
- }
-
- return nl_data_get(cls->c_subdata);
-}
-
-/** @} */
-
-struct nl_object_ops cls_obj_ops = {
- .oo_name = "route/cls",
- .oo_size = sizeof(struct rtnl_cls),
- .oo_free_data = cls_free_data,
- .oo_clone = cls_clone,
- .oo_dump = {
- [NL_DUMP_LINE] = cls_dump_line,
- [NL_DUMP_DETAILS] = cls_dump_details,
- [NL_DUMP_STATS] = cls_dump_stats,
- },
- .oo_compare = tca_compare,
- .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
-};
-
-/** @} */
diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c
index 2867e63..6ec3a40 100644
--- a/lib/route/qdisc.c
+++ b/lib/route/qdisc.c
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
@@ -87,44 +87,29 @@
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/classifier.h>
-#include <netlink/route/qdisc-modules.h>
static struct nl_cache_ops rtnl_qdisc_ops;
static int qdisc_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *n, struct nl_parser_param *pp)
{
- int err;
struct rtnl_qdisc *qdisc;
- struct rtnl_qdisc_ops *qops;
-
- qdisc = rtnl_qdisc_alloc();
- if (!qdisc) {
- err = -NLE_NOMEM;
- goto errout;
- }
-
- qdisc->ce_msgtype = n->nlmsg_type;
+ int err;
- err = tca_msg_parser(n, (struct rtnl_tc *) qdisc);
- if (err < 0)
- goto errout_free;
+ if (!(qdisc = rtnl_qdisc_alloc()))
+ return -NLE_NOMEM;
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_msg_parser) {
- err = qops->qo_msg_parser(qdisc);
- if (err < 0)
- goto errout_free;
- }
+ if ((err = rtnl_tc_msg_parse(n, TC_CAST(qdisc))) < 0)
+ goto errout;
- err = pp->pp_cb((struct nl_object *) qdisc, pp);
-errout_free:
- rtnl_qdisc_put(qdisc);
+ err = pp->pp_cb(OBJ_CAST(qdisc), pp);
errout:
+ rtnl_qdisc_put(qdisc);
+
return err;
}
@@ -147,25 +132,9 @@ static int qdisc_request_update(struct nl_cache *c, struct nl_sock *sk)
static int qdisc_build(struct rtnl_qdisc *qdisc, int type, int flags,
struct nl_msg **result)
{
- struct rtnl_qdisc_ops *qops;
- int err;
-
- err = tca_build_msg((struct rtnl_tc *) qdisc, type, flags, result);
- if (err < 0)
- return err;
+ return rtnl_tc_msg_build(TC_CAST(qdisc), type, flags, result);
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_get_opts) {
- struct nl_msg *opts;
-
- opts = qops->qo_get_opts(qdisc);
- if (opts) {
- err = nla_put_nested(*result, TCA_OPTIONS, opts);
- nlmsg_free(opts);
- if (err < 0)
- goto errout;
- }
- }
+#if 0
/* Some qdiscs don't accept properly nested messages (e.g. netem). To
* accomodate for this, they can complete the message themselves.
*/
@@ -174,12 +143,7 @@ static int qdisc_build(struct rtnl_qdisc *qdisc, int type, int flags,
if (err < 0)
goto errout;
}
-
- return 0;
-errout:
- nlmsg_free(*result);
-
- return err;
+#endif
}
/**
@@ -440,6 +404,101 @@ struct rtnl_qdisc * rtnl_qdisc_get(struct nl_cache *cache,
/** @} */
+/**
+ * @name Allocation/Freeing
+ * @{
+ */
+
+struct rtnl_qdisc *rtnl_qdisc_alloc(void)
+{
+ struct rtnl_tc *tc;
+
+ tc = TC_CAST(nl_object_alloc(&qdisc_obj_ops));
+ if (tc)
+ tc->tc_type = RTNL_TC_TYPE_QDISC;
+
+ return (struct rtnl_qdisc *) tc;
+}
+
+void rtnl_qdisc_put(struct rtnl_qdisc *qdisc)
+{
+ nl_object_put((struct nl_object *) qdisc);
+}
+
+/** @} */
+
+/**
+ * @name Iterators
+ * @{
+ */
+
+/**
+ * Call a callback for each child class of a qdisc
+ * @arg qdisc the parent qdisc
+ * @arg cache a class cache including all classes of the interface
+ * the specified qdisc is attached to
+ * @arg cb callback function
+ * @arg arg argument to be passed to callback function
+ */
+void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ struct rtnl_class *filter;
+
+ filter = rtnl_class_alloc();
+ if (!filter)
+ return;
+
+ rtnl_tc_set_parent(TC_CAST(filter), qdisc->q_handle);
+ rtnl_tc_set_ifindex(TC_CAST(filter), qdisc->q_ifindex);
+ rtnl_tc_set_kind(TC_CAST(filter), qdisc->q_kind);
+
+ nl_cache_foreach_filter(cache, OBJ_CAST(filter), cb, arg);
+
+ rtnl_class_put(filter);
+}
+
+/**
+ * Call a callback for each filter attached to the qdisc
+ * @arg qdisc the parent qdisc
+ * @arg cache a filter cache including at least all the filters
+ * attached to the specified qdisc
+ * @arg cb callback function
+ * @arg arg argument to be passed to callback function
+ */
+void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
+ void (*cb)(struct nl_object *, void *), void *arg)
+{
+ struct rtnl_cls *filter;
+
+ filter = rtnl_cls_alloc();
+ if (!filter)
+ return;
+
+ rtnl_tc_set_ifindex((struct rtnl_tc *) filter, qdisc->q_ifindex);
+ rtnl_tc_set_parent((struct rtnl_tc *) filter, qdisc->q_parent);
+
+ nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
+ rtnl_cls_put(filter);
+}
+
+/** @} */
+
+static void qdisc_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p)
+{
+ struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
+
+ nl_dump(p, "refcnt %u ", qdisc->q_info);
+}
+
+static struct rtnl_tc_type_ops qdisc_ops = {
+ .tt_type = RTNL_TC_TYPE_QDISC,
+ .tt_dump_prefix = "qdisc",
+ .tt_dump = {
+ [NL_DUMP_DETAILS] = qdisc_dump_details,
+ },
+};
+
static struct nl_cache_ops rtnl_qdisc_ops = {
.co_name = "route/qdisc",
.co_hdrsize = sizeof(struct tcmsg),
@@ -455,14 +514,30 @@ static struct nl_cache_ops rtnl_qdisc_ops = {
.co_obj_ops = &qdisc_obj_ops,
};
+struct nl_object_ops qdisc_obj_ops = {
+ .oo_name = "route/qdisc",
+ .oo_size = sizeof(struct rtnl_qdisc),
+ .oo_free_data = rtnl_tc_free_data,
+ .oo_clone = rtnl_tc_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = rtnl_tc_dump_line,
+ [NL_DUMP_DETAILS] = rtnl_tc_dump_details,
+ [NL_DUMP_STATS] = rtnl_tc_dump_stats,
+ },
+ .oo_compare = rtnl_tc_compare,
+ .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
+};
+
static void __init qdisc_init(void)
{
+ rtnl_tc_type_register(&qdisc_ops);
nl_cache_mngt_register(&rtnl_qdisc_ops);
}
static void __exit qdisc_exit(void)
{
nl_cache_mngt_unregister(&rtnl_qdisc_ops);
+ rtnl_tc_type_unregister(&qdisc_ops);
}
/** @} */
diff --git a/lib/route/qdisc_api.c b/lib/route/qdisc_api.c
deleted file mode 100644
index 089f212..0000000
--- a/lib/route/qdisc_api.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * lib/route/qdisc_api.c Queueing Discipline Module API
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup qdisc
- * @defgroup qdisc_api Queueing Discipline Modules
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/utils.h>
-#include <netlink/route/link.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/qdisc.h>
-#include <netlink/route/class.h>
-#include <netlink/route/classifier.h>
-#include <netlink/route/qdisc-modules.h>
-
-static struct rtnl_qdisc_ops *qdisc_ops_list;
-
-/**
- * @name Module API
- * @{
- */
-
-/**
- * Register a qdisc module
- * @arg qops qdisc module operations
- */
-int rtnl_qdisc_register(struct rtnl_qdisc_ops *qops)
-{
- struct rtnl_qdisc_ops *o, **op;
-
- if (!qops->qo_kind[0])
- BUG();
-
- for (op = &qdisc_ops_list; (o = *op) != NULL; op = &o->qo_next)
- if (!strcasecmp(qops->qo_kind, o->qo_kind))
- return -NLE_EXIST;
-
- qops->qo_next = NULL;
- *op = qops;
-
- return 0;
-}
-
-/**
- * Unregister a qdisc module
- * @arg qops qdisc module operations
- */
-int rtnl_qdisc_unregister(struct rtnl_qdisc_ops *qops)
-{
- struct rtnl_qdisc_ops *o, **op;
-
- for (op = &qdisc_ops_list; (o = *op) != NULL; op = &o->qo_next)
- if (!strcasecmp(qops->qo_kind, o->qo_kind))
- break;
-
- if (!o)
- return -NLE_OBJ_NOTFOUND;
-
- *op = qops->qo_next;
-
- return 0;
-}
-
-struct rtnl_qdisc_ops *__rtnl_qdisc_lookup_ops(const char *kind)
-{
- struct rtnl_qdisc_ops *qops;
-
- for (qops = qdisc_ops_list; qops; qops = qops->qo_next)
- if (!strcmp(kind, qops->qo_kind))
- return qops;
-
- return NULL;
-}
-
-struct rtnl_qdisc_ops *rtnl_qdisc_lookup_ops(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_ops)
- qdisc->q_ops = __rtnl_qdisc_lookup_ops(qdisc->q_kind);
-
- return qdisc->q_ops;
-}
-
-/** @} */
-
-/** @} */
diff --git a/lib/route/qdisc_obj.c b/lib/route/qdisc_obj.c
deleted file mode 100644
index baa00b2..0000000
--- a/lib/route/qdisc_obj.c
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * lib/route/qdisc_obj.c Queueing Discipline Object
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation version 2.1
- * of the License.
- *
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
- */
-
-/**
- * @ingroup qdisc
- * @defgroup qdisc_obj Queueing Discipline Object
- * @{
- */
-
-#include <netlink-local.h>
-#include <netlink-tc.h>
-#include <netlink/netlink.h>
-#include <netlink/utils.h>
-#include <netlink/route/link.h>
-#include <netlink/route/tc.h>
-#include <netlink/route/qdisc.h>
-#include <netlink/route/class.h>
-#include <netlink/route/classifier.h>
-#include <netlink/route/qdisc-modules.h>
-
-static void qdisc_free_data(struct nl_object *obj)
-{
- struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj;
- struct rtnl_qdisc_ops *qops;
-
- tca_free_data((struct rtnl_tc *) qdisc);
-
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_free_data)
- qops->qo_free_data(qdisc);
-}
-
-static int qdisc_clone(struct nl_object *_dst, struct nl_object *_src)
-{
- struct rtnl_qdisc *dst = (struct rtnl_qdisc *) _dst;
- struct rtnl_qdisc *src = (struct rtnl_qdisc *) _src;
- struct rtnl_qdisc_ops *qops;
- int err;
-
- err = tca_clone((struct rtnl_tc *) dst, (struct rtnl_tc *) src);
- if (err < 0)
- goto errout;
-
- qops = rtnl_qdisc_lookup_ops(src);
- if (qops && qops->qo_clone)
- err = qops->qo_clone(dst, src);
-errout:
- return err;
-}
-
-static void qdisc_dump_line(struct nl_object *obj, struct nl_dump_params *p)
-{
- struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj;
- struct rtnl_qdisc_ops *qops;
-
- tca_dump_line((struct rtnl_tc *) qdisc, "qdisc", p);
-
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_dump[NL_DUMP_LINE])
- qops->qo_dump[NL_DUMP_LINE](qdisc, p);
-
- nl_dump(p, "\n");
-}
-
-static void qdisc_dump_details(struct nl_object *arg, struct nl_dump_params *p)
-{
- struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg;
- struct rtnl_qdisc_ops *qops;
-
- qdisc_dump_line(arg, p);
-
- tca_dump_details((struct rtnl_tc *) qdisc, p);
- nl_dump(p, "refcnt %u ", qdisc->q_info);
-
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_dump[NL_DUMP_DETAILS])
- qops->qo_dump[NL_DUMP_DETAILS](qdisc, p);
-
- nl_dump(p, "\n");
-}
-
-static void qdisc_dump_stats(struct nl_object *arg, struct nl_dump_params *p)
-{
- struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) arg;
- struct rtnl_qdisc_ops *qops;
-
- qdisc_dump_details(arg, p);
- tca_dump_stats((struct rtnl_tc *) qdisc, p);
- nl_dump(p, "\n");
-
- qops = rtnl_qdisc_lookup_ops(qdisc);
- if (qops && qops->qo_dump[NL_DUMP_STATS])
- qops->qo_dump[NL_DUMP_STATS](qdisc, p);
-}
-
-/**
- * @name Allocation/Freeing
- * @{
- */
-
-struct rtnl_qdisc *rtnl_qdisc_alloc(void)
-{
- return (struct rtnl_qdisc *) nl_object_alloc(&qdisc_obj_ops);
-}
-
-void rtnl_qdisc_put(struct rtnl_qdisc *qdisc)
-{
- nl_object_put((struct nl_object *) qdisc);
-}
-
-/** @} */
-
-/**
- * @name Iterators
- * @{
- */
-
-/**
- * Call a callback for each child class of a qdisc
- * @arg qdisc the parent qdisc
- * @arg cache a class cache including all classes of the interface
- * the specified qdisc is attached to
- * @arg cb callback function
- * @arg arg argument to be passed to callback function
- */
-void rtnl_qdisc_foreach_child(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
- void (*cb)(struct nl_object *, void *), void *arg)
-{
- struct rtnl_class *filter;
-
- filter = rtnl_class_alloc();
- if (!filter)
- return;
-
- rtnl_tc_set_parent((struct rtnl_tc *) filter, qdisc->q_handle);
- rtnl_tc_set_ifindex((struct rtnl_tc *) filter, qdisc->q_ifindex);
- rtnl_class_set_kind(filter, qdisc->q_kind);
-
- nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
-
- rtnl_class_put(filter);
-}
-
-/**
- * Call a callback for each filter attached to the qdisc
- * @arg qdisc the parent qdisc
- * @arg cache a filter cache including at least all the filters
- * attached to the specified qdisc
- * @arg cb callback function
- * @arg arg argument to be passed to callback function
- */
-void rtnl_qdisc_foreach_cls(struct rtnl_qdisc *qdisc, struct nl_cache *cache,
- void (*cb)(struct nl_object *, void *), void *arg)
-{
- struct rtnl_cls *filter;
-
- filter = rtnl_cls_alloc();
- if (!filter)
- return;
-
- rtnl_tc_set_ifindex((struct rtnl_tc *) filter, qdisc->q_ifindex);
- rtnl_tc_set_parent((struct rtnl_tc *) filter, qdisc->q_parent);
-
- nl_cache_foreach_filter(cache, (struct nl_object *) filter, cb, arg);
- rtnl_cls_put(filter);
-}
-
-/** @} */
-
-/**
- * @name Attributes
- * @{
- */
-
-void rtnl_qdisc_set_kind(struct rtnl_qdisc *qdisc, const char *name)
-{
- tca_set_kind((struct rtnl_tc *) qdisc, name);
- qdisc->q_ops = __rtnl_qdisc_lookup_ops(name);
-}
-
-/** @} */
-
-/**
- * @name Qdisc Specific Options
- * @{
- */
-
-/**
- * Return qdisc specific options for use in TCA_OPTIONS
- * @arg qdisc qdisc carrying the optiosn
- *
- * @return new headerless netlink message carrying the options as payload
- */
-struct nl_msg *rtnl_qdisc_get_opts(struct rtnl_qdisc *qdisc)
-{
- struct rtnl_qdisc_ops *ops;
-
- ops = rtnl_qdisc_lookup_ops(qdisc);
- if (ops && ops->qo_get_opts)
- return ops->qo_get_opts(qdisc);
-
- return NULL;
-}
-
-/** @} */
-
-struct nl_object_ops qdisc_obj_ops = {
- .oo_name = "route/qdisc",
- .oo_size = sizeof(struct rtnl_qdisc),
- .oo_free_data = qdisc_free_data,
- .oo_clone = qdisc_clone,
- .oo_dump = {
- [NL_DUMP_LINE] = qdisc_dump_line,
- [NL_DUMP_DETAILS] = qdisc_dump_details,
- [NL_DUMP_STATS] = qdisc_dump_stats,
- },
- .oo_compare = tca_compare,
- .oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
-};
-
-/** @} */
diff --git a/lib/route/sch/blackhole.c b/lib/route/sch/blackhole.c
index a30b693..064963e 100644
--- a/lib/route/sch/blackhole.c
+++ b/lib/route/sch/blackhole.c
@@ -6,33 +6,32 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup blackhole Blackhole
+ * @ingroup qdisc
+ * @defgroup qdisc_blackhole Blackhole
* @{
*/
#include <netlink-local.h>
-#include <netlink-tc.h>
#include <netlink/netlink.h>
-#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
+#include <netlink/route/tc-api.h>
-static struct rtnl_qdisc_ops blackhole_ops = {
- .qo_kind = "blackhole",
+static struct rtnl_tc_ops blackhole_ops = {
+ .to_kind = "blackhole",
+ .to_type = RTNL_TC_TYPE_QDISC,
};
static void __init blackhole_init(void)
{
- rtnl_qdisc_register(&blackhole_ops);
+ rtnl_tc_register(&blackhole_ops);
}
static void __exit blackhole_exit(void)
{
- rtnl_qdisc_unregister(&blackhole_ops);
+ rtnl_tc_unregister(&blackhole_ops);
}
/** @} */
diff --git a/lib/route/sch/cbq.c b/lib/route/sch/cbq.c
index 989745c..f750ccd 100644
--- a/lib/route/sch/cbq.c
+++ b/lib/route/sch/cbq.c
@@ -6,25 +6,24 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/route/link.h>
#include <netlink/route/sch/cbq.h>
#include <netlink/route/cls/police.h>
/**
- * @ingroup qdisc_api
- * @ingroup class_api
- * @defgroup cbq Class Based Queueing (CBQ)
+ * @ingroup qdisc
+ * @ingroup class
+ * @defgroup qdisc_cbq Class Based Queueing (CBQ)
* @{
*/
@@ -73,34 +72,16 @@ static struct nla_policy cbq_policy[TCA_CBQ_MAX+1] = {
[TCA_CBQ_POLICE] = { .minlen = sizeof(struct tc_cbq_police) },
};
-static inline struct rtnl_cbq *cbq_qdisc(struct rtnl_tc *tca)
-{
- return (struct rtnl_cbq *) tca->tc_subdata;
-}
-
-static inline struct rtnl_cbq *cbq_alloc(struct rtnl_tc *tca)
-{
- if (!tca->tc_subdata)
- tca->tc_subdata = calloc(1, sizeof(struct rtnl_qdisc));
-
- return cbq_qdisc(tca);
-}
-
-
-static int cbq_msg_parser(struct rtnl_tc *tca)
+static int cbq_msg_parser(struct rtnl_tc *tc, void *data)
{
struct nlattr *tb[TCA_CBQ_MAX + 1];
- struct rtnl_cbq *cbq;
+ struct rtnl_cbq *cbq = data;
int err;
- err = tca_parse(tb, TCA_CBQ_MAX, tca, cbq_policy);
+ err = tca_parse(tb, TCA_CBQ_MAX, tc, cbq_policy);
if (err < 0)
return err;
- cbq = cbq_alloc(tca);
- if (!cbq)
- return -NLE_NOMEM;
-
nla_memcpy(&cbq->cbq_lss, tb[TCA_CBQ_LSSOPT], sizeof(cbq->cbq_lss));
nla_memcpy(&cbq->cbq_rate, tb[TCA_CBQ_RATE], sizeof(cbq->cbq_rate));
nla_memcpy(&cbq->cbq_wrr, tb[TCA_CBQ_WRROPT], sizeof(cbq->cbq_wrr));
@@ -113,53 +94,13 @@ static int cbq_msg_parser(struct rtnl_tc *tca)
return 0;
}
-static int cbq_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
-{
- return cbq_msg_parser((struct rtnl_tc *) qdisc);
-}
-
-static int cbq_class_msg_parser(struct rtnl_class *class)
-{
- return cbq_msg_parser((struct rtnl_tc *) class);
-}
-
-static void cbq_qdisc_free_data(struct rtnl_qdisc *qdisc)
-{
- free(qdisc->q_subdata);
-}
-
-static int cbq_clone(struct rtnl_tc *_dst, struct rtnl_tc *_src)
-{
- struct rtnl_cbq *src = cbq_qdisc(_src);
-
- if (src && !cbq_alloc(_dst))
- return -NLE_NOMEM;
- else
- return 0;
-}
-
-static int cbq_qdisc_clone(struct rtnl_qdisc *dst, struct rtnl_qdisc *src)
-{
- return cbq_clone((struct rtnl_tc *) dst, (struct rtnl_tc *) src);
-}
-
-static void cbq_class_free_data(struct rtnl_class *class)
+static void cbq_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- free(class->c_subdata);
-}
-
-static int cbq_class_clone(struct rtnl_class *dst, struct rtnl_class *src)
-{
- return cbq_clone((struct rtnl_tc *) dst, (struct rtnl_tc *) src);
-}
-
-static void cbq_dump_line(struct rtnl_tc *tca, struct nl_dump_params *p)
-{
- struct rtnl_cbq *cbq;
+ struct rtnl_cbq *cbq = data;
double r, rbit;
char *ru, *rubit;
- cbq = cbq_qdisc(tca);
if (!cbq)
return;
@@ -170,26 +111,14 @@ static void cbq_dump_line(struct rtnl_tc *tca, struct nl_dump_params *p)
r, ru, rbit, rubit, cbq->cbq_wrr.priority);
}
-static void cbq_qdisc_dump_line(struct rtnl_qdisc *qdisc,
- struct nl_dump_params *p)
+static void cbq_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- cbq_dump_line((struct rtnl_tc *) qdisc, p);
-}
-
-static void cbq_class_dump_line(struct rtnl_class *class,
- struct nl_dump_params *p)
-{
- cbq_dump_line((struct rtnl_tc *) class, p);
-}
-
-static void cbq_dump_details(struct rtnl_tc *tca, struct nl_dump_params *p)
-{
- struct rtnl_cbq *cbq;
+ struct rtnl_cbq *cbq = data;
char *unit, buf[32];
double w;
uint32_t el;
- cbq = cbq_qdisc(tca);
if (!cbq)
return;
@@ -222,23 +151,12 @@ static void cbq_dump_details(struct rtnl_tc *tca, struct nl_dump_params *p)
nl_police2str(cbq->cbq_police.police, buf, sizeof(buf)));
}
-static void cbq_qdisc_dump_details(struct rtnl_qdisc *qdisc,
- struct nl_dump_params *p)
-{
- cbq_dump_details((struct rtnl_tc *) qdisc, p);
-}
-
-static void cbq_class_dump_details(struct rtnl_class *class,
- struct nl_dump_params *p)
+static void cbq_dump_stats(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- cbq_dump_details((struct rtnl_tc *) class, p);
-}
-
-static void cbq_dump_stats(struct rtnl_tc *tca, struct nl_dump_params *p)
-{
- struct tc_cbq_xstats *x = tca_xstats(tca);
-
- if (!x)
+ struct tc_cbq_xstats *x;
+
+ if (!(x = tca_xstats(tc)))
return;
nl_dump_line(p, " borrows overact "
@@ -247,52 +165,40 @@ static void cbq_dump_stats(struct rtnl_tc *tca, struct nl_dump_params *p)
x->borrows, x->overactions, x->avgidle, x->undertime);
}
-static void cbq_qdisc_dump_stats(struct rtnl_qdisc *qdisc,
- struct nl_dump_params *p)
-{
- cbq_dump_stats((struct rtnl_tc *) qdisc, p);
-}
-
-static void cbq_class_dump_stats(struct rtnl_class *class,
- struct nl_dump_params *p)
-{
- cbq_dump_stats((struct rtnl_tc *) class, p);
-}
-
-static struct rtnl_qdisc_ops cbq_qdisc_ops = {
- .qo_kind = "cbq",
- .qo_msg_parser = cbq_qdisc_msg_parser,
- .qo_free_data = cbq_qdisc_free_data,
- .qo_clone = cbq_qdisc_clone,
- .qo_dump = {
- [NL_DUMP_LINE] = cbq_qdisc_dump_line,
- [NL_DUMP_DETAILS] = cbq_qdisc_dump_details,
- [NL_DUMP_STATS] = cbq_qdisc_dump_stats,
+static struct rtnl_tc_ops cbq_qdisc_ops = {
+ .to_kind = "cbq",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_cbq),
+ .to_msg_parser = cbq_msg_parser,
+ .to_dump = {
+ [NL_DUMP_LINE] = cbq_dump_line,
+ [NL_DUMP_DETAILS] = cbq_dump_details,
+ [NL_DUMP_STATS] = cbq_dump_stats,
},
};
-static struct rtnl_class_ops cbq_class_ops = {
- .co_kind = "cbq",
- .co_msg_parser = cbq_class_msg_parser,
- .co_free_data = cbq_class_free_data,
- .co_clone = cbq_class_clone,
- .co_dump = {
- [NL_DUMP_LINE] = cbq_class_dump_line,
- [NL_DUMP_DETAILS] = cbq_class_dump_details,
- [NL_DUMP_STATS] = cbq_class_dump_stats,
+static struct rtnl_tc_ops cbq_class_ops = {
+ .to_kind = "cbq",
+ .to_type = RTNL_TC_TYPE_CLASS,
+ .to_size = sizeof(struct rtnl_cbq),
+ .to_msg_parser = cbq_msg_parser,
+ .to_dump = {
+ [NL_DUMP_LINE] = cbq_dump_line,
+ [NL_DUMP_DETAILS] = cbq_dump_details,
+ [NL_DUMP_STATS] = cbq_dump_stats,
},
};
static void __init cbq_init(void)
{
- rtnl_qdisc_register(&cbq_qdisc_ops);
- rtnl_class_register(&cbq_class_ops);
+ rtnl_tc_register(&cbq_qdisc_ops);
+ rtnl_tc_register(&cbq_class_ops);
}
static void __exit cbq_exit(void)
{
- rtnl_qdisc_unregister(&cbq_qdisc_ops);
- rtnl_class_unregister(&cbq_class_ops);
+ rtnl_tc_unregister(&cbq_qdisc_ops);
+ rtnl_tc_unregister(&cbq_class_ops);
}
/** @} */
diff --git a/lib/route/sch/dsmark.c b/lib/route/sch/dsmark.c
index a2e1628..372d0b6 100644
--- a/lib/route/sch/dsmark.c
+++ b/lib/route/sch/dsmark.c
@@ -6,13 +6,13 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @ingroup class_api
- * @defgroup dsmark Differentiated Services Marker (DSMARK)
+ * @ingroup qdisc
+ * @ingroup class
+ * @defgroup qdisc_dsmark Differentiated Services Marker (DSMARK)
* @{
*/
@@ -21,9 +21,8 @@
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/route/sch/dsmark.h>
/** @cond SKIP */
@@ -35,20 +34,6 @@
#define SCH_DSMARK_ATTR_VALUE 0x2
/** @endcond */
-static inline struct rtnl_dsmark_qdisc *dsmark_qdisc(struct rtnl_qdisc *qdisc)
-{
- return (struct rtnl_dsmark_qdisc *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_dsmark_qdisc *
-dsmark_qdisc_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_dsmark_qdisc));
-
- return dsmark_qdisc(qdisc);
-}
-
static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = {
[TCA_DSMARK_INDICES] = { .type = NLA_U16 },
[TCA_DSMARK_DEFAULT_INDEX] = { .type = NLA_U16 },
@@ -57,21 +42,16 @@ static struct nla_policy dsmark_policy[TCA_DSMARK_MAX+1] = {
[TCA_DSMARK_MASK] = { .type = NLA_U8 },
};
-static int dsmark_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
+static int dsmark_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
{
- int err;
+ struct rtnl_dsmark_qdisc *dsmark = data;
struct nlattr *tb[TCA_DSMARK_MAX + 1];
- struct rtnl_dsmark_qdisc *dsmark;
+ int err;
- err = tca_parse(tb, TCA_DSMARK_MAX, (struct rtnl_tc *) qdisc,
- dsmark_policy);
+ err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
if (err < 0)
return err;
- dsmark = dsmark_qdisc_alloc(qdisc);
- if (!dsmark)
- return -NLE_NOMEM;
-
if (tb[TCA_DSMARK_INDICES]) {
dsmark->qdm_indices = nla_get_u16(tb[TCA_DSMARK_INDICES]);
dsmark->qdm_mask |= SCH_DSMARK_ATTR_INDICES;
@@ -91,35 +71,16 @@ static int dsmark_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
return 0;
}
-static inline struct rtnl_dsmark_class *dsmark_class(struct rtnl_class *class)
+static int dsmark_class_msg_parser(struct rtnl_tc *tc, void *data)
{
- return (struct rtnl_dsmark_class *) class->c_subdata;
-}
-
-static inline struct rtnl_dsmark_class *
-dsmark_class_alloc(struct rtnl_class *class)
-{
- if (!class->c_subdata)
- class->c_subdata = calloc(1, sizeof(struct rtnl_dsmark_class));
-
- return dsmark_class(class);
-}
-
-static int dsmark_class_msg_parser(struct rtnl_class *class)
-{
- int err;
+ struct rtnl_dsmark_class *dsmark = data;
struct nlattr *tb[TCA_DSMARK_MAX + 1];
- struct rtnl_dsmark_class *dsmark;
+ int err;
- err = tca_parse(tb, TCA_DSMARK_MAX, (struct rtnl_tc *) class,
- dsmark_policy);
+ err = tca_parse(tb, TCA_DSMARK_MAX, tc, dsmark_policy);
if (err < 0)
return err;
- dsmark = dsmark_class_alloc(class);
- if (!dsmark)
- return -NLE_NOMEM;
-
if (tb[TCA_DSMARK_MASK]) {
dsmark->cdm_bmask = nla_get_u8(tb[TCA_DSMARK_MASK]);
dsmark->cdm_mask |= SCH_DSMARK_ATTR_MASK;
@@ -133,19 +94,19 @@ static int dsmark_class_msg_parser(struct rtnl_class *class)
return 0;
}
-static void dsmark_qdisc_dump_line(struct rtnl_qdisc *qdisc,
+static void dsmark_qdisc_dump_line(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
+ struct rtnl_dsmark_qdisc *dsmark = data;
if (dsmark && (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES))
nl_dump(p, " indices 0x%04x", dsmark->qdm_indices);
}
-static void dsmark_qdisc_dump_details(struct rtnl_qdisc *qdisc,
+static void dsmark_qdisc_dump_details(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
+ struct rtnl_dsmark_qdisc *dsmark = data;
if (!dsmark)
return;
@@ -157,10 +118,10 @@ static void dsmark_qdisc_dump_details(struct rtnl_qdisc *qdisc,
nl_dump(p, " set-tc-index");
}
-static void dsmark_class_dump_line(struct rtnl_class *class,
+static void dsmark_class_dump_line(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_dsmark_class *dsmark = dsmark_class(class);
+ struct rtnl_dsmark_class *dsmark = data;
if (!dsmark)
return;
@@ -172,17 +133,13 @@ static void dsmark_class_dump_line(struct rtnl_class *class,
nl_dump(p, " mask 0x%02x", dsmark->cdm_bmask);
}
-static struct nl_msg *dsmark_qdisc_get_opts(struct rtnl_qdisc *qdisc)
+static int dsmark_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_dsmark_qdisc *dsmark = dsmark_qdisc(qdisc);
- struct nl_msg *msg;
+ struct rtnl_dsmark_qdisc *dsmark = data;
if (!dsmark)
- return NULL;
-
- msg = nlmsg_alloc();
- if (!msg)
- goto nla_put_failure;
+ return 0;
if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
NLA_PUT_U16(msg, TCA_DSMARK_INDICES, dsmark->qdm_indices);
@@ -194,24 +151,19 @@ static struct nl_msg *dsmark_qdisc_get_opts(struct rtnl_qdisc *qdisc)
if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
NLA_PUT_FLAG(msg, TCA_DSMARK_SET_TC_INDEX);
- return msg;
+ return 0;
nla_put_failure:
- nlmsg_free(msg);
- return NULL;
+ return -NLE_MSGSIZE;
}
-static struct nl_msg *dsmark_class_get_opts(struct rtnl_class *class)
+static int dsmark_class_msg_fill(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_dsmark_class *dsmark = dsmark_class(class);
- struct nl_msg *msg;
+ struct rtnl_dsmark_class *dsmark = data;
if (!dsmark)
- return NULL;
-
- msg = nlmsg_alloc();
- if (!msg)
- goto nla_put_failure;
+ return 0;
if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
NLA_PUT_U8(msg, TCA_DSMARK_MASK, dsmark->cdm_bmask);
@@ -219,11 +171,10 @@ static struct nl_msg *dsmark_class_get_opts(struct rtnl_class *class)
if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
NLA_PUT_U8(msg, TCA_DSMARK_VALUE, dsmark->cdm_value);
- return msg;
+ return 0;
nla_put_failure:
- nlmsg_free(msg);
- return NULL;
+ return -NLE_MSGSIZE;
}
/**
@@ -241,8 +192,7 @@ int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
{
struct rtnl_dsmark_class *dsmark;
- dsmark = dsmark_class(class);
- if (!dsmark)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
return -NLE_NOMEM;
dsmark->cdm_bmask = mask;
@@ -259,9 +209,11 @@ int rtnl_class_dsmark_set_bitmask(struct rtnl_class *class, uint8_t mask)
int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
{
struct rtnl_dsmark_class *dsmark;
+
+ if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
- dsmark = dsmark_class(class);
- if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
+ if (dsmark->cdm_mask & SCH_DSMARK_ATTR_MASK)
return dsmark->cdm_bmask;
else
return -NLE_NOATTR;
@@ -276,9 +228,8 @@ int rtnl_class_dsmark_get_bitmask(struct rtnl_class *class)
int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
{
struct rtnl_dsmark_class *dsmark;
-
- dsmark = dsmark_class(class);
- if (!dsmark)
+
+ if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
return -NLE_NOMEM;
dsmark->cdm_value = value;
@@ -295,9 +246,11 @@ int rtnl_class_dsmark_set_value(struct rtnl_class *class, uint8_t value)
int rtnl_class_dsmark_get_value(struct rtnl_class *class)
{
struct rtnl_dsmark_class *dsmark;
+
+ if (!(dsmark = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
- dsmark = dsmark_class(class);
- if (dsmark && dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
+ if (dsmark->cdm_mask & SCH_DSMARK_ATTR_VALUE)
return dsmark->cdm_value;
else
return -NLE_NOATTR;
@@ -319,8 +272,7 @@ int rtnl_qdisc_dsmark_set_indices(struct rtnl_qdisc *qdisc, uint16_t indices)
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (!dsmark)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
dsmark->qdm_indices = indices;
@@ -338,8 +290,10 @@ int rtnl_qdisc_dsmark_get_indices(struct rtnl_qdisc *qdisc)
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (dsmark->qdm_mask & SCH_DSMARK_ATTR_INDICES)
return dsmark->qdm_indices;
else
return -NLE_NOATTR;
@@ -356,8 +310,7 @@ int rtnl_qdisc_dsmark_set_default_index(struct rtnl_qdisc *qdisc,
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (!dsmark)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
dsmark->qdm_default_index = default_index;
@@ -375,8 +328,10 @@ int rtnl_qdisc_dsmark_get_default_index(struct rtnl_qdisc *qdisc)
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (dsmark->qdm_mask & SCH_DSMARK_ATTR_DEFAULT_INDEX)
return dsmark->qdm_default_index;
else
return -NLE_NOATTR;
@@ -392,8 +347,7 @@ int rtnl_qdisc_dsmark_set_set_tc_index(struct rtnl_qdisc *qdisc, int flag)
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (!dsmark)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
dsmark->qdm_set_tc_index = !!flag;
@@ -412,8 +366,10 @@ int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
{
struct rtnl_dsmark_qdisc *dsmark;
- dsmark = dsmark_qdisc(qdisc);
- if (dsmark && dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
+ if (!(dsmark = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (dsmark->qdm_mask & SCH_DSMARK_ATTR_SET_TC_INDEX)
return dsmark->qdm_set_tc_index;
else
return -NLE_NOATTR;
@@ -421,33 +377,37 @@ int rtnl_qdisc_dsmark_get_set_tc_index(struct rtnl_qdisc *qdisc)
/** @} */
-static struct rtnl_qdisc_ops dsmark_qdisc_ops = {
- .qo_kind = "dsmark",
- .qo_msg_parser = dsmark_qdisc_msg_parser,
- .qo_dump = {
+static struct rtnl_tc_ops dsmark_qdisc_ops = {
+ .to_kind = "dsmark",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_dsmark_qdisc),
+ .to_msg_parser = dsmark_qdisc_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = dsmark_qdisc_dump_line,
[NL_DUMP_DETAILS] = dsmark_qdisc_dump_details,
},
- .qo_get_opts = dsmark_qdisc_get_opts,
+ .to_msg_fill = dsmark_qdisc_msg_fill,
};
-static struct rtnl_class_ops dsmark_class_ops = {
- .co_kind = "dsmark",
- .co_msg_parser = dsmark_class_msg_parser,
- .co_dump[NL_DUMP_LINE] = dsmark_class_dump_line,
- .co_get_opts = dsmark_class_get_opts,
+static struct rtnl_tc_ops dsmark_class_ops = {
+ .to_kind = "dsmark",
+ .to_type = RTNL_TC_TYPE_CLASS,
+ .to_size = sizeof(struct rtnl_dsmark_class),
+ .to_msg_parser = dsmark_class_msg_parser,
+ .to_dump[NL_DUMP_LINE] = dsmark_class_dump_line,
+ .to_msg_fill = dsmark_class_msg_fill,
};
static void __init dsmark_init(void)
{
- rtnl_qdisc_register(&dsmark_qdisc_ops);
- rtnl_class_register(&dsmark_class_ops);
+ rtnl_tc_register(&dsmark_qdisc_ops);
+ rtnl_tc_register(&dsmark_class_ops);
}
static void __exit dsmark_exit(void)
{
- rtnl_qdisc_unregister(&dsmark_qdisc_ops);
- rtnl_class_unregister(&dsmark_class_ops);
+ rtnl_tc_unregister(&dsmark_qdisc_ops);
+ rtnl_tc_unregister(&dsmark_class_ops);
}
/** @} */
diff --git a/lib/route/sch/fifo.c b/lib/route/sch/fifo.c
index 464af30..1399c0a 100644
--- a/lib/route/sch/fifo.c
+++ b/lib/route/sch/fifo.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup fifo Packet/Bytes FIFO (pfifo/bfifo)
+ * @ingroup qdisc
+ * @defgroup qdisc_fifo Packet/Bytes FIFO (pfifo/bfifo)
* @brief
*
* The FIFO qdisc comes in two flavours:
@@ -25,15 +25,15 @@
*
* The configuration is exactly the same, the decision which of
* the two variations is going to be used is made based on the
- * kind of the qdisc (rtnl_qdisc_set_kind()).
+ * kind of the qdisc (rtnl_tc_set_kind()).
* @{
*/
#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/sch/fifo.h>
#include <netlink/utils.h>
@@ -41,88 +41,55 @@
#define SCH_FIFO_ATTR_LIMIT 1
/** @endcond */
-static inline struct rtnl_fifo *fifo_qdisc(struct rtnl_qdisc *qdisc)
+static int fifo_msg_parser(struct rtnl_tc *tc, void *data)
{
- return (struct rtnl_fifo *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_fifo *fifo_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_fifo));
-
- return fifo_qdisc(qdisc);
-}
-
-static int fifo_msg_parser(struct rtnl_qdisc *qdisc)
-{
- struct rtnl_fifo *fifo;
+ struct rtnl_fifo *fifo = data;
struct tc_fifo_qopt *opt;
- if (qdisc->q_opts->d_size < sizeof(struct tc_fifo_qopt))
+ if (tc->tc_opts->d_size < sizeof(struct tc_fifo_qopt))
return -NLE_INVAL;
- fifo = fifo_alloc(qdisc);
- if (!fifo)
- return -NLE_NOMEM;
-
- opt = (struct tc_fifo_qopt *) qdisc->q_opts->d_data;
+ opt = (struct tc_fifo_qopt *) tc->tc_opts->d_data;
fifo->qf_limit = opt->limit;
fifo->qf_mask = SCH_FIFO_ATTR_LIMIT;
return 0;
}
-static void fifo_free_data(struct rtnl_qdisc *qdisc)
+static void pfifo_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- free(qdisc->q_subdata);
-}
-
-static void pfifo_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
-{
- struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
+ struct rtnl_fifo *fifo = data;
if (fifo)
nl_dump(p, " limit %u packets", fifo->qf_limit);
}
-static void bfifo_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void bfifo_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_fifo *fifo = fifo_qdisc(qdisc);
+ struct rtnl_fifo *fifo = data;
+ char *unit;
+ double r;
- if (fifo) {
- char *unit;
- double r;
+ if (!fifo)
+ return;
- r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
- nl_dump(p, " limit %.1f%s", r, unit);
- }
+ r = nl_cancel_down_bytes(fifo->qf_limit, &unit);
+ nl_dump(p, " limit %.1f%s", r, unit);
}
-static struct nl_msg *fifo_get_opts(struct rtnl_qdisc *qdisc)
+static int fifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_fifo *fifo;
- struct tc_fifo_qopt opts;
- struct nl_msg *msg;
+ struct rtnl_fifo *fifo = data;
+ struct tc_fifo_qopt opts = {0};
- fifo = fifo_qdisc(qdisc);
if (!fifo || !(fifo->qf_mask & SCH_FIFO_ATTR_LIMIT))
- return NULL;
-
- msg = nlmsg_alloc();
- if (!msg)
- goto errout;
+ return -NLE_INVAL;
- memset(&opts, 0, sizeof(opts));
opts.limit = fifo->qf_limit;
- if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
- goto errout;
-
- return msg;
-errout:
- nlmsg_free(msg);
- return NULL;
+ return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
}
/**
@@ -140,8 +107,7 @@ int rtnl_qdisc_fifo_set_limit(struct rtnl_qdisc *qdisc, int limit)
{
struct rtnl_fifo *fifo;
- fifo = fifo_alloc(qdisc);
- if (!fifo)
+ if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
fifo->qf_limit = limit;
@@ -159,8 +125,10 @@ int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
{
struct rtnl_fifo *fifo;
- fifo = fifo_qdisc(qdisc);
- if (fifo && fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
+ if (!(fifo = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (fifo->qf_mask & SCH_FIFO_ATTR_LIMIT)
return fifo->qf_limit;
else
return -NLE_NOATTR;
@@ -168,32 +136,34 @@ int rtnl_qdisc_fifo_get_limit(struct rtnl_qdisc *qdisc)
/** @} */
-static struct rtnl_qdisc_ops pfifo_ops = {
- .qo_kind = "pfifo",
- .qo_msg_parser = fifo_msg_parser,
- .qo_free_data = fifo_free_data,
- .qo_dump[NL_DUMP_LINE] = pfifo_dump_line,
- .qo_get_opts = fifo_get_opts,
+static struct rtnl_tc_ops pfifo_ops = {
+ .to_kind = "pfifo",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_fifo),
+ .to_msg_parser = fifo_msg_parser,
+ .to_dump[NL_DUMP_LINE] = pfifo_dump_line,
+ .to_msg_fill = fifo_msg_fill,
};
-static struct rtnl_qdisc_ops bfifo_ops = {
- .qo_kind = "bfifo",
- .qo_msg_parser = fifo_msg_parser,
- .qo_free_data = fifo_free_data,
- .qo_dump[NL_DUMP_LINE] = bfifo_dump_line,
- .qo_get_opts = fifo_get_opts,
+static struct rtnl_tc_ops bfifo_ops = {
+ .to_kind = "bfifo",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_fifo),
+ .to_msg_parser = fifo_msg_parser,
+ .to_dump[NL_DUMP_LINE] = bfifo_dump_line,
+ .to_msg_fill = fifo_msg_fill,
};
static void __init fifo_init(void)
{
- rtnl_qdisc_register(&pfifo_ops);
- rtnl_qdisc_register(&bfifo_ops);
+ rtnl_tc_register(&pfifo_ops);
+ rtnl_tc_register(&bfifo_ops);
}
static void __exit fifo_exit(void)
{
- rtnl_qdisc_unregister(&pfifo_ops);
- rtnl_qdisc_unregister(&bfifo_ops);
+ rtnl_tc_unregister(&pfifo_ops);
+ rtnl_tc_unregister(&bfifo_ops);
}
/** @} */
diff --git a/lib/route/sch/htb.c b/lib/route/sch/htb.c
index 79a58be..7f2a384 100644
--- a/lib/route/sch/htb.c
+++ b/lib/route/sch/htb.c
@@ -6,15 +6,15 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
* Copyright (c) 2005-2006 Petr Gotthard <petr.gotthard@siemens.com>
* Copyright (c) 2005-2006 Siemens AG Oesterreich
*/
/**
- * @ingroup qdisc_api
- * @ingroup class_api
- * @defgroup htb Hierachical Token Bucket (HTB)
+ * @ingroup qdisc
+ * @ingroup class
+ * @defgroup qdisc_htb Hierachical Token Bucket (HTB)
* @{
*/
@@ -23,11 +23,9 @@
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/route/link.h>
#include <netlink/route/sch/htb.h>
@@ -43,236 +41,190 @@
#define SCH_HTB_HAS_QUANTUM 0x020
/** @endcond */
-static inline struct rtnl_htb_qdisc *htb_qdisc(struct rtnl_qdisc *qdisc)
-{
- if (qdisc->q_subdata == NULL)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_htb_qdisc));
-
- return (struct rtnl_htb_qdisc *) qdisc->q_subdata;
-}
-
static struct nla_policy htb_policy[TCA_HTB_MAX+1] = {
[TCA_HTB_INIT] = { .minlen = sizeof(struct tc_htb_glob) },
[TCA_HTB_PARMS] = { .minlen = sizeof(struct tc_htb_opt) },
};
-static int htb_qdisc_msg_parser(struct rtnl_qdisc *qdisc)
+static int htb_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
{
- int err;
struct nlattr *tb[TCA_HTB_MAX + 1];
- struct rtnl_htb_qdisc *d;
+ struct rtnl_htb_qdisc *htb = data;
+ int err;
- err = tca_parse(tb, TCA_HTB_MAX, (struct rtnl_tc *) qdisc, htb_policy);
- if (err < 0)
+ if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
return err;
- d = htb_qdisc(qdisc);
-
if (tb[TCA_HTB_INIT]) {
struct tc_htb_glob opts;
nla_memcpy(&opts, tb[TCA_HTB_INIT], sizeof(opts));
- d->qh_rate2quantum = opts.rate2quantum;
- d->qh_defcls = opts.defcls;
+ htb->qh_rate2quantum = opts.rate2quantum;
+ htb->qh_defcls = opts.defcls;
- d->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
+ htb->qh_mask = (SCH_HTB_HAS_RATE2QUANTUM | SCH_HTB_HAS_DEFCLS);
}
return 0;
}
-static void htb_qdisc_free_data(struct rtnl_qdisc *qdisc)
-{
- free(qdisc->q_subdata);
-}
-
-static inline struct rtnl_htb_class *htb_class(struct rtnl_class *class)
-{
- if (class->c_subdata == NULL)
- class->c_subdata = calloc(1, sizeof(struct rtnl_htb_class));
-
- return (struct rtnl_htb_class *) class->c_subdata;
-}
-
-static int htb_class_msg_parser(struct rtnl_class *class)
+static int htb_class_msg_parser(struct rtnl_tc *tc, void *data)
{
- int err;
struct nlattr *tb[TCA_HTB_MAX + 1];
- struct rtnl_htb_class *d;
- struct rtnl_tc *tc = (struct rtnl_tc *) class;
+ struct rtnl_htb_class *htb = data;
+ int err;
- err = tca_parse(tb, TCA_HTB_MAX, (struct rtnl_tc *) class, htb_policy);
- if (err < 0)
+ if ((err = tca_parse(tb, TCA_HTB_MAX, tc, htb_policy)) < 0)
return err;
- d = htb_class(class);
-
if (tb[TCA_HTB_PARMS]) {
struct tc_htb_opt opts;
nla_memcpy(&opts, tb[TCA_HTB_PARMS], sizeof(opts));
- d->ch_prio = opts.prio;
- rtnl_copy_ratespec(&d->ch_rate, &opts.rate);
- rtnl_copy_ratespec(&d->ch_ceil, &opts.ceil);
- d->ch_rbuffer = rtnl_tc_calc_bufsize(opts.buffer, opts.rate.rate);
- d->ch_cbuffer = rtnl_tc_calc_bufsize(opts.cbuffer, opts.ceil.rate);
- d->ch_quantum = opts.quantum;
-
- rtnl_tc_set_mpu(tc, d->ch_rate.rs_mpu);
- rtnl_tc_set_overhead(tc, d->ch_rate.rs_overhead);
-
- d->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
- SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
- SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM);
+ htb->ch_prio = opts.prio;
+ rtnl_copy_ratespec(&htb->ch_rate, &opts.rate);
+ rtnl_copy_ratespec(&htb->ch_ceil, &opts.ceil);
+ htb->ch_rbuffer = rtnl_tc_calc_bufsize(opts.buffer, opts.rate.rate);
+ htb->ch_cbuffer = rtnl_tc_calc_bufsize(opts.cbuffer, opts.ceil.rate);
+ htb->ch_quantum = opts.quantum;
+
+ rtnl_tc_set_mpu(tc, htb->ch_rate.rs_mpu);
+ rtnl_tc_set_overhead(tc, htb->ch_rate.rs_overhead);
+
+ htb->ch_mask = (SCH_HTB_HAS_PRIO | SCH_HTB_HAS_RATE |
+ SCH_HTB_HAS_CEIL | SCH_HTB_HAS_RBUFFER |
+ SCH_HTB_HAS_CBUFFER | SCH_HTB_HAS_QUANTUM);
}
return 0;
}
-static void htb_class_free_data(struct rtnl_class *class)
-{
- free(class->c_subdata);
-}
-
-static void htb_qdisc_dump_line(struct rtnl_qdisc *qdisc,
+static void htb_qdisc_dump_line(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_htb_qdisc *d = (struct rtnl_htb_qdisc *) qdisc->q_subdata;
+ struct rtnl_htb_qdisc *htb = data;
- if (d == NULL)
+ if (!htb)
return;
- if (d->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
- nl_dump(p, " r2q %u", d->qh_rate2quantum);
+ if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
+ nl_dump(p, " r2q %u", htb->qh_rate2quantum);
- if (d->qh_mask & SCH_HTB_HAS_DEFCLS) {
+ if (htb->qh_mask & SCH_HTB_HAS_DEFCLS) {
char buf[32];
nl_dump(p, " default %s",
- rtnl_tc_handle2str(d->qh_defcls, buf, sizeof(buf)));
+ rtnl_tc_handle2str(htb->qh_defcls, buf, sizeof(buf)));
}
}
-static void htb_class_dump_line(struct rtnl_class *class,
+static void htb_class_dump_line(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata;
+ struct rtnl_htb_class *htb = data;
- if (d == NULL)
+ if (!htb)
return;
- if (d->ch_mask & SCH_HTB_HAS_RATE) {
+ if (htb->ch_mask & SCH_HTB_HAS_RATE) {
double r, rbit;
char *ru, *rubit;
- r = nl_cancel_down_bytes(d->ch_rate.rs_rate, &ru);
- rbit = nl_cancel_down_bits(d->ch_rate.rs_rate*8, &rubit);
+ r = nl_cancel_down_bytes(htb->ch_rate.rs_rate, &ru);
+ rbit = nl_cancel_down_bits(htb->ch_rate.rs_rate*8, &rubit);
nl_dump(p, " rate %.2f%s/s (%.0f%s) log %u",
- r, ru, rbit, rubit, 1<<d->ch_rate.rs_cell_log);
+ r, ru, rbit, rubit, 1<<htb->ch_rate.rs_cell_log);
}
}
-static void htb_class_dump_details(struct rtnl_class *class,
+static void htb_class_dump_details(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
- struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata;
+ struct rtnl_htb_class *htb = data;
- if (d == NULL)
+ if (!htb)
return;
/* line 1 */
- if (d->ch_mask & SCH_HTB_HAS_CEIL) {
+ if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
double r, rbit;
char *ru, *rubit;
- r = nl_cancel_down_bytes(d->ch_ceil.rs_rate, &ru);
- rbit = nl_cancel_down_bits(d->ch_ceil.rs_rate*8, &rubit);
+ r = nl_cancel_down_bytes(htb->ch_ceil.rs_rate, &ru);
+ rbit = nl_cancel_down_bits(htb->ch_ceil.rs_rate*8, &rubit);
- nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u",
- r, ru, rbit, rubit, 1<<d->ch_ceil.rs_cell_log);
+ nl_dump(p, " ceil %.2f%s/s (%.0f%s) log %u",
+ r, ru, rbit, rubit, 1<<htb->ch_ceil.rs_cell_log);
}
- if (d->ch_mask & SCH_HTB_HAS_PRIO)
- nl_dump(p, " prio %u", d->ch_prio);
+ if (htb->ch_mask & SCH_HTB_HAS_PRIO)
+ nl_dump(p, " prio %u", htb->ch_prio);
- if (d->ch_mask & SCH_HTB_HAS_RBUFFER) {
+ if (htb->ch_mask & SCH_HTB_HAS_RBUFFER) {
double b;
char *bu;
- b = nl_cancel_down_bytes(d->ch_rbuffer, &bu);
+ b = nl_cancel_down_bytes(htb->ch_rbuffer, &bu);
nl_dump(p, " rbuffer %.2f%s", b, bu);
}
- if (d->ch_mask & SCH_HTB_HAS_CBUFFER) {
+ if (htb->ch_mask & SCH_HTB_HAS_CBUFFER) {
double b;
char *bu;
- b = nl_cancel_down_bytes(d->ch_cbuffer, &bu);
+ b = nl_cancel_down_bytes(htb->ch_cbuffer, &bu);
nl_dump(p, " cbuffer %.2f%s", b, bu);
}
- if (d->ch_mask & SCH_HTB_HAS_QUANTUM)
- nl_dump(p, " quantum %u", d->ch_quantum);
+ if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
+ nl_dump(p, " quantum %u", htb->ch_quantum);
}
-static struct nl_msg *htb_qdisc_get_opts(struct rtnl_qdisc *qdisc)
+static int htb_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_htb_qdisc *d = (struct rtnl_htb_qdisc *) qdisc->q_subdata;
- struct tc_htb_glob opts;
- struct nl_msg *msg;
-
- msg = nlmsg_alloc();
- if (msg == NULL)
- return NULL;
+ struct rtnl_htb_qdisc *htb = data;
+ struct tc_htb_glob opts = {0};
- memset(&opts, 0, sizeof(opts));
opts.version = TC_HTB_PROTOVER;
opts.rate2quantum = 10;
- if (d) {
- if (d->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
- opts.rate2quantum = d->qh_rate2quantum;
- if (d->qh_mask & SCH_HTB_HAS_DEFCLS)
- opts.defcls = d->qh_defcls;
- }
+ if (htb) {
+ if (htb->qh_mask & SCH_HTB_HAS_RATE2QUANTUM)
+ opts.rate2quantum = htb->qh_rate2quantum;
- nla_put(msg, TCA_HTB_INIT, sizeof(opts), &opts);
+ if (htb->qh_mask & SCH_HTB_HAS_DEFCLS)
+ opts.defcls = htb->qh_defcls;
+ }
- return msg;
+ return nla_put(msg, TCA_HTB_INIT, sizeof(opts), &opts);
}
-static struct nl_msg *htb_class_get_opts(struct rtnl_class *class)
+static int htb_class_msg_fill(struct rtnl_tc *tc, void *data,
+ struct nl_msg *msg)
{
- struct rtnl_htb_class *d = (struct rtnl_htb_class *) class->c_subdata;
+ struct rtnl_htb_class *htb = data;
uint32_t mtu, rtable[RTNL_TC_RTABLE_SIZE], ctable[RTNL_TC_RTABLE_SIZE];
struct tc_htb_opt opts;
- struct nl_msg *msg;
int buffer, cbuffer;
- if (d == NULL)
- return NULL;
-
- if (!(d->ch_mask & SCH_HTB_HAS_RATE))
+ if (!htb || !(htb->ch_mask & SCH_HTB_HAS_RATE))
BUG();
- msg = nlmsg_alloc();
- if (!msg)
- return NULL;
+ /* if not set, zero (0) is used as priority */
+ if (htb->ch_mask & SCH_HTB_HAS_PRIO)
+ opts.prio = htb->ch_prio;
memset(&opts, 0, sizeof(opts));
- /* if not set, zero (0) is used as priority */
- if (d->ch_mask & SCH_HTB_HAS_PRIO)
- opts.prio = d->ch_prio;
-
- mtu = rtnl_tc_get_mtu((struct rtnl_tc *) class);
+ mtu = rtnl_tc_get_mtu(tc);
- rtnl_tc_build_rate_table((struct rtnl_tc *) class, &d->ch_rate, rtable);
- rtnl_rcopy_ratespec(&opts.rate, &d->ch_rate);
+ rtnl_tc_build_rate_table(tc, &htb->ch_rate, rtable);
+ rtnl_rcopy_ratespec(&opts.rate, &htb->ch_rate);
- if (d->ch_mask & SCH_HTB_HAS_CEIL) {
- rtnl_tc_build_rate_table((struct rtnl_tc *) class, &d->ch_ceil, ctable);
- rtnl_rcopy_ratespec(&opts.ceil, &d->ch_ceil);
+ if (htb->ch_mask & SCH_HTB_HAS_CEIL) {
+ rtnl_tc_build_rate_table(tc, &htb->ch_ceil, ctable);
+ rtnl_rcopy_ratespec(&opts.ceil, &htb->ch_ceil);
} else {
/*
* If not set, configured rate is used as ceil, which implies
@@ -281,28 +233,31 @@ static struct nl_msg *htb_class_get_opts(struct rtnl_class *class)
memcpy(&opts.ceil, &opts.rate, sizeof(struct tc_ratespec));
}
- if (d->ch_mask & SCH_HTB_HAS_RBUFFER)
- buffer = d->ch_rbuffer;
+ if (htb->ch_mask & SCH_HTB_HAS_RBUFFER)
+ buffer = htb->ch_rbuffer;
else
buffer = opts.rate.rate / nl_get_user_hz() + mtu; /* XXX */
opts.buffer = rtnl_tc_calc_txtime(buffer, opts.rate.rate);
- if (d->ch_mask & SCH_HTB_HAS_CBUFFER)
- cbuffer = d->ch_cbuffer;
+ if (htb->ch_mask & SCH_HTB_HAS_CBUFFER)
+ cbuffer = htb->ch_cbuffer;
else
cbuffer = opts.ceil.rate / nl_get_user_hz() + mtu; /* XXX */
opts.cbuffer = rtnl_tc_calc_txtime(cbuffer, opts.ceil.rate);
- if (d->ch_mask & SCH_HTB_HAS_QUANTUM)
- opts.quantum = d->ch_quantum;
+ if (htb->ch_mask & SCH_HTB_HAS_QUANTUM)
+ opts.quantum = htb->ch_quantum;
- nla_put(msg, TCA_HTB_PARMS, sizeof(opts), &opts);
- nla_put(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable);
- nla_put(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable);
+ NLA_PUT(msg, TCA_HTB_PARMS, sizeof(opts), &opts);
+ NLA_PUT(msg, TCA_HTB_RTAB, sizeof(rtable), &rtable);
+ NLA_PUT(msg, TCA_HTB_CTAB, sizeof(ctable), &ctable);
- return msg;
+ return 0;
+
+nla_put_failure:
+ return -NLE_MSGSIZE;
}
/**
@@ -312,12 +267,13 @@ static struct nl_msg *htb_class_get_opts(struct rtnl_class *class)
void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
{
- struct rtnl_htb_qdisc *d = htb_qdisc(qdisc);
- if (d == NULL)
- return;
+ struct rtnl_htb_qdisc *htb;
- d->qh_rate2quantum = rate2quantum;
- d->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
+ if (!(htb = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ htb->qh_rate2quantum = rate2quantum;
+ htb->qh_mask |= SCH_HTB_HAS_RATE2QUANTUM;
}
/**
@@ -327,22 +283,24 @@ void rtnl_htb_set_rate2quantum(struct rtnl_qdisc *qdisc, uint32_t rate2quantum)
*/
void rtnl_htb_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
{
- struct rtnl_htb_qdisc *d = htb_qdisc(qdisc);
- if (d == NULL)
- return;
+ struct rtnl_htb_qdisc *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
- d->qh_defcls = defcls;
- d->qh_mask |= SCH_HTB_HAS_DEFCLS;
+ htb->qh_defcls = defcls;
+ htb->qh_mask |= SCH_HTB_HAS_DEFCLS;
}
void rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_prio = prio;
- d->ch_mask |= SCH_HTB_HAS_PRIO;
+ htb->ch_prio = prio;
+ htb->ch_mask |= SCH_HTB_HAS_PRIO;
}
/**
@@ -352,22 +310,24 @@ void rtnl_htb_set_prio(struct rtnl_class *class, uint32_t prio)
*/
void rtnl_htb_set_rate(struct rtnl_class *class, uint32_t rate)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */
- d->ch_rate.rs_rate = rate;
- d->ch_mask |= SCH_HTB_HAS_RATE;
+ htb->ch_rate.rs_cell_log = UINT8_MAX; /* use default value */
+ htb->ch_rate.rs_rate = rate;
+ htb->ch_mask |= SCH_HTB_HAS_RATE;
}
uint32_t rtnl_htb_get_rate(struct rtnl_class *class)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
return 0;
- return d->ch_rate.rs_rate;
+ return htb->ch_rate.rs_rate;
}
/**
@@ -377,13 +337,14 @@ uint32_t rtnl_htb_get_rate(struct rtnl_class *class)
*/
void rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */
- d->ch_ceil.rs_rate = ceil;
- d->ch_mask |= SCH_HTB_HAS_CEIL;
+ htb->ch_ceil.rs_cell_log = UINT8_MAX; /* use default value */
+ htb->ch_ceil.rs_rate = ceil;
+ htb->ch_mask |= SCH_HTB_HAS_CEIL;
}
/**
@@ -393,12 +354,13 @@ void rtnl_htb_set_ceil(struct rtnl_class *class, uint32_t ceil)
*/
void rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_rbuffer = rbuffer;
- d->ch_mask |= SCH_HTB_HAS_RBUFFER;
+ htb->ch_rbuffer = rbuffer;
+ htb->ch_mask |= SCH_HTB_HAS_RBUFFER;
}
/**
@@ -408,12 +370,13 @@ void rtnl_htb_set_rbuffer(struct rtnl_class *class, uint32_t rbuffer)
*/
void rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_cbuffer = cbuffer;
- d->ch_mask |= SCH_HTB_HAS_CBUFFER;
+ htb->ch_cbuffer = cbuffer;
+ htb->ch_mask |= SCH_HTB_HAS_CBUFFER;
}
/**
@@ -423,45 +386,48 @@ void rtnl_htb_set_cbuffer(struct rtnl_class *class, uint32_t cbuffer)
*/
void rtnl_htb_set_quantum(struct rtnl_class *class, uint32_t quantum)
{
- struct rtnl_htb_class *d = htb_class(class);
- if (d == NULL)
- return;
+ struct rtnl_htb_class *htb;
+
+ if (!(htb = rtnl_tc_data(TC_CAST(class))))
+ BUG();
- d->ch_quantum = quantum;
- d->ch_mask |= SCH_HTB_HAS_QUANTUM;
+ htb->ch_quantum = quantum;
+ htb->ch_mask |= SCH_HTB_HAS_QUANTUM;
}
/** @} */
-static struct rtnl_qdisc_ops htb_qdisc_ops = {
- .qo_kind = "htb",
- .qo_msg_parser = htb_qdisc_msg_parser,
- .qo_free_data = htb_qdisc_free_data,
- .qo_dump[NL_DUMP_LINE] = htb_qdisc_dump_line,
- .qo_get_opts = htb_qdisc_get_opts,
+static struct rtnl_tc_ops htb_qdisc_ops = {
+ .to_kind = "htb",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_htb_qdisc),
+ .to_msg_parser = htb_qdisc_msg_parser,
+ .to_dump[NL_DUMP_LINE] = htb_qdisc_dump_line,
+ .to_msg_fill = htb_qdisc_msg_fill,
};
-static struct rtnl_class_ops htb_class_ops = {
- .co_kind = "htb",
- .co_msg_parser = htb_class_msg_parser,
- .co_free_data = htb_class_free_data,
- .co_dump = {
+static struct rtnl_tc_ops htb_class_ops = {
+ .to_kind = "htb",
+ .to_type = RTNL_TC_TYPE_CLASS,
+ .to_size = sizeof(struct rtnl_htb_class),
+ .to_msg_parser = htb_class_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = htb_class_dump_line,
[NL_DUMP_DETAILS] = htb_class_dump_details,
},
- .co_get_opts = htb_class_get_opts,
+ .to_msg_fill = htb_class_msg_fill,
};
static void __init htb_init(void)
{
- rtnl_qdisc_register(&htb_qdisc_ops);
- rtnl_class_register(&htb_class_ops);
+ rtnl_tc_register(&htb_qdisc_ops);
+ rtnl_tc_register(&htb_class_ops);
}
static void __exit htb_exit(void)
{
- rtnl_qdisc_unregister(&htb_qdisc_ops);
- rtnl_class_unregister(&htb_class_ops);
+ rtnl_tc_unregister(&htb_qdisc_ops);
+ rtnl_tc_unregister(&htb_class_ops);
}
/** @} */
diff --git a/lib/route/sch/netem.c b/lib/route/sch/netem.c
index 18878a7..981d96e 100644
--- a/lib/route/sch/netem.c
+++ b/lib/route/sch/netem.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup netem Network Emulator
+ * @ingroup qdisc
+ * @defgroup qdisc_netem Network Emulator
* @brief
*
* For further documentation see http://linux-net.osdl.org/index.php/Netem
@@ -22,8 +22,8 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/sch/netem.h>
/** @cond SKIP */
@@ -43,39 +43,22 @@
#define SCH_NETEM_ATTR_DIST 0x2000
/** @endcond */
-static inline struct rtnl_netem *netem_qdisc(struct rtnl_qdisc *qdisc)
-{
- return (struct rtnl_netem *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_netem *netem_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_netem));
-
- return netem_qdisc(qdisc);
-}
-
static struct nla_policy netem_policy[TCA_NETEM_MAX+1] = {
[TCA_NETEM_CORR] = { .minlen = sizeof(struct tc_netem_corr) },
[TCA_NETEM_REORDER] = { .minlen = sizeof(struct tc_netem_reorder) },
[TCA_NETEM_CORRUPT] = { .minlen = sizeof(struct tc_netem_corrupt) },
};
-static int netem_msg_parser(struct rtnl_qdisc *qdisc)
+static int netem_msg_parser(struct rtnl_tc *tc, void *data)
{
- int len, err = 0;
- struct rtnl_netem *netem;
+ struct rtnl_netem *netem = data;
struct tc_netem_qopt *opts;
+ int len, err = 0;
- if (qdisc->q_opts->d_size < sizeof(*opts))
+ if (tc->tc_opts->d_size < sizeof(*opts))
return -NLE_INVAL;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
-
- opts = (struct tc_netem_qopt *) qdisc->q_opts->d_data;
+ opts = (struct tc_netem_qopt *) tc->tc_opts->d_data;
netem->qnm_latency = opts->latency;
netem->qnm_limit = opts->limit;
netem->qnm_loss = opts->loss;
@@ -87,13 +70,13 @@ static int netem_msg_parser(struct rtnl_qdisc *qdisc)
SCH_NETEM_ATTR_LOSS | SCH_NETEM_ATTR_GAP |
SCH_NETEM_ATTR_DUPLICATE | SCH_NETEM_ATTR_JITTER);
- len = qdisc->q_opts->d_size - sizeof(*opts);
+ len = tc->tc_opts->d_size - sizeof(*opts);
if (len > 0) {
struct nlattr *tb[TCA_NETEM_MAX+1];
err = nla_parse(tb, TCA_NETEM_MAX, (struct nlattr *)
- (qdisc->q_opts->d_data + sizeof(*opts)),
+ (tc->tc_opts->d_data + sizeof(*opts)),
len, netem_policy);
if (err < 0) {
free(netem);
@@ -143,52 +126,45 @@ static int netem_msg_parser(struct rtnl_qdisc *qdisc)
return 0;
}
-static void netem_free_data(struct rtnl_qdisc *qdisc)
+static void netem_free_data(struct rtnl_tc *tc, void *data)
{
- struct rtnl_netem *netem;
-
- if ( ! qdisc ) return;
-
- netem = netem_qdisc(qdisc);
- if ( ! netem ) return;
+ struct rtnl_netem *netem = data;
- if ( netem->qnm_dist.dist_data )
- free(netem->qnm_dist.dist_data);
-
- netem = NULL;
+ if (!netem)
+ return;
- free (qdisc->q_subdata);
+ free(netem->qnm_dist.dist_data);
}
-static void netem_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void netem_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_netem *netem = netem_qdisc(qdisc);
+ struct rtnl_netem *netem = data;
if (netem)
nl_dump(p, "limit %d", netem->qnm_limit);
}
-int netem_build_msg(struct rtnl_qdisc *qdisc, struct nl_msg *msg)
+int netem_msg_fill_raw(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
int err = 0;
struct tc_netem_qopt opts;
struct tc_netem_corr cor;
struct tc_netem_reorder reorder;
struct tc_netem_corrupt corrupt;
- struct rtnl_netem *netem;
+ struct rtnl_netem *netem = data;
unsigned char set_correlation = 0, set_reorder = 0,
set_corrupt = 0, set_dist = 0;
+ if (!netem)
+ BUG();
+
memset(&opts, 0, sizeof(opts));
memset(&cor, 0, sizeof(cor));
memset(&reorder, 0, sizeof(reorder));
memset(&corrupt, 0, sizeof(corrupt));
- netem = netem_qdisc(qdisc);
- if (!netem || !msg)
- return EFAULT;
-
msg->nm_nlh->nlmsg_flags |= NLM_F_REQUEST;
if ( netem->qnm_ro.nmro_probability != 0 ) {
@@ -316,18 +292,15 @@ nla_put_failure:
* @arg limit New limit in bytes.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_limit(struct rtnl_qdisc *qdisc, int limit)
+void rtnl_netem_set_limit(struct rtnl_qdisc *qdisc, int limit)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_limit = limit;
netem->qnm_mask |= SCH_NETEM_ATTR_LIMIT;
-
- return 0;
}
/**
@@ -339,8 +312,10 @@ int rtnl_netem_get_limit(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LIMIT))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_LIMIT)
return netem->qnm_limit;
else
return -NLE_NOATTR;
@@ -359,18 +334,15 @@ int rtnl_netem_get_limit(struct rtnl_qdisc *qdisc)
* @arg gap New gap in number of packets.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_gap(struct rtnl_qdisc *qdisc, int gap)
+void rtnl_netem_set_gap(struct rtnl_qdisc *qdisc, int gap)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_gap = gap;
netem->qnm_mask |= SCH_NETEM_ATTR_GAP;
-
- return 0;
}
/**
@@ -382,8 +354,10 @@ int rtnl_netem_get_gap(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_GAP))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_GAP)
return netem->qnm_gap;
else
return -NLE_NOATTR;
@@ -395,18 +369,15 @@ int rtnl_netem_get_gap(struct rtnl_qdisc *qdisc)
* @arg prob New re-ordering probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_reorder_probability(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_reorder_probability(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_ro.nmro_probability = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_RO_PROB;
-
- return 0;
}
/**
@@ -418,8 +389,10 @@ int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_RO_PROB))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_RO_PROB)
return netem->qnm_ro.nmro_probability;
else
return -NLE_NOATTR;
@@ -431,18 +404,15 @@ int rtnl_netem_get_reorder_probability(struct rtnl_qdisc *qdisc)
* @arg prob New re-ordering correlation probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_reorder_correlation(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_ro.nmro_correlation = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_RO_CORR;
-
- return 0;
}
/**
@@ -454,8 +424,10 @@ int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_RO_CORR))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_RO_CORR)
return netem->qnm_ro.nmro_correlation;
else
return -NLE_NOATTR;
@@ -474,18 +446,15 @@ int rtnl_netem_get_reorder_correlation(struct rtnl_qdisc *qdisc)
* @arg prob New corruption probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_corruption_probability(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_corruption_probability(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_crpt.nmcr_probability = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_CORRUPT_PROB;
-
- return 0;
}
/**
@@ -497,8 +466,10 @@ int rtnl_netem_get_corruption_probability(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_PROB))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_PROB)
return netem->qnm_crpt.nmcr_probability;
else
return -NLE_NOATTR;
@@ -510,18 +481,15 @@ int rtnl_netem_get_corruption_probability(struct rtnl_qdisc *qdisc)
* @arg prob New corruption correlation probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_corruption_correlation(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_crpt.nmcr_correlation = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_CORRUPT_CORR;
-
- return 0;
}
/**
@@ -533,8 +501,10 @@ int rtnl_netem_get_corruption_correlation(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_CORR))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_CORRUPT_CORR)
return netem->qnm_crpt.nmcr_correlation;
else
return -NLE_NOATTR;
@@ -553,18 +523,15 @@ int rtnl_netem_get_corruption_correlation(struct rtnl_qdisc *qdisc)
* @arg prob New packet loss probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_loss(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_loss(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_loss = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_LOSS;
-
- return 0;
}
/**
@@ -576,8 +543,10 @@ int rtnl_netem_get_loss(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LOSS))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS)
return netem->qnm_loss;
else
return -NLE_NOATTR;
@@ -589,18 +558,15 @@ int rtnl_netem_get_loss(struct rtnl_qdisc *qdisc)
* @arg prob New packet loss correlation.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_loss_correlation(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_loss_correlation(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_corr.nmc_loss = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_LOSS_CORR;
-
- return 0;
}
/**
@@ -612,8 +578,10 @@ int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LOSS_CORR))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_LOSS_CORR)
return netem->qnm_corr.nmc_loss;
else
return -NLE_NOATTR;
@@ -632,18 +600,15 @@ int rtnl_netem_get_loss_correlation(struct rtnl_qdisc *qdisc)
* @arg prob New packet duplication probability.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_duplicate(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_duplicate(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_duplicate = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_DUPLICATE;
-
- return 0;
}
/**
@@ -655,8 +620,10 @@ int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DUPLICATE))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_DUPLICATE)
return netem->qnm_duplicate;
else
return -NLE_NOATTR;
@@ -668,18 +635,15 @@ int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc)
* @arg prob New packet duplication correlation probability.
* @return 0 on sucess or a negative error code.
*/
-int rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_corr.nmc_duplicate = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_DUP_CORR;
-
- return 0;
}
/**
@@ -691,8 +655,10 @@ int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DUP_CORR))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_DUP_CORR)
return netem->qnm_corr.nmc_duplicate;
else
return -NLE_NOATTR;
@@ -711,18 +677,15 @@ int rtnl_netem_get_duplicate_correlation(struct rtnl_qdisc *qdisc)
* @arg delay New packet delay in micro seconds.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_delay(struct rtnl_qdisc *qdisc, int delay)
+void rtnl_netem_set_delay(struct rtnl_qdisc *qdisc, int delay)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_latency = nl_us2ticks(delay);
netem->qnm_mask |= SCH_NETEM_ATTR_LATENCY;
-
- return 0;
}
/**
@@ -734,8 +697,10 @@ int rtnl_netem_get_delay(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_LATENCY))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_LATENCY)
return nl_ticks2us(netem->qnm_latency);
else
return -NLE_NOATTR;
@@ -747,18 +712,15 @@ int rtnl_netem_get_delay(struct rtnl_qdisc *qdisc)
* @arg jitter New packet delay jitter in micro seconds.
* @return 0 on success or a negative error code.
*/
-int rtnl_netem_set_jitter(struct rtnl_qdisc *qdisc, int jitter)
+void rtnl_netem_set_jitter(struct rtnl_qdisc *qdisc, int jitter)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_jitter = nl_us2ticks(jitter);
netem->qnm_mask |= SCH_NETEM_ATTR_JITTER;
-
- return 0;
}
/**
@@ -770,8 +732,10 @@ int rtnl_netem_get_jitter(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_JITTER))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_JITTER)
return nl_ticks2us(netem->qnm_jitter);
else
return -NLE_NOATTR;
@@ -782,18 +746,15 @@ int rtnl_netem_get_jitter(struct rtnl_qdisc *qdisc)
* @arg qdisc Netem qdisc to be modified.
* @arg prob New packet delay correlation probability.
*/
-int rtnl_netem_set_delay_correlation(struct rtnl_qdisc *qdisc, int prob)
+void rtnl_netem_set_delay_correlation(struct rtnl_qdisc *qdisc, int prob)
{
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
netem->qnm_corr.nmc_delay = prob;
netem->qnm_mask |= SCH_NETEM_ATTR_DELAY_CORR;
-
- return 0;
}
/**
@@ -805,8 +766,10 @@ int rtnl_netem_get_delay_correlation(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DELAY_CORR))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_DELAY_CORR)
return netem->qnm_corr.nmc_delay;
else
return -NLE_NOATTR;
@@ -821,8 +784,10 @@ int rtnl_netem_get_delay_distribution_size(struct rtnl_qdisc *qdisc)
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DIST))
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_DIST)
return netem->qnm_dist.dist_size;
else
return -NLE_NOATTR;
@@ -838,12 +803,13 @@ int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *qdisc, int16_t **dist_p
{
struct rtnl_netem *netem;
- netem = netem_qdisc(qdisc);
- if (netem && (netem->qnm_mask & SCH_NETEM_ATTR_DIST)) {
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (netem->qnm_mask & SCH_NETEM_ATTR_DIST) {
*dist_ptr = netem->qnm_dist.dist_data;
return 0;
- }
- else
+ } else
return -NLE_NOATTR;
}
@@ -856,9 +822,8 @@ int rtnl_netem_get_delay_distribution(struct rtnl_qdisc *qdisc, int16_t **dist_p
int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist_type) {
struct rtnl_netem *netem;
- netem = netem_alloc(qdisc);
- if (!netem)
- return -NLE_NOMEM;
+ if (!(netem = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
FILE *f = NULL;
int i, n = 0;
@@ -917,23 +882,24 @@ int rtnl_netem_set_delay_distribution(struct rtnl_qdisc *qdisc, const char *dist
/** @} */
-static struct rtnl_qdisc_ops netem_ops = {
- .qo_kind = "netem",
- .qo_msg_parser = netem_msg_parser,
- .qo_free_data = netem_free_data,
- .qo_dump[NL_DUMP_LINE] = netem_dump_line,
- .qo_get_opts = 0,
- .qo_build_msg = netem_build_msg
+static struct rtnl_tc_ops netem_ops = {
+ .to_kind = "netem",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_netem),
+ .to_msg_parser = netem_msg_parser,
+ .to_free_data = netem_free_data,
+ .to_dump[NL_DUMP_LINE] = netem_dump_line,
+ .to_msg_fill_raw = netem_msg_fill_raw,
};
static void __init netem_init(void)
{
- rtnl_qdisc_register(&netem_ops);
+ rtnl_tc_register(&netem_ops);
}
static void __exit netem_exit(void)
{
- rtnl_qdisc_unregister(&netem_ops);
+ rtnl_tc_unregister(&netem_ops);
}
/** @} */
diff --git a/lib/route/sch/prio.c b/lib/route/sch/prio.c
index e08e117..6f8ff34 100644
--- a/lib/route/sch/prio.c
+++ b/lib/route/sch/prio.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup prio (Fast) Prio
+ * @ingroup qdisc
+ * @defgroup qdisc_prio (Fast) Prio
* @brief
*
* @par 1) Typical PRIO configuration
@@ -30,8 +30,8 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/sch/prio.h>
/** @cond SKIP */
@@ -39,32 +39,15 @@
#define SCH_PRIO_ATTR_PRIOMAP 2
/** @endcond */
-static inline struct rtnl_prio *prio_qdisc(struct rtnl_qdisc *qdisc)
+static int prio_msg_parser(struct rtnl_tc *tc, void *data)
{
- return (struct rtnl_prio *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_prio *prio_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_prio));
-
- return prio_qdisc(qdisc);
-}
-
-static int prio_msg_parser(struct rtnl_qdisc *qdisc)
-{
- struct rtnl_prio *prio;
+ struct rtnl_prio *prio = data;
struct tc_prio_qopt *opt;
- if (qdisc->q_opts->d_size < sizeof(*opt))
+ if (tc->tc_opts->d_size < sizeof(*opt))
return -NLE_INVAL;
- prio = prio_alloc(qdisc);
- if (!prio)
- return -NLE_NOMEM;
-
- opt = (struct tc_prio_qopt *) qdisc->q_opts->d_data;
+ opt = (struct tc_prio_qopt *) tc->tc_opts->d_data;
prio->qp_bands = opt->bands;
memcpy(prio->qp_priomap, opt->priomap, sizeof(prio->qp_priomap));
prio->qp_mask = (SCH_PRIO_ATTR_BANDS | SCH_PRIO_ATTR_PRIOMAP);
@@ -72,22 +55,19 @@ static int prio_msg_parser(struct rtnl_qdisc *qdisc)
return 0;
}
-static void prio_free_data(struct rtnl_qdisc *qdisc)
-{
- free(qdisc->q_subdata);
-}
-
-static void prio_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void prio_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_prio *prio = prio_qdisc(qdisc);
+ struct rtnl_prio *prio = data;
if (prio)
nl_dump(p, " bands %u", prio->qp_bands);
}
-static void prio_dump_details(struct rtnl_qdisc *qdisc,struct nl_dump_params *p)
+static void prio_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_prio *prio = prio_qdisc(qdisc);
+ struct rtnl_prio *prio = data;
int i, hp;
if (!prio)
@@ -121,32 +101,18 @@ static void prio_dump_details(struct rtnl_qdisc *qdisc,struct nl_dump_params *p)
}
}
-static struct nl_msg *prio_get_opts(struct rtnl_qdisc *qdisc)
+static int prio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_prio *prio;
+ struct rtnl_prio *prio = data;
struct tc_prio_qopt opts;
- struct nl_msg *msg;
- prio = prio_qdisc(qdisc);
- if (!prio ||
- !(prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP))
- goto errout;
+ if (!prio || !(prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP))
+ BUG();
opts.bands = prio->qp_bands;
memcpy(opts.priomap, prio->qp_priomap, sizeof(opts.priomap));
- msg = nlmsg_alloc();
- if (!msg)
- goto errout;
-
- if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0) {
- nlmsg_free(msg);
- goto errout;
- }
-
- return msg;
-errout:
- return NULL;
+ return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
}
/**
@@ -160,18 +126,15 @@ errout:
* @arg bands New number of bands.
* @return 0 on success or a negative error code.
*/
-int rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *qdisc, int bands)
+void rtnl_qdisc_prio_set_bands(struct rtnl_qdisc *qdisc, int bands)
{
struct rtnl_prio *prio;
-
- prio = prio_alloc(qdisc);
- if (!prio)
- return -NLE_NOMEM;
+
+ if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
prio->qp_bands = bands;
prio->qp_mask |= SCH_PRIO_ATTR_BANDS;
-
- return 0;
}
/**
@@ -183,8 +146,10 @@ int rtnl_qdisc_prio_get_bands(struct rtnl_qdisc *qdisc)
{
struct rtnl_prio *prio;
- prio = prio_qdisc(qdisc);
- if (prio && prio->qp_mask & SCH_PRIO_ATTR_BANDS)
+ if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (prio->qp_mask & SCH_PRIO_ATTR_BANDS)
return prio->qp_bands;
else
return -NLE_NOMEM;
@@ -203,9 +168,8 @@ int rtnl_qdisc_prio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
struct rtnl_prio *prio;
int i;
- prio = prio_alloc(qdisc);
- if (!prio)
- return -NLE_NOMEM;
+ if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
if (!(prio->qp_mask & SCH_PRIO_ATTR_BANDS))
return -NLE_MISSING_ATTR;
@@ -234,8 +198,10 @@ uint8_t *rtnl_qdisc_prio_get_priomap(struct rtnl_qdisc *qdisc)
{
struct rtnl_prio *prio;
- prio = prio_qdisc(qdisc);
- if (prio && prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP)
+ if (!(prio = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (prio->qp_mask & SCH_PRIO_ATTR_PRIOMAP)
return prio->qp_priomap;
else
return NULL;
@@ -289,38 +255,40 @@ int rtnl_str2prio(const char *name)
/** @} */
-static struct rtnl_qdisc_ops prio_ops = {
- .qo_kind = "prio",
- .qo_msg_parser = prio_msg_parser,
- .qo_free_data = prio_free_data,
- .qo_dump = {
+static struct rtnl_tc_ops prio_ops = {
+ .to_kind = "prio",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_prio),
+ .to_msg_parser = prio_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = prio_dump_line,
[NL_DUMP_DETAILS] = prio_dump_details,
},
- .qo_get_opts = prio_get_opts,
+ .to_msg_fill = prio_msg_fill,
};
-static struct rtnl_qdisc_ops pfifo_fast_ops = {
- .qo_kind = "pfifo_fast",
- .qo_msg_parser = prio_msg_parser,
- .qo_free_data = prio_free_data,
- .qo_dump = {
+static struct rtnl_tc_ops pfifo_fast_ops = {
+ .to_kind = "pfifo_fast",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_prio),
+ .to_msg_parser = prio_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = prio_dump_line,
[NL_DUMP_DETAILS] = prio_dump_details,
},
- .qo_get_opts = prio_get_opts,
+ .to_msg_fill = prio_msg_fill,
};
static void __init prio_init(void)
{
- rtnl_qdisc_register(&prio_ops);
- rtnl_qdisc_register(&pfifo_fast_ops);
+ rtnl_tc_register(&prio_ops);
+ rtnl_tc_register(&pfifo_fast_ops);
}
static void __exit prio_exit(void)
{
- rtnl_qdisc_unregister(&prio_ops);
- rtnl_qdisc_unregister(&pfifo_fast_ops);
+ rtnl_tc_unregister(&prio_ops);
+ rtnl_tc_unregister(&pfifo_fast_ops);
}
/** @} */
diff --git a/lib/route/sch/red.c b/lib/route/sch/red.c
index 727db17..5df3f3c 100644
--- a/lib/route/sch/red.c
+++ b/lib/route/sch/red.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup red Random Early Detection (RED)
+ * @ingroup qdisc
+ * @defgroup qdisc_red Random Early Detection (RED)
* @brief
* @{
*/
@@ -20,8 +20,8 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/sch/red.h>
/** @cond SKIP */
@@ -34,44 +34,27 @@
#define RED_ATTR_SCELL_LOG 0x40
/** @endcond */
-static inline struct rtnl_red *red_qdisc(struct rtnl_qdisc *qdisc)
-{
- return (struct rtnl_red *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_red *red_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_red));
-
- return red_qdisc(qdisc);
-}
-
static struct nla_policy red_policy[TCA_RED_MAX+1] = {
[TCA_RED_PARMS] = { .minlen = sizeof(struct tc_red_qopt) },
};
-static int red_msg_parser(struct rtnl_qdisc *qdisc)
+static int red_msg_parser(struct rtnl_tc *tc, void *data)
{
struct nlattr *tb[TCA_RED_MAX+1];
- struct rtnl_red *red;
+ struct rtnl_red *red = data;
struct tc_red_qopt *opts;
int err;
- if (!(qdisc->ce_mask & TCA_ATTR_OPTS))
+ if (!(tc->ce_mask & TCA_ATTR_OPTS))
return 0;
- err = tca_parse(tb, TCA_RED_MAX, (struct rtnl_tc *) qdisc, red_policy);
+ err = tca_parse(tb, TCA_RED_MAX, tc, red_policy);
if (err < 0)
return err;
if (!tb[TCA_RED_PARMS])
return -NLE_MISSING_ATTR;
- red = red_alloc(qdisc);
- if (!red)
- return -NLE_NOMEM;
-
opts = nla_data(tb[TCA_RED_PARMS]);
red->qr_limit = opts->limit;
@@ -89,45 +72,42 @@ static int red_msg_parser(struct rtnl_qdisc *qdisc)
return 0;
}
-static void red_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void red_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_red *red = red_qdisc(qdisc);
+ struct rtnl_red *red = data;
if (red) {
/* XXX: limit, min, max, flags */
}
}
-static void red_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void red_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_red *red = red_qdisc(qdisc);
+ struct rtnl_red *red = data;
if (red) {
/* XXX: wlog, plog, scell_log */
}
}
-static void red_dump_stats(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void red_dump_stats(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_red *red = red_qdisc(qdisc);
+ struct rtnl_red *red = data;
if (red) {
/* XXX: xstats */
}
}
-static struct nl_msg *red_get_opts(struct rtnl_qdisc *qdisc)
+static int red_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_red *red;
- struct nl_msg *msg;
+ struct rtnl_red *red = data;
- red = red_qdisc(qdisc);
if (!red)
- return NULL;
-
- msg = nlmsg_alloc();
- if (!msg)
- goto errout;
+ BUG();
#if 0
memset(&opts, 0, sizeof(opts));
@@ -139,10 +119,7 @@ static struct nl_msg *red_get_opts(struct rtnl_qdisc *qdisc)
goto errout;
#endif
- return msg;
-errout:
- nlmsg_free(msg);
- return NULL;
+ return -NLE_OPNOTSUPP;
}
/**
@@ -156,18 +133,15 @@ errout:
* @arg limit New limit in number of packets.
* @return 0 on success or a negative error code.
*/
-int rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit)
+void rtnl_red_set_limit(struct rtnl_qdisc *qdisc, int limit)
{
struct rtnl_red *red;
- red = red_alloc(qdisc);
- if (!red)
- return -NLE_NOMEM;
+ if (!(red = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
red->qr_limit = limit;
red->qr_mask |= RED_ATTR_LIMIT;
-
- return 0;
}
/**
@@ -179,8 +153,10 @@ int rtnl_red_get_limit(struct rtnl_qdisc *qdisc)
{
struct rtnl_red *red;
- red = red_qdisc(qdisc);
- if (red && (red->qr_mask & RED_ATTR_LIMIT))
+ if (!(red = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (red->qr_mask & RED_ATTR_LIMIT)
return red->qr_limit;
else
return -NLE_NOATTR;
@@ -188,25 +164,27 @@ int rtnl_red_get_limit(struct rtnl_qdisc *qdisc)
/** @} */
-static struct rtnl_qdisc_ops red_ops = {
- .qo_kind = "red",
- .qo_msg_parser = red_msg_parser,
- .qo_dump = {
+static struct rtnl_tc_ops red_ops = {
+ .to_kind = "red",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_red),
+ .to_msg_parser = red_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = red_dump_line,
[NL_DUMP_DETAILS] = red_dump_details,
[NL_DUMP_STATS] = red_dump_stats,
},
- .qo_get_opts = red_get_opts,
+ .to_msg_fill = red_msg_fill,
};
static void __init red_init(void)
{
- rtnl_qdisc_register(&red_ops);
+ rtnl_tc_register(&red_ops);
}
static void __exit red_exit(void)
{
- rtnl_qdisc_unregister(&red_ops);
+ rtnl_tc_unregister(&red_ops);
}
/** @} */
diff --git a/lib/route/sch/sfq.c b/lib/route/sch/sfq.c
index cad99fd..e817a6a 100644
--- a/lib/route/sch/sfq.c
+++ b/lib/route/sch/sfq.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup sfq Stochastic Fairness Queueing (SFQ)
+ * @ingroup qdisc
+ * @defgroup qdisc_sfq Stochastic Fairness Queueing (SFQ)
* @brief
*
* @par Parameter Description
@@ -27,8 +27,8 @@
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/sch/sfq.h>
/** @cond SKIP */
@@ -39,35 +39,18 @@
#define SCH_SFQ_ATTR_FLOWS 0x10
/** @endcond */
-static inline struct rtnl_sfq *sfq_qdisc(struct rtnl_qdisc *qdisc)
+static int sfq_msg_parser(struct rtnl_tc *tc, void *data)
{
- return (struct rtnl_sfq *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_sfq *sfq_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_sfq));
-
- return sfq_qdisc(qdisc);
-}
-
-static int sfq_msg_parser(struct rtnl_qdisc *qdisc)
-{
- struct rtnl_sfq *sfq;
+ struct rtnl_sfq *sfq = data;
struct tc_sfq_qopt *opts;
- if (!(qdisc->ce_mask & TCA_ATTR_OPTS))
+ if (!(tc->ce_mask & TCA_ATTR_OPTS))
return 0;
- if (qdisc->q_opts->d_size < sizeof(*opts))
+ if (tc->tc_opts->d_size < sizeof(*opts))
return -NLE_INVAL;
- sfq = sfq_alloc(qdisc);
- if (!sfq)
- return -NLE_NOMEM;
-
- opts = (struct tc_sfq_qopt *) qdisc->q_opts->d_data;
+ opts = (struct tc_sfq_qopt *) tc->tc_opts->d_data;
sfq->qs_quantum = opts->quantum;
sfq->qs_perturb = opts->perturb_period;
@@ -82,55 +65,39 @@ static int sfq_msg_parser(struct rtnl_qdisc *qdisc)
return 0;
}
-static void sfq_free_data(struct rtnl_qdisc *qdisc)
-{
- free(qdisc->q_subdata);
-}
-
-static void sfq_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void sfq_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
+ struct rtnl_sfq *sfq = data;
if (sfq)
nl_dump(p, " quantum %u perturb %us", sfq->qs_quantum,
sfq->qs_perturb);
}
-static void sfq_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void sfq_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_sfq *sfq = sfq_qdisc(qdisc);
+ struct rtnl_sfq *sfq = data;
if (sfq)
nl_dump(p, "limit %u divisor %u",
sfq->qs_limit, sfq->qs_divisor);
}
-static struct nl_msg *sfq_get_opts(struct rtnl_qdisc *qdisc)
+static int sfq_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct rtnl_sfq *sfq;
- struct tc_sfq_qopt opts;
- struct nl_msg *msg;
+ struct rtnl_sfq *sfq = data;
+ struct tc_sfq_qopt opts = {0};
- sfq = sfq_qdisc(qdisc);
if (!sfq)
- return NULL;
-
- msg = nlmsg_alloc();
- if (!msg)
- goto errout;
+ BUG();
- memset(&opts, 0, sizeof(opts));
opts.quantum = sfq->qs_quantum;
opts.perturb_period = sfq->qs_perturb;
opts.limit = sfq->qs_limit;
- if (nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD) < 0)
- goto errout;
-
- return msg;
-errout:
- nlmsg_free(msg);
- return NULL;
+ return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
}
/**
@@ -144,18 +111,15 @@ errout:
* @arg quantum New quantum in bytes.
* @return 0 on success or a negative error code.
*/
-int rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
+void rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
{
struct rtnl_sfq *sfq;
- sfq = sfq_alloc(qdisc);
- if (!sfq)
- return -NLE_NOMEM;
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
sfq->qs_quantum = quantum;
sfq->qs_mask |= SCH_SFQ_ATTR_QUANTUM;
-
- return 0;
}
/**
@@ -166,9 +130,11 @@ int rtnl_sfq_set_quantum(struct rtnl_qdisc *qdisc, int quantum)
int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
{
struct rtnl_sfq *sfq;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
- sfq = sfq_qdisc(qdisc);
- if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
+ if (sfq->qs_mask & SCH_SFQ_ATTR_QUANTUM)
return sfq->qs_quantum;
else
return -NLE_NOATTR;
@@ -180,18 +146,15 @@ int rtnl_sfq_get_quantum(struct rtnl_qdisc *qdisc)
* @arg limit New limit in number of packets.
* @return 0 on success or a negative error code.
*/
-int rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
+void rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
{
struct rtnl_sfq *sfq;
-
- sfq = sfq_alloc(qdisc);
- if (!sfq)
- return -NLE_NOMEM;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
sfq->qs_limit = limit;
sfq->qs_mask |= SCH_SFQ_ATTR_LIMIT;
-
- return 0;
}
/**
@@ -202,9 +165,11 @@ int rtnl_sfq_set_limit(struct rtnl_qdisc *qdisc, int limit)
int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
{
struct rtnl_sfq *sfq;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
- sfq = sfq_qdisc(qdisc);
- if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
+ if (sfq->qs_mask & SCH_SFQ_ATTR_LIMIT)
return sfq->qs_limit;
else
return -NLE_NOATTR;
@@ -217,18 +182,15 @@ int rtnl_sfq_get_limit(struct rtnl_qdisc *qdisc)
* @note A value of 0 disables perturbation altogether.
* @return 0 on success or a negative error code.
*/
-int rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
+void rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
{
struct rtnl_sfq *sfq;
-
- sfq = sfq_alloc(qdisc);
- if (!sfq)
- return -NLE_NOMEM;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
sfq->qs_perturb = perturb;
sfq->qs_mask |= SCH_SFQ_ATTR_PERTURB;
-
- return 0;
}
/**
@@ -239,9 +201,11 @@ int rtnl_sfq_set_perturb(struct rtnl_qdisc *qdisc, int perturb)
int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
{
struct rtnl_sfq *sfq;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
- sfq = sfq_qdisc(qdisc);
- if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
+ if (sfq->qs_mask & SCH_SFQ_ATTR_PERTURB)
return sfq->qs_perturb;
else
return -NLE_NOATTR;
@@ -255,9 +219,11 @@ int rtnl_sfq_get_perturb(struct rtnl_qdisc *qdisc)
int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
{
struct rtnl_sfq *sfq;
+
+ if (!(sfq = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
- sfq = sfq_qdisc(qdisc);
- if (sfq && sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
+ if (sfq->qs_mask & SCH_SFQ_ATTR_DIVISOR)
return sfq->qs_divisor;
else
return -NLE_NOATTR;
@@ -265,25 +231,26 @@ int rtnl_sfq_get_divisor(struct rtnl_qdisc *qdisc)
/** @} */
-static struct rtnl_qdisc_ops sfq_ops = {
- .qo_kind = "sfq",
- .qo_msg_parser = sfq_msg_parser,
- .qo_free_data = sfq_free_data,
- .qo_dump = {
+static struct rtnl_tc_ops sfq_ops = {
+ .to_kind = "sfq",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_sfq),
+ .to_msg_parser = sfq_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = sfq_dump_line,
[NL_DUMP_DETAILS] = sfq_dump_details,
},
- .qo_get_opts = sfq_get_opts,
+ .to_msg_fill = sfq_msg_fill,
};
static void __init sfq_init(void)
{
- rtnl_qdisc_register(&sfq_ops);
+ rtnl_tc_register(&sfq_ops);
}
static void __exit sfq_exit(void)
{
- rtnl_qdisc_unregister(&sfq_ops);
+ rtnl_tc_unregister(&sfq_ops);
}
/** @} */
diff --git a/lib/route/sch/tbf.c b/lib/route/sch/tbf.c
index c61810e..8e76a5b 100644
--- a/lib/route/sch/tbf.c
+++ b/lib/route/sch/tbf.c
@@ -6,12 +6,12 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
- * @ingroup qdisc_api
- * @defgroup tbf Token Bucket Filter (TBF)
+ * @ingroup qdisc
+ * @defgroup qdisc_tbf Token Bucket Filter (TBF)
* @{
*/
@@ -20,11 +20,9 @@
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
#include <netlink/route/qdisc.h>
-#include <netlink/route/qdisc-modules.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
#include <netlink/route/link.h>
#include <netlink/route/sch/tbf.h>
@@ -34,37 +32,19 @@
#define TBF_ATTR_PEAKRATE 0x10
/** @endcond */
-static inline struct rtnl_tbf *tbf_qdisc(struct rtnl_qdisc *qdisc)
-{
- return (struct rtnl_tbf *) qdisc->q_subdata;
-}
-
-static inline struct rtnl_tbf *tbf_alloc(struct rtnl_qdisc *qdisc)
-{
- if (!qdisc->q_subdata)
- qdisc->q_subdata = calloc(1, sizeof(struct rtnl_tbf));
-
- return tbf_qdisc(qdisc);
-}
-
static struct nla_policy tbf_policy[TCA_TBF_MAX+1] = {
[TCA_TBF_PARMS] = { .minlen = sizeof(struct tc_tbf_qopt) },
};
-static int tbf_msg_parser(struct rtnl_qdisc *q)
+static int tbf_msg_parser(struct rtnl_tc *tc, void *data)
{
- int err;
struct nlattr *tb[TCA_TBF_MAX + 1];
- struct rtnl_tbf *tbf;
+ struct rtnl_tbf *tbf = data;
+ int err;
- err = tca_parse(tb, TCA_TBF_MAX, (struct rtnl_tc *) q, tbf_policy);
- if (err < 0)
+ if ((err = tca_parse(tb, TCA_TBF_MAX, tc, tbf_policy)) < 0)
return err;
- tbf = tbf_alloc(q);
- if (!tbf)
- return -NLE_NOMEM;
-
if (tb[TCA_TBF_PARMS]) {
struct tc_tbf_qopt opts;
int bufsize;
@@ -84,8 +64,8 @@ static int tbf_msg_parser(struct rtnl_qdisc *q)
opts.peakrate.rate);
tbf->qt_peakrate_bucket = bufsize;
- rtnl_tc_set_mpu((struct rtnl_tc *) q, tbf->qt_rate.rs_mpu);
- rtnl_tc_set_overhead((struct rtnl_tc *) q, tbf->qt_rate.rs_overhead);
+ rtnl_tc_set_mpu(tc, tbf->qt_rate.rs_mpu);
+ rtnl_tc_set_overhead(tc, tbf->qt_rate.rs_overhead);
tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_RATE | TBF_ATTR_PEAKRATE);
}
@@ -93,16 +73,12 @@ static int tbf_msg_parser(struct rtnl_qdisc *q)
return 0;
}
-static void tbf_free_data(struct rtnl_qdisc *qdisc)
-{
- free(qdisc->q_subdata);
-}
-
-static void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void tbf_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
double r, rbit, lim;
char *ru, *rubit, *limu;
- struct rtnl_tbf *tbf = tbf_qdisc(qdisc);
+ struct rtnl_tbf *tbf = data;
if (!tbf)
return;
@@ -115,9 +91,10 @@ static void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
r, ru, rbit, rubit, lim, limu);
}
-static void tbf_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
+static void tbf_dump_details(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
{
- struct rtnl_tbf *tbf = tbf_qdisc(qdisc);
+ struct rtnl_tbf *tbf = data;
if (!tbf)
return;
@@ -151,51 +128,40 @@ static void tbf_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
}
}
-static struct nl_msg *tbf_get_opts(struct rtnl_qdisc *qdisc)
+static int tbf_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
- struct tc_tbf_qopt opts;
- struct rtnl_tbf *tbf;
- struct nl_msg *msg;
uint32_t rtab[RTNL_TC_RTABLE_SIZE], ptab[RTNL_TC_RTABLE_SIZE];
+ struct tc_tbf_qopt opts;
+ struct rtnl_tbf *tbf = data;
int required = TBF_ATTR_RATE | TBF_ATTR_LIMIT;
- memset(&opts, 0, sizeof(opts));
-
- tbf = tbf_qdisc(qdisc);
- if (!tbf)
- return NULL;
-
if (!(tbf->qt_mask & required) != required)
- return NULL;
+ return -NLE_MISSING_ATTR;
+ memset(&opts, 0, sizeof(opts));
opts.limit = tbf->qt_limit;
opts.buffer = tbf->qt_rate_txtime;
- rtnl_tc_build_rate_table((struct rtnl_tc *) qdisc, &tbf->qt_rate, rtab);
+ rtnl_tc_build_rate_table(tc, &tbf->qt_rate, rtab);
rtnl_rcopy_ratespec(&opts.rate, &tbf->qt_rate);
if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
opts.mtu = tbf->qt_peakrate_txtime;
- rtnl_tc_build_rate_table((struct rtnl_tc *) qdisc, &tbf->qt_peakrate, ptab);
+ rtnl_tc_build_rate_table(tc, &tbf->qt_peakrate, ptab);
rtnl_rcopy_ratespec(&opts.peakrate, &tbf->qt_peakrate);
}
- msg = nlmsg_alloc();
- if (!msg)
- goto nla_put_failure;
-
NLA_PUT(msg, TCA_TBF_PARMS, sizeof(opts), &opts);
NLA_PUT(msg, TCA_TBF_RTAB, sizeof(rtab), rtab);
if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
NLA_PUT(msg, TCA_TBF_PTAB, sizeof(ptab), ptab);
- return msg;
+ return 0;
nla_put_failure:
- nlmsg_free(msg);
- return NULL;
+ return -NLE_MSGSIZE;
}
/**
@@ -209,18 +175,15 @@ nla_put_failure:
* @arg limit New limit in bytes.
* @return 0 on success or a negative error code.
*/
-int rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *qdisc, int limit)
+void rtnl_qdisc_tbf_set_limit(struct rtnl_qdisc *qdisc, int limit)
{
struct rtnl_tbf *tbf;
- tbf = tbf_alloc(qdisc);
- if (!tbf)
- return -NLE_NOMEM;
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
tbf->qt_limit = limit;
tbf->qt_mask |= TBF_ATTR_LIMIT;
-
- return 0;
}
static inline double calc_limit(struct rtnl_ratespec *spec, int latency,
@@ -257,9 +220,8 @@ int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *qdisc, int latency)
struct rtnl_tbf *tbf;
double limit, limit2;
- tbf = tbf_alloc(qdisc);
- if (!tbf)
- return -NLE_NOMEM;
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
if (!(tbf->qt_mask & TBF_ATTR_RATE))
return -NLE_MISSING_ATTR;
@@ -274,7 +236,9 @@ int rtnl_qdisc_tbf_set_limit_by_latency(struct rtnl_qdisc *qdisc, int latency)
limit = limit2;
}
- return rtnl_qdisc_tbf_set_limit(qdisc, (int) limit);
+ rtnl_qdisc_tbf_set_limit(qdisc, (int) limit);
+
+ return 0;
}
/**
@@ -286,8 +250,10 @@ int rtnl_qdisc_tbf_get_limit(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_LIMIT))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_LIMIT)
return tbf->qt_limit;
else
return -NLE_NOATTR;
@@ -307,15 +273,14 @@ static inline int calc_cell_log(int cell, int bucket)
* @arg cell Size of a rate cell or 0 to get default value.
* @return 0 on success or a negative error code.
*/
-int rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket,
+void rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket,
int cell)
{
struct rtnl_tbf *tbf;
int cell_log;
- tbf = tbf_alloc(qdisc);
- if (!tbf)
- return -NLE_NOMEM;
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
if (!cell)
cell_log = UINT8_MAX;
@@ -327,8 +292,6 @@ int rtnl_qdisc_tbf_set_rate(struct rtnl_qdisc *qdisc, int rate, int bucket,
tbf->qt_rate.rs_cell_log = cell_log;
tbf->qt_rate_txtime = rtnl_tc_calc_txtime(bucket, rate);
tbf->qt_mask |= TBF_ATTR_RATE;
-
- return 0;
}
/**
@@ -340,8 +303,10 @@ int rtnl_qdisc_tbf_get_rate(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_RATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_RATE)
return tbf->qt_rate.rs_rate;
else
return -1;
@@ -356,8 +321,10 @@ int rtnl_qdisc_tbf_get_rate_bucket(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_RATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_RATE)
return tbf->qt_rate_bucket;
else
return -1;
@@ -372,8 +339,10 @@ int rtnl_qdisc_tbf_get_rate_cell(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_RATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_RATE)
return (1 << tbf->qt_rate.rs_cell_log);
else
return -1;
@@ -393,9 +362,8 @@ int rtnl_qdisc_tbf_set_peakrate(struct rtnl_qdisc *qdisc, int rate, int bucket,
struct rtnl_tbf *tbf;
int cell_log;
- tbf = tbf_alloc(qdisc);
- if (!tbf)
- return -NLE_NOMEM;
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
cell_log = calc_cell_log(cell, bucket);
if (cell_log < 0)
@@ -420,8 +388,10 @@ int rtnl_qdisc_tbf_get_peakrate(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
return tbf->qt_peakrate.rs_rate;
else
return -1;
@@ -436,8 +406,10 @@ int rtnl_qdisc_tbf_get_peakrate_bucket(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
return tbf->qt_peakrate_bucket;
else
return -1;
@@ -452,8 +424,10 @@ int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *qdisc)
{
struct rtnl_tbf *tbf;
- tbf = tbf_qdisc(qdisc);
- if (tbf && (tbf->qt_mask & TBF_ATTR_PEAKRATE))
+ if (!(tbf = rtnl_tc_data(TC_CAST(qdisc))))
+ BUG();
+
+ if (tbf->qt_mask & TBF_ATTR_PEAKRATE)
return (1 << tbf->qt_peakrate.rs_cell_log);
else
return -1;
@@ -461,25 +435,26 @@ int rtnl_qdisc_tbf_get_peakrate_cell(struct rtnl_qdisc *qdisc)
/** @} */
-static struct rtnl_qdisc_ops tbf_qdisc_ops = {
- .qo_kind = "tbf",
- .qo_msg_parser = tbf_msg_parser,
- .qo_dump = {
+static struct rtnl_tc_ops tbf_tc_ops = {
+ .to_kind = "tbf",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_tbf),
+ .to_msg_parser = tbf_msg_parser,
+ .to_dump = {
[NL_DUMP_LINE] = tbf_dump_line,
[NL_DUMP_DETAILS] = tbf_dump_details,
},
- .qo_free_data = tbf_free_data,
- .qo_get_opts = tbf_get_opts,
+ .to_msg_fill = tbf_msg_fill,
};
static void __init tbf_init(void)
{
- rtnl_qdisc_register(&tbf_qdisc_ops);
+ rtnl_tc_register(&tbf_tc_ops);
}
static void __exit tbf_exit(void)
{
- rtnl_qdisc_unregister(&tbf_qdisc_ops);
+ rtnl_tc_unregister(&tbf_tc_ops);
}
/** @} */
diff --git a/lib/route/tc.c b/lib/route/tc.c
index 6a0233a..e4faf92 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
@@ -22,9 +22,13 @@
#include <netlink/route/rtnl.h>
#include <netlink/route/link.h>
#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
/** @cond SKIP */
+static struct nl_list_head tc_ops_list[__RTNL_TC_TYPE_MAX];
+static struct rtnl_tc_type_ops *tc_type_ops[__RTNL_TC_TYPE_MAX];
+
static struct nla_policy tc_policy[TCA_MAX+1] = {
[TCA_KIND] = { .type = NLA_STRING,
.maxlen = TCKINDSIZ },
@@ -54,12 +58,16 @@ static struct nla_policy tc_stats2_policy[TCA_STATS_MAX+1] = {
[TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) },
};
-int tca_msg_parser(struct nlmsghdr *n, struct rtnl_tc *g)
+int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc)
{
+ struct rtnl_tc_ops *ops;
struct nlattr *tb[TCA_MAX + 1];
+ char kind[TCKINDSIZ];
struct tcmsg *tm;
int err;
+ tc->ce_msgtype = n->nlmsg_type;
+
err = nlmsg_parse(n, sizeof(*tm), tb, TCA_MAX, tc_policy);
if (err < 0)
return err;
@@ -67,25 +75,25 @@ int tca_msg_parser(struct nlmsghdr *n, struct rtnl_tc *g)
if (tb[TCA_KIND] == NULL)
return -NLE_MISSING_ATTR;
- nla_strlcpy(g->tc_kind, tb[TCA_KIND], TCKINDSIZ);
+ nla_strlcpy(kind, tb[TCA_KIND], sizeof(kind));
+ rtnl_tc_set_kind(tc, kind);
tm = nlmsg_data(n);
- g->tc_family = tm->tcm_family;
- g->tc_ifindex = tm->tcm_ifindex;
- g->tc_handle = tm->tcm_handle;
- g->tc_parent = tm->tcm_parent;
- g->tc_info = tm->tcm_info;
+ tc->tc_family = tm->tcm_family;
+ tc->tc_ifindex = tm->tcm_ifindex;
+ tc->tc_handle = tm->tcm_handle;
+ tc->tc_parent = tm->tcm_parent;
+ tc->tc_info = tm->tcm_info;
- g->ce_mask = (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE |
- TCA_ATTR_PARENT | TCA_ATTR_INFO | TCA_ATTR_KIND);
+ tc->ce_mask |= (TCA_ATTR_FAMILY | TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE|
+ TCA_ATTR_PARENT | TCA_ATTR_INFO);
if (tb[TCA_OPTIONS]) {
- g->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
- if (!g->tc_opts)
+ tc->tc_opts = nl_data_alloc_attr(tb[TCA_OPTIONS]);
+ if (!tc->tc_opts)
return -NLE_NOMEM;
- g->ce_mask |= TCA_ATTR_OPTS;
+ tc->ce_mask |= TCA_ATTR_OPTS;
}
-
if (tb[TCA_STATS2]) {
struct nlattr *tbs[TCA_STATS_MAX + 1];
@@ -99,34 +107,34 @@ int tca_msg_parser(struct nlmsghdr *n, struct rtnl_tc *g)
struct gnet_stats_basic *bs;
bs = nla_data(tbs[TCA_STATS_BASIC]);
- g->tc_stats[RTNL_TC_BYTES] = bs->bytes;
- g->tc_stats[RTNL_TC_PACKETS] = bs->packets;
+ tc->tc_stats[RTNL_TC_BYTES] = bs->bytes;
+ tc->tc_stats[RTNL_TC_PACKETS] = bs->packets;
}
if (tbs[TCA_STATS_RATE_EST]) {
struct gnet_stats_rate_est *re;
re = nla_data(tbs[TCA_STATS_RATE_EST]);
- g->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
- g->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
+ tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
+ tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
}
if (tbs[TCA_STATS_QUEUE]) {
struct gnet_stats_queue *q;
q = nla_data(tbs[TCA_STATS_QUEUE]);
- g->tc_stats[RTNL_TC_QLEN] = q->qlen;
- g->tc_stats[RTNL_TC_BACKLOG] = q->backlog;
- g->tc_stats[RTNL_TC_DROPS] = q->drops;
- g->tc_stats[RTNL_TC_REQUEUES] = q->requeues;
- g->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
+ tc->tc_stats[RTNL_TC_QLEN] = q->qlen;
+ tc->tc_stats[RTNL_TC_BACKLOG] = q->backlog;
+ tc->tc_stats[RTNL_TC_DROPS] = q->drops;
+ tc->tc_stats[RTNL_TC_REQUEUES] = q->requeues;
+ tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
}
- g->ce_mask |= TCA_ATTR_STATS;
+ tc->ce_mask |= TCA_ATTR_STATS;
if (tbs[TCA_STATS_APP]) {
- g->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
- if (g->tc_xstats == NULL)
+ tc->tc_xstats = nl_data_alloc_attr(tbs[TCA_STATS_APP]);
+ if (tc->tc_xstats == NULL)
return -NLE_NOMEM;
} else
goto compat_xstats;
@@ -134,159 +142,54 @@ int tca_msg_parser(struct nlmsghdr *n, struct rtnl_tc *g)
if (tb[TCA_STATS]) {
struct tc_stats *st = nla_data(tb[TCA_STATS]);
- g->tc_stats[RTNL_TC_BYTES] = st->bytes;
- g->tc_stats[RTNL_TC_PACKETS] = st->packets;
- g->tc_stats[RTNL_TC_RATE_BPS] = st->bps;
- g->tc_stats[RTNL_TC_RATE_PPS] = st->pps;
- g->tc_stats[RTNL_TC_QLEN] = st->qlen;
- g->tc_stats[RTNL_TC_BACKLOG] = st->backlog;
- g->tc_stats[RTNL_TC_DROPS] = st->drops;
- g->tc_stats[RTNL_TC_OVERLIMITS] = st->overlimits;
+ tc->tc_stats[RTNL_TC_BYTES] = st->bytes;
+ tc->tc_stats[RTNL_TC_PACKETS] = st->packets;
+ tc->tc_stats[RTNL_TC_RATE_BPS] = st->bps;
+ tc->tc_stats[RTNL_TC_RATE_PPS] = st->pps;
+ tc->tc_stats[RTNL_TC_QLEN] = st->qlen;
+ tc->tc_stats[RTNL_TC_BACKLOG] = st->backlog;
+ tc->tc_stats[RTNL_TC_DROPS] = st->drops;
+ tc->tc_stats[RTNL_TC_OVERLIMITS]= st->overlimits;
- g->ce_mask |= TCA_ATTR_STATS;
+ tc->ce_mask |= TCA_ATTR_STATS;
}
compat_xstats:
if (tb[TCA_XSTATS]) {
- g->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
- if (g->tc_xstats == NULL)
+ tc->tc_xstats = nl_data_alloc_attr(tb[TCA_XSTATS]);
+ if (tc->tc_xstats == NULL)
return -NLE_NOMEM;
- g->ce_mask |= TCA_ATTR_XSTATS;
+ tc->ce_mask |= TCA_ATTR_XSTATS;
}
}
+ ops = rtnl_tc_get_ops(tc);
+ if (ops && ops->to_msg_parser) {
+ void *data = rtnl_tc_data(tc);
- return 0;
-}
-
-void tca_free_data(struct rtnl_tc *tca)
-{
- rtnl_link_put(tca->tc_link);
- nl_data_free(tca->tc_opts);
- nl_data_free(tca->tc_xstats);
-}
-
-int tca_clone(struct rtnl_tc *dst, struct rtnl_tc *src)
-{
- if (src->tc_link) {
- dst->tc_link = (struct rtnl_link *)
- nl_object_clone(OBJ_CAST(src->tc_link));
- if (!dst->tc_link)
+ if (!data)
return -NLE_NOMEM;
- }
- if (src->tc_opts) {
- dst->tc_opts = nl_data_clone(src->tc_opts);
- if (!dst->tc_opts)
- return -NLE_NOMEM;
- }
-
- if (src->tc_xstats) {
- dst->tc_xstats = nl_data_clone(src->tc_xstats);
- if (!dst->tc_xstats)
- return -NLE_NOMEM;
+ err = ops->to_msg_parser(tc, data);
+ if (err < 0)
+ return err;
}
return 0;
}
-void tca_dump_line(struct rtnl_tc *g, const char *type,
- struct nl_dump_params *p)
-{
- char handle[32], parent[32];
- struct nl_cache *link_cache;
-
- link_cache = nl_cache_mngt_require("route/link");
-
- nl_dump_line(p, "%s %s ", type, g->tc_kind);
-
- if (link_cache) {
- char buf[32];
- nl_dump(p, "dev %s ",
- rtnl_link_i2name(link_cache, g->tc_ifindex,
- buf, sizeof(buf)));
- } else
- nl_dump(p, "dev %u ", g->tc_ifindex);
-
- nl_dump(p, "id %s parent %s",
- rtnl_tc_handle2str(g->tc_handle, handle, sizeof(handle)),
- rtnl_tc_handle2str(g->tc_parent, parent, sizeof(parent)));
-}
-
-void tca_dump_details(struct rtnl_tc *tc, struct nl_dump_params *p)
-{
- nl_dump_line(p, " ");
-
- if (tc->ce_mask & TCA_ATTR_MTU)
- nl_dump(p, " mtu %u", tc->tc_mtu);
-
- if (tc->ce_mask & TCA_ATTR_MPU)
- nl_dump(p, " mput %u", tc->tc_mpu);
-
- if (tc->ce_mask & TCA_ATTR_OVERHEAD)
- nl_dump(p, " overhead %u", tc->tc_overhead);
-}
-
-void tca_dump_stats(struct rtnl_tc *g, struct nl_dump_params *p)
-{
- char *unit, fmt[64];
- float res;
- strcpy(fmt, " %7.2f %s %10u %10u %10u %10u %10u\n");
-
- nl_dump_line(p,
- " Stats: bytes packets drops overlimits" \
- " qlen backlog\n");
-
- res = nl_cancel_down_bytes(g->tc_stats[RTNL_TC_BYTES], &unit);
- if (*unit == 'B')
- fmt[11] = '9';
-
- nl_dump_line(p, fmt, res, unit,
- g->tc_stats[RTNL_TC_PACKETS],
- g->tc_stats[RTNL_TC_DROPS],
- g->tc_stats[RTNL_TC_OVERLIMITS],
- g->tc_stats[RTNL_TC_QLEN],
- g->tc_stats[RTNL_TC_BACKLOG]);
-
- res = nl_cancel_down_bytes(g->tc_stats[RTNL_TC_RATE_BPS], &unit);
-
- strcpy(fmt, " %7.2f %s/s%9u pps");
-
- if (*unit == 'B')
- fmt[11] = '9';
-
- nl_dump_line(p, fmt, res, unit, g->tc_stats[RTNL_TC_RATE_PPS]);
-}
-
-int tca_compare(struct nl_object *_a, struct nl_object *_b,
- uint32_t attrs, int flags)
-{
- struct rtnl_tc *a = (struct rtnl_tc *) _a;
- struct rtnl_tc *b = (struct rtnl_tc *) _b;
- int diff = 0;
-
-#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
-
- diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle);
- diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent);
- diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex);
- diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind));
-
-#undef TC_DIFF
-
- return diff;
-}
-
-int tca_build_msg(struct rtnl_tc *tca, int type, int flags,
- struct nl_msg **result)
+int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags,
+ struct nl_msg **result)
{
struct nl_msg *msg;
+ struct rtnl_tc_ops *ops;
struct tcmsg tchdr = {
.tcm_family = AF_UNSPEC,
- .tcm_ifindex = tca->tc_ifindex,
- .tcm_handle = tca->tc_handle,
- .tcm_parent = tca->tc_parent,
+ .tcm_ifindex = tc->tc_ifindex,
+ .tcm_handle = tc->tc_handle,
+ .tcm_parent = tc->tc_parent,
};
+ int err = -NLE_MSGSIZE;
msg = nlmsg_alloc_simple(type, flags);
if (!msg)
@@ -295,15 +198,29 @@ int tca_build_msg(struct rtnl_tc *tca, int type, int flags,
if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
- if (tca->ce_mask & TCA_ATTR_KIND)
- NLA_PUT_STRING(msg, TCA_KIND, tca->tc_kind);
+ if (tc->ce_mask & TCA_ATTR_KIND)
+ NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind);
+
+ ops = rtnl_tc_get_ops(tc);
+ if (ops && ops->to_msg_fill) {
+ struct nlattr *opts;
+ void *data = rtnl_tc_data(tc);
+
+ if (!(opts = nla_nest_start(msg, TCA_OPTIONS)))
+ goto nla_put_failure;
+
+ if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
+ goto nla_put_failure;
+
+ nla_nest_end(msg, opts);
+ }
*result = msg;
return 0;
nla_put_failure:
nlmsg_free(msg);
- return -NLE_MSGSIZE;
+ return err;
}
void tca_set_kind(struct rtnl_tc *t, const char *kind)
@@ -547,6 +464,27 @@ uint32_t rtnl_tc_get_parent(struct rtnl_tc *tc)
}
/**
+ * Define the type of traffic control object
+ * @arg tc traffic control object
+ * @arg kind name of the tc object type
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_tc_set_kind(struct rtnl_tc *tc, const char *kind)
+{
+ if (tc->ce_mask & TCA_ATTR_KIND)
+ return -NLE_EXIST;
+
+ strncpy(tc->tc_kind, kind, sizeof(tc->tc_kind) - 1);
+ tc->ce_mask |= TCA_ATTR_KIND;
+
+ /* Force allocation of data */
+ rtnl_tc_data(tc);
+
+ return 0;
+}
+
+/**
* Return kind of traffic control object
* @arg tc traffic control object
*
@@ -567,7 +505,7 @@ char *rtnl_tc_get_kind(struct rtnl_tc *tc)
*
* @return Value of requested statistic counter or 0.
*/
-uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, int id)
+uint64_t rtnl_tc_get_stat(struct rtnl_tc *tc, enum rtnl_tc_stat id)
{
if (id < 0 || id > RTNL_TC_STATS_MAX)
return 0;
@@ -745,5 +683,312 @@ int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *spec,
/** @} */
+/**
+ * @name TC implementation of cache functions
+ */
+
+void rtnl_tc_free_data(struct nl_object *obj)
+{
+ struct rtnl_tc *tc = TC_CAST(obj);
+ struct rtnl_tc_ops *ops;
+
+ rtnl_link_put(tc->tc_link);
+ nl_data_free(tc->tc_opts);
+ nl_data_free(tc->tc_xstats);
+
+ if (tc->tc_subdata) {
+ ops = rtnl_tc_get_ops(tc);
+ if (ops && ops->to_free_data)
+ ops->to_free_data(tc, nl_data_get(tc->tc_subdata));
+
+ nl_data_free(tc->tc_subdata);
+ }
+}
+
+int rtnl_tc_clone(struct nl_object *dstobj, struct nl_object *srcobj)
+{
+ struct rtnl_tc *dst = TC_CAST(dstobj);
+ struct rtnl_tc *src = TC_CAST(srcobj);
+ struct rtnl_tc_ops *ops;
+
+ if (src->tc_link) {
+ dst->tc_link = (struct rtnl_link *)
+ nl_object_clone(OBJ_CAST(src->tc_link));
+ if (!dst->tc_link)
+ return -NLE_NOMEM;
+ }
+
+ if (src->tc_opts) {
+ dst->tc_opts = nl_data_clone(src->tc_opts);
+ if (!dst->tc_opts)
+ return -NLE_NOMEM;
+ }
+
+ if (src->tc_xstats) {
+ dst->tc_xstats = nl_data_clone(src->tc_xstats);
+ if (!dst->tc_xstats)
+ return -NLE_NOMEM;
+ }
+
+ if (src->tc_subdata) {
+ if (!(dst->tc_subdata = nl_data_clone(src->tc_subdata))) {
+ return -NLE_NOMEM;
+ }
+ }
+
+ ops = rtnl_tc_get_ops(src);
+ if (ops && ops->to_clone) {
+ void *a = rtnl_tc_data(dst), *b = rtnl_tc_data(src);
+
+ if (!a)
+ return 0;
+ else if (!b)
+ return -NLE_NOMEM;
+
+ return ops->to_clone(a, b);
+ }
+
+ return 0;
+}
+
+static int tc_dump(struct rtnl_tc *tc, enum nl_dump_type type,
+ struct nl_dump_params *p)
+{
+ struct rtnl_tc_type_ops *type_ops;
+ struct rtnl_tc_ops *ops;
+ void *data = rtnl_tc_data(tc);
+
+ type_ops = tc_type_ops[tc->tc_type];
+ if (type_ops && type_ops->tt_dump[type])
+ type_ops->tt_dump[type](tc, p);
+
+ ops = rtnl_tc_get_ops(tc);
+ if (ops && ops->to_dump[type]) {
+ ops->to_dump[type](tc, data, p);
+ return 1;
+ }
+
+ return 0;
+}
+
+void rtnl_tc_dump_line(struct nl_object *obj, struct nl_dump_params *p)
+{
+ struct rtnl_tc_type_ops *type_ops;
+ struct rtnl_tc *tc = TC_CAST(obj);
+ struct nl_cache *link_cache;
+ char buf[32];
+
+ nl_new_line(p);
+
+ type_ops = tc_type_ops[tc->tc_type];
+ if (type_ops && type_ops->tt_dump_prefix)
+ nl_dump(p, "%s ", type_ops->tt_dump_prefix);
+
+ nl_dump(p, "%s ", tc->tc_kind);
+
+ if ((link_cache = nl_cache_mngt_require("route/link"))) {
+ nl_dump(p, "dev %s ",
+ rtnl_link_i2name(link_cache, tc->tc_ifindex,
+ buf, sizeof(buf)));
+ } else
+ nl_dump(p, "dev %u ", tc->tc_ifindex);
+
+ nl_dump(p, "id %s ",
+ rtnl_tc_handle2str(tc->tc_handle, buf, sizeof(buf)));
+
+ nl_dump(p, "parent %s",
+ rtnl_tc_handle2str(tc->tc_parent, buf, sizeof(buf)));
+
+ tc_dump(tc, NL_DUMP_LINE, p);
+ nl_dump(p, "\n");
+}
+
+void rtnl_tc_dump_details(struct nl_object *obj, struct nl_dump_params *p)
+{
+ struct rtnl_tc *tc = TC_CAST(obj);
+
+ rtnl_tc_dump_line(OBJ_CAST(tc), p);
+
+ nl_dump_line(p, " ");
+
+ if (tc->ce_mask & TCA_ATTR_MTU)
+ nl_dump(p, " mtu %u", tc->tc_mtu);
+
+ if (tc->ce_mask & TCA_ATTR_MPU)
+ nl_dump(p, " mpu %u", tc->tc_mpu);
+
+ if (tc->ce_mask & TCA_ATTR_OVERHEAD)
+ nl_dump(p, " overhead %u", tc->tc_overhead);
+
+ if (!tc_dump(tc, NL_DUMP_DETAILS, p))
+ nl_dump(p, "no options");
+ nl_dump(p, "\n");
+}
+
+void rtnl_tc_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
+{
+ struct rtnl_tc *tc = TC_CAST(obj);
+ char *unit, fmt[64];
+ float res;
+
+ rtnl_tc_dump_details(OBJ_CAST(tc), p);
+
+ strcpy(fmt, " %7.2f %s %10u %10u %10u %10u %10u\n");
+
+ nl_dump_line(p,
+ " Stats: bytes packets drops overlimits" \
+ " qlen backlog\n");
+
+ res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_BYTES], &unit);
+ if (*unit == 'B')
+ fmt[11] = '9';
+
+ nl_dump_line(p, fmt, res, unit,
+ tc->tc_stats[RTNL_TC_PACKETS],
+ tc->tc_stats[RTNL_TC_DROPS],
+ tc->tc_stats[RTNL_TC_OVERLIMITS],
+ tc->tc_stats[RTNL_TC_QLEN],
+ tc->tc_stats[RTNL_TC_BACKLOG]);
+
+ res = nl_cancel_down_bytes(tc->tc_stats[RTNL_TC_RATE_BPS], &unit);
+
+ strcpy(fmt, " %7.2f %s/s%9u pps");
+
+ if (*unit == 'B')
+ fmt[11] = '9';
+
+ nl_dump_line(p, fmt, res, unit, tc->tc_stats[RTNL_TC_RATE_PPS]);
+
+ tc_dump(tc, NL_DUMP_LINE, p);
+ nl_dump(p, "\n");
+}
+
+int rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
+ uint32_t attrs, int flags)
+{
+ struct rtnl_tc *a = TC_CAST(aobj);
+ struct rtnl_tc *b = TC_CAST(bobj);
+ int diff = 0;
+
+#define TC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TCA_ATTR_##ATTR, a, b, EXPR)
+
+ diff |= TC_DIFF(HANDLE, a->tc_handle != b->tc_handle);
+ diff |= TC_DIFF(PARENT, a->tc_parent != b->tc_parent);
+ diff |= TC_DIFF(IFINDEX, a->tc_ifindex != b->tc_ifindex);
+ diff |= TC_DIFF(KIND, strcmp(a->tc_kind, b->tc_kind));
+
+#undef TC_DIFF
+
+ return diff;
+}
+
+/** @} */
+
+/**
+ * @name Modules API
+ */
+
+struct rtnl_tc_ops *rtnl_tc_lookup_ops(enum rtnl_tc_type type, const char *kind)
+{
+ struct rtnl_tc_ops *ops;
+
+ nl_list_for_each_entry(ops, &tc_ops_list[type], to_list)
+ if (!strcmp(kind, ops->to_kind))
+ return ops;
+
+ return NULL;
+}
+
+struct rtnl_tc_ops *rtnl_tc_get_ops(struct rtnl_tc *tc)
+{
+ if (!tc->tc_ops)
+ tc->tc_ops = rtnl_tc_lookup_ops(tc->tc_type, tc->tc_kind);
+
+ return tc->tc_ops;
+}
+
+/**
+ * Register a traffic control module
+ * @arg ops traffic control module operations
+ */
+int rtnl_tc_register(struct rtnl_tc_ops *ops)
+{
+ static int init = 0;
+
+ /*
+ * Initialiation hack, make sure list is initialized when
+ * the first tc module registers. Putting this in a
+ * separate __init would required correct ordering of init
+ * functions
+ */
+ if (!init) {
+ int i;
+
+ for (i = 0; i < __RTNL_TC_TYPE_MAX; i++)
+ nl_init_list_head(&tc_ops_list[i]);
+
+ init = 1;
+ }
+
+ if (!ops->to_kind || ops->to_type > RTNL_TC_TYPE_MAX)
+ BUG();
+
+ if (rtnl_tc_lookup_ops(ops->to_type, ops->to_kind))
+ return -NLE_EXIST;
+
+ nl_list_add_tail(&ops->to_list, &tc_ops_list[ops->to_type]);
+
+ return 0;
+}
+
+/**
+ * Unregister a traffic control module
+ * @arg ops traffic control module operations
+ */
+void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
+{
+ nl_list_del(&ops->to_list);
+}
+
+void *rtnl_tc_data(struct rtnl_tc *tc)
+{
+ if (!tc->tc_subdata) {
+ size_t size;
+
+ if (!tc->tc_ops) {
+ if (!tc->tc_kind)
+ BUG();
+
+ if (!rtnl_tc_get_ops(tc))
+ return NULL;
+ }
+
+ if (!(size = tc->tc_ops->to_size))
+ BUG();
+
+ if (!(tc->tc_subdata = nl_data_alloc(NULL, size)))
+ return NULL;
+ }
+
+ return nl_data_get(tc->tc_subdata);
+}
+
+void rtnl_tc_type_register(struct rtnl_tc_type_ops *ops)
+{
+ if (ops->tt_type > RTNL_TC_TYPE_MAX)
+ BUG();
+
+ tc_type_ops[ops->tt_type] = ops;
+}
+
+void rtnl_tc_type_unregister(struct rtnl_tc_type_ops *ops)
+{
+ if (ops->tt_type > RTNL_TC_TYPE_MAX)
+ BUG();
+
+ tc_type_ops[ops->tt_type] = NULL;
+}
+
+/** @} */
/** @} */
diff --git a/src/lib/class.c b/src/lib/class.c
index c6b5525..96f60cd 100644
--- a/src/lib/class.c
+++ b/src/lib/class.c
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
@@ -22,8 +22,7 @@ struct rtnl_class *nl_cli_class_alloc(void)
{
struct rtnl_class *class;
- class = rtnl_class_alloc();
- if (!class)
+ if (!(class = rtnl_class_alloc()))
nl_cli_fatal(ENOMEM, "Unable to allocate class object");
return class;
@@ -43,9 +42,4 @@ struct nl_cache *nl_cli_class_alloc_cache(struct nl_sock *sock, int ifindex)
return cache;
}
-void nl_cli_class_parse_kind(struct rtnl_class *class, char *arg)
-{
- rtnl_class_set_kind(class, arg);
-}
-
/** @} */
diff --git a/src/lib/cls.c b/src/lib/cls.c
index 7ada3d6..86d775d 100644
--- a/src/lib/cls.c
+++ b/src/lib/cls.c
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2010-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
@@ -23,8 +23,7 @@ struct rtnl_cls *nl_cli_cls_alloc(void)
{
struct rtnl_cls *cls;
- cls = rtnl_cls_alloc();
- if (!cls)
+ if (!(cls = rtnl_cls_alloc()))
nl_cli_fatal(ENOMEM, "Unable to allocate classifier object");
return cls;
@@ -43,11 +42,6 @@ struct nl_cache *nl_cli_cls_alloc_cache(struct nl_sock *sock, int ifindex,
return cache;
}
-void nl_cli_cls_parse_kind(struct rtnl_cls *cls, char *arg)
-{
- rtnl_cls_set_kind(cls, arg);
-}
-
void nl_cli_cls_parse_proto(struct rtnl_cls *cls, char *arg)
{
int proto;
@@ -74,59 +68,4 @@ struct rtnl_ematch_tree *nl_cli_cls_parse_ematch(struct rtnl_cls *cls, char *arg
return tree;
}
-static NL_LIST_HEAD(cls_modules);
-
-struct nl_cli_cls_module *__nl_cli_cls_lookup(struct rtnl_cls_ops *ops)
-{
- struct nl_cli_cls_module *cm;
-
- nl_list_for_each_entry(cm, &cls_modules, cm_list)
- if (cm->cm_ops == ops)
- return cm;
-
- return NULL;
-}
-
-struct nl_cli_cls_module *nl_cli_cls_lookup(struct rtnl_cls_ops *ops)
-{
- struct nl_cli_cls_module *cm;
-
- if ((cm = __nl_cli_cls_lookup(ops)))
- return cm;
-
- nl_cli_load_module("cli/cls", ops->co_kind);
-
- if (!(cm = __nl_cli_cls_lookup(ops))) {
- nl_cli_fatal(EINVAL, "Application bug: The shared library for "
- "the classifier \"%s\" was successfully loaded but it "
- "seems that module did not register itself");
- }
-
- return cm;
-}
-
-void nl_cli_cls_register(struct nl_cli_cls_module *cm)
-{
- struct rtnl_cls_ops *ops;
-
- if (!(ops = __rtnl_cls_lookup_ops(cm->cm_name))) {
- nl_cli_fatal(ENOENT, "Unable to register CLI classifier module "
- "\"%s\": No matching libnl cls module found.", cm->cm_name);
- }
-
- if (__nl_cli_cls_lookup(ops)) {
- nl_cli_fatal(EEXIST, "Unable to register CLI classifier module "
- "\"%s\": Module already registered.", cm->cm_name);
- }
-
- cm->cm_ops = ops;
-
- nl_list_add_tail(&cm->cm_list, &cls_modules);
-}
-
-void nl_cli_cls_unregister(struct nl_cli_cls_module *cm)
-{
- nl_list_del(&cm->cm_list);
-}
-
/** @} */
diff --git a/src/lib/qdisc.c b/src/lib/qdisc.c
index 4c64e7b..ccf7d26 100644
--- a/src/lib/qdisc.c
+++ b/src/lib/qdisc.c
@@ -6,7 +6,7 @@
* License as published by the Free Software Foundation version 2.1
* of the License.
*
- * Copyright (c) 2008-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2008-2011 Thomas Graf <tgraf@suug.ch>
*/
/**
@@ -18,107 +18,15 @@
#include <netlink/cli/utils.h>
#include <netlink/cli/qdisc.h>
#include <netlink/route/class.h>
-#include <netlink/route/class-modules.h>
struct rtnl_qdisc *nl_cli_qdisc_alloc(void)
{
struct rtnl_qdisc *qdisc;
- qdisc = rtnl_qdisc_alloc();
- if (!qdisc)
+ if (!(qdisc = rtnl_qdisc_alloc()))
nl_cli_fatal(ENOMEM, "Unable to allocate qdisc object");
return qdisc;
}
-void nl_cli_qdisc_parse_kind(struct rtnl_qdisc *qdisc, char *arg)
-{
- rtnl_qdisc_set_kind(qdisc, arg);
-}
-
-static NL_LIST_HEAD(qdisc_modules);
-
-struct nl_cli_qdisc_module *__nl_cli_qdisc_lookup(struct rtnl_qdisc_ops *ops)
-{
- struct nl_cli_qdisc_module *qm;
-
- nl_list_for_each_entry(qm, &qdisc_modules, qm_list)
- if (qm->qm_ops == ops)
- return qm;
-
- return NULL;
-}
-
-struct nl_cli_qdisc_module *__nl_cli_class_lookup(struct rtnl_class_ops *ops)
-{
- struct nl_cli_qdisc_module *qm;
-
- nl_list_for_each_entry(qm, &qdisc_modules, qm_list)
- if (qm->qm_class_ops == ops)
- return qm;
-
- return NULL;
-}
-
-struct nl_cli_qdisc_module *nl_cli_qdisc_lookup(struct rtnl_qdisc_ops *ops)
-{
- struct nl_cli_qdisc_module *qm;
-
- if ((qm = __nl_cli_qdisc_lookup(ops)))
- return qm;
-
- nl_cli_load_module("cli/qdisc", ops->qo_kind);
-
- if (!(qm = __nl_cli_qdisc_lookup(ops))) {
- nl_cli_fatal(EINVAL, "Application bug: The shared library for "
- "the qdisc \"%s\" was successfully loaded but it "
- "seems that module did not register itself");
- }
-
- return qm;
-}
-
-struct nl_cli_qdisc_module *nl_cli_qdisc_lookup_by_class(struct rtnl_class_ops *ops)
-{
- struct nl_cli_qdisc_module *qm;
-
- if ((qm = __nl_cli_class_lookup(ops)))
- return qm;
-
- nl_cli_load_module("cli/qdisc", ops->co_kind);
-
- if (!(qm = __nl_cli_class_lookup(ops))) {
- nl_cli_fatal(EINVAL, "Application bug: The shared library for "
- "the class \"%s\" was successfully loaded but it "
- "seems that module did not register itself");
- }
-
- return qm;
-}
-
-void nl_cli_qdisc_register(struct nl_cli_qdisc_module *qm)
-{
- struct rtnl_qdisc_ops *ops;
-
- if (!(ops = __rtnl_qdisc_lookup_ops(qm->qm_name))) {
- nl_cli_fatal(ENOENT, "Unable to register CLI qdisc module "
- "\"%s\": No matching libnl qdisc module found.", qm->qm_name);
- }
-
- if (__nl_cli_qdisc_lookup(ops)) {
- nl_cli_fatal(EEXIST, "Unable to register CLI qdisc module "
- "\"%s\": Module already registered.", qm->qm_name);
- }
-
- qm->qm_ops = ops;
- qm->qm_class_ops = __rtnl_class_lookup_ops(qm->qm_name);
-
- nl_list_add_tail(&qm->qm_list, &qdisc_modules);
-}
-
-void nl_cli_qdisc_unregister(struct nl_cli_qdisc_module *qm)
-{
- nl_list_del(&qm->qm_list);
-}
-
/** @} */
diff --git a/src/lib/tc.c b/src/lib/tc.c
index 72407cf..8d013f9 100644
--- a/src/lib/tc.c
+++ b/src/lib/tc.c
@@ -11,7 +11,7 @@
#include <netlink/cli/utils.h>
#include <netlink/cli/tc.h>
-#include <netlink/route/tc.h>
+#include <netlink/route/tc-api.h>
/**
* @ingroup cli
@@ -76,6 +76,11 @@ void nl_cli_tc_parse_overhead(struct rtnl_tc *tc, char *arg)
rtnl_tc_set_overhead(tc, nl_cli_parse_u32(arg));
}
+void nl_cli_tc_parse_kind(struct rtnl_tc *tc, char *arg)
+{
+ rtnl_tc_set_kind(tc, arg);
+}
+
void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg)
{
int type;
@@ -87,4 +92,74 @@ void nl_cli_tc_parse_linktype(struct rtnl_tc *tc, char *arg)
rtnl_tc_set_linktype(tc, type);
}
+static NL_LIST_HEAD(tc_modules);
+
+struct nl_cli_tc_module *__nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
+{
+ struct nl_cli_tc_module *tm;
+
+ nl_list_for_each_entry(tm, &tc_modules, tm_list)
+ if (tm->tm_ops == ops)
+ return tm;
+
+ return NULL;
+}
+
+struct nl_cli_tc_module *nl_cli_tc_lookup(struct rtnl_tc_ops *ops)
+{
+ struct nl_cli_tc_module *tm;
+
+ if ((tm = __nl_cli_tc_lookup(ops)))
+ return tm;
+
+ switch (ops->to_type) {
+ case RTNL_TC_TYPE_QDISC:
+ case RTNL_TC_TYPE_CLASS:
+ nl_cli_load_module("cli/qdisc", ops->to_kind);
+ break;
+
+ case RTNL_TC_TYPE_CLS:
+ nl_cli_load_module("cli/cls", ops->to_kind);
+ break;
+
+ default:
+ nl_cli_fatal(EINVAL, "BUG: unhandled TC object type %d",
+ ops->to_type);
+ }
+
+ if (!(tm = __nl_cli_tc_lookup(ops))) {
+ nl_cli_fatal(EINVAL, "Application bug: The shared library for "
+ "the tc object \"%s\" was successfully loaded but it "
+ "seems that module did not register itself",
+ ops->to_kind);
+ }
+
+ return tm;
+}
+
+void nl_cli_tc_register(struct nl_cli_tc_module *tm)
+{
+ struct rtnl_tc_ops *ops;
+
+ if (!(ops = rtnl_tc_lookup_ops(tm->tm_type, tm->tm_name))) {
+ nl_cli_fatal(ENOENT, "Unable to register CLI TC module "
+ "\"%s\": No matching libnl TC module found.", tm->tm_name);
+ }
+
+ if (__nl_cli_tc_lookup(ops)) {
+ nl_cli_fatal(EEXIST, "Unable to register CLI TC module "
+ "\"%s\": Module already registered.", tm->tm_name);
+ }
+
+ tm->tm_ops = ops;
+
+ nl_list_add_tail(&tm->tm_list, &tc_modules);
+}
+
+void nl_cli_tc_unregister(struct nl_cli_tc_module *tm)
+{
+ nl_list_del(&tm->tm_list);
+}
+
+
/** @} */
diff --git a/src/nl-class-add.c b/src/nl-class-add.c
index 80ea826..9698f0d 100644
--- a/src/nl-class-add.c
+++ b/src/nl-class-add.c
@@ -56,8 +56,8 @@ int main(int argc, char *argv[])
.dp_type = NL_DUMP_DETAILS,
.dp_fd = stdout,
};
- struct nl_cli_qdisc_module *qm;
- struct rtnl_class_ops *ops;
+ struct nl_cli_tc_module *tm;
+ struct rtnl_tc_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind, *id = NULL;
@@ -131,15 +131,15 @@ int main(int argc, char *argv[])
}
kind = argv[optind++];
- rtnl_class_set_kind(class, kind);
+ rtnl_tc_set_kind(tc, kind);
- if (!(ops = rtnl_class_lookup_ops(class)))
+ if (!(ops = rtnl_tc_get_ops(tc)))
nl_cli_fatal(ENOENT, "Unknown class \"%s\"", kind);
- if (!(qm = nl_cli_qdisc_lookup_by_class(ops)))
+ if (!(tm = nl_cli_tc_lookup(ops)))
nl_cli_fatal(ENOTSUP, "class type \"%s\" not supported.", kind);
- qm->qm_parse_class_argv(class, argc, argv);
+ tm->tm_parse_argv(tc, argc, argv);
if (!quiet) {
printf("Adding ");
diff --git a/src/nl-class-delete.c b/src/nl-class-delete.c
index 3c5cdc1..3df5a9a 100644
--- a/src/nl-class-delete.c
+++ b/src/nl-class-delete.c
@@ -110,7 +110,7 @@ int main(int argc, char *argv[])
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
- case 'k': nl_cli_class_parse_kind(class, optarg); break;
+ case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
}
}
diff --git a/src/nl-class-list.c b/src/nl-class-list.c
index fccc512..44ca49b 100644
--- a/src/nl-class-list.c
+++ b/src/nl-class-list.c
@@ -104,7 +104,7 @@ int main(int argc, char *argv[])
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
- case 'k': nl_cli_class_parse_kind(class, optarg); break;
+ case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
}
}
diff --git a/src/nl-cls-add.c b/src/nl-cls-add.c
index fad9313..054bab3 100644
--- a/src/nl-cls-add.c
+++ b/src/nl-cls-add.c
@@ -5,7 +5,7 @@
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation version 2 of the License.
*
- * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
#include <netlink/cli/utils.h>
@@ -56,8 +56,8 @@ int main(int argc, char *argv[])
.dp_type = NL_DUMP_DETAILS,
.dp_fd = stdout,
};
- struct nl_cli_cls_module *cm;
- struct rtnl_cls_ops *ops;
+ struct nl_cli_tc_module *tm;
+ struct rtnl_tc_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind, *id = NULL;
@@ -139,16 +139,15 @@ int main(int argc, char *argv[])
}
kind = argv[optind++];
- rtnl_cls_set_kind(cls, kind);
+ rtnl_tc_set_kind(tc, kind);
- if (!(ops = rtnl_cls_lookup_ops(cls)))
+ if (!(ops = rtnl_tc_get_ops(tc)))
nl_cli_fatal(ENOENT, "Unknown classifier \"%s\".", kind);
- if (!(cm = nl_cli_cls_lookup(ops)))
+ if (!(tm = nl_cli_tc_lookup(ops)))
nl_cli_fatal(ENOTSUP, "Classifier type \"%s\" not supported.", kind);
- if ((err = cm->cm_parse_argv(cls, argc, argv)) < 0)
- nl_cli_fatal(err, "Unable to parse classifier options");
+ tm->tm_parse_argv(tc, argc, argv);
if (!quiet) {
printf("Adding ");
diff --git a/src/nl-cls-delete.c b/src/nl-cls-delete.c
index 359d15e..7d998fd 100644
--- a/src/nl-cls-delete.c
+++ b/src/nl-cls-delete.c
@@ -135,7 +135,7 @@ int main(int argc, char *argv[])
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
- case 'k': nl_cli_cls_parse_kind(cls, optarg); break;
+ case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break;
case ARG_PRIO:
rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg));
diff --git a/src/nl-cls-list.c b/src/nl-cls-list.c
index e7c9a12..fcb5dcb 100644
--- a/src/nl-cls-list.c
+++ b/src/nl-cls-list.c
@@ -112,7 +112,7 @@ int main(int argc, char *argv[])
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
- case 'k': nl_cli_cls_parse_kind(cls, optarg); break;
+ case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
case ARG_PROTO: nl_cli_cls_parse_proto(cls, optarg); break;
case ARG_PRIO:
rtnl_cls_set_prio(cls, nl_cli_parse_u32(optarg));
diff --git a/src/nl-qdisc-add.c b/src/nl-qdisc-add.c
index 9da0f18..dd2ed2b 100644
--- a/src/nl-qdisc-add.c
+++ b/src/nl-qdisc-add.c
@@ -53,8 +53,8 @@ int main(int argc, char *argv[])
.dp_type = NL_DUMP_DETAILS,
.dp_fd = stdout,
};
- struct nl_cli_qdisc_module *qm;
- struct rtnl_qdisc_ops *ops;
+ struct nl_cli_tc_module *tm;
+ struct rtnl_tc_ops *ops;
int err, flags = NLM_F_CREATE | NLM_F_EXCL;
char *kind, *id = NULL;
@@ -122,15 +122,15 @@ int main(int argc, char *argv[])
}
kind = argv[optind++];
- rtnl_qdisc_set_kind(qdisc, kind);
+ rtnl_tc_set_kind(tc, kind);
- if (!(ops = rtnl_qdisc_lookup_ops(qdisc)))
+ if (!(ops = rtnl_tc_get_ops(tc)))
nl_cli_fatal(ENOENT, "Unknown qdisc \"%s\"", kind);
- if (!(qm = nl_cli_qdisc_lookup(ops)))
+ if (!(tm = nl_cli_tc_lookup(ops)))
nl_cli_fatal(ENOTSUP, "Qdisc type \"%s\" not supported.", kind);
- qm->qm_parse_qdisc_argv(qdisc, argc, argv);
+ tm->tm_parse_argv(tc, argc, argv);
if (!quiet) {
printf("Adding ");
diff --git a/src/nl-qdisc-delete.c b/src/nl-qdisc-delete.c
index b230063..9c7ec14 100644
--- a/src/nl-qdisc-delete.c
+++ b/src/nl-qdisc-delete.c
@@ -123,7 +123,7 @@ int main(int argc, char *argv[])
break;
case 'k':
nfilter++;
- nl_cli_qdisc_parse_kind(qdisc, optarg);
+ nl_cli_tc_parse_kind(tc, optarg);
break;
}
}
diff --git a/src/nl-qdisc-list.c b/src/nl-qdisc-list.c
index 670fa3d..5b0a3f0 100644
--- a/src/nl-qdisc-list.c
+++ b/src/nl-qdisc-list.c
@@ -170,7 +170,7 @@ int main(int argc, char *argv[])
case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break;
case 'p': nl_cli_tc_parse_parent(tc, optarg); break;
case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break;
- case 'k': nl_cli_qdisc_parse_kind(qdisc, optarg); break;
+ case 'k': nl_cli_tc_parse_kind(tc, optarg); break;
}
}