summaryrefslogtreecommitdiff
path: root/lib/route
diff options
context:
space:
mode:
Diffstat (limited to 'lib/route')
-rw-r--r--lib/route/act.c109
-rw-r--r--lib/route/act/gact.c15
-rw-r--r--lib/route/act/mirred.c15
-rw-r--r--lib/route/act/nat.c11
-rw-r--r--lib/route/act/skbedit.c20
-rw-r--r--lib/route/act/vlan.c21
-rw-r--r--lib/route/addr.c102
-rw-r--r--lib/route/class.c16
-rw-r--r--lib/route/classid.c14
-rw-r--r--lib/route/cls.c22
-rw-r--r--lib/route/cls/basic.c18
-rw-r--r--lib/route/cls/cgroup.c16
-rw-r--r--lib/route/cls/ematch.c10
-rw-r--r--lib/route/cls/ematch/cmp.c9
-rw-r--r--lib/route/cls/ematch/container.c8
-rw-r--r--lib/route/cls/ematch/meta.c11
-rw-r--r--lib/route/cls/ematch/nbyte.c9
-rw-r--r--lib/route/cls/ematch/text.c10
-rw-r--r--lib/route/cls/ematch_grammar.l8
-rw-r--r--lib/route/cls/ematch_syntax.y22
-rw-r--r--lib/route/cls/flower.c41
-rw-r--r--lib/route/cls/fw.c20
-rw-r--r--lib/route/cls/mall.c28
-rw-r--r--lib/route/cls/police.c7
-rw-r--r--lib/route/cls/u32.c32
-rw-r--r--lib/route/link-sriov.h20
-rw-r--r--lib/route/link.c82
-rw-r--r--lib/route/link/api.c11
-rw-r--r--lib/route/link/bonding.c188
-rw-r--r--lib/route/link/bridge.c42
-rw-r--r--lib/route/link/bridge_info.c306
-rw-r--r--lib/route/link/can.c72
-rw-r--r--lib/route/link/dummy.c10
-rw-r--r--lib/route/link/geneve.c10
-rw-r--r--lib/route/link/ifb.c10
-rw-r--r--lib/route/link/inet.c14
-rw-r--r--lib/route/link/inet6.c64
-rw-r--r--lib/route/link/ip6gre.c14
-rw-r--r--lib/route/link/ip6tnl.c15
-rw-r--r--lib/route/link/ip6vti.c14
-rw-r--r--lib/route/link/ipgre.c14
-rw-r--r--lib/route/link/ipip.c14
-rw-r--r--lib/route/link/ipvlan.c13
-rw-r--r--lib/route/link/ipvti.c14
-rw-r--r--lib/route/link/link-api.h191
-rw-r--r--lib/route/link/macsec.c62
-rw-r--r--lib/route/link/macvlan.c15
-rw-r--r--lib/route/link/ppp.c12
-rw-r--r--lib/route/link/sit.c14
-rw-r--r--lib/route/link/sriov.c31
-rw-r--r--lib/route/link/team.c10
-rw-r--r--lib/route/link/veth.c15
-rw-r--r--lib/route/link/vlan.c30
-rw-r--r--lib/route/link/vrf.c15
-rw-r--r--lib/route/link/vxlan.c79
-rw-r--r--lib/route/link/xfrmi.c15
-rw-r--r--lib/route/mdb.c39
-rw-r--r--lib/route/neigh.c103
-rw-r--r--lib/route/neightbl.c156
-rw-r--r--lib/route/netconf.c45
-rw-r--r--lib/route/nexthop-encap.h35
-rw-r--r--lib/route/nexthop.c45
-rw-r--r--lib/route/nexthop_encap.c8
-rw-r--r--lib/route/nh.c590
-rw-r--r--lib/route/nh_encap_mpls.c11
-rw-r--r--lib/route/nl-route.h191
-rw-r--r--lib/route/pktloc.c10
-rw-r--r--lib/route/pktloc_grammar.l6
-rw-r--r--lib/route/pktloc_syntax.y4
-rw-r--r--lib/route/qdisc.c11
-rw-r--r--lib/route/qdisc/blackhole.c10
-rw-r--r--lib/route/qdisc/cbq.c20
-rw-r--r--lib/route/qdisc/dsmark.c24
-rw-r--r--lib/route/qdisc/fifo.c16
-rw-r--r--lib/route/qdisc/fq_codel.c21
-rw-r--r--lib/route/qdisc/hfsc.c23
-rw-r--r--lib/route/qdisc/htb.c29
-rw-r--r--lib/route/qdisc/ingress.c11
-rw-r--r--lib/route/qdisc/mqprio.c24
-rw-r--r--lib/route/qdisc/netem.c49
-rw-r--r--lib/route/qdisc/plug.c16
-rw-r--r--lib/route/qdisc/prio.c17
-rw-r--r--lib/route/qdisc/red.c22
-rw-r--r--lib/route/qdisc/sfq.c20
-rw-r--r--lib/route/qdisc/tbf.c22
-rw-r--r--lib/route/route.c13
-rw-r--r--lib/route/route_obj.c109
-rw-r--r--lib/route/route_utils.c15
-rw-r--r--lib/route/rtnl.c5
-rw-r--r--lib/route/rule.c75
-rw-r--r--lib/route/tc-api.h104
-rw-r--r--lib/route/tc.c61
92 files changed, 3247 insertions, 723 deletions
diff --git a/lib/route/act.c b/lib/route/act.c
index f7c0a78e..670810fa 100644
--- a/lib/route/act.c
+++ b/lib/route/act.c
@@ -9,15 +9,20 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/gen_stats.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/link.h>
#include <netlink/route/action.h>
+#include "nl-route.h"
+#include "tc-api.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-route/nl-route.h"
static struct nl_object_ops act_obj_ops;
static struct nl_cache_ops rtnl_act_ops;
@@ -293,7 +298,7 @@ int rtnl_act_build_change_request(struct rtnl_act *act, int flags,
* sends the request to the kernel and waits for the next ACK to be
* received and thus blocks until the request has been processed.
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_act_change(struct nl_sock *sk, struct rtnl_act *act, int flags)
{
@@ -387,9 +392,16 @@ void rtnl_act_put_all(struct rtnl_act **head)
*head = NULL;
}
+static struct nla_policy tc_act_stats_policy[TCA_STATS_MAX+1] = {
+ [TCA_STATS_BASIC] = { .minlen = sizeof(struct gnet_stats_basic) },
+ [TCA_STATS_QUEUE] = { .minlen = sizeof(struct gnet_stats_queue) },
+ [TCA_STATS_RATE_EST] = { .minlen = sizeof(struct gnet_stats_rate_est) },
+ [TCA_STATS_RATE_EST64] = { .minlen = sizeof(struct gnet_stats_rate_est64) },
+};
+
int rtnl_act_parse(struct rtnl_act **head, struct nlattr *tb)
{
- struct rtnl_act *act;
+ _nl_auto_rtnl_act_all struct rtnl_act *tmp_head = NULL;
struct rtnl_tc_ops *ops;
struct nlattr *tb2[TCA_ACT_MAX + 1];
struct nlattr *nla[TCA_ACT_MAX_PRIO + 1];
@@ -402,63 +414,92 @@ int rtnl_act_parse(struct rtnl_act **head, struct nlattr *tb)
return err;
for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
+ _nl_auto_rtnl_act struct rtnl_act *act = NULL;
struct rtnl_tc *tc;
if (nla[i] == NULL)
continue;
act = rtnl_act_alloc();
- if (!act) {
- err = -NLE_NOMEM;
- goto err_free;
- }
+ if (!act)
+ return -NLE_NOMEM;
+
tc = TC_CAST(act);
err = nla_parse(tb2, TCA_ACT_MAX, nla_data(nla[i]),
nla_len(nla[i]), NULL);
if (err < 0)
- goto err_free;
+ return err;
- if (tb2[TCA_ACT_KIND] == NULL) {
- err = -NLE_MISSING_ATTR;
- goto err_free;
- }
+ if (tb2[TCA_ACT_KIND] == NULL)
+ return -NLE_MISSING_ATTR;
nla_strlcpy(kind, tb2[TCA_ACT_KIND], sizeof(kind));
rtnl_tc_set_kind(tc, kind);
if (tb2[TCA_ACT_OPTIONS]) {
tc->tc_opts = nl_data_alloc_attr(tb2[TCA_ACT_OPTIONS]);
- if (!tc->tc_opts) {
- err = -NLE_NOMEM;
- goto err_free;
- }
+ if (!tc->tc_opts)
+ return -NLE_NOMEM;
tc->ce_mask |= TCA_ATTR_OPTS;
}
+ if (tb2[TCA_ACT_STATS]) {
+ struct nlattr *tb3[TCA_STATS_MAX + 1];
+
+ err = nla_parse_nested(tb3, TCA_STATS_MAX, tb2[TCA_ACT_STATS],
+ tc_act_stats_policy);
+ if (err < 0)
+ return err;
+
+ if (tb3[TCA_STATS_BASIC]) {
+ struct gnet_stats_basic bs;
+
+ memcpy(&bs, nla_data(tb3[TCA_STATS_BASIC]),
+ sizeof(bs));
+ tc->tc_stats[RTNL_TC_BYTES] = bs.bytes;
+ tc->tc_stats[RTNL_TC_PACKETS] = bs.packets;
+ }
+ if (tb3[TCA_STATS_RATE_EST64]) {
+ struct gnet_stats_rate_est64 re;
+
+ memcpy(&re, nla_data(tb3[TCA_STATS_RATE_EST64]),
+ sizeof(re));
+ tc->tc_stats[RTNL_TC_RATE_BPS] = re.bps;
+ tc->tc_stats[RTNL_TC_RATE_PPS] = re.pps;
+ } else if (tb3[TCA_STATS_RATE_EST]) {
+ struct gnet_stats_rate_est *re;
+
+ re = nla_data(tb3[TCA_STATS_RATE_EST]);
+ tc->tc_stats[RTNL_TC_RATE_BPS] = re->bps;
+ tc->tc_stats[RTNL_TC_RATE_PPS] = re->pps;
+ }
+ if (tb3[TCA_STATS_QUEUE]) {
+ struct gnet_stats_queue *q;
+
+ q = nla_data(tb3[TCA_STATS_QUEUE]);
+ tc->tc_stats[RTNL_TC_DROPS] = q->drops;
+ tc->tc_stats[RTNL_TC_OVERLIMITS] = q->overlimits;
+ }
+ }
+
ops = rtnl_tc_get_ops(tc);
if (ops && ops->to_msg_parser) {
void *data = rtnl_tc_data(tc);
- if (!data) {
- err = -NLE_NOMEM;
- goto err_free;
- }
+ if (!data)
+ return -NLE_NOMEM;
err = ops->to_msg_parser(tc, data);
if (err < 0)
- goto err_free;
+ return err;
}
- err = rtnl_act_append(head, act);
+ err = _rtnl_act_append_take(&tmp_head, _nl_steal_pointer(&act));
if (err < 0)
- goto err_free;
+ return err;
}
- return 0;
-err_free:
- rtnl_act_put (act);
- rtnl_act_put_all(head);
-
- return err;
+ *head = _nl_steal_pointer(&tmp_head);
+ return 0;
}
static int rtnl_act_msg_parse(struct nlmsghdr *n, struct rtnl_act **act)
@@ -575,13 +616,13 @@ static struct nl_object_ops act_obj_ops = {
.oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
};
-static void __init act_init(void)
+static void _nl_init act_init(void)
{
rtnl_tc_type_register(&act_ops);
nl_cache_mngt_register(&rtnl_act_ops);
}
-static void __exit act_exit(void)
+static void _nl_exit act_exit(void)
{
nl_cache_mngt_unregister(&rtnl_act_ops);
rtnl_tc_type_unregister(&act_ops);
diff --git a/lib/route/act/gact.c b/lib/route/act/gact.c
index 1a4bacb5..2e04c5a3 100644
--- a/lib/route/act/gact.c
+++ b/lib/route/act/gact.c
@@ -10,14 +10,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/act/gact.h>
+#include "tc-api.h"
+
+struct rtnl_gact {
+ struct tc_gact g_parm;
+};
+
static struct nla_policy gact_policy[TCA_GACT_MAX + 1] = {
[TCA_GACT_PARMS] = { .minlen = sizeof(struct tc_gact) },
};
@@ -144,12 +149,12 @@ static struct rtnl_tc_ops gact_ops = {
},
};
-static void __init gact_init(void)
+static void _nl_init gact_init(void)
{
rtnl_tc_register(&gact_ops);
}
-static void __exit gact_exit(void)
+static void _nl_exit gact_exit(void)
{
rtnl_tc_unregister(&gact_ops);
}
diff --git a/lib/route/act/mirred.c b/lib/route/act/mirred.c
index 01da1346..72ead6b0 100644
--- a/lib/route/act/mirred.c
+++ b/lib/route/act/mirred.c
@@ -10,14 +10,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/act/mirred.h>
+#include "tc-api.h"
+
+struct rtnl_mirred {
+ struct tc_mirred m_parm;
+};
+
static struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
[TCA_MIRRED_PARMS] = { .minlen = sizeof(struct tc_mirred) },
};
@@ -204,12 +209,12 @@ static struct rtnl_tc_ops mirred_ops = {
},
};
-static void __init mirred_init(void)
+static void _nl_init mirred_init(void)
{
rtnl_tc_register(&mirred_ops);
}
-static void __exit mirred_exit(void)
+static void _nl_exit mirred_exit(void)
{
rtnl_tc_unregister(&mirred_ops);
}
diff --git a/lib/route/act/nat.c b/lib/route/act/nat.c
index 21c42476..ffc9d2be 100644
--- a/lib/route/act/nat.c
+++ b/lib/route/act/nat.c
@@ -10,15 +10,16 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/act/nat.h>
#include <netlink/route/tc.h>
+#include "tc-api.h"
+
static struct nla_policy nat_policy[TCA_NAT_MAX + 1] = {
[TCA_NAT_PARMS] = { .minlen = sizeof(struct tc_nat) },
};
@@ -273,12 +274,12 @@ static struct rtnl_tc_ops nat_ops = {
},
};
-static void __init nat_init(void)
+static void _nl_init nat_init(void)
{
rtnl_tc_register(&nat_ops);
}
-static void __exit nat_exit(void)
+static void _nl_exit nat_exit(void)
{
rtnl_tc_unregister(&nat_ops);
}
diff --git a/lib/route/act/skbedit.c b/lib/route/act/skbedit.c
index 24f57e56..32a3506f 100644
--- a/lib/route/act/skbedit.c
+++ b/lib/route/act/skbedit.c
@@ -10,14 +10,24 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/act/skbedit.h>
+#include "nl-route.h"
+#include "tc-api.h"
+
+struct rtnl_skbedit {
+ struct tc_skbedit s_parm;
+ uint32_t s_flags;
+ uint32_t s_mark;
+ uint32_t s_prio;
+ uint16_t s_queue_mapping;
+};
+
static struct nla_policy skbedit_policy[TCA_SKBEDIT_MAX + 1] = {
[TCA_SKBEDIT_PARMS] = { .minlen = sizeof(struct tc_skbedit) },
[TCA_SKBEDIT_PRIORITY] = { .type = NLA_U32 },
@@ -261,12 +271,12 @@ static struct rtnl_tc_ops skbedit_ops = {
},
};
-static void __init skbedit_init(void)
+static void _nl_init skbedit_init(void)
{
rtnl_tc_register(&skbedit_ops);
}
-static void __exit skbedit_exit(void)
+static void _nl_exit skbedit_exit(void)
{
rtnl_tc_unregister(&skbedit_ops);
}
diff --git a/lib/route/act/vlan.c b/lib/route/act/vlan.c
index 3d9fc334..71f16e52 100644
--- a/lib/route/act/vlan.c
+++ b/lib/route/act/vlan.c
@@ -10,14 +10,25 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_act/tc_vlan.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/act/vlan.h>
+#include "tc-api.h"
+
+struct rtnl_vlan
+{
+ struct tc_vlan v_parm;
+ uint16_t v_vid;
+ uint16_t v_proto;
+ uint8_t v_prio;
+ uint32_t v_flags;
+};
#define VLAN_F_VID (1 << 0)
#define VLAN_F_PROTO (1 << 1)
@@ -399,12 +410,12 @@ static struct rtnl_tc_ops vlan_ops = {
},
};
-static void __init vlan_init(void)
+static void _nl_init vlan_init(void)
{
rtnl_tc_register(&vlan_ops);
}
-static void __exit vlan_exit(void)
+static void _nl_exit vlan_exit(void)
{
rtnl_tc_unregister(&vlan_ops);
}
diff --git a/lib/route/addr.c b/lib/route/addr.c
index 28734499..1f72c535 100644
--- a/lib/route/addr.c
+++ b/lib/route/addr.c
@@ -100,7 +100,8 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/addr.h>
@@ -108,7 +109,47 @@
#include <netlink/route/link.h>
#include <netlink/utils.h>
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
/** @cond SKIP */
+struct rtnl_addr_cacheinfo {
+ /* Preferred lifetime in seconds, ticking from when the message gets constructed */
+ uint32_t aci_prefered;
+
+ /* Valid lifetime in seconds, ticking from when the message gets constructed */
+ uint32_t aci_valid;
+
+ /* Timestamp of creation in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
+ uint32_t aci_cstamp;
+
+ /* Timestamp of last update in 1/100s since boottime, clock_gettime(CLOCK_MONOTONIC) */
+ uint32_t aci_tstamp;
+};
+
+struct rtnl_addr {
+ NLHDR_COMMON
+
+ uint8_t a_family;
+ uint8_t a_prefixlen;
+ uint8_t a_scope;
+ uint32_t a_flags;
+ uint32_t a_ifindex;
+
+ struct nl_addr *a_peer;
+ struct nl_addr *a_local;
+ struct nl_addr *a_bcast;
+ struct nl_addr *a_anycast;
+ struct nl_addr *a_multicast;
+
+ struct rtnl_addr_cacheinfo a_cacheinfo;
+
+ char a_label[IFNAMSIZ];
+ uint32_t a_flag_mask;
+ struct rtnl_link *a_link;
+};
+
#define ADDR_ATTR_FAMILY 0x0001
#define ADDR_ATTR_PREFIXLEN 0x0002
#define ADDR_ATTR_FLAGS 0x0004
@@ -493,41 +534,40 @@ static uint64_t addr_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_addr *b = (struct rtnl_addr *) _b;
uint64_t diff = 0;
-#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR)
-
- diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex);
- diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family);
- diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope);
- diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label));
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(ADDR_ATTR_IFINDEX, a->a_ifindex != b->a_ifindex);
+ diff |= _DIFF(ADDR_ATTR_FAMILY, a->a_family != b->a_family);
+ diff |= _DIFF(ADDR_ATTR_SCOPE, a->a_scope != b->a_scope);
+ diff |= _DIFF(ADDR_ATTR_LABEL, strcmp(a->a_label, b->a_label));
if (attrs & ADDR_ATTR_PEER) {
- if ( (flags & ID_COMPARISON)
- && a->a_family == AF_INET
- && b->a_family == AF_INET
- && a->a_peer
- && b->a_peer
- && a->a_prefixlen == b->a_prefixlen) {
+ if ((flags & ID_COMPARISON) && a->a_family == AF_INET &&
+ b->a_family == AF_INET && a->a_peer && b->a_peer &&
+ a->a_prefixlen == b->a_prefixlen) {
/* when comparing two IPv4 addresses for id-equality, the network part
* of the PEER address shall be compared.
*/
- diff |= ADDR_DIFF(PEER, nl_addr_cmp_prefix(a->a_peer, b->a_peer));
+ diff |= _DIFF(ADDR_ATTR_PEER,
+ nl_addr_cmp_prefix(a->a_peer, b->a_peer));
} else
- diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer));
+ diff |= _DIFF(ADDR_ATTR_PEER,
+ nl_addr_cmp(a->a_peer, b->a_peer));
}
- diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local));
- diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast,
- b->a_multicast));
- diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
- diff |= ADDR_DIFF(ANYCAST, nl_addr_cmp(a->a_anycast, b->a_anycast));
- diff |= ADDR_DIFF(CACHEINFO, memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
- sizeof (a->a_cacheinfo)));
+ diff |= _DIFF(ADDR_ATTR_LOCAL, nl_addr_cmp(a->a_local, b->a_local));
+ diff |= _DIFF(ADDR_ATTR_MULTICAST,
+ nl_addr_cmp(a->a_multicast, b->a_multicast));
+ diff |= _DIFF(ADDR_ATTR_BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast));
+ diff |= _DIFF(ADDR_ATTR_ANYCAST,
+ nl_addr_cmp(a->a_anycast, b->a_anycast));
+ diff |= _DIFF(ADDR_ATTR_CACHEINFO,
+ memcmp(&a->a_cacheinfo, &b->a_cacheinfo,
+ sizeof(a->a_cacheinfo)));
if (flags & LOOSE_COMPARISON)
- diff |= ADDR_DIFF(FLAGS,
- (a->a_flags ^ b->a_flags) & b->a_flag_mask);
+ diff |= _DIFF(ADDR_ATTR_FLAGS,
+ (a->a_flags ^ b->a_flags) & b->a_flag_mask);
else
- diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags);
-
-#undef ADDR_DIFF
+ diff |= _DIFF(ADDR_ATTR_FLAGS, a->a_flags != b->a_flags);
+#undef _DIFF
return diff;
}
@@ -743,7 +783,7 @@ int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags,
*
* @see rtnl_addr_build_add_request()
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
{
@@ -815,7 +855,7 @@ int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags,
*
* @see rtnl_addr_build_delete_request();
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags)
{
@@ -1198,12 +1238,12 @@ static struct nl_cache_ops rtnl_addr_ops = {
.co_obj_ops = &addr_obj_ops,
};
-static void __init addr_init(void)
+static void _nl_init addr_init(void)
{
nl_cache_mngt_register(&rtnl_addr_ops);
}
-static void __exit addr_exit(void)
+static void _nl_exit addr_exit(void)
{
nl_cache_mngt_unregister(&rtnl_addr_ops);
}
diff --git a/lib/route/class.c b/lib/route/class.c
index 76cfac99..29ba8094 100644
--- a/lib/route/class.c
+++ b/lib/route/class.c
@@ -9,15 +9,21 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/class.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/classifier.h>
#include <netlink/utils.h>
+#include "nl-route.h"
+#include "tc-api.h"
+
+struct rtnl_class {
+ NL_TC_GENERIC(c);
+};
+
static struct nl_cache_ops rtnl_class_ops;
static struct nl_object_ops class_obj_ops;
@@ -485,13 +491,13 @@ static struct nl_cache_ops rtnl_class_ops = {
.co_obj_ops = &class_obj_ops,
};
-static void __init class_init(void)
+static void _nl_init class_init(void)
{
rtnl_tc_type_register(&class_ops);
nl_cache_mngt_register(&rtnl_class_ops);
}
-static void __exit class_exit(void)
+static void _nl_exit class_exit(void)
{
nl_cache_mngt_unregister(&rtnl_class_ops);
rtnl_tc_type_unregister(&class_ops);
diff --git a/lib/route/classid.c b/lib/route/classid.c
index 350962ac..f5a75f07 100644
--- a/lib/route/classid.c
+++ b/lib/route/classid.c
@@ -9,12 +9,18 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <sys/stat.h>
+#include <search.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/tc.h>
+#include "nl-route.h"
+#include "nl-aux-core/nl-core.h"
+
struct classid_map
{
uint32_t classid;
@@ -427,7 +433,7 @@ errout:
/** @} */
-static void __init classid_init(void)
+static void _nl_init classid_init(void)
{
int err, i;
@@ -444,7 +450,7 @@ static void free_map(void *map)
free(map);
}
-static void __exit classid_exit(void)
+static void _nl_exit classid_exit(void)
{
tdestroy(id_root, free_map);
}
diff --git a/lib/route/cls.c b/lib/route/cls.c
index 8583103b..8f970b12 100644
--- a/lib/route/cls.c
+++ b/lib/route/cls.c
@@ -9,15 +9,25 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/ethtool.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/link.h>
+#include "nl-route.h"
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_cls {
+ NL_TC_GENERIC(c);
+ uint16_t c_prio;
+ uint16_t c_protocol;
+};
+
#define CLS_ATTR_PRIO (TCA_ATTR_MAX << 1)
#define CLS_ATTR_PROTOCOL (TCA_ATTR_MAX << 2)
/** @endcond */
@@ -215,7 +225,7 @@ int rtnl_cls_build_change_request(struct rtnl_cls *cls, int flags,
* sends the request to the kernel and waits for the next ACK to be
* received and thus blocks until the request has been processed.
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_cls_change(struct nl_sock *sk, struct rtnl_cls *cls, int flags)
{
@@ -516,13 +526,13 @@ static struct nl_object_ops cls_obj_ops = {
.oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
};
-static void __init cls_init(void)
+static void _nl_init cls_init(void)
{
rtnl_tc_type_register(&cls_ops);
nl_cache_mngt_register(&rtnl_cls_ops);
}
-static void __exit cls_exit(void)
+static void _nl_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 93bf75d3..dc19256b 100644
--- a/lib/route/cls/basic.c
+++ b/lib/route/cls/basic.c
@@ -16,15 +16,17 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/action.h>
#include <netlink/route/cls/basic.h>
#include <netlink/route/cls/ematch.h>
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
+
struct rtnl_basic
{
uint32_t b_target;
@@ -222,12 +224,10 @@ int rtnl_basic_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
if (!(b = rtnl_tc_data(TC_CAST(cls))))
return -NLE_NOMEM;
- b->b_mask |= BASIC_ATTR_ACTION;
- if ((err = rtnl_act_append(&b->b_act, act)))
+ if ((err = _rtnl_act_append_get(&b->b_act, act)) < 0)
return err;
- /* In case user frees it */
- rtnl_act_get(act);
+ b->b_mask |= BASIC_ATTR_ACTION;
return 0;
}
@@ -282,12 +282,12 @@ static struct rtnl_tc_ops basic_ops = {
},
};
-static void __init basic_init(void)
+static void _nl_init basic_init(void)
{
rtnl_tc_register(&basic_ops);
}
-static void __exit basic_exit(void)
+static void _nl_exit basic_exit(void)
{
rtnl_tc_unregister(&basic_ops);
}
diff --git a/lib/route/cls/cgroup.c b/lib/route/cls/cgroup.c
index ff993d18..3534281a 100644
--- a/lib/route/cls/cgroup.c
+++ b/lib/route/cls/cgroup.c
@@ -10,17 +10,23 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/cgroup.h>
#include <netlink/route/cls/ematch.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_cgroup {
+ struct rtnl_ematch_tree *cg_ematch;
+ int cg_mask;
+};
+
#define CGROUP_ATTR_EMATCH 0x001
/** @endcond */
@@ -180,12 +186,12 @@ static struct rtnl_tc_ops cgroup_ops = {
},
};
-static void __init cgroup_init(void)
+static void _nl_init cgroup_init(void)
{
rtnl_tc_register(&cgroup_ops);
}
-static void __exit cgroup_exit(void)
+static void _nl_exit cgroup_exit(void)
{
rtnl_tc_unregister(&cgroup_ops);
}
diff --git a/lib/route/cls/ematch.c b/lib/route/cls/ematch.c
index 90520302..5a5a2104 100644
--- a/lib/route/cls/ematch.c
+++ b/lib/route/cls/ematch.c
@@ -10,13 +10,17 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
#include <netlink/netlink.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/cmp.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
+
+#include "nl-route.h"
+#include "nl-aux-core/nl-core.h"
#include "ematch_syntax.h"
#include "ematch_grammar.h"
diff --git a/lib/route/cls/ematch/cmp.c b/lib/route/cls/ematch/cmp.c
index f5758669..9feb2e58 100644
--- a/lib/route/cls/ematch/cmp.c
+++ b/lib/route/cls/ematch/cmp.c
@@ -10,12 +10,13 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/cmp.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
void rtnl_ematch_cmp_set(struct rtnl_ematch *e, struct tcf_em_cmp *cfg)
{
@@ -80,7 +81,7 @@ static struct rtnl_ematch_ops cmp_ops = {
.eo_dump = cmp_dump,
};
-static void __init cmp_init(void)
+static void _nl_init cmp_init(void)
{
rtnl_ematch_register(&cmp_ops);
}
diff --git a/lib/route/cls/ematch/container.c b/lib/route/cls/ematch/container.c
index b23169bb..ea2d1666 100644
--- a/lib/route/cls/ematch/container.c
+++ b/lib/route/cls/ematch/container.c
@@ -3,11 +3,13 @@
* Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
+#include "nl-route.h"
+
static int container_parse(struct rtnl_ematch *e, void *data, size_t len __attribute__((unused)))
{
/*
@@ -35,7 +37,7 @@ static struct rtnl_ematch_ops container_ops = {
.eo_fill = container_fill,
};
-static void __init container_init(void)
+static void _nl_init container_init(void)
{
rtnl_ematch_register(&container_ops);
}
diff --git a/lib/route/cls/ematch/meta.c b/lib/route/cls/ematch/meta.c
index 3f63cdea..2c884dc3 100644
--- a/lib/route/cls/ematch/meta.c
+++ b/lib/route/cls/ematch/meta.c
@@ -10,12 +10,15 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_meta.h>
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/meta.h>
-#include <linux/tc_ematch/tc_em_meta.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
struct rtnl_meta_value
{
@@ -322,7 +325,7 @@ static struct rtnl_ematch_ops meta_ops = {
.eo_free = meta_free,
};
-static void __init meta_init(void)
+static void _nl_init meta_init(void)
{
rtnl_ematch_register(&meta_ops);
}
diff --git a/lib/route/cls/ematch/nbyte.c b/lib/route/cls/ematch/nbyte.c
index 735dfc86..d0ab84ba 100644
--- a/lib/route/cls/ematch/nbyte.c
+++ b/lib/route/cls/ematch/nbyte.c
@@ -10,12 +10,13 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_nbyte.h>
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/nbyte.h>
-#include <linux/tc_ematch/tc_em_nbyte.h>
struct nbyte_data
{
@@ -126,7 +127,7 @@ static struct rtnl_ematch_ops nbyte_ops = {
.eo_free = nbyte_free,
};
-static void __init nbyte_init(void)
+static void _nl_init nbyte_init(void)
{
rtnl_ematch_register(&nbyte_ops);
}
diff --git a/lib/route/cls/ematch/text.c b/lib/route/cls/ematch/text.c
index b5248332..d7a233f8 100644
--- a/lib/route/cls/ematch/text.c
+++ b/lib/route/cls/ematch/text.c
@@ -10,13 +10,13 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/tc_ematch/tc_em_text.h>
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/text.h>
-#include <linux/tc_ematch/tc_em_text.h>
struct text_data
{
@@ -171,7 +171,7 @@ static struct rtnl_ematch_ops text_ops = {
.eo_free = text_free,
};
-static void __init text_init(void)
+static void _nl_init text_init(void)
{
rtnl_ematch_register(&text_ops);
}
diff --git a/lib/route/cls/ematch_grammar.l b/lib/route/cls/ematch_grammar.l
index 4f57951e..1035079c 100644
--- a/lib/route/cls/ematch_grammar.l
+++ b/lib/route/cls/ematch_grammar.l
@@ -4,12 +4,14 @@
*/
%{
- #include <netlink-private/netlink.h>
- #include <netlink-private/tc.h>
+ #include <linux/tc_ematch/tc_em_cmp.h>
+
#include <netlink/netlink.h>
#include <netlink/route/cls/ematch.h>
#include <netlink/route/cls/ematch/cmp.h>
- #include <linux/tc_ematch/tc_em_cmp.h>
+
+ #include "nl-route.h"
+
#include "ematch_syntax.h"
int ematch_get_column(yyscan_t);
diff --git a/lib/route/cls/ematch_syntax.y b/lib/route/cls/ematch_syntax.y
index 0c89603f..961ee43e 100644
--- a/lib/route/cls/ematch_syntax.y
+++ b/lib/route/cls/ematch_syntax.y
@@ -4,8 +4,10 @@
*/
%{
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include <linux/tc_ematch/tc_em_meta.h>
+
+#include <linux/tc_ematch/tc_em_cmp.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/pktloc.h>
@@ -14,8 +16,8 @@
#include <netlink/route/cls/ematch/nbyte.h>
#include <netlink/route/cls/ematch/text.h>
#include <netlink/route/cls/ematch/meta.h>
-#include <linux/tc_ematch/tc_em_meta.h>
-#include <linux/tc_ematch/tc_em_cmp.h>
+
+#include "nl-route.h"
#define META_ALLOC rtnl_meta_value_alloc_id
#define META_ID(name) TCF_META_ID_##name
@@ -23,6 +25,16 @@
#define META_VAR TCF_META_TYPE_VAR
%}
+%code requires {
+
+struct ematch_quoted {
+ char * data;
+ size_t len;
+ int index;
+};
+
+}
+
%error-verbose
%define api.pure
%name-prefix "ematch_"
@@ -406,7 +418,7 @@ pattern:
if (nl_addr_parse($1, AF_UNSPEC, &addr) == 0) {
$$.len = nl_addr_get_len(addr);
- $$.index = min_t(int, $$.len, nl_addr_get_prefixlen(addr)/8);
+ $$.index = _NL_MIN($$.len, nl_addr_get_prefixlen(addr)/8);
if (!($$.data = calloc(1, $$.len))) {
nl_addr_put(addr);
diff --git a/lib/route/cls/flower.c b/lib/route/cls/flower.c
index 11bd7095..56f24c3e 100644
--- a/lib/route/cls/flower.c
+++ b/lib/route/cls/flower.c
@@ -3,18 +3,41 @@
* Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@gmail.com>
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/ethtool.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/action.h>
#include <netlink/route/cls/flower.h>
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
/** @cond SKIP */
+struct rtnl_flower {
+ struct rtnl_act *cf_act;
+ int cf_mask;
+ uint32_t cf_flags;
+ uint16_t cf_proto;
+ uint16_t cf_vlan_id;
+ uint16_t cf_vlan_ethtype;
+ uint8_t cf_vlan_prio;
+ uint8_t cf_src_mac[ETH_ALEN];
+ uint8_t cf_src_mac_mask[ETH_ALEN];
+ uint8_t cf_dst_mac[ETH_ALEN];
+ uint8_t cf_dst_mac_mask[ETH_ALEN];
+ in_addr_t cf_ipv4_src;
+ in_addr_t cf_ipv4_src_mask;
+ in_addr_t cf_ipv4_dst;
+ in_addr_t cf_ipv4_dst_mask;
+ uint8_t cf_ip_dscp;
+ uint8_t cf_ip_dscp_mask;
+};
+
#define FLOWER_ATTR_FLAGS (1 << 0)
#define FLOWER_ATTR_ACTION (1 << 1)
#define FLOWER_ATTR_VLAN_ID (1 << 2)
@@ -787,6 +810,7 @@ int rtnl_flower_get_ipv4_dst(struct rtnl_cls *cls, in_addr_t *out_addr,
int rtnl_flower_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
{
struct rtnl_flower *f;
+ int err;
if (!act)
return 0;
@@ -794,10 +818,11 @@ int rtnl_flower_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
if (!(f = rtnl_tc_data(TC_CAST(cls))))
return -NLE_NOMEM;
- f->cf_mask |= FLOWER_ATTR_ACTION;
+ if ((err = _rtnl_act_append_get(&f->cf_act, act)) < 0)
+ return err;
- rtnl_act_get(act);
- return rtnl_act_append(&f->cf_act, act);
+ f->cf_mask |= FLOWER_ATTR_ACTION;
+ return 0;
}
/**
@@ -885,12 +910,12 @@ static struct rtnl_tc_ops flower_ops = {
},
};
-static void __init flower_init(void)
+static void _nl_init flower_init(void)
{
rtnl_tc_register(&flower_ops);
}
-static void __exit flower_exit(void)
+static void _nl_exit flower_exit(void)
{
rtnl_tc_unregister(&flower_ops);
}
diff --git a/lib/route/cls/fw.c b/lib/route/cls/fw.c
index 2952efc9..01be33fd 100644
--- a/lib/route/cls/fw.c
+++ b/lib/route/cls/fw.c
@@ -12,14 +12,24 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/fw.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_fw {
+ uint32_t cf_classid;
+ struct nl_data *cf_act;
+ struct nl_data *cf_police;
+ char cf_indev[IFNAMSIZ];
+ uint32_t cf_fwmask;
+ int cf_mask;
+};
+
#define FW_ATTR_CLASSID 0x001
#define FW_ATTR_ACTION 0x002
#define FW_ATTR_POLICE 0x004
@@ -203,12 +213,12 @@ static struct rtnl_tc_ops fw_ops = {
},
};
-static void __init fw_init(void)
+static void _nl_init fw_init(void)
{
rtnl_tc_register(&fw_ops);
}
-static void __exit fw_exit(void)
+static void _nl_exit fw_exit(void)
{
rtnl_tc_unregister(&fw_ops);
}
diff --git a/lib/route/cls/mall.c b/lib/route/cls/mall.c
index ded08c6e..030eaa81 100644
--- a/lib/route/cls/mall.c
+++ b/lib/route/cls/mall.c
@@ -10,16 +10,24 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/matchall.h>
#include <netlink/route/action.h>
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
+
+struct rtnl_mall {
+ uint32_t m_classid;
+ uint32_t m_flags;
+ struct rtnl_act *m_act;
+ int m_mask;
+};
#define MALL_ATTR_CLASSID 0x01
#define MALL_ATTR_FLAGS 0x02
@@ -100,12 +108,10 @@ int rtnl_mall_append_action(struct rtnl_cls *cls, struct rtnl_act *act)
if (!(mall = rtnl_tc_data(TC_CAST(cls))))
return -NLE_NOMEM;
- mall->m_mask |= MALL_ATTR_ACTION;
- err = rtnl_act_append(&mall->m_act, act);
- if (err < 0)
- return err;
+ if ((err = _rtnl_act_append_get(&mall->m_act, act)) < 0)
+ return err;
- rtnl_act_get(act);
+ mall->m_mask |= MALL_ATTR_ACTION;
return 0;
}
@@ -238,7 +244,7 @@ static int mall_clone(void *_dst, void *_src)
if (!new)
return -NLE_NOMEM;
- err = rtnl_act_append(&dst->m_act, new);
+ err = _rtnl_act_append_take(&dst->m_act, new);
if (err < 0)
return err;
@@ -288,12 +294,12 @@ static struct rtnl_tc_ops mall_ops = {
},
};
-static void __init mall_init(void)
+static void _nl_init mall_init(void)
{
rtnl_tc_register(&mall_ops);
}
-static void __exit mall_exit(void)
+static void _nl_exit mall_exit(void)
{
rtnl_tc_unregister(&mall_ops);
}
diff --git a/lib/route/cls/police.c b/lib/route/cls/police.c
index f7771ae4..e7e3926a 100644
--- a/lib/route/cls/police.c
+++ b/lib/route/cls/police.c
@@ -3,14 +3,15 @@
* Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/police.h>
+#include "nl-priv-dynamic-core/nl-core.h"
+
/**
* @name Policer Type
* @{
diff --git a/lib/route/cls/u32.c b/lib/route/cls/u32.c
index 56952fb2..52f6e31c 100644
--- a/lib/route/cls/u32.c
+++ b/lib/route/cls/u32.c
@@ -12,19 +12,33 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/classifier.h>
#include <netlink/route/cls/u32.h>
#include <netlink/route/action.h>
-#include "netlink-private/utils.h"
+#include "tc-api.h"
+#include "nl-aux-route/nl-route.h"
/** @cond SKIP */
+struct rtnl_u32 {
+ uint32_t cu_divisor;
+ uint32_t cu_hash;
+ uint32_t cu_classid;
+ uint32_t cu_link;
+ struct nl_data *cu_pcnt;
+ struct nl_data *cu_selector;
+ struct nl_data *cu_mark;
+ struct rtnl_act *cu_act;
+ struct nl_data *cu_police;
+ char cu_indev[IFNAMSIZ];
+ int cu_mask;
+};
+
#define U32_ATTR_DIVISOR 0x001
#define U32_ATTR_HASH 0x002
#define U32_ATTR_CLASSID 0x004
@@ -598,12 +612,10 @@ int rtnl_u32_add_action(struct rtnl_cls *cls, struct rtnl_act *act)
if (!(u = rtnl_tc_data(TC_CAST(cls))))
return -NLE_NOMEM;
- u->cu_mask |= U32_ATTR_ACTION;
- if ((err = rtnl_act_append(&u->cu_act, act)))
+ if ((err = _rtnl_act_append_get(&u->cu_act, act)) < 0)
return err;
- /* In case user frees it */
- rtnl_act_get(act);
+ u->cu_mask |= U32_ATTR_ACTION;
return 0;
}
@@ -885,12 +897,12 @@ static struct rtnl_tc_ops u32_ops = {
},
};
-static void __init u32_init(void)
+static void _nl_init u32_init(void)
{
rtnl_tc_register(&u32_ops);
}
-static void __exit u32_exit(void)
+static void _nl_exit u32_exit(void)
{
rtnl_tc_unregister(&u32_ops);
}
diff --git a/lib/route/link-sriov.h b/lib/route/link-sriov.h
new file mode 100644
index 00000000..6493a577
--- /dev/null
+++ b/lib/route/link-sriov.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2016 Intel Corp. All rights reserved.
+ * Copyright (c) 2016 Jef Oliver <jef.oliver@intel.com>
+ */
+
+#ifndef NETLINK_PRIV_LINK_SRIOV_H_
+#define NETLINK_PRIV_LINK_SRIOV_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/link/sriov.h>
+
+extern int rtnl_link_sriov_clone(struct rtnl_link *, struct rtnl_link *);
+extern void rtnl_link_sriov_dump_details(struct rtnl_link *, struct nl_dump_params *);
+extern void rtnl_link_sriov_dump_stats(struct rtnl_link *, struct nl_dump_params *);
+extern int rtnl_link_sriov_fill_vflist(struct nl_msg *, struct rtnl_link *);
+extern void rtnl_link_sriov_free_data(struct rtnl_link *);
+extern int rtnl_link_sriov_parse_vflist(struct rtnl_link *, struct nlattr **);
+
+#endif
diff --git a/lib/route/link.c b/lib/route/link.c
index df8ea5bb..ce1355b9 100644
--- a/lib/route/link.c
+++ b/lib/route/link.c
@@ -12,7 +12,10 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_arp.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
@@ -21,9 +24,13 @@
#include <netlink/data.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink-private/route/link/sriov.h>
-#include <netlink-private/utils.h>
+
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-route.h"
+#include "link-sriov.h"
+#include "link/link-api.h"
/** @cond SKIP */
#define LINK_ATTR_MTU (1 << 0)
@@ -115,7 +122,7 @@ static int af_request_type(int af_type, struct rtnl_link *changes)
struct rtnl_link_af_ops *ops;
ops = rtnl_link_af_ops_lookup(af_type);
- if (ops && ops->ao_override_rtm(changes))
+ if (ops && ops->ao_override_rtm && ops->ao_override_rtm(changes))
return RTM_SETLINK;
return RTM_NEWLINK;
@@ -1090,7 +1097,7 @@ static void link_keygen(struct nl_object *obj, uint32_t *hashkey,
struct link_hash_key {
uint32_t l_index;
uint32_t l_family;
- } __attribute__((packed)) lkey;
+ } _nl_packed lkey;
lkey_sz = sizeof(lkey);
lkey.l_index = link->l_index;
@@ -1111,34 +1118,37 @@ static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_link *b = (struct rtnl_link *) _b;
uint64_t diff = 0;
-#define LINK_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, LINK_ATTR_##ATTR, a, b, EXPR)
-
- diff |= LINK_DIFF(IFINDEX, a->l_index != b->l_index);
- diff |= LINK_DIFF(MTU, a->l_mtu != b->l_mtu);
- diff |= LINK_DIFF(LINK, a->l_link != b->l_link);
- diff |= LINK_DIFF(LINK_NETNSID, a->l_link_netnsid != b->l_link_netnsid);
- diff |= LINK_DIFF(TXQLEN, a->l_txqlen != b->l_txqlen);
- diff |= LINK_DIFF(WEIGHT, a->l_weight != b->l_weight);
- diff |= LINK_DIFF(MASTER, a->l_master != b->l_master);
- diff |= LINK_DIFF(FAMILY, a->l_family != b->l_family);
- diff |= LINK_DIFF(OPERSTATE, a->l_operstate != b->l_operstate);
- diff |= LINK_DIFF(LINKMODE, a->l_linkmode != b->l_linkmode);
- diff |= LINK_DIFF(QDISC, strcmp(a->l_qdisc, b->l_qdisc));
- diff |= LINK_DIFF(IFNAME, strcmp(a->l_name, b->l_name));
- diff |= LINK_DIFF(ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
- diff |= LINK_DIFF(BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
- diff |= LINK_DIFF(IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
- diff |= LINK_DIFF(NUM_VF, a->l_num_vf != b->l_num_vf);
- diff |= LINK_DIFF(PROMISCUITY, a->l_promiscuity != b->l_promiscuity);
- diff |= LINK_DIFF(NUM_TX_QUEUES,a->l_num_tx_queues != b->l_num_tx_queues);
- diff |= LINK_DIFF(NUM_RX_QUEUES,a->l_num_rx_queues != b->l_num_rx_queues);
- diff |= LINK_DIFF(GROUP, a->l_group != b->l_group);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(LINK_ATTR_IFINDEX, a->l_index != b->l_index);
+ diff |= _DIFF(LINK_ATTR_MTU, a->l_mtu != b->l_mtu);
+ diff |= _DIFF(LINK_ATTR_LINK, a->l_link != b->l_link);
+ diff |= _DIFF(LINK_ATTR_LINK_NETNSID,
+ a->l_link_netnsid != b->l_link_netnsid);
+ diff |= _DIFF(LINK_ATTR_TXQLEN, a->l_txqlen != b->l_txqlen);
+ diff |= _DIFF(LINK_ATTR_WEIGHT, a->l_weight != b->l_weight);
+ diff |= _DIFF(LINK_ATTR_MASTER, a->l_master != b->l_master);
+ diff |= _DIFF(LINK_ATTR_FAMILY, a->l_family != b->l_family);
+ diff |= _DIFF(LINK_ATTR_OPERSTATE, a->l_operstate != b->l_operstate);
+ diff |= _DIFF(LINK_ATTR_LINKMODE, a->l_linkmode != b->l_linkmode);
+ diff |= _DIFF(LINK_ATTR_QDISC, strcmp(a->l_qdisc, b->l_qdisc));
+ diff |= _DIFF(LINK_ATTR_IFNAME, strcmp(a->l_name, b->l_name));
+ diff |= _DIFF(LINK_ATTR_ADDR, nl_addr_cmp(a->l_addr, b->l_addr));
+ diff |= _DIFF(LINK_ATTR_BRD, nl_addr_cmp(a->l_bcast, b->l_bcast));
+ diff |= _DIFF(LINK_ATTR_IFALIAS, strcmp(a->l_ifalias, b->l_ifalias));
+ diff |= _DIFF(LINK_ATTR_NUM_VF, a->l_num_vf != b->l_num_vf);
+ diff |= _DIFF(LINK_ATTR_PROMISCUITY,
+ a->l_promiscuity != b->l_promiscuity);
+ diff |= _DIFF(LINK_ATTR_NUM_TX_QUEUES,
+ a->l_num_tx_queues != b->l_num_tx_queues);
+ diff |= _DIFF(LINK_ATTR_NUM_RX_QUEUES,
+ a->l_num_rx_queues != b->l_num_rx_queues);
+ diff |= _DIFF(LINK_ATTR_GROUP, a->l_group != b->l_group);
if (flags & LOOSE_COMPARISON)
- diff |= LINK_DIFF(FLAGS,
+ diff |= _DIFF(LINK_ATTR_FLAGS,
(a->l_flags ^ b->l_flags) & b->l_flag_mask);
else
- diff |= LINK_DIFF(FLAGS, a->l_flags != b->l_flags);
+ diff |= _DIFF(LINK_ATTR_FLAGS, a->l_flags != b->l_flags);
/*
* Compare LINK_ATTR_PROTINFO af_data
@@ -1148,15 +1158,15 @@ static uint64_t link_compare(struct nl_object *_a, struct nl_object *_b,
goto protinfo_mismatch;
}
- diff |= LINK_DIFF(LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0);
+ diff |= _DIFF(LINK_ATTR_LINKINFO, rtnl_link_info_data_compare(a, b, flags) != 0);
out:
return diff;
protinfo_mismatch:
- diff |= LINK_DIFF(PROTINFO, 1);
+ diff |= _DIFF(LINK_ATTR_PROTINFO, 1);
goto out;
-#undef LINK_DIFF
+#undef _DIFF
}
static const struct trans_tbl link_attrs[] = {
@@ -1913,7 +1923,7 @@ struct rtnl_link *rtnl_link_alloc(void)
}
/**
- * Return a link object reference
+ * Release a link object reference
* @arg link Link object
*/
void rtnl_link_put(struct rtnl_link *link)
@@ -3204,12 +3214,12 @@ static struct nl_cache_ops rtnl_link_ops = {
.co_obj_ops = &link_obj_ops,
};
-static void __init link_init(void)
+static void _nl_init link_init(void)
{
nl_cache_mngt_register(&rtnl_link_ops);
}
-static void __exit link_exit(void)
+static void _nl_exit link_exit(void)
{
nl_cache_mngt_unregister(&rtnl_link_ops);
}
diff --git a/lib/route/link/api.c b/lib/route/link/api.c
index cd2c42bb..abc9e6a7 100644
--- a/lib/route/link/api.c
+++ b/lib/route/link/api.c
@@ -19,12 +19,12 @@
* .io_free = vlan_free,
* };
*
- * static void __init vlan_init(void)
+ * static void _nl_init vlan_init(void)
* {
* rtnl_link_register_info(&vlan_info_ops);
* }
*
- * static void __exit vlan_exit(void)
+ * static void _nl_exit vlan_exit(void)
* {
* rtnl_link_unregister_info(&vlan_info_ops);
* }
@@ -33,11 +33,14 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
static NL_LIST_HEAD(info_ops);
diff --git a/lib/route/link/bonding.c b/lib/route/link/bonding.c
index 90e64703..63fd4749 100644
--- a/lib/route/link/bonding.c
+++ b/lib/route/link/bonding.c
@@ -14,10 +14,186 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/route/link/bonding.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+
+#define BOND_HAS_MODE (1 << 0)
+#define BOND_HAS_ACTIVE_SLAVE (1 << 1)
+#define BOND_HAS_HASHING_TYPE (1 << 2)
+#define BOND_HAS_MIIMON (1 << 3)
+#define BOND_HAS_MIN_LINKS (1 << 4)
+
+struct bond_info {
+ uint8_t bn_mode;
+ uint8_t hashing_type;
+ uint32_t ifindex;
+ uint32_t bn_mask;
+ uint32_t miimon;
+ uint32_t min_links;
+};
+
+static int bond_info_alloc(struct rtnl_link *link)
+{
+ struct bond_info *bn;
+
+ if (link->l_info)
+ memset(link->l_info, 0, sizeof(*bn));
+ else {
+ bn = calloc(1, sizeof(*bn));
+ if (!bn)
+ return -NLE_NOMEM;
+
+ link->l_info = bn;
+ }
+
+ return 0;
+}
+
+static void bond_info_free(struct rtnl_link *link)
+{
+ _nl_clear_free(&link->l_info);
+}
+
+static int bond_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
+{
+ struct bond_info *bn = link->l_info;
+ struct nlattr *data;
+
+ data = nla_nest_start(msg, IFLA_INFO_DATA);
+ if (!data)
+ return -NLE_MSGSIZE;
+ if (bn->bn_mask & BOND_HAS_MODE)
+ NLA_PUT_U8(msg, IFLA_BOND_MODE, bn->bn_mode);
+
+ if (bn->bn_mask & BOND_HAS_ACTIVE_SLAVE)
+ NLA_PUT_U32(msg, IFLA_BOND_ACTIVE_SLAVE, bn->ifindex);
+
+ if (bn->bn_mask & BOND_HAS_HASHING_TYPE)
+ NLA_PUT_U8(msg, IFLA_BOND_XMIT_HASH_POLICY, bn->hashing_type);
+
+ if (bn->bn_mask & BOND_HAS_MIIMON)
+ NLA_PUT_U32(msg, IFLA_BOND_MIIMON, bn->miimon);
+
+ if (bn->bn_mask & BOND_HAS_MIN_LINKS)
+ NLA_PUT_U32(msg, IFLA_BOND_MIN_LINKS, bn->min_links);
+
+ nla_nest_end(msg, data);
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(msg, data);
+ return -NLE_MSGSIZE;
+}
+
+static struct rtnl_link_info_ops bonding_info_ops = {
+ .io_name = "bond",
+ .io_alloc = bond_info_alloc,
+ .io_put_attrs = bond_put_attrs,
+ .io_free = bond_info_free,
+};
+
+#define IS_BOND_INFO_ASSERT(link) \
+ do { \
+ if (link->l_info_ops != &bonding_info_ops) { \
+ APPBUG("Link is not a bond link. Set type \"bond\" first."); \
+ } \
+ } while (0)
+
+/**
+ * Set active slave for bond
+ * @arg link Link object of type bond
+ * @arg active ifindex of active slave to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_activeslave(struct rtnl_link *link, int active_slave)
+{
+ struct bond_info *bn = link->l_info;
+
+ IS_BOND_INFO_ASSERT(link);
+
+ bn->ifindex = active_slave;
+
+ bn->bn_mask |= BOND_HAS_ACTIVE_SLAVE;
+}
+
+/**
+ * Set bond mode
+ * @arg link Link object of type bond
+ * @arg mode bond mode to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_mode(struct rtnl_link *link, uint8_t mode)
+{
+ struct bond_info *bn = link->l_info;
+
+ IS_BOND_INFO_ASSERT(link);
+
+ bn->bn_mode = mode;
+
+ bn->bn_mask |= BOND_HAS_MODE;
+}
+
+/**
+ * Set hashing type
+ * @arg link Link object of type bond
+ * @arg type bond hashing type to set
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_hashing_type (struct rtnl_link *link, uint8_t type)
+{
+ struct bond_info *bn = link->l_info;
+
+ IS_BOND_INFO_ASSERT(link);
+
+ bn->hashing_type = type;
+
+ bn->bn_mask |= BOND_HAS_HASHING_TYPE;
+}
+
+/**
+ * Set MII monitoring interval
+ * @arg link Link object of type bond
+ * @arg miimon interval in milliseconds
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_miimon (struct rtnl_link *link, uint32_t miimon)
+{
+ struct bond_info *bn = link->l_info;
+
+ IS_BOND_INFO_ASSERT(link);
+
+ bn->miimon = miimon;
+
+ bn->bn_mask |= BOND_HAS_MIIMON;
+}
+
+/**
+ * Set the minimum number of member ports that must be up before
+ * marking the bond device as up
+ * @arg link Link object of type bond
+ * @arg min_links Number of links
+ *
+ * @return void
+ */
+void rtnl_link_bond_set_min_links (struct rtnl_link *link, uint32_t min_links)
+{
+ struct bond_info *bn = link->l_info;
+
+ IS_BOND_INFO_ASSERT(link);
+
+ bn->min_links = min_links;
+
+ bn->bn_mask |= BOND_HAS_MIN_LINKS;
+}
/**
* Allocate link object of type bond
@@ -204,16 +380,12 @@ int rtnl_link_bond_release(struct nl_sock *sock, struct rtnl_link *slave)
rtnl_link_get_ifindex(slave));
}
-static struct rtnl_link_info_ops bonding_info_ops = {
- .io_name = "bond",
-};
-
-static void __init bonding_init(void)
+static void _nl_init bonding_init(void)
{
rtnl_link_register_info(&bonding_info_ops);
}
-static void __exit bonding_exit(void)
+static void _nl_exit bonding_exit(void)
{
rtnl_link_unregister_info(&bonding_info_ops);
}
diff --git a/lib/route/link/bridge.c b/lib/route/link/bridge.c
index bd042539..5b441648 100644
--- a/lib/route/link/bridge.c
+++ b/lib/route/link/bridge.c
@@ -11,13 +11,18 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_bridge.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/bridge.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_bridge.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */
@@ -189,6 +194,7 @@ static int bridge_parse_af_full(struct rtnl_link *link, struct nlattr *attr_full
if (nla_type(attr) == IFLA_BRIDGE_MODE) {
bd->b_hwmode = nla_get_u16(attr);
bd->ce_mask |= BRIDGE_ATTR_HWMODE;
+ continue;
} else if (nla_type(attr) != IFLA_BRIDGE_VLAN_INFO)
continue;
@@ -430,21 +436,23 @@ static int bridge_compare(struct rtnl_link *_a, struct rtnl_link *_b,
struct bridge_data *b = bridge_data(_b);
int diff = 0;
-#define BRIDGE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, BRIDGE_ATTR_##ATTR, a, b, EXPR)
- diff |= BRIDGE_DIFF(PORT_STATE, a->b_port_state != b->b_port_state);
- diff |= BRIDGE_DIFF(PRIORITY, a->b_priority != b->b_priority);
- diff |= BRIDGE_DIFF(COST, a->b_cost != b->b_cost);
- diff |= BRIDGE_DIFF(PORT_VLAN, memcmp(&a->vlan_info, &b->vlan_info,
- sizeof(struct rtnl_link_bridge_vlan)));
- diff |= BRIDGE_DIFF(HWMODE, a->b_hwmode != b->b_hwmode);
- diff |= BRIDGE_DIFF(SELF, a->b_self != b->b_self);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(BRIDGE_ATTR_PORT_STATE,
+ a->b_port_state != b->b_port_state);
+ diff |= _DIFF(BRIDGE_ATTR_PRIORITY, a->b_priority != b->b_priority);
+ diff |= _DIFF(BRIDGE_ATTR_COST, a->b_cost != b->b_cost);
+ diff |= _DIFF(BRIDGE_ATTR_PORT_VLAN,
+ memcmp(&a->vlan_info, &b->vlan_info,
+ sizeof(struct rtnl_link_bridge_vlan)));
+ diff |= _DIFF(BRIDGE_ATTR_HWMODE, a->b_hwmode != b->b_hwmode);
+ diff |= _DIFF(BRIDGE_ATTR_SELF, a->b_self != b->b_self);
if (flags & LOOSE_COMPARISON)
- diff |= BRIDGE_DIFF(FLAGS,
- (a->b_flags ^ b->b_flags) & b->b_flags_mask);
+ diff |= _DIFF(BRIDGE_ATTR_FLAGS,
+ (a->b_flags ^ b->b_flags) & b->b_flags_mask);
else
- diff |= BRIDGE_DIFF(FLAGS, a->b_flags != b->b_flags);
-#undef BRIDGE_DIFF
+ diff |= _DIFF(BRIDGE_ATTR_FLAGS, a->b_flags != b->b_flags);
+#undef _DIFF
return diff;
}
@@ -972,12 +980,12 @@ static struct rtnl_link_af_ops bridge_ops = {
.ao_fill_af_no_nest = 1,
};
-static void __init bridge_init(void)
+static void _nl_init bridge_init(void)
{
rtnl_link_af_register(&bridge_ops);
}
-static void __exit bridge_exit(void)
+static void _nl_exit bridge_exit(void)
{
rtnl_link_af_unregister(&bridge_ops);
}
diff --git a/lib/route/link/bridge_info.c b/lib/route/link/bridge_info.c
new file mode 100644
index 00000000..61b885f0
--- /dev/null
+++ b/lib/route/link/bridge_info.c
@@ -0,0 +1,306 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 MaxLinear, Inc.
+ */
+
+/**
+ * @ingroup link
+ * @defgroup bridge Bridging
+ *
+ * @details
+ * @{
+ */
+
+#include "nl-default.h"
+
+#include <netlink/route/link/bridge_info.h>
+
+#include "nl-route.h"
+#include "link-api.h"
+
+#define BRIDGE_ATTR_VLAN_FILTERING (1 << 0)
+#define BRIDGE_ATTR_VLAN_PROTOCOL (1 << 1)
+#define BRIDGE_ATTR_VLAN_STATS_ENABLED (1 << 2)
+
+struct bridge_info {
+ uint32_t ce_mask; /* to support attr macros */
+ uint16_t b_vlan_protocol;
+ uint8_t b_vlan_filtering;
+ uint8_t b_vlan_stats_enabled;
+};
+
+static const struct nla_policy bi_attrs_policy[IFLA_BR_MAX + 1] = {
+ [IFLA_BR_VLAN_FILTERING] = { .type = NLA_U8 },
+ [IFLA_BR_VLAN_PROTOCOL] = { .type = NLA_U16 },
+ [IFLA_BR_VLAN_STATS_ENABLED] = { .type = NLA_U8 },
+};
+
+static inline struct bridge_info *bridge_info(struct rtnl_link *link)
+{
+ return link->l_info;
+}
+
+static int bridge_info_alloc(struct rtnl_link *link)
+{
+ struct bridge_info *bi;
+
+ if (link->l_info)
+ memset(link->l_info, 0, sizeof(*bi));
+ else {
+ bi = calloc(1, sizeof(*bi));
+ if (!bi)
+ return -NLE_NOMEM;
+
+ link->l_info = bi;
+ }
+
+ return 0;
+}
+
+static int bridge_info_parse(struct rtnl_link *link, struct nlattr *data,
+ struct nlattr *xstats)
+{
+ struct nlattr *tb[IFLA_BR_MAX + 1];
+ struct bridge_info *bi;
+ int err;
+
+ NL_DBG(3, "Parsing Bridge link info\n");
+
+ if ((err = nla_parse_nested(tb, IFLA_BR_MAX, data, bi_attrs_policy)) <
+ 0)
+ return err;
+
+ if ((err = bridge_info_alloc(link)) < 0)
+ return err;
+
+ bi = link->l_info;
+
+ if (tb[IFLA_BR_VLAN_FILTERING]) {
+ bi->b_vlan_filtering = nla_get_u8(tb[IFLA_BR_VLAN_FILTERING]);
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
+ }
+
+ if (tb[IFLA_BR_VLAN_PROTOCOL]) {
+ bi->b_vlan_protocol =
+ ntohs(nla_get_u16(tb[IFLA_BR_VLAN_PROTOCOL]));
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
+ }
+
+ if (tb[IFLA_BR_VLAN_STATS_ENABLED]) {
+ bi->b_vlan_stats_enabled =
+ nla_get_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]);
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
+ }
+
+ return 0;
+}
+
+static int bridge_info_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
+{
+ struct bridge_info *bi = link->l_info;
+ struct nlattr *data;
+
+ data = nla_nest_start(msg, IFLA_INFO_DATA);
+ if (!data)
+ return -NLE_MSGSIZE;
+
+ if (bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING)
+ NLA_PUT_U8(msg, IFLA_BR_VLAN_FILTERING, bi->b_vlan_filtering);
+
+ if (bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL)
+ NLA_PUT_U16(msg, IFLA_BR_VLAN_PROTOCOL,
+ htons(bi->b_vlan_protocol));
+
+ if (bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED)
+ NLA_PUT_U8(msg, IFLA_BR_VLAN_STATS_ENABLED,
+ bi->b_vlan_stats_enabled);
+
+ nla_nest_end(msg, data);
+ return 0;
+
+nla_put_failure:
+ nla_nest_cancel(msg, data);
+ return -NLE_MSGSIZE;
+}
+
+static void bridge_info_free(struct rtnl_link *link)
+{
+ _nl_clear_free(&link->l_info);
+}
+
+static struct rtnl_link_info_ops bridge_info_ops = {
+ .io_name = "bridge",
+ .io_alloc = bridge_info_alloc,
+ .io_parse = bridge_info_parse,
+ .io_put_attrs = bridge_info_put_attrs,
+ .io_free = bridge_info_free,
+};
+
+#define IS_BRIDGE_INFO_ASSERT(link) \
+ do { \
+ if ((link)->l_info_ops != &bridge_info_ops) { \
+ APPBUG("Link is not a bridge link. Set type \"bridge\" first."); \
+ } \
+ } while (0)
+
+/**
+ * Set VLAN filtering flag
+ * @arg link Link object of type bridge
+ * @arg vlan_filtering VLAN_filtering boolean flag to set.
+ *
+ * @see rtnl_link_bridge_get_vlan_filtering()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_filtering(struct rtnl_link *link,
+ uint8_t vlan_filtering)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_vlan_filtering = vlan_filtering;
+
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_FILTERING;
+}
+
+/**
+ * Get VLAN filtering flag
+ * @arg link Link object of type bridge
+ * @arg vlan_filtering Output argument.
+ *
+ * @see rtnl_link_bridge_set_vlan_filtering()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_filtering(struct rtnl_link *link,
+ uint8_t *vlan_filtering)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_FILTERING))
+ return -NLE_NOATTR;
+
+ if (!vlan_filtering)
+ return -NLE_INVAL;
+
+ *vlan_filtering = bi->b_vlan_filtering;
+ return 0;
+}
+
+/**
+ * Set VLAN protocol
+ * @arg link Link object of type bridge
+ * @arg vlan_protocol VLAN protocol to set. The protocol
+ * numbers is in host byte order.
+ *
+ * @see rtnl_link_bridge_get_vlan_protocol()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_protocol(struct rtnl_link *link,
+ uint16_t vlan_protocol)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_vlan_protocol = vlan_protocol;
+
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_PROTOCOL;
+}
+
+/**
+ * Get VLAN protocol
+ * @arg link Link object of type bridge
+ * @arg vlan_protocol Output argument. The protocol number is in host byte order.
+ *
+ * @see rtnl_link_bridge_set_vlan_protocol()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_protocol(struct rtnl_link *link,
+ uint16_t *vlan_protocol)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_PROTOCOL))
+ return -NLE_NOATTR;
+
+ if (!vlan_protocol)
+ return -NLE_INVAL;
+
+ *vlan_protocol = bi->b_vlan_protocol;
+
+ return 0;
+}
+
+/**
+ * Set VLAN stats enabled flag
+ * @arg link Link object of type bridge
+ * @arg vlan_stats_enabled VLAN stats enabled flag to set
+ *
+ * @see rtnl_link_bridge_get_vlan_stats_enabled()
+ *
+ * @return void
+ */
+void rtnl_link_bridge_set_vlan_stats_enabled(struct rtnl_link *link,
+ uint8_t vlan_stats_enabled)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ bi->b_vlan_stats_enabled = vlan_stats_enabled;
+
+ bi->ce_mask |= BRIDGE_ATTR_VLAN_STATS_ENABLED;
+}
+
+/**
+ * Get VLAN stats enabled flag
+ * @arg link Link object of type bridge
+ * @arg vlan_stats_enabled Output argument.
+ *
+ * @see rtnl_link_bridge_set_vlan_stats_enabled()
+ *
+ * @return Zero on success, otherwise a negative error code.
+ * @retval -NLE_NOATTR
+ * @retval -NLE_INVAL
+ */
+int rtnl_link_bridge_get_vlan_stats_enabled(struct rtnl_link *link,
+ uint8_t *vlan_stats_enabled)
+{
+ struct bridge_info *bi = bridge_info(link);
+
+ IS_BRIDGE_INFO_ASSERT(link);
+
+ if (!(bi->ce_mask & BRIDGE_ATTR_VLAN_STATS_ENABLED))
+ return -NLE_NOATTR;
+
+ if (!vlan_stats_enabled)
+ return -NLE_INVAL;
+
+ *vlan_stats_enabled = bi->b_vlan_stats_enabled;
+
+ return 0;
+}
+
+static void _nl_init bridge_info_init(void)
+{
+ rtnl_link_register_info(&bridge_info_ops);
+}
+
+static void _nl_exit bridge_info_exit(void)
+{
+ rtnl_link_unregister_info(&bridge_info_ops);
+}
+
+/** @} */
diff --git a/lib/route/link/can.c b/lib/route/link/can.c
index da8f092d..da00144f 100644
--- a/lib/route/link/can.c
+++ b/lib/route/link/can.c
@@ -16,16 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/can/netlink.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/can.h>
-#include <linux/can/netlink.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define CAN_HAS_BITTIMING (1<<0)
@@ -38,6 +41,7 @@
#define CAN_HAS_BERR_COUNTER (1<<7)
#define CAN_HAS_DATA_BITTIMING (1<<8)
#define CAN_HAS_DATA_BITTIMING_CONST (1<<9)
+#define CAN_HAS_DEVICE_STATS (1<<10)
struct can_info {
uint32_t ci_state;
@@ -51,6 +55,7 @@ struct can_info {
uint32_t ci_mask;
struct can_bittiming ci_data_bittiming;
struct can_bittiming_const ci_data_bittiming_const;
+ struct can_device_stats ci_device_stats;
};
/** @endcond */
@@ -163,6 +168,11 @@ static int can_parse(struct rtnl_link *link, struct nlattr *data,
ci->ci_mask |= CAN_HAS_DATA_BITTIMING_CONST;
}
+ if (xstats && nla_len(xstats) >= sizeof(ci->ci_device_stats)) {
+ nla_memcpy(&ci->ci_device_stats, xstats, sizeof(ci->ci_device_stats));
+ ci->ci_mask |= CAN_HAS_DEVICE_STATS;
+ }
+
err = 0;
errout:
return err;
@@ -220,11 +230,8 @@ static void can_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
{
struct can_info *ci = link->l_info;
- char buf [64];
- rtnl_link_can_ctrlmode2str(ci->ci_ctrlmode.flags, buf, sizeof(buf));
- nl_dump(p, " bitrate %d %s <%s>",
- ci->ci_bittiming.bitrate, print_can_state(ci->ci_state), buf);
+ can_dump_line(link, p);
if (ci->ci_mask & CAN_HAS_RESTART) {
if (ci->ci_restart)
@@ -283,8 +290,28 @@ static void can_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
nl_dump_line(p," bus error TX %d\n",
ci->ci_berr_counter.txerr);
}
+}
- return;
+static void can_dump_stats(struct rtnl_link *link, struct nl_dump_params *p)
+{
+ struct can_info *ci = link->l_info;
+
+ can_dump_details(link, p);
+
+ if (ci->ci_mask & CAN_HAS_DEVICE_STATS) {
+ nl_dump_line(p," bus errors %d\n",
+ ci->ci_device_stats.bus_error);
+ nl_dump_line(p," error warning state changes %d\n",
+ ci->ci_device_stats.error_warning);
+ nl_dump_line(p," error passive state changes %d\n",
+ ci->ci_device_stats.error_passive);
+ nl_dump_line(p," bus off state changes %d\n",
+ ci->ci_device_stats.bus_off);
+ nl_dump_line(p," arbitration lost errors %d\n",
+ ci->ci_device_stats.arbitration_lost);
+ nl_dump_line(p," restarts %d\n",
+ ci->ci_device_stats.restarts);
+ }
}
static int can_clone(struct rtnl_link *dst, struct rtnl_link *src)
@@ -361,6 +388,7 @@ static struct rtnl_link_info_ops can_info_ops = {
.io_dump = {
[NL_DUMP_LINE] = can_dump_line,
[NL_DUMP_DETAILS] = can_dump_details,
+ [NL_DUMP_STATS] = can_dump_stats,
},
.io_clone = can_clone,
.io_put_attrs = can_put_attrs,
@@ -861,6 +889,30 @@ int rtnl_link_can_set_data_bittiming(struct rtnl_link *link,
return 0;
}
+/**
+ * Get CAN device stats
+ * @arg link Link object
+ * @arg device_stats CAN device stats
+ *
+ * @return 0 on success or a negative error code
+ */
+int rtnl_link_can_get_device_stats(struct rtnl_link* link,
+ struct can_device_stats *device_stats)
+{
+ struct can_info *ci = link->l_info;
+
+ IS_CAN_LINK_ASSERT(link);
+ if (!device_stats)
+ return -NLE_INVAL;
+
+ if (ci->ci_mask & CAN_HAS_DEVICE_STATS)
+ *device_stats = ci->ci_device_stats;
+ else
+ return -NLE_MISSING_ATTR;
+
+ return 0;
+}
+
/** @} */
/**
@@ -892,12 +944,12 @@ int rtnl_link_can_str2ctrlmode(const char *name)
/** @} */
-static void __init can_init(void)
+static void _nl_init can_init(void)
{
rtnl_link_register_info(&can_info_ops);
}
-static void __exit can_exit(void)
+static void _nl_exit can_exit(void)
{
rtnl_link_unregister_info(&can_info_ops);
}
diff --git a/lib/route/link/dummy.c b/lib/route/link/dummy.c
index a6478d00..83d6ba79 100644
--- a/lib/route/link/dummy.c
+++ b/lib/route/link/dummy.c
@@ -13,20 +13,22 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
static struct rtnl_link_info_ops dummy_info_ops = {
.io_name = "dummy",
};
-static void __init dummy_init(void)
+static void _nl_init dummy_init(void)
{
rtnl_link_register_info(&dummy_info_ops);
}
-static void __exit dummy_exit(void)
+static void _nl_exit dummy_exit(void)
{
rtnl_link_unregister_info(&dummy_info_ops);
}
diff --git a/lib/route/link/geneve.c b/lib/route/link/geneve.c
index cab57cc0..61dd1f1f 100644
--- a/lib/route/link/geneve.c
+++ b/lib/route/link/geneve.c
@@ -15,14 +15,16 @@
*
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/geneve.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define GENEVE_ATTR_ID (1<<0)
@@ -788,12 +790,12 @@ int rtnl_link_geneve_get_flags(struct rtnl_link *link, uint8_t *flags)
}
/** @} */
-static void __init geneve_init(void)
+static void _nl_init geneve_init(void)
{
rtnl_link_register_info(&geneve_info_ops);
}
-static void __exit geneve_exit(void)
+static void _nl_exit geneve_exit(void)
{
rtnl_link_unregister_info(&geneve_info_ops);
}
diff --git a/lib/route/link/ifb.c b/lib/route/link/ifb.c
index 528647e0..d5fc6855 100644
--- a/lib/route/link/ifb.c
+++ b/lib/route/link/ifb.c
@@ -13,20 +13,22 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
static struct rtnl_link_info_ops ifb_info_ops = {
.io_name = "ifb",
};
-static void __init ifb_init(void)
+static void _nl_init ifb_init(void)
{
rtnl_link_register_info(&ifb_info_ops);
}
-static void __exit ifb_exit(void)
+static void _nl_exit ifb_exit(void)
{
rtnl_link_unregister_info(&ifb_info_ops);
}
diff --git a/lib/route/link/inet.c b/lib/route/link/inet.c
index 2f95fb6e..7ed705e2 100644
--- a/lib/route/link/inet.c
+++ b/lib/route/link/inet.c
@@ -51,12 +51,16 @@
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/ip.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/inet.h>
-#include <netlink-private/route/link/api.h>
+
+#include "link-api.h"
/** @cond SKIP */
struct inet_data
@@ -104,7 +108,7 @@ static int inet_parse_af(struct rtnl_link *link, struct nlattr *attr, void *data
if (tb[IFLA_INET_CONF]) {
int i;
- int len = min_t(int, IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
+ int len = _NL_MIN(IPV4_DEVCONF_MAX, nla_len(tb[IFLA_INET_CONF]) / 4);
for (i = 0; i < len; i++)
id->i_confset[i] = 1;
@@ -277,12 +281,12 @@ int rtnl_link_inet_set_conf(struct rtnl_link *link, const unsigned int cfgid,
}
-static void __init inet_init(void)
+static void _nl_init inet_init(void)
{
rtnl_link_af_register(&inet_ops);
}
-static void __exit inet_exit(void)
+static void _nl_exit inet_exit(void)
{
rtnl_link_af_unregister(&inet_ops);
}
diff --git a/lib/route/link/inet6.c b/lib/route/link/inet6.c
index afcbbceb..87b057f2 100644
--- a/lib/route/link/inet6.c
+++ b/lib/route/link/inet6.c
@@ -3,15 +3,19 @@
* Copyright (c) 2010 Thomas Graf <tgraf@suug.ch>
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/ipv6.h>
+#include <linux/snmp.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/inet6.h>
-#include <netlink-private/route/link/api.h>
-#include "netlink-private/route/utils.h"
-#include "netlink-private/utils.h"
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-static-route/nl-priv-static-route.h"
#define I6_ADDR_GEN_MODE_UNKNOWN UINT8_MAX
@@ -21,6 +25,7 @@ struct inet6_data
struct ifla_cacheinfo i6_cacheinfo;
uint32_t i6_conf[DEVCONF_MAX];
struct in6_addr i6_token;
+ uint8_t i6_conf_len;
uint8_t i6_addr_gen_mode;
};
@@ -165,9 +170,13 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
nla_memcpy(&i6->i6_cacheinfo, tb[IFLA_INET6_CACHEINFO],
sizeof(i6->i6_cacheinfo));
- if (tb[IFLA_INET6_CONF])
+ if (tb[IFLA_INET6_CONF]) {
+ i6->i6_conf_len = _NL_MIN(ARRAY_SIZE(i6->i6_conf),
+ nla_len(tb[IFLA_INET6_CONF]) /
+ sizeof(i6->i6_conf[0]));
nla_memcpy(&i6->i6_conf, tb[IFLA_INET6_CONF],
- sizeof(i6->i6_conf));
+ sizeof(i6->i6_conf[0]) * i6->i6_conf_len);
+ }
if (tb[IFLA_INET6_TOKEN])
nla_memcpy(&i6->i6_token, tb[IFLA_INET6_TOKEN],
@@ -197,7 +206,7 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
map_stat_id = map_stat_id_from_IPSTATS_MIB_v1;
}
- len = min_t(int, __IPSTATS_MIB_MAX, len);
+ len = _NL_MIN(__IPSTATS_MIB_MAX, len);
for (i = 1; i < len; i++) {
memcpy(&stat, &cnt[i * sizeof(stat)], sizeof(stat));
rtnl_link_set_stat(link, map_stat_id[i], stat);
@@ -205,12 +214,13 @@ static int inet6_parse_protinfo(struct rtnl_link *link, struct nlattr *attr,
}
if (tb[IFLA_INET6_ICMP6STATS]) {
+#define _NL_ICMP6_MIB_MAX 6
unsigned char *cnt = nla_data(tb[IFLA_INET6_ICMP6STATS]);
uint64_t stat;
int i;
- int len = min_t(int, __ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
+ int len = _NL_MIN(_NL_ICMP6_MIB_MAX, nla_len(tb[IFLA_INET6_ICMP6STATS]) / 8);
- _NL_STATIC_ASSERT (__ICMP6_MIB_MAX == 6);
+ _NL_STATIC_ASSERT (__ICMP6_MIB_MAX >= _NL_ICMP6_MIB_MAX);
_NL_STATIC_ASSERT (RTNL_LINK_ICMP6_CSUMERRORS - RTNL_LINK_ICMP6_INMSGS + 1 == 5);
for (i = 1; i < len; i++) {
@@ -351,7 +361,7 @@ static void inet6_dump_details(struct rtnl_link *link,
nl_dump_line(p, " devconf:\n");
nl_dump_line(p, " ");
- for (i = 0; i < DEVCONF_MAX; i++) {
+ for (i = 0; i < (int) i6->i6_conf_len; i++) {
char buf2[64];
uint32_t value = i6->i6_conf[i];
int x, offset;
@@ -689,12 +699,42 @@ int rtnl_link_inet6_set_addr_gen_mode(struct rtnl_link *link, uint8_t mode)
return 0;
}
-static void __init inet6_init(void)
+/**
+ * Get value of a ipv6 link configuration setting
+ * @arg link Link object
+ * @arg cfgid Configuration identifier
+ * @arg res Result pointer
+ *
+ * Stores the value of the specified configuration setting in the provided
+ * result pointer.
+ *
+ * @return 0 on success or a negative error code.
+ * @return -NLE_RANGE cfgid is out of range or not provided by kernel.
+ * @return -NLE_NOATTR configuration setting not available
+ */
+int rtnl_link_inet6_get_conf(struct rtnl_link *link, unsigned int cfgid,
+ uint32_t *res)
+{
+ struct inet6_data *id;
+
+ if (!(id = rtnl_link_af_data(link, &inet6_ops)))
+ return -NLE_NOATTR;
+
+ if (cfgid >= id->i6_conf_len)
+ return -NLE_RANGE;
+
+ *res = id->i6_conf[cfgid];
+
+ return 0;
+}
+
+
+static void _nl_init inet6_init(void)
{
rtnl_link_af_register(&inet6_ops);
}
-static void __exit inet6_exit(void)
+static void _nl_exit inet6_exit(void)
{
rtnl_link_af_unregister(&inet6_ops);
}
diff --git a/lib/route/link/ip6gre.c b/lib/route/link/ip6gre.c
index 5d5c3a01..51d4609c 100644
--- a/lib/route/link/ip6gre.c
+++ b/lib/route/link/ip6gre.c
@@ -13,15 +13,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ip6gre.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IP6GRE_ATTR_LINK (1 << 0)
#define IP6GRE_ATTR_IFLAGS (1 << 1)
@@ -875,12 +879,12 @@ int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ip6gre_init(void)
+static void _nl_init ip6gre_init(void)
{
rtnl_link_register_info(&ip6gre_info_ops);
}
-static void __exit ip6gre_exit(void)
+static void _nl_exit ip6gre_exit(void)
{
rtnl_link_unregister_info(&ip6gre_info_ops);
}
diff --git a/lib/route/link/ip6tnl.c b/lib/route/link/ip6tnl.c
index cdc90241..9b3abfd1 100644
--- a/lib/route/link/ip6tnl.c
+++ b/lib/route/link/ip6tnl.c
@@ -16,16 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ip6tnl.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
-#include <netinet/in.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IP6_TNL_ATTR_LINK (1 << 0)
#define IP6_TNL_ATTR_LOCAL (1 << 1)
@@ -732,12 +735,12 @@ int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ip6_tnl_init(void)
+static void _nl_init ip6_tnl_init(void)
{
rtnl_link_register_info(&ip6_tnl_info_ops);
}
-static void __exit ip6_tnl_exit(void)
+static void _nl_exit ip6_tnl_exit(void)
{
rtnl_link_unregister_info(&ip6_tnl_info_ops);
}
diff --git a/lib/route/link/ip6vti.c b/lib/route/link/ip6vti.c
index 8c603abe..b6c7a1b2 100644
--- a/lib/route/link/ip6vti.c
+++ b/lib/route/link/ip6vti.c
@@ -13,15 +13,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ip6vti.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IP6VTI_ATTR_LINK (1 << 0)
#define IP6VTI_ATTR_IKEY (1 << 1)
@@ -543,12 +547,12 @@ int rtnl_link_ip6vti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ip6vti_init(void)
+static void _nl_init ip6vti_init(void)
{
rtnl_link_register_info(&ip6vti_info_ops);
}
-static void __exit ip6vti_exit(void)
+static void _nl_exit ip6vti_exit(void)
{
rtnl_link_unregister_info(&ip6vti_info_ops);
}
diff --git a/lib/route/link/ipgre.c b/lib/route/link/ipgre.c
index f5a4998b..bd3cc40f 100644
--- a/lib/route/link/ipgre.c
+++ b/lib/route/link/ipgre.c
@@ -16,15 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ipgre.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IPGRE_ATTR_LINK (1 << 0)
#define IPGRE_ATTR_IFLAGS (1 << 1)
@@ -879,13 +883,13 @@ int rtnl_link_ipgre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ipgre_init(void)
+static void _nl_init ipgre_init(void)
{
rtnl_link_register_info(&ipgre_info_ops);
rtnl_link_register_info(&ipgretap_info_ops);
}
-static void __exit ipgre_exit(void)
+static void _nl_exit ipgre_exit(void)
{
rtnl_link_unregister_info(&ipgre_info_ops);
rtnl_link_unregister_info(&ipgretap_info_ops);
diff --git a/lib/route/link/ipip.c b/lib/route/link/ipip.c
index e905ef99..74db8901 100644
--- a/lib/route/link/ipip.c
+++ b/lib/route/link/ipip.c
@@ -16,15 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ipip.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IPIP_ATTR_LINK (1 << 0)
#define IPIP_ATTR_LOCAL (1 << 1)
@@ -578,12 +582,12 @@ int rtnl_link_ipip_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ipip_init(void)
+static void _nl_init ipip_init(void)
{
rtnl_link_register_info(&ipip_info_ops);
}
-static void __exit ipip_exit(void)
+static void _nl_exit ipip_exit(void)
{
rtnl_link_unregister_info(&ipip_info_ops);
}
diff --git a/lib/route/link/ipvlan.c b/lib/route/link/ipvlan.c
index 020f2cb9..807942bb 100644
--- a/lib/route/link/ipvlan.c
+++ b/lib/route/link/ipvlan.c
@@ -16,16 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/ipvlan.h>
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define IPVLAN_HAS_MODE (1<<0)
@@ -257,12 +260,12 @@ int rtnl_link_ipvlan_str2mode(const char *name)
/** @} */
-static void __init ipvlan_init(void)
+static void _nl_init ipvlan_init(void)
{
rtnl_link_register_info(&ipvlan_info_ops);
}
-static void __exit ipvlan_exit(void)
+static void _nl_exit ipvlan_exit(void)
{
rtnl_link_unregister_info(&ipvlan_info_ops);
}
diff --git a/lib/route/link/ipvti.c b/lib/route/link/ipvti.c
index 9f9d3d68..fd578959 100644
--- a/lib/route/link/ipvti.c
+++ b/lib/route/link/ipvti.c
@@ -16,15 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/ipvti.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define IPVTI_ATTR_LINK (1 << 0)
#define IPVTI_ATTR_IKEY (1 << 1)
@@ -527,12 +531,12 @@ int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init ipvti_init(void)
+static void _nl_init ipvti_init(void)
{
rtnl_link_register_info(&ipvti_info_ops);
}
-static void __exit ipvti_exit(void)
+static void _nl_exit ipvti_exit(void)
{
rtnl_link_unregister_info(&ipvti_info_ops);
}
diff --git a/lib/route/link/link-api.h b/lib/route/link/link-api.h
new file mode 100644
index 00000000..0e54057d
--- /dev/null
+++ b/lib/route/link/link-api.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ */
+
+#ifndef NETLINK_LINK_API_H_
+#define NETLINK_LINK_API_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
+
+#include "nl-priv-dynamic-core/nl-core.h"
+
+/**
+ * @ingroup link_api
+ *
+ * Available operations to modules implementing a link info type.
+ */
+struct rtnl_link_info_ops
+{
+ /** Name of link info type, must match name on kernel side */
+ char * io_name;
+
+ /** Reference count, DO NOT MODIFY */
+ int io_refcnt;
+
+ /** Called to assign an info type to a link.
+ * Has to allocate enough resources to hold attributes. Can
+ * use link->l_info to store a pointer. */
+ int (*io_alloc)(struct rtnl_link *);
+
+ /** Called to parse the link info attribute.
+ * Must parse the attribute and assign all values to the link.
+ */
+ int (*io_parse)(struct rtnl_link *,
+ struct nlattr *,
+ struct nlattr *);
+
+ /** Called when the link object is dumped.
+ * Must dump the info type specific attributes. */
+ void (*io_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
+ struct nl_dump_params *);
+
+ /** Called when a link object is cloned.
+ * Must clone all info type specific attributes. */
+ int (*io_clone)(struct rtnl_link *, struct rtnl_link *);
+
+ /** Called when construction a link netlink message.
+ * Must append all info type specific attributes to the message. */
+ int (*io_put_attrs)(struct nl_msg *, struct rtnl_link *);
+
+ /** Called to release all resources previously allocated
+ * in either io_alloc() or io_parse(). */
+ void (*io_free)(struct rtnl_link *);
+
+ /** Called to compare link info parameters between two links. */
+ int (*io_compare)(struct rtnl_link *, struct rtnl_link *,
+ int flags);
+
+ struct nl_list_head io_list;
+};
+
+extern struct rtnl_link_info_ops *rtnl_link_info_ops_lookup(const char *);
+extern void rtnl_link_info_ops_get(struct rtnl_link_info_ops *);
+extern void rtnl_link_info_ops_put(struct rtnl_link_info_ops *);
+extern int rtnl_link_register_info(struct rtnl_link_info_ops *);
+extern int rtnl_link_unregister_info(struct rtnl_link_info_ops *);
+
+
+/**
+ * @ingroup link_api
+ *
+ * Available operations to modules implementing a link address family.
+ */
+struct rtnl_link_af_ops
+{
+ /** The address family this operations set implements */
+ const unsigned int ao_family;
+
+ /** Number of users of this operations, DO NOT MODIFY. */
+ int ao_refcnt;
+
+ /** Validation policy for IFLA_PROTINFO attribute. This pointer
+ * can be set to a nla_policy structure describing the minimal
+ * requirements the attribute must meet. Failure of meeting these
+ * requirements will result in a parsing error. */
+ const struct nla_policy *ao_protinfo_policy;
+
+ /** Called after address family has been assigned to link. Must
+ * allocate data buffer to hold address family specific data and
+ * store it in link->l_af_data. */
+ void * (*ao_alloc)(struct rtnl_link *);
+
+ /** Called when the link is cloned, must allocate a clone of the
+ * address family specific buffer and return it. */
+ void * (*ao_clone)(struct rtnl_link *, void *);
+
+ /** Called when the link gets freed. Must free all allocated data */
+ void (*ao_free)(struct rtnl_link *, void *);
+
+ /** Called if a IFLA_PROTINFO attribute needs to be parsed. Typically
+ * stores the parsed data in the address family specific buffer. */
+ int (*ao_parse_protinfo)(struct rtnl_link *,
+ struct nlattr *, void *);
+
+ /** Called if a IFLA_AF_SPEC attribute needs to be parsed. Typically
+ * stores the parsed data in the address family specific buffer. */
+ int (*ao_parse_af)(struct rtnl_link *,
+ struct nlattr *, void *);
+
+ /** Called if a link message is sent to the kernel. Must append the
+ * link address family specific attributes to the message. */
+ int (*ao_fill_af)(struct rtnl_link *,
+ struct nl_msg *msg, void *);
+
+ /** Called if the full IFLA_AF_SPEC data needs to be parsed. Typically
+ * stores the parsed data in the address family specific buffer. */
+ int (*ao_parse_af_full)(struct rtnl_link *,
+ struct nlattr *, void *);
+
+ /** Called for GETLINK message to the kernel. Used to append
+ * link address family specific attributes to the request message. */
+ int (*ao_get_af)(struct nl_msg *msg,
+ uint32_t *ext_filter_mask);
+
+ /** Dump address family specific link attributes */
+ void (*ao_dump[NL_DUMP_MAX+1])(struct rtnl_link *,
+ struct nl_dump_params *,
+ void *);
+
+ /** Comparison function
+ *
+ * Will be called when two links are compared for their af data. It
+ * takes two link objects in question, an object specific bitmask
+ * defining which attributes should be compared and flags to control
+ * the behaviour
+ *
+ * The function must return a bitmask with the relevant bit set for
+ * each attribute that mismatches
+ */
+ int (*ao_compare)(struct rtnl_link *,
+ struct rtnl_link *, int, uint32_t, int);
+
+ /* RTM_NEWLINK override
+ *
+ * Called if a change link request is set to the kernel. If this returns
+ * anything other than zero, RTM_NEWLINK will be overriden with
+ * RTM_SETLINK when rtnl_link_build_change_request() is called.
+ */
+ int (*ao_override_rtm)(struct rtnl_link *);
+
+ /** Called if a link message is sent to the kernel. Must append the
+ * link protocol specific attributes to the message. (IFLA_PROTINFO) */
+ int (*ao_fill_pi)(struct rtnl_link *,
+ struct nl_msg *msg, void *);
+
+ /** PROTINFO type
+ *
+ * Called if a link message is sent to the kernel. If this is set,
+ * the default IFLA_PROTINFO is bitmasked with what is specified
+ * here. (eg. NLA_F_NESTED)
+ */
+ const int ao_fill_pi_flags;
+
+ /** IFLA_AF_SPEC nesting override
+ *
+ * Called if a link message is sent to the kernel. If this is set,
+ * the AF specific nest is not created. Instead, AF specific attributes
+ * are nested directly in the IFLA_AF_SPEC attribute.
+ */
+ const int ao_fill_af_no_nest;
+};
+
+extern struct rtnl_link_af_ops *rtnl_link_af_ops_lookup(unsigned int);
+extern void rtnl_link_af_ops_put(struct rtnl_link_af_ops *);
+extern void * rtnl_link_af_alloc(struct rtnl_link *,
+ const struct rtnl_link_af_ops *);
+extern void * rtnl_link_af_data(const struct rtnl_link *,
+ const struct rtnl_link_af_ops *);
+extern int rtnl_link_af_register(struct rtnl_link_af_ops *);
+extern int rtnl_link_af_unregister(struct rtnl_link_af_ops *);
+extern int rtnl_link_af_data_compare(struct rtnl_link *a,
+ struct rtnl_link *b,
+ int family);
+extern int rtnl_link_info_data_compare(struct rtnl_link *a,
+ struct rtnl_link *b,
+ int flags);
+
+extern struct rtnl_link *link_lookup(struct nl_cache *cache, int ifindex);
+
+#endif
diff --git a/lib/route/link/macsec.c b/lib/route/link/macsec.c
index 16b65b04..a989eed8 100644
--- a/lib/route/link/macsec.c
+++ b/lib/route/link/macsec.c
@@ -15,17 +15,21 @@
*
* @{
*/
-#include <netlink-private/netlink.h>
+
+#include "nl-default.h"
+
+#include <linux/if_macsec.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/macsec.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink-private/utils.h>
-#include <linux/if_macsec.h>
+#include "nl-route.h"
+#include "link-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
/** @cond SKIP */
#define MACSEC_ATTR_SCI (1 << 0)
@@ -367,33 +371,38 @@ static int macsec_compare(struct rtnl_link *link_a, struct rtnl_link *link_b,
int diff = 0;
uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
-#define MACSEC_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MACSEC_ATTR_##ATTR, a, b, EXPR)
-
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
if (a->ce_mask & MACSEC_ATTR_SCI && b->ce_mask & MACSEC_ATTR_SCI)
- diff |= MACSEC_DIFF(SCI, a->sci != b->sci);
+ diff |= _DIFF(MACSEC_ATTR_SCI, a->sci != b->sci);
else if (a->ce_mask & MACSEC_ATTR_PORT && b->ce_mask & MACSEC_ATTR_PORT)
- diff |= MACSEC_DIFF(PORT, a->port != b->port);
+ diff |= _DIFF(MACSEC_ATTR_PORT, a->port != b->port);
- if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE && b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
- diff |= MACSEC_DIFF(ICV_LEN, a->icv_len != b->icv_len);
- diff |= MACSEC_DIFF(CIPHER_SUITE, a->cipher_suite != b->cipher_suite);
+ if (a->ce_mask & MACSEC_ATTR_CIPHER_SUITE &&
+ b->ce_mask & MACSEC_ATTR_CIPHER_SUITE) {
+ diff |= _DIFF(MACSEC_ATTR_ICV_LEN, a->icv_len != b->icv_len);
+ diff |= _DIFF(MACSEC_ATTR_CIPHER_SUITE,
+ a->cipher_suite != b->cipher_suite);
}
- if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT && b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
- int d = MACSEC_DIFF(REPLAY_PROTECT, a->replay_protect != b->replay_protect);
- if (a->replay_protect && b->replay_protect)
- d |= MACSEC_DIFF(WINDOW, a->window != b->window);
+ if (a->ce_mask & MACSEC_ATTR_REPLAY_PROTECT &&
+ b->ce_mask & MACSEC_ATTR_REPLAY_PROTECT) {
+ int d = _DIFF(MACSEC_ATTR_REPLAY_PROTECT,
+ a->replay_protect != b->replay_protect);
+ if (a->replay_protect && b->replay_protect) {
+ d |= _DIFF(MACSEC_ATTR_WINDOW, a->window != b->window);
+ }
diff |= d;
}
- diff |= MACSEC_DIFF(ENCODING_SA, a->encoding_sa != b->encoding_sa);
- diff |= MACSEC_DIFF(ENCRYPT, a->encrypt != b->encrypt);
- diff |= MACSEC_DIFF(PROTECT, a->protect != b->protect);
- diff |= MACSEC_DIFF(INC_SCI, a->send_sci != b->send_sci);
- diff |= MACSEC_DIFF(ES, a->end_station != b->end_station);
- diff |= MACSEC_DIFF(SCB, a->scb != b->scb);
- diff |= MACSEC_DIFF(VALIDATION, a->validate != b->validate);
-#undef MACSEC_DIFF
+ diff |= _DIFF(MACSEC_ATTR_ENCODING_SA,
+ a->encoding_sa != b->encoding_sa);
+ diff |= _DIFF(MACSEC_ATTR_ENCRYPT, a->encrypt != b->encrypt);
+ diff |= _DIFF(MACSEC_ATTR_PROTECT, a->protect != b->protect);
+ diff |= _DIFF(MACSEC_ATTR_INC_SCI, a->send_sci != b->send_sci);
+ diff |= _DIFF(MACSEC_ATTR_ES, a->end_station != b->end_station);
+ diff |= _DIFF(MACSEC_ATTR_SCB, a->scb != b->scb);
+ diff |= _DIFF(MACSEC_ATTR_VALIDATION, a->validate != b->validate);
+#undef _DIFF
return diff;
}
@@ -413,12 +422,12 @@ static struct rtnl_link_info_ops macsec_info_ops = {
.io_compare = macsec_compare,
};
-static void __init macsec_init(void)
+static void _nl_init macsec_init(void)
{
rtnl_link_register_info(&macsec_info_ops);
}
-static void __exit macsec_exit(void)
+static void _nl_exit macsec_exit(void)
{
rtnl_link_unregister_info(&macsec_info_ops);
}
@@ -652,9 +661,6 @@ int rtnl_link_macsec_set_offload(struct rtnl_link *link, uint8_t offload)
IS_MACSEC_LINK_ASSERT(link);
- if (offload > 1)
- return -NLE_INVAL;
-
info->offload = offload;
info->ce_mask |= MACSEC_ATTR_OFFLOAD;
diff --git a/lib/route/link/macvlan.c b/lib/route/link/macvlan.c
index df61bb20..5452d9eb 100644
--- a/lib/route/link/macvlan.c
+++ b/lib/route/link/macvlan.c
@@ -17,17 +17,22 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
+#include <linux/ethtool.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/macvlan.h>
#include <netlink/route/link/macvtap.h>
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define MACVLAN_HAS_MODE (1<<0)
@@ -855,13 +860,13 @@ int rtnl_link_macvtap_str2mode(const char *name)
/** @} */
-static void __init macvlan_init(void)
+static void _nl_init macvlan_init(void)
{
rtnl_link_register_info(&macvlan_info_ops);
rtnl_link_register_info(&macvtap_info_ops);
}
-static void __exit macvlan_exit(void)
+static void _nl_exit macvlan_exit(void)
{
rtnl_link_unregister_info(&macvlan_info_ops);
rtnl_link_unregister_info(&macvtap_info_ops);
diff --git a/lib/route/link/ppp.c b/lib/route/link/ppp.c
index a5fb400d..34ca5f66 100644
--- a/lib/route/link/ppp.c
+++ b/lib/route/link/ppp.c
@@ -14,11 +14,13 @@
* @{
*/
-#include <netlink/route/link/ppp.h>
+#include "nl-default.h"
-#include <netlink-private/netlink.h>
+#include <netlink/route/link/ppp.h>
#include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define PPP_ATTR_FD (1<<0)
@@ -204,12 +206,12 @@ int rtnl_link_ppp_get_fd(struct rtnl_link *link, int32_t *fd)
/** @} */
-static void __init ppp_init(void)
+static void _nl_init ppp_init(void)
{
rtnl_link_register_info(&ppp_info_ops);
}
-static void __exit ppp_exit(void)
+static void _nl_exit ppp_exit(void)
{
rtnl_link_unregister_info(&ppp_info_ops);
}
diff --git a/lib/route/link/sit.c b/lib/route/link/sit.c
index fabb811f..69dd3163 100644
--- a/lib/route/link/sit.c
+++ b/lib/route/link/sit.c
@@ -16,15 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_tunnel.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/sit.h>
-#include <netlink-private/route/link/api.h>
-#include <linux/if_tunnel.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define SIT_ATTR_LINK (1 << 0)
#define SIT_ATTR_LOCAL (1 << 1)
@@ -858,12 +862,12 @@ int rtnl_link_sit_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
return 0;
}
-static void __init sit_init(void)
+static void _nl_init sit_init(void)
{
rtnl_link_register_info(&sit_info_ops);
}
-static void __exit sit_exit(void)
+static void _nl_exit sit_exit(void)
{
rtnl_link_unregister_info(&sit_info_ops);
}
diff --git a/lib/route/link/sriov.c b/lib/route/link/sriov.c
index 3a728147..d47d1ddf 100644
--- a/lib/route/link/sriov.c
+++ b/lib/route/link/sriov.c
@@ -19,17 +19,38 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/route/link/api.h>
-#include <netlink/netlink.h>
-#include <netlink/route/link.h>
+#include "nl-default.h"
#include <linux/if_ether.h>
#include <linux/if_link.h>
-#include <netlink-private/route/link/sriov.h>
+
+#include <netlink/netlink.h>
+#include <netlink/route/link.h>
#include <netlink/route/link/sriov.h>
+#include "nl-route.h"
+#include "link-sriov.h"
+#include "link-api.h"
+
/** @cond SKIP */
+struct rtnl_link_vf {
+ struct nl_list_head vf_list;
+ int ce_refcnt;
+ uint32_t ce_mask;
+ uint32_t vf_index;
+ uint64_t vf_guid_node;
+ uint64_t vf_guid_port;
+ uint32_t vf_linkstate;
+ struct nl_addr *vf_lladdr;
+ uint32_t vf_max_tx_rate;
+ uint32_t vf_min_tx_rate;
+ uint32_t vf_rate;
+ uint32_t vf_rss_query_en;
+ uint32_t vf_spoofchk;
+ uint64_t vf_stats[RTNL_LINK_VF_STATS_MAX + 1];
+ uint32_t vf_trust;
+ struct nl_vf_vlans *vf_vlans;
+};
#define SRIOVON "on"
#define SRIOVOFF "off"
diff --git a/lib/route/link/team.c b/lib/route/link/team.c
index 1bcc86ed..0f1161be 100644
--- a/lib/route/link/team.c
+++ b/lib/route/link/team.c
@@ -14,11 +14,13 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/team.h>
+#include "link-api.h"
+
/**
* Allocate link object of type team
*
@@ -89,12 +91,12 @@ static struct rtnl_link_info_ops team_info_ops = {
.io_name = "team",
};
-static void __init team_init(void)
+static void _nl_init team_init(void)
{
rtnl_link_register_info(&team_info_ops);
}
-static void __exit team_exit(void)
+static void _nl_exit team_exit(void)
{
rtnl_link_unregister_info(&team_info_ops);
}
diff --git a/lib/route/link/veth.c b/lib/route/link/veth.c
index 37f43f69..be4b795c 100644
--- a/lib/route/link/veth.c
+++ b/lib/route/link/veth.c
@@ -16,17 +16,20 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+#include <linux/veth.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/veth.h>
-#include <linux/if_link.h>
-#include <linux/veth.h>
+#include "nl-route.h"
+#include "link-api.h"
static struct nla_policy veth_policy[VETH_INFO_MAX+1] = {
[VETH_INFO_PEER] = { .minlen = sizeof(struct ifinfomsg) },
@@ -289,12 +292,12 @@ int rtnl_link_veth_add(struct nl_sock *sock, const char *name,
/** @} */
-static void __init veth_init(void)
+static void _nl_init veth_init(void)
{
rtnl_link_register_info(&veth_info_ops);
}
-static void __exit veth_exit(void)
+static void _nl_exit veth_exit(void)
{
rtnl_link_unregister_info(&veth_info_ops);
}
diff --git a/lib/route/link/vlan.c b/lib/route/link/vlan.c
index 36f88225..60e4358f 100644
--- a/lib/route/link/vlan.c
+++ b/lib/route/link/vlan.c
@@ -16,16 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_vlan.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/vlan.h>
-#include <linux/if_vlan.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define VLAN_HAS_ID (1<<0)
@@ -288,9 +291,12 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
{
struct vlan_info *vi = link->l_info;
struct nlattr *data;
+ int nest_count = 0;
if (!(data = nla_nest_start(msg, IFLA_INFO_DATA)))
- return -NLE_MSGSIZE;
+ goto nla_put_failure;
+
+ nest_count++;
if (vi->vi_mask & VLAN_HAS_ID)
NLA_PUT_U16(msg, IFLA_VLAN_ID, vi->vi_vlan_id);
@@ -315,6 +321,8 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
if (!(qos = nla_nest_start(msg, IFLA_VLAN_INGRESS_QOS)))
goto nla_put_failure;
+ nest_count++;
+
for (i = 0; i <= VLAN_PRIO_MAX; i++) {
if (vi->vi_ingress_qos_mask & (1 << i)) {
map.from = i;
@@ -325,6 +333,7 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
}
nla_nest_end(msg, qos);
+ nest_count--;
}
if (vi->vi_mask & VLAN_HAS_EGRESS_QOS) {
@@ -335,6 +344,8 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
if (!(qos = nla_nest_start(msg, IFLA_VLAN_EGRESS_QOS)))
goto nla_put_failure;
+ nest_count++;
+
for (i = 0; i < vi->vi_negress; i++) {
map.from = vi->vi_egress_qos[i].vm_from;
map.to = vi->vi_egress_qos[i].vm_to;
@@ -343,13 +354,16 @@ static int vlan_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
}
nla_nest_end(msg, qos);
+ nest_count--;
}
nla_nest_end(msg, data);
+ return 0;
nla_put_failure:
-
- return 0;
+ for (; nest_count > 0; nest_count--)
+ nla_nest_cancel(msg, data);
+ return -NLE_MSGSIZE;
}
static struct rtnl_link_info_ops vlan_info_ops = {
@@ -661,12 +675,12 @@ int rtnl_link_vlan_str2flags(const char *name)
/** @} */
-static void __init vlan_init(void)
+static void _nl_init vlan_init(void)
{
rtnl_link_register_info(&vlan_info_ops);
}
-static void __exit vlan_exit(void)
+static void _nl_exit vlan_exit(void)
{
rtnl_link_unregister_info(&vlan_info_ops);
}
diff --git a/lib/route/link/vrf.c b/lib/route/link/vrf.c
index c4edd3ef..17cb3bde 100644
--- a/lib/route/link/vrf.c
+++ b/lib/route/link/vrf.c
@@ -17,17 +17,20 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+#include <linux/rtnetlink.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/vrf.h>
-#include <linux/if_link.h>
-#include <linux-private/linux/rtnetlink.h>
+#include "nl-route.h"
+#include "link-api.h"
#define VRF_TABLE_ID_MAX RT_TABLE_MAX
@@ -244,12 +247,12 @@ int rtnl_link_vrf_set_tableid(struct rtnl_link *link, uint32_t id)
/** @} */
-static void __init vrf_init(void)
+static void _nl_init vrf_init(void)
{
rtnl_link_register_info(&vrf_info_ops);
}
-static void __exit vrf_exit(void)
+static void _nl_exit vrf_exit(void)
{
rtnl_link_unregister_info(&vrf_info_ops);
}
diff --git a/lib/route/link/vxlan.c b/lib/route/link/vxlan.c
index 7b8429c8..4606dd5f 100644
--- a/lib/route/link/vxlan.c
+++ b/lib/route/link/vxlan.c
@@ -16,16 +16,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_link.h>
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
-#include <netlink-private/route/link/api.h>
#include <netlink/route/link/vxlan.h>
-#include <linux/if_link.h>
+#include "nl-route.h"
+#include "link-api.h"
/** @cond SKIP */
#define VXLAN_ATTR_ID (1<<0)
@@ -616,37 +619,41 @@ static int vxlan_compare(struct rtnl_link *link_a, struct rtnl_link *link_b,
int diff = 0;
uint32_t attrs = flags & LOOSE_COMPARISON ? b->ce_mask : ~0;
-#define VXLAN_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, VXLAN_ATTR_##ATTR, a, b, EXPR)
-
- diff |= VXLAN_DIFF(ID, a->vxi_id != b->vxi_id);
- diff |= VXLAN_DIFF(GROUP, a->vxi_group != b->vxi_group);
- diff |= VXLAN_DIFF(LINK, a->vxi_link != b->vxi_link);
- diff |= VXLAN_DIFF(LOCAL, a->vxi_local != b->vxi_local);
- diff |= VXLAN_DIFF(TOS, a->vxi_tos != b->vxi_tos);
- diff |= VXLAN_DIFF(TTL, a->vxi_ttl != b->vxi_ttl);
- diff |= VXLAN_DIFF(LEARNING, a->vxi_learning != b->vxi_learning);
- diff |= VXLAN_DIFF(AGEING, a->vxi_ageing != b->vxi_ageing);
- diff |= VXLAN_DIFF(LIMIT, a->vxi_limit != b->vxi_limit);
- diff |= VXLAN_DIFF(PORT_RANGE,
- a->vxi_port_range.low != b->vxi_port_range.low);
- diff |= VXLAN_DIFF(PORT_RANGE,
- a->vxi_port_range.high != b->vxi_port_range.high);
- diff |= VXLAN_DIFF(PROXY, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(RSC, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(L2MISS, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(L3MISS, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(PORT, a->vxi_port != b->vxi_port);
- diff |= VXLAN_DIFF(GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6, sizeof(a->vxi_group6)) != 0);
- diff |= VXLAN_DIFF(LOCAL6, memcmp(&a->vxi_local6, &b->vxi_local6, sizeof(a->vxi_local6)) != 0);
- diff |= VXLAN_DIFF(UDP_CSUM, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_TX, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(UDP_ZERO_CSUM6_RX, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(REMCSUM_TX, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(REMCSUM_RX, a->vxi_proxy != b->vxi_proxy);
- diff |= VXLAN_DIFF(COLLECT_METADATA, a->vxi_collect_metadata != b->vxi_collect_metadata);
- diff |= VXLAN_DIFF(LABEL, a->vxi_label != b->vxi_label);
- diff |= VXLAN_DIFF(FLAGS, a->vxi_flags != b->vxi_flags);
-#undef VXLAN_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(VXLAN_ATTR_ID, a->vxi_id != b->vxi_id);
+ diff |= _DIFF(VXLAN_ATTR_GROUP, a->vxi_group != b->vxi_group);
+ diff |= _DIFF(VXLAN_ATTR_LINK, a->vxi_link != b->vxi_link);
+ diff |= _DIFF(VXLAN_ATTR_LOCAL, a->vxi_local != b->vxi_local);
+ diff |= _DIFF(VXLAN_ATTR_TOS, a->vxi_tos != b->vxi_tos);
+ diff |= _DIFF(VXLAN_ATTR_TTL, a->vxi_ttl != b->vxi_ttl);
+ diff |= _DIFF(VXLAN_ATTR_LEARNING, a->vxi_learning != b->vxi_learning);
+ diff |= _DIFF(VXLAN_ATTR_AGEING, a->vxi_ageing != b->vxi_ageing);
+ diff |= _DIFF(VXLAN_ATTR_LIMIT, a->vxi_limit != b->vxi_limit);
+ diff |= _DIFF(VXLAN_ATTR_PORT_RANGE,
+ a->vxi_port_range.low != b->vxi_port_range.low);
+ diff |= _DIFF(VXLAN_ATTR_PORT_RANGE,
+ a->vxi_port_range.high != b->vxi_port_range.high);
+ diff |= _DIFF(VXLAN_ATTR_PROXY, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_RSC, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_L2MISS, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_L3MISS, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_PORT, a->vxi_port != b->vxi_port);
+ diff |= _DIFF(VXLAN_ATTR_GROUP6, memcmp(&a->vxi_group6, &b->vxi_group6,
+ sizeof(a->vxi_group6)) != 0);
+ diff |= _DIFF(VXLAN_ATTR_LOCAL6, memcmp(&a->vxi_local6, &b->vxi_local6,
+ sizeof(a->vxi_local6)) != 0);
+ diff |= _DIFF(VXLAN_ATTR_UDP_CSUM, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_TX,
+ a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_UDP_ZERO_CSUM6_RX,
+ a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_REMCSUM_TX, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_REMCSUM_RX, a->vxi_proxy != b->vxi_proxy);
+ diff |= _DIFF(VXLAN_ATTR_COLLECT_METADATA,
+ a->vxi_collect_metadata != b->vxi_collect_metadata);
+ diff |= _DIFF(VXLAN_ATTR_LABEL, a->vxi_label != b->vxi_label);
+ diff |= _DIFF(VXLAN_ATTR_FLAGS, a->vxi_flags != b->vxi_flags);
+#undef _DIFF
return diff;
}
@@ -1767,12 +1774,12 @@ int rtnl_link_vxlan_get_flags(struct rtnl_link *link, uint32_t *out_flags)
/** @} */
-static void __init vxlan_init(void)
+static void _nl_init vxlan_init(void)
{
rtnl_link_register_info(&vxlan_info_ops);
}
-static void __exit vxlan_exit(void)
+static void _nl_exit vxlan_exit(void)
{
rtnl_link_unregister_info(&vxlan_info_ops);
}
diff --git a/lib/route/link/xfrmi.c b/lib/route/link/xfrmi.c
index 92531f24..09ceb809 100644
--- a/lib/route/link/xfrmi.c
+++ b/lib/route/link/xfrmi.c
@@ -18,14 +18,17 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/attr.h>
#include <netlink/utils.h>
#include <netlink/object.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link/xfrmi.h>
-#include <netlink-private/route/link/api.h>
+
+#include "nl-route.h"
+#include "link-api.h"
#define XFRMI_ATTR_LINK (1 << 0)
#define XFRMI_ATTR_IF_ID (1 << 1)
@@ -248,7 +251,7 @@ int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index)
* @arg link Link object
* @arg out_link The output value on success
*
- * @return 0 on sucess or a negative error code
+ * @return 0 on success or a negative error code
*/
int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link)
{
@@ -287,7 +290,7 @@ int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id)
* @arg link Link object
* @arg out_if_id The output value on success
*
- * @return 0 on sucess or a negative error code
+ * @return 0 on success or a negative error code
*/
int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id)
{
@@ -302,12 +305,12 @@ int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id)
return 0;
}
-static void __init xfrmi_init(void)
+static void _nl_init xfrmi_init(void)
{
rtnl_link_register_info(&xfrmi_info_ops);
}
-static void __exit xfrmi_exit(void)
+static void _nl_exit xfrmi_exit(void)
{
rtnl_link_unregister_info(&xfrmi_info_ops);
}
diff --git a/lib/route/mdb.c b/lib/route/mdb.c
index 459959ee..7749c164 100644
--- a/lib/route/mdb.c
+++ b/lib/route/mdb.c
@@ -3,16 +3,41 @@
* lib/route/mdb.c Multicast Database
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/if_bridge.h>
+
#include <netlink/netlink.h>
#include <netlink/route/mdb.h>
+#include <netlink/route/nexthop.h>
#include <netlink/utils.h>
-#include <linux/if_bridge.h>
+#include <netlink/route/rtnl.h>
+
+#include "nl-route.h"
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-core/cache-api.h"
/** @cond SKIP */
#define MDB_ATTR_IFINDEX 0x000001
#define MDB_ATTR_ENTRIES 0x000002
+struct rtnl_mdb {
+ NLHDR_COMMON
+ uint32_t ifindex;
+
+ struct nl_list_head mdb_entry_list;
+};
+
+struct rtnl_mdb_entry {
+ struct nl_list_head mdb_list;
+ struct nl_addr *addr;
+ uint32_t ifindex;
+ uint16_t vid;
+ uint16_t proto;
+ uint8_t state;
+};
+
static struct rtnl_mdb_entry *rtnl_mdb_entry_alloc(void);
static void rtnl_mdb_entry_free(struct rtnl_mdb_entry *mdb_entry);
@@ -55,9 +80,9 @@ static uint64_t mdb_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_mdb_entry *a_entry, *b_entry;
uint64_t diff = 0;
-#define MDB_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, MDB_ATTR_##ATTR, a, b, EXPR)
- diff |= MDB_DIFF(IFINDEX, a->ifindex != b->ifindex);
-#undef MDB_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(MDB_ATTR_IFINDEX, a->ifindex != b->ifindex);
+#undef _DIFF
a_entry = nl_list_entry(a->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
b_entry = nl_list_entry(b->mdb_entry_list.next, struct rtnl_mdb_entry, mdb_list);
@@ -453,12 +478,12 @@ static struct nl_cache_ops rtnl_mdb_ops = {
.co_obj_ops = &mdb_obj_ops,
};
-static void __init mdb_init(void)
+static void _nl_init mdb_init(void)
{
nl_cache_mngt_register(&rtnl_mdb_ops);
}
-static void __exit mdb_exit(void)
+static void _nl_exit mdb_exit(void)
{
nl_cache_mngt_unregister(&rtnl_mdb_ops);
}
diff --git a/lib/route/neigh.c b/lib/route/neigh.c
index e1ef6a14..91500244 100644
--- a/lib/route/neigh.c
+++ b/lib/route/neigh.c
@@ -143,7 +143,8 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/hashtable.h>
@@ -152,7 +153,36 @@
#include <netlink/route/link.h>
#include <netlink/hashtable.h>
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
/** @cond SKIP */
+struct rtnl_ncacheinfo {
+ uint32_t nci_confirmed; /**< Time since neighbour validty was last confirmed */
+ uint32_t nci_used; /**< Time since neighbour entry was last ued */
+ uint32_t nci_updated; /**< Time since last update */
+ uint32_t nci_refcnt; /**< Reference counter */
+};
+
+struct rtnl_neigh {
+ NLHDR_COMMON
+ uint32_t n_family;
+ uint32_t n_ifindex;
+ uint16_t n_state;
+ uint8_t n_flags;
+ uint8_t n_type;
+ struct nl_addr *n_lladdr;
+ struct nl_addr *n_dst;
+ uint32_t n_nhid;
+ uint32_t n_probes;
+ struct rtnl_ncacheinfo n_cacheinfo;
+ uint32_t n_state_mask;
+ uint32_t n_flag_mask;
+ uint32_t n_master;
+ uint16_t n_vlan;
+};
+
#define NEIGH_ATTR_FLAGS 0x01
#define NEIGH_ATTR_STATE 0x02
#define NEIGH_ATTR_LLADDR 0x04
@@ -164,6 +194,7 @@
#define NEIGH_ATTR_PROBES 0x100
#define NEIGH_ATTR_MASTER 0x200
#define NEIGH_ATTR_VLAN 0x400
+#define NEIGH_ATTR_NHID 0x800
static struct nl_cache_ops rtnl_neigh_ops;
static struct nl_object_ops neigh_obj_ops;
@@ -210,7 +241,7 @@ static void neigh_keygen(struct nl_object *obj, uint32_t *hashkey,
uint32_t n_ifindex;
uint16_t n_vlan;
char n_addr[0];
- } __attribute__((packed)) *nkey;
+ } _nl_packed *nkey;
#ifdef NL_DEBUG
char buf[INET6_ADDRSTRLEN+5];
#endif
@@ -265,27 +296,26 @@ static uint64_t neigh_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_neigh *b = (struct rtnl_neigh *) _b;
uint64_t diff = 0;
-#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR)
-
- diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex);
- diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family);
- diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type);
- diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
- diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst));
- diff |= NEIGH_DIFF(MASTER, a->n_master != b->n_master);
- diff |= NEIGH_DIFF(VLAN, a->n_vlan != b->n_vlan);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(NEIGH_ATTR_IFINDEX, a->n_ifindex != b->n_ifindex);
+ diff |= _DIFF(NEIGH_ATTR_FAMILY, a->n_family != b->n_family);
+ diff |= _DIFF(NEIGH_ATTR_TYPE, a->n_type != b->n_type);
+ diff |= _DIFF(NEIGH_ATTR_LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr));
+ diff |= _DIFF(NEIGH_ATTR_DST, nl_addr_cmp(a->n_dst, b->n_dst));
+ diff |= _DIFF(NEIGH_ATTR_MASTER, a->n_master != b->n_master);
+ diff |= _DIFF(NEIGH_ATTR_VLAN, a->n_vlan != b->n_vlan);
+ diff |= _DIFF(NEIGH_ATTR_NHID, a->n_nhid != b->n_nhid);
if (flags & LOOSE_COMPARISON) {
- diff |= NEIGH_DIFF(STATE,
- (a->n_state ^ b->n_state) & b->n_state_mask);
- diff |= NEIGH_DIFF(FLAGS,
- (a->n_flags ^ b->n_flags) & b->n_flag_mask);
+ diff |= _DIFF(NEIGH_ATTR_STATE,
+ (a->n_state ^ b->n_state) & b->n_state_mask);
+ diff |= _DIFF(NEIGH_ATTR_FLAGS,
+ (a->n_flags ^ b->n_flags) & b->n_flag_mask);
} else {
- diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state);
- diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags);
+ diff |= _DIFF(NEIGH_ATTR_STATE, a->n_state != b->n_state);
+ diff |= _DIFF(NEIGH_ATTR_FLAGS, a->n_flags != b->n_flags);
}
-
-#undef NEIGH_DIFF
+#undef _DIFF
return diff;
}
@@ -302,6 +332,7 @@ static const struct trans_tbl neigh_attrs[] = {
__ADD(NEIGH_ATTR_PROBES, probes),
__ADD(NEIGH_ATTR_MASTER, master),
__ADD(NEIGH_ATTR_VLAN, vlan),
+ __ADD(NEIGH_ATTR_NHID, nhid),
};
static char *neigh_attrs2str(int attrs, char *buf, size_t len)
@@ -318,6 +349,7 @@ static uint32_t neigh_id_attrs_get(struct nl_object *obj)
if (neigh->n_flags & NTF_SELF)
return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX |
((neigh->ce_mask & NEIGH_ATTR_DST) ? NEIGH_ATTR_DST: 0) |
+ ((neigh->ce_mask & NEIGH_ATTR_NHID) ? NEIGH_ATTR_NHID: 0) |
((neigh->ce_mask & NEIGH_ATTR_VLAN) ? NEIGH_ATTR_VLAN : 0));
else
return (NEIGH_ATTR_LLADDR | NEIGH_ATTR_FAMILY | NEIGH_ATTR_MASTER | NEIGH_ATTR_VLAN);
@@ -419,6 +451,11 @@ int rtnl_neigh_parse(struct nlmsghdr *n, struct rtnl_neigh **result)
neigh->ce_mask |= NEIGH_ATTR_VLAN;
}
+ if (tb[NDA_NH_ID]) {
+ neigh->n_nhid = nla_get_u32(tb[NDA_NH_ID]);
+ neigh->ce_mask |= NEIGH_ATTR_NHID;
+ }
+
/*
* Get the bridge index for AF_BRIDGE family entries
*/
@@ -511,6 +548,9 @@ static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p)
if (n->ce_mask & NEIGH_ATTR_VLAN)
nl_dump(p, "vlan %d ", n->n_vlan);
+ if (n->ce_mask & NEIGH_ATTR_NHID)
+ nl_dump(p, "nhid %u ", n->n_nhid);
+
if (n->ce_mask & NEIGH_ATTR_MASTER) {
if (link_cache)
nl_dump(p, "%s ", rtnl_link_i2name(link_cache, n->n_master,
@@ -721,6 +761,9 @@ static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags,
if (tmpl->ce_mask & NEIGH_ATTR_VLAN)
NLA_PUT_U16(msg, NDA_VLAN, tmpl->n_vlan);
+ if (tmpl->ce_mask & NEIGH_ATTR_NHID)
+ NLA_PUT_U32(msg, NDA_NH_ID, tmpl->n_nhid);
+
*result = msg;
return 0;
@@ -771,7 +814,7 @@ int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags,
* - Destination address (rtnl_neigh_set_dst())
* - Link layer address (rtnl_neigh_set_lladdr())
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags)
{
@@ -826,7 +869,7 @@ int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags,
* sends the request to the kernel and waits for the next ACK to be
* received and thus blocks until the request has been fullfilled.
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh,
int flags)
@@ -1066,6 +1109,20 @@ int rtnl_neigh_get_master(struct rtnl_neigh *neigh) {
return neigh->n_master;
}
+void rtnl_neigh_set_nhid(struct rtnl_neigh *neigh, uint32_t nhid)
+{
+ neigh->n_nhid = nhid;
+ neigh->ce_mask |= NEIGH_ATTR_NHID;
+}
+
+int rtnl_neigh_get_nhid(struct rtnl_neigh *neigh, uint32_t *out_val) {
+ if (!(neigh->ce_mask & NEIGH_ATTR_NHID))
+ return -NLE_NOATTR;
+
+ *out_val = neigh->n_nhid;
+ return NLE_SUCCESS;
+}
+
/** @} */
static struct nl_object_ops neigh_obj_ops = {
@@ -1107,12 +1164,12 @@ static struct nl_cache_ops rtnl_neigh_ops = {
.co_obj_ops = &neigh_obj_ops,
};
-static void __init neigh_init(void)
+static void _nl_init neigh_init(void)
{
nl_cache_mngt_register(&rtnl_neigh_ops);
}
-static void __exit neigh_exit(void)
+static void _nl_exit neigh_exit(void)
{
nl_cache_mngt_unregister(&rtnl_neigh_ops);
}
diff --git a/lib/route/neightbl.c b/lib/route/neightbl.c
index c4244fc6..a699867d 100644
--- a/lib/route/neightbl.c
+++ b/lib/route/neightbl.c
@@ -10,14 +10,130 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/neightbl.h>
#include <netlink/route/link.h>
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+struct rtnl_neightbl_parms {
+ /**
+ * Interface index of the device this parameter set is assigned
+ * to or 0 for the default set.
+ */
+ uint32_t ntp_ifindex;
+
+ /**
+ * Number of references to this parameter set.
+ */
+ uint32_t ntp_refcnt;
+
+ /**
+ * Queue length for pending arp requests, i.e. the number of
+ * packets which are accepted from other layers while the
+ * neighbour address is still being resolved
+ */
+ uint32_t ntp_queue_len;
+
+ /**
+ * Number of requests to send to the user level ARP daemon.
+ * Specify 0 to disable.
+ */
+ uint32_t ntp_app_probes;
+
+ /**
+ * Maximum number of retries for unicast solicitation.
+ */
+ uint32_t ntp_ucast_probes;
+
+ /**
+ * Maximum number of retries for multicast solicitation.
+ */
+ uint32_t ntp_mcast_probes;
+
+ /**
+ * Base value in milliseconds to ompute reachable time, see RFC2461.
+ */
+ uint64_t ntp_base_reachable_time;
+
+ /**
+ * Actual reachable time (read-only)
+ */
+ uint64_t ntp_reachable_time; /* secs */
+
+ /**
+ * The time in milliseconds between retransmitted Neighbor
+ * Solicitation messages.
+ */
+ uint64_t ntp_retrans_time;
+
+ /**
+ * Interval in milliseconds to check for stale neighbour
+ * entries.
+ */
+ uint64_t ntp_gc_stale_time; /* secs */
+
+ /**
+ * Delay in milliseconds for the first time probe if
+ * the neighbour is reachable.
+ */
+ uint64_t ntp_probe_delay; /* secs */
+
+ /**
+ * Maximum delay in milliseconds of an answer to a neighbour
+ * solicitation message.
+ */
+ uint64_t ntp_anycast_delay;
+
+ /**
+ * Minimum age in milliseconds before a neighbour entry
+ * may be replaced.
+ */
+ uint64_t ntp_locktime;
+
+ /**
+ * Delay in milliseconds before answering to an ARP request
+ * for which a proxy ARP entry exists.
+ */
+ uint64_t ntp_proxy_delay;
+
+ /**
+ * Queue length for the delayed proxy arp requests.
+ */
+ uint32_t ntp_proxy_qlen;
+
+ /**
+ * Mask of available parameter attributes
+ */
+ uint32_t ntp_mask;
+};
+
+#define NTBLNAMSIZ 32
+
+/**
+ * Neighbour table
+ * @ingroup neightbl
+ */
+struct rtnl_neightbl {
+ NLHDR_COMMON
+
+ char nt_name[NTBLNAMSIZ];
+ uint32_t nt_family;
+ uint32_t nt_gc_thresh1;
+ uint32_t nt_gc_thresh2;
+ uint32_t nt_gc_thresh3;
+ uint64_t nt_gc_interval;
+ struct ndt_config nt_config;
+ struct rtnl_neightbl_parms nt_parms;
+ struct ndt_stats nt_stats;
+};
+
/** @cond SKIP */
#define NEIGHTBL_ATTR_FAMILY 0x001
#define NEIGHTBL_ATTR_STATS 0x002
@@ -56,16 +172,18 @@ static uint64_t neightbl_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_neightbl *b = (struct rtnl_neightbl *)_b;
uint64_t diff = 0;
-#define NT_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGHTBL_ATTR_##ATTR, a, b, EXPR)
-
- diff |= NT_DIFF(FAMILY, a->nt_family != b->nt_family);
- diff |= NT_DIFF(NAME, strcmp(a->nt_name, b->nt_name));
- diff |= NT_DIFF(THRESH1, a->nt_gc_thresh1 != b->nt_gc_thresh1);
- diff |= NT_DIFF(THRESH2, a->nt_gc_thresh2 != b->nt_gc_thresh2);
- diff |= NT_DIFF(THRESH3, a->nt_gc_thresh3 != b->nt_gc_thresh3);
- diff |= NT_DIFF(GC_INTERVAL, a->nt_gc_interval != b->nt_gc_interval);
-
-#undef NT_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(NEIGHTBL_ATTR_FAMILY, a->nt_family != b->nt_family);
+ diff |= _DIFF(NEIGHTBL_ATTR_NAME, strcmp(a->nt_name, b->nt_name));
+ diff |= _DIFF(NEIGHTBL_ATTR_THRESH1,
+ a->nt_gc_thresh1 != b->nt_gc_thresh1);
+ diff |= _DIFF(NEIGHTBL_ATTR_THRESH2,
+ a->nt_gc_thresh2 != b->nt_gc_thresh2);
+ diff |= _DIFF(NEIGHTBL_ATTR_THRESH3,
+ a->nt_gc_thresh3 != b->nt_gc_thresh3);
+ diff |= _DIFF(NEIGHTBL_ATTR_GC_INTERVAL,
+ a->nt_gc_interval != b->nt_gc_interval);
+#undef _DIFF
if (!(a->ce_mask & NEIGHTBL_ATTR_PARMS) &&
!(b->ce_mask & NEIGHTBL_ATTR_PARMS))
@@ -182,10 +300,10 @@ static int neightbl_msg_parser(struct nl_cache_ops *ops,
if (err < 0)
goto errout;
-#define COPY_ENTRY(name, var) \
- if (tbp[NDTPA_##name]) { \
- p->ntp_##var = nla_get_u32(tbp[NDTPA_##name]); \
- p->ntp_mask |= NEIGHTBLPARM_ATTR_##name; \
+#define COPY_ENTRY(name, var) \
+ if (tbp[NDTPA_##name]) { \
+ p->ntp_##var = nla_get_u32(tbp[NDTPA_##name]); \
+ p->ntp_mask |= NEIGHTBLPARM_ATTR_##name; \
}
COPY_ENTRY(IFINDEX, ifindex);
@@ -414,7 +532,7 @@ struct rtnl_neightbl *rtnl_neightbl_get(struct nl_cache *cache,
if (cache->c_ops != &rtnl_neightbl_ops)
return NULL;
- nl_list_for_each_entry (nt, &cache->c_items, ce_list) {
+ nl_list_for_each_entry(nt, &cache->c_items, ce_list) {
if (!strcasecmp(nt->nt_name, name) &&
((!ifindex && !nt->nt_parms.ntp_ifindex) ||
(ifindex && ifindex == nt->nt_parms.ntp_ifindex))) {
@@ -803,12 +921,12 @@ static struct nl_cache_ops rtnl_neightbl_ops = {
.co_obj_ops = &neightbl_obj_ops,
};
-static void __init neightbl_init(void)
+static void _nl_init neightbl_init(void)
{
nl_cache_mngt_register(&rtnl_neightbl_ops);
}
-static void __exit neightbl_exit(void)
+static void _nl_exit neightbl_exit(void)
{
nl_cache_mngt_unregister(&rtnl_neightbl_ops);
}
diff --git a/lib/route/netconf.c b/lib/route/netconf.c
index 50c91bfe..7863da66 100644
--- a/lib/route/netconf.c
+++ b/lib/route/netconf.c
@@ -11,14 +11,21 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/netconf.h>
+#include <linux/socket.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/netconf.h>
-#include <linux/netconf.h>
-#include <linux/socket.h>
#include <netlink/hashtable.h>
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-priv-dynamic-core/object-api.h"
+
/** @cond SKIP */
#define NETCONF_ATTR_FAMILY 0x0001
#define NETCONF_ATTR_IFINDEX 0x0002
@@ -270,7 +277,7 @@ static void netconf_keygen(struct nl_object *obj, uint32_t *hashkey,
struct nc_hash_key {
int nc_family;
int nc_index;
- } __attribute__((packed)) nckey;
+ } _nl_packed nckey;
nckey_sz = sizeof(nckey);
nckey.nc_family = nc->family;
@@ -289,19 +296,19 @@ static uint64_t netconf_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_netconf *b = (struct rtnl_netconf *) _b;
uint64_t diff = 0;
-#define NETCONF_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NETCONF_ATTR_##ATTR, a, b, EXPR)
-
- diff |= NETCONF_DIFF(FAMILY, a->family != b->family);
- diff |= NETCONF_DIFF(IFINDEX, a->ifindex != b->ifindex);
- diff |= NETCONF_DIFF(RP_FILTER, a->rp_filter != b->rp_filter);
- diff |= NETCONF_DIFF(FWDING, a->forwarding != b->forwarding);
- diff |= NETCONF_DIFF(MC_FWDING, a->mc_forwarding != b->mc_forwarding);
- diff |= NETCONF_DIFF(PROXY_NEIGH, a->proxy_neigh != b->proxy_neigh);
- diff |= NETCONF_DIFF(IGNORE_RT_LINKDWN,
- a->ignore_routes_linkdown != b->ignore_routes_linkdown);
- diff |= NETCONF_DIFF(INPUT, a->input != b->input);
-
-#undef NETCONF_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(NETCONF_ATTR_FAMILY, a->family != b->family);
+ diff |= _DIFF(NETCONF_ATTR_IFINDEX, a->ifindex != b->ifindex);
+ diff |= _DIFF(NETCONF_ATTR_RP_FILTER, a->rp_filter != b->rp_filter);
+ diff |= _DIFF(NETCONF_ATTR_FWDING, a->forwarding != b->forwarding);
+ diff |= _DIFF(NETCONF_ATTR_MC_FWDING,
+ a->mc_forwarding != b->mc_forwarding);
+ diff |= _DIFF(NETCONF_ATTR_PROXY_NEIGH,
+ a->proxy_neigh != b->proxy_neigh);
+ diff |= _DIFF(NETCONF_ATTR_IGNORE_RT_LINKDWN,
+ a->ignore_routes_linkdown != b->ignore_routes_linkdown);
+ diff |= _DIFF(NETCONF_ATTR_INPUT, a->input != b->input);
+#undef _DIFF
return diff;
}
@@ -553,12 +560,12 @@ static struct nl_cache_ops rtnl_netconf_ops = {
.co_obj_ops = &netconf_obj_ops,
};
-static void __init netconf_init(void)
+static void _nl_init netconf_init(void)
{
nl_cache_mngt_register(&rtnl_netconf_ops);
}
-static void __exit netconf_exit(void)
+static void _nl_exit netconf_exit(void)
{
nl_cache_mngt_unregister(&rtnl_netconf_ops);
}
diff --git a/lib/route/nexthop-encap.h b/lib/route/nexthop-encap.h
new file mode 100644
index 00000000..dde1bfbe
--- /dev/null
+++ b/lib/route/nexthop-encap.h
@@ -0,0 +1,35 @@
+#ifndef NETLINK_NEXTHOP_ENCAP_H_
+#define NETLINK_NEXTHOP_ENCAP_H_
+
+struct nh_encap_ops {
+ uint16_t encap_type;
+
+ int (*build_msg)(struct nl_msg *msg, void *priv);
+ int (*parse_msg)(struct nlattr *nla, struct rtnl_nexthop *rtnh);
+
+ int (*compare)(void *a, void *b);
+
+ void (*dump)(void *priv, struct nl_dump_params *dp);
+ void (*destructor)(void *priv);
+};
+
+struct rtnl_nh_encap;
+
+/*
+ * generic nexthop encap
+ */
+void nh_set_encap(struct rtnl_nexthop *nh, struct rtnl_nh_encap *rtnh_encap);
+
+int nh_encap_parse_msg(struct nlattr *encap, struct nlattr *encap_type,
+ struct rtnl_nexthop *rtnh);
+int nh_encap_build_msg(struct nl_msg *msg, struct rtnl_nh_encap *rtnh_encap);
+
+void nh_encap_dump(struct rtnl_nh_encap *rtnh_encap, struct nl_dump_params *dp);
+
+int nh_encap_compare(struct rtnl_nh_encap *a, struct rtnl_nh_encap *b);
+
+/*
+ * MPLS encap
+ */
+extern struct nh_encap_ops mpls_encap_ops;
+#endif
diff --git a/lib/route/nexthop.c b/lib/route/nexthop.c
index 68351371..962f2bab 100644
--- a/lib/route/nexthop.c
+++ b/lib/route/nexthop.c
@@ -9,13 +9,17 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
+#include "nexthop-encap.h"
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+
/** @cond SKIP */
#define NH_ATTR_FLAGS 0x000001
#define NH_ATTR_WEIGHT 0x000002
@@ -108,29 +112,26 @@ void rtnl_route_nh_free(struct rtnl_nexthop *nh)
int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
uint32_t attrs, int loose)
{
- int diff = 0;
-
-#define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR)
-
- diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
- diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight);
- diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms);
- diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway,
- b->rtnh_gateway));
- diff |= NH_DIFF(NEWDST, nl_addr_cmp(a->rtnh_newdst,
- b->rtnh_newdst));
- diff |= NH_DIFF(VIA, nl_addr_cmp(a->rtnh_via,
- b->rtnh_via));
- diff |= NH_DIFF(ENCAP, nh_encap_compare(a->rtnh_encap,
- b->rtnh_encap));
+ uint32_t diff = 0;
+
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(NH_ATTR_IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
+ diff |= _DIFF(NH_ATTR_WEIGHT, a->rtnh_weight != b->rtnh_weight);
+ diff |= _DIFF(NH_ATTR_REALMS, a->rtnh_realms != b->rtnh_realms);
+ diff |= _DIFF(NH_ATTR_GATEWAY,
+ nl_addr_cmp(a->rtnh_gateway, b->rtnh_gateway));
+ diff |= _DIFF(NH_ATTR_NEWDST,
+ nl_addr_cmp(a->rtnh_newdst, b->rtnh_newdst));
+ diff |= _DIFF(NH_ATTR_VIA, nl_addr_cmp(a->rtnh_via, b->rtnh_via));
+ diff |= _DIFF(NH_ATTR_ENCAP,
+ nh_encap_compare(a->rtnh_encap, b->rtnh_encap));
if (loose)
- diff |= NH_DIFF(FLAGS,
- (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask);
+ diff |= _DIFF(NH_ATTR_FLAGS, (a->rtnh_flags ^ b->rtnh_flags) &
+ b->rtnh_flag_mask);
else
- diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags);
-
-#undef NH_DIFF
+ diff |= _DIFF(NH_ATTR_FLAGS, a->rtnh_flags != b->rtnh_flags);
+#undef _DIFF
return diff;
}
diff --git a/lib/route/nexthop_encap.c b/lib/route/nexthop_encap.c
index 2382886a..226b901a 100644
--- a/lib/route/nexthop_encap.c
+++ b/lib/route/nexthop_encap.c
@@ -1,10 +1,12 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
-#include <netlink-private/netlink.h>
-#include <netlink-private/types.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
#include <linux/lwtunnel.h>
+#include "nl-route.h"
+#include "nexthop-encap.h"
+
static struct lwtunnel_encap_type {
const char *name;
struct nh_encap_ops *ops;
diff --git a/lib/route/nh.c b/lib/route/nh.c
new file mode 100644
index 00000000..1072172d
--- /dev/null
+++ b/lib/route/nh.c
@@ -0,0 +1,590 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2022 Stanislav Zaikin <zstaseg@gmail.com>
+ */
+
+#include "nl-default.h"
+
+#include <linux/nexthop.h>
+
+#include <netlink/route/nh.h>
+#include <netlink/hashtable.h>
+#include <netlink/route/nexthop.h>
+
+#include "nl-aux-route/nl-route.h"
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+/** @cond SKIP */
+struct rtnl_nh {
+ NLHDR_COMMON
+
+ uint8_t nh_family;
+ uint32_t nh_flags;
+
+ uint32_t nh_id;
+ uint32_t nh_group_type;
+ nl_nh_group_t *nh_group;
+ uint32_t nh_oif;
+ struct nl_addr *nh_gateway;
+};
+
+#define NH_ATTR_FLAGS (1 << 0)
+#define NH_ATTR_ID (1 << 1)
+#define NH_ATTR_GROUP (1 << 2)
+#define NH_ATTR_FLAG_BLACKHOLE (1 << 3)
+#define NH_ATTR_OIF (1 << 4)
+#define NH_ATTR_GATEWAY (1 << 5)
+#define NH_ATTR_FLAG_GROUPS (1 << 6)
+#define NH_ATTR_FLAG_FDB (1 << 8)
+/** @endcond */
+
+struct nla_policy rtnl_nh_policy[NHA_MAX + 1] = {
+ [NHA_UNSPEC] = { .type = NLA_UNSPEC },
+ [NHA_ID] = { .type = NLA_U32 },
+ [NHA_GROUP] = { .type = NLA_NESTED },
+ [NHA_GROUP_TYPE] = { .type = NLA_U16 },
+ [NHA_BLACKHOLE] = { .type = NLA_UNSPEC },
+ [NHA_OIF] = { .type = NLA_U32 },
+};
+
+static struct nl_cache_ops rtnl_nh_ops;
+static struct nl_object_ops nh_obj_ops;
+
+static nl_nh_group_t *rtnl_nh_grp_alloc(unsigned size)
+{
+ nl_nh_group_t *nhg;
+
+ _nl_assert(size <= (unsigned)INT_MAX);
+
+ if (!(nhg = calloc(1, sizeof(*nhg))))
+ return NULL;
+
+ nhg->size = size;
+
+ if (!(nhg->entries = calloc(size, sizeof(*nhg->entries)))) {
+ free(nhg);
+ return NULL;
+ }
+
+ nhg->ce_refcnt = 1;
+
+ return nhg;
+}
+
+static void rtnl_nh_grp_put(nl_nh_group_t *nhg)
+{
+ if (!nhg)
+ return;
+
+ _nl_assert(nhg->ce_refcnt > 0);
+
+ nhg->ce_refcnt--;
+
+ if (nhg->ce_refcnt > 0)
+ return;
+
+ free(nhg);
+}
+
+static int rtnh_nh_grp_cmp(const nl_nh_group_t *a, const nl_nh_group_t *b)
+{
+ unsigned i;
+
+ _NL_CMP_SELF(a, b);
+ _NL_CMP_DIRECT(a->size, b->size);
+ for (i = 0; i < a->size; i++) {
+ _NL_CMP_DIRECT(a->entries[i].nh_id, b->entries[i].nh_id);
+ _NL_CMP_DIRECT(a->entries[i].weight, b->entries[i].weight);
+ }
+ return 0;
+}
+
+static int rtnh_nh_grp_clone(nl_nh_group_t *src, nl_nh_group_t **dst)
+{
+ nl_nh_group_t *ret;
+ unsigned i;
+
+ ret = rtnl_nh_grp_alloc(src->size);
+
+ if (!ret)
+ return -NLE_NOMEM;
+
+ for (i = 0; i < src->size; i++) {
+ ret->entries[i].nh_id = src->entries[i].nh_id;
+ ret->entries[i].weight = src->entries[i].weight;
+ }
+
+ *dst = ret;
+
+ return NLE_SUCCESS;
+}
+
+struct rtnl_nh *rtnl_nh_alloc(void)
+{
+ return (struct rtnl_nh *)nl_object_alloc(&nh_obj_ops);
+}
+
+static int nh_clone(struct nl_object *_src, struct nl_object *_dst)
+{
+ struct rtnl_nh *dst = nl_object_priv(_dst);
+ struct rtnl_nh *src = nl_object_priv(_src);
+
+ dst->nh_flags = src->nh_flags;
+ dst->nh_family = src->nh_family;
+ dst->nh_id = src->nh_id;
+ dst->nh_oif = src->nh_oif;
+ dst->ce_mask = src->ce_mask;
+
+ if (src->nh_gateway) {
+ dst->nh_gateway = nl_addr_clone(src->nh_gateway);
+ if (!dst->nh_gateway) {
+ return -NLE_NOMEM;
+ }
+ }
+
+ if (src->nh_group) {
+ if (rtnh_nh_grp_clone(src->nh_group, &dst->nh_group) < 0) {
+ return -NLE_NOMEM;
+ }
+ }
+
+ return 0;
+}
+
+static void nh_free(struct nl_object *obj)
+{
+ struct rtnl_nh *nh = nl_object_priv(obj);
+ nl_addr_put(nh->nh_gateway);
+
+ if (nh->nh_group)
+ rtnl_nh_grp_put(nh->nh_group);
+}
+
+void rtnl_nh_put(struct rtnl_nh *nh)
+{
+ struct nl_object *obj = (struct nl_object *)nh;
+
+ nl_object_put(obj);
+}
+
+static void nexthop_keygen(struct nl_object *obj, uint32_t *hashkey,
+ uint32_t table_sz)
+{
+ struct rtnl_nh *nexthop = nl_object_priv(obj);
+ unsigned int lkey_sz;
+ struct nexthop_hash_key {
+ uint32_t nh_id;
+ } __attribute__((packed)) lkey;
+
+ lkey_sz = sizeof(lkey);
+ lkey.nh_id = nexthop->nh_id;
+
+ *hashkey = nl_hash(&lkey, lkey_sz, 0) % table_sz;
+
+ return;
+}
+
+int rtnl_nh_set_gateway(struct rtnl_nh *nexthop, struct nl_addr *addr)
+{
+ if (nexthop->ce_mask & NH_ATTR_GATEWAY) {
+ nl_addr_put(nexthop->nh_gateway);
+ }
+
+ nexthop->nh_gateway = nl_addr_clone(addr);
+ nexthop->ce_mask |= NH_ATTR_GATEWAY;
+
+ return 0;
+}
+
+struct nl_addr *rtnl_nh_get_gateway(struct rtnl_nh *nexthop)
+{
+ return nexthop->nh_gateway;
+}
+
+int rtnl_nh_set_fdb(struct rtnl_nh *nexthop, int value)
+{
+ if (value)
+ nexthop->ce_mask |= NH_ATTR_FLAG_FDB;
+ else
+ nexthop->ce_mask &= ~NH_ATTR_FLAG_FDB;
+
+ return 0;
+}
+
+int rtnl_nh_get_oif(struct rtnl_nh *nexthop)
+{
+ if (nexthop->ce_mask & NH_ATTR_OIF)
+ return nexthop->nh_oif;
+
+ return 0;
+}
+
+int rtnl_nh_get_fdb(struct rtnl_nh *nexthop)
+{
+ return nexthop->ce_mask & NH_ATTR_FLAG_FDB;
+}
+
+int rtnl_nh_get_group_entry(struct rtnl_nh *nexthop, int n)
+{
+ if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group)
+ return -NLE_MISSING_ATTR;
+
+ if (n < 0 || ((unsigned)n) >= nexthop->nh_group->size)
+ return -NLE_INVAL;
+
+ return nexthop->nh_group->entries[n].nh_id;
+}
+
+int rtnl_nh_get_group_size(struct rtnl_nh *nexthop)
+{
+ if (!(nexthop->ce_mask & NH_ATTR_GROUP) || !nexthop->nh_group)
+ return -NLE_MISSING_ATTR;
+
+ _nl_assert(nexthop->nh_group->size <= INT_MAX);
+
+ return (int)nexthop->nh_group->size;
+}
+
+static int rtnl_nh_grp_info(unsigned size, const struct nexthop_grp *vi,
+ nl_nh_group_t **nvi)
+{
+ nl_nh_group_t *ret;
+ unsigned i;
+
+ if (!(ret = rtnl_nh_grp_alloc(size)))
+ return -NLE_NOMEM;
+
+ for (i = 0; i < size; i++) {
+ ret->entries[i].nh_id = vi[i].id;
+ ret->entries[i].weight = vi[i].weight;
+ }
+
+ *nvi = ret;
+ return NLE_SUCCESS;
+}
+
+int rtnl_nh_get_id(struct rtnl_nh *nh)
+{
+ if (nh->ce_mask & NH_ATTR_ID)
+ return nh->nh_id;
+
+ return -NLE_INVAL;
+}
+
+static int nexthop_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
+ struct nlmsghdr *n, struct nl_parser_param *pp)
+{
+ _nl_auto_rtnl_nh struct rtnl_nh *nexthop = NULL;
+ struct nhmsg *ifi;
+ struct nlattr *tb[NHA_MAX + 1];
+ int err;
+ int family;
+
+ nexthop = rtnl_nh_alloc();
+ if (nexthop == NULL)
+ return -NLE_NOMEM;
+
+ nexthop->ce_msgtype = n->nlmsg_type;
+
+ if (!nlmsg_valid_hdr(n, sizeof(*ifi)))
+ return -NLE_MSG_TOOSHORT;
+
+ ifi = nlmsg_data(n);
+ family = ifi->nh_family;
+ nexthop->nh_family = family;
+ nexthop->nh_flags = ifi->nh_flags;
+ nexthop->ce_mask = (NH_ATTR_FLAGS);
+
+ err = nlmsg_parse(n, sizeof(*ifi), tb, NHA_MAX, rtnl_nh_policy);
+ if (err < 0)
+ return err;
+
+ if (tb[NHA_ID]) {
+ nexthop->nh_id = nla_get_u32(tb[NHA_ID]);
+ nexthop->ce_mask |= NH_ATTR_ID;
+ }
+
+ if (tb[NHA_OIF]) {
+ nexthop->nh_oif = nla_get_u32(tb[NHA_OIF]);
+ nexthop->ce_mask |= NH_ATTR_OIF;
+ }
+
+ if (tb[NHA_GATEWAY]) {
+ nexthop->nh_gateway =
+ nl_addr_alloc_attr(tb[NHA_GATEWAY], family);
+ nexthop->ce_mask |= NH_ATTR_GATEWAY;
+ }
+
+ if (tb[NHA_BLACKHOLE]) {
+ nexthop->ce_mask |= NH_ATTR_FLAG_BLACKHOLE;
+ }
+
+ if (tb[NHA_GROUPS]) {
+ nexthop->ce_mask |= NH_ATTR_FLAG_GROUPS;
+ }
+
+ if (tb[NHA_FDB]) {
+ nexthop->ce_mask |= NH_ATTR_FLAG_FDB;
+ }
+
+ if (tb[NHA_GROUP]) {
+ nl_nh_group_t *nh_group = NULL;
+ const void *data;
+ unsigned size;
+ unsigned len;
+
+ data = nla_data(tb[NHA_GROUP]);
+ len = nla_len(tb[NHA_GROUP]);
+ size = len / sizeof(struct nexthop_grp);
+
+ err = rtnl_nh_grp_info(size, (const struct nexthop_grp *)data,
+ &nh_group);
+ if (err < 0) {
+ return err;
+ }
+
+ nexthop->nh_group = nh_group;
+ nexthop->ce_mask |= NH_ATTR_GROUP;
+ }
+
+ return pp->pp_cb((struct nl_object *)nexthop, pp);
+}
+
+static int nexthop_request_update(struct nl_cache *cache, struct nl_sock *sk)
+{
+ _nl_auto_nl_msg struct nl_msg *msg = NULL;
+ int family = cache->c_iarg1;
+ struct nhmsg hdr = { .nh_family = family };
+ int err;
+
+ msg = nlmsg_alloc_simple(RTM_GETNEXTHOP, NLM_F_DUMP);
+ if (!msg)
+ return -NLE_NOMEM;
+
+ if (nlmsg_append(msg, &hdr, sizeof(hdr), NLMSG_ALIGNTO) < 0)
+ return -NLE_MSGSIZE;
+
+ err = nl_send_auto(sk, msg);
+ if (err < 0)
+ return err;
+
+ return NLE_SUCCESS;
+}
+
+static void dump_nh_group(nl_nh_group_t *group, struct nl_dump_params *dp)
+{
+ unsigned i;
+
+ nl_dump(dp, " nh_grp:");
+ for (i = 0; i < group->size; i++) {
+ nl_dump(dp, " %u", group->entries[i].nh_id);
+ }
+}
+
+static void nh_dump_line(struct nl_object *obj, struct nl_dump_params *dp)
+{
+ struct nl_cache *cache;
+ char buf[128];
+ struct rtnl_nh *nh = nl_object_priv(obj);
+
+ cache = nl_cache_mngt_require_safe("route/nh");
+
+ if (nh->ce_mask & NH_ATTR_ID)
+ nl_dump(dp, "nhid %u", nh->nh_id);
+
+ if (nh->ce_mask & NH_ATTR_OIF)
+ nl_dump(dp, " oif %d", nh->nh_oif);
+
+ if (nh->ce_mask & NH_ATTR_GATEWAY)
+ nl_dump(dp, " via %s",
+ nl_addr2str(nh->nh_gateway, buf, sizeof(buf)));
+
+ if (nh->ce_mask & NH_ATTR_FLAG_BLACKHOLE)
+ nl_dump(dp, " blackhole");
+
+ if (nh->ce_mask & NH_ATTR_FLAG_GROUPS)
+ nl_dump(dp, " groups");
+
+ if (nh->ce_mask & NH_ATTR_GROUP)
+ dump_nh_group(nh->nh_group, dp);
+
+ if (nh->ce_mask & NH_ATTR_FLAG_FDB)
+ nl_dump(dp, " fdb");
+
+ nl_dump(dp, "\n");
+
+ if (cache)
+ nl_cache_put(cache);
+}
+
+static void nh_dump_details(struct nl_object *nh, struct nl_dump_params *dp)
+{
+ nh_dump_line(nh, dp);
+}
+
+static uint64_t nh_compare(struct nl_object *a, struct nl_object *b,
+ uint64_t attrs, int loose)
+{
+ int diff = 0;
+ struct rtnl_nh *src = nl_object_priv(a);
+ struct rtnl_nh *dst = nl_object_priv(b);
+
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(NH_ATTR_ID, src->nh_id != dst->nh_id);
+ diff |= _DIFF(NH_ATTR_GATEWAY,
+ nl_addr_cmp(src->nh_gateway, dst->nh_gateway));
+ diff |= _DIFF(NH_ATTR_OIF, src->nh_oif != dst->nh_oif);
+ diff |= _DIFF(NH_ATTR_GROUP,
+ rtnh_nh_grp_cmp(src->nh_group, dst->nh_group));
+ diff |= _DIFF(NH_ATTR_FLAG_FDB, false);
+ diff |= _DIFF(NH_ATTR_FLAG_GROUPS, false);
+ diff |= _DIFF(NH_ATTR_FLAG_BLACKHOLE, false);
+#undef _DIFF
+
+ return diff;
+}
+
+struct rtnl_nh *rtnl_nh_get(struct nl_cache *cache, int nhid)
+{
+ struct rtnl_nh *nh;
+
+ if (cache->c_ops != &rtnl_nh_ops)
+ return NULL;
+
+ nl_list_for_each_entry(nh, &cache->c_items, ce_list) {
+ if (nh->nh_id == nhid) {
+ nl_object_get((struct nl_object *)nh);
+ return nh;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Allocate nexthop cache and fill in all configured nexthops.
+ * @arg sk Netnexthop socket.
+ * @arg family nexthop address family or AF_UNSPEC
+ * @arg result Pointer to store resulting cache.
+ * @arg flags Flags to set in nexthop cache before filling
+ *
+ * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop
+ * message is sent to the kernel requesting a full dump of all configured
+ * nexthops. The returned messages are parsed and filled into the cache. If
+ * the operation succeeds, the resulting cache will contain a nexthop object for
+ * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the
+ * cache is still empty.
+ *
+ * If \c family is set to an address family other than \c AF_UNSPEC the
+ * contents of the cache can be limited to a specific address family.
+ * Currently the following address families are supported:
+ * - AF_BRIDGE
+ * - AF_INET6
+ *
+ * @route_doc{nexthop_list, Get List of nexthops}
+ * @see rtnl_nh_get()
+ * @see rtnl_nh_get_by_name()
+ * @return 0 on success or a negative error code.
+ */
+static int rtnl_nh_alloc_cache_flags(struct nl_sock *sk, int family,
+ struct nl_cache **result,
+ unsigned int flags)
+{
+ struct nl_cache *cache;
+ int err;
+
+ cache = nl_cache_alloc(&rtnl_nh_ops);
+ if (!cache)
+ return -NLE_NOMEM;
+
+ cache->c_iarg1 = family;
+
+ if (flags)
+ nl_cache_set_flags(cache, flags);
+
+ if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
+ nl_cache_free(cache);
+ return err;
+ }
+
+ *result = cache;
+ return 0;
+}
+
+/**
+ * Allocate nexthop cache and fill in all configured nexthops.
+ * @arg sk Netnexthop socket.
+ * @arg family nexthop address family or AF_UNSPEC
+ * @arg result Pointer to store resulting cache.
+ *
+ * Allocates and initializes a new nexthop cache. If \c sk is valid, a netnexthop
+ * message is sent to the kernel requesting a full dump of all configured
+ * nexthops. The returned messages are parsed and filled into the cache. If
+ * the operation succeeds, the resulting cache will contain a nexthop object for
+ * each nexthop configured in the kernel. If \c sk is NULL, returns 0 but the
+ * cache is still empty.
+ *
+ * If \c family is set to an address family other than \c AF_UNSPEC the
+ * contents of the cache can be limited to a specific address family.
+ * Currently the following address families are supported:
+ * - AF_BRIDGE
+ * - AF_INET6
+ *
+ * @route_doc{nexthop_list, Get List of nexthops}
+ * @see rtnl_nh_get()
+ * @see rtnl_nh_get_by_name()
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nh_alloc_cache(struct nl_sock *sk, int family,
+ struct nl_cache **result)
+{
+ return rtnl_nh_alloc_cache_flags(sk, family, result, 0);
+}
+
+static struct nl_object_ops nh_obj_ops = {
+ .oo_name = "route/nh",
+ .oo_size = sizeof(struct rtnl_nh),
+ .oo_free_data = nh_free,
+ .oo_clone = nh_clone,
+ .oo_dump = {
+ [NL_DUMP_LINE] = nh_dump_line,
+ [NL_DUMP_DETAILS] = nh_dump_details,
+ },
+ .oo_compare = nh_compare,
+ .oo_keygen = nexthop_keygen,
+ .oo_attrs2str = rtnl_route_nh_flags2str,
+ .oo_id_attrs = NH_ATTR_ID,
+};
+
+static struct nl_af_group nh_groups[] = {
+ { AF_UNSPEC, RTNLGRP_NEXTHOP },
+ { END_OF_GROUP_LIST },
+};
+
+static struct nl_cache_ops rtnl_nh_ops = {
+ .co_name = "route/nh",
+ .co_hdrsize = sizeof(struct nhmsg),
+ .co_msgtypes = {
+ { RTM_NEWNEXTHOP, NL_ACT_NEW, "new" },
+ { RTM_DELNEXTHOP, NL_ACT_DEL, "del" },
+ { RTM_GETNEXTHOP, NL_ACT_GET, "get" },
+ END_OF_MSGTYPES_LIST,
+ },
+ .co_protocol = NETLINK_ROUTE,
+ .co_groups = nh_groups,
+ .co_request_update = nexthop_request_update,
+ .co_msg_parser = nexthop_msg_parser,
+ .co_obj_ops = &nh_obj_ops,
+};
+
+static void _nl_init nexthop_init(void)
+{
+ nl_cache_mngt_register(&rtnl_nh_ops);
+}
+
+static void _nl_exit nexthop_exit(void)
+{
+ nl_cache_mngt_unregister(&rtnl_nh_ops);
+}
diff --git a/lib/route/nh_encap_mpls.c b/lib/route/nh_encap_mpls.c
index d30acc2c..a7802917 100644
--- a/lib/route/nh_encap_mpls.c
+++ b/lib/route/nh_encap_mpls.c
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: LGPL-2.1-only */
-#include <netlink-private/netlink.h>
-#include <netlink-private/types.h>
-#include <netlink-private/route/nexthop-encap.h>
-#include <netlink/route/nexthop.h>
+#include "nl-default.h"
+
#include <linux/mpls_iptunnel.h>
#include <linux/lwtunnel.h>
+#include <netlink/route/nexthop.h>
+
+#include "nl-route.h"
+#include "nexthop-encap.h"
+
struct mpls_iptunnel_encap {
struct nl_addr *dst;
uint8_t ttl;
diff --git a/lib/route/nl-route.h b/lib/route/nl-route.h
new file mode 100644
index 00000000..28d01662
--- /dev/null
+++ b/lib/route/nl-route.h
@@ -0,0 +1,191 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2003-2013 Thomas Graf <tgraf@suug.ch>
+ * Copyright (c) 2013 Sassano Systems LLC <joe@sassanosystems.com>
+ */
+
+#ifndef __LIB_ROUTE_NL_ROUTE_H__
+#define __LIB_ROUTE_NL_ROUTE_H__
+
+#include <netlink/route/tc.h>
+
+#include "nl-priv-dynamic-core/object-api.h"
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
+#include "nl-aux-core/nl-core.h"
+
+/*****************************************************************************/
+
+struct rtnl_link_map {
+ uint64_t lm_mem_start;
+ uint64_t lm_mem_end;
+ uint64_t lm_base_addr;
+ uint16_t lm_irq;
+ uint8_t lm_dma;
+ uint8_t lm_port;
+};
+
+#define IFQDISCSIZ 32
+
+struct rtnl_link {
+ NLHDR_COMMON
+
+ char l_name[IFNAMSIZ];
+ uint32_t l_family;
+ uint32_t l_arptype;
+ uint32_t l_index;
+ uint32_t l_flags;
+ uint32_t l_change;
+ uint32_t l_mtu;
+ uint32_t l_link;
+ int32_t l_link_netnsid;
+ uint32_t l_txqlen;
+ uint32_t l_weight;
+ uint32_t l_master;
+ struct nl_addr *l_addr;
+ struct nl_addr *l_bcast;
+ char l_qdisc[IFQDISCSIZ];
+ struct rtnl_link_map l_map;
+ uint64_t l_stats[RTNL_LINK_STATS_MAX + 1];
+ uint32_t l_flag_mask;
+ uint32_t l_num_vf;
+ uint8_t l_operstate;
+ uint8_t l_linkmode;
+ /* 2 byte hole */
+ char *l_info_kind;
+ char *l_info_slave_kind;
+ struct rtnl_link_info_ops *l_info_ops;
+ void *l_af_data[AF_MAX];
+ void *l_info;
+ char *l_ifalias;
+ uint32_t l_promiscuity;
+ uint32_t l_num_tx_queues;
+ uint32_t l_num_rx_queues;
+ uint32_t l_gso_max_segs;
+ uint32_t l_gso_max_size;
+ uint32_t l_group;
+ uint8_t l_carrier;
+ /* 3 byte hole */
+ uint32_t l_carrier_changes;
+ struct rtnl_link_af_ops *l_af_ops;
+ struct nl_data *l_phys_port_id;
+ char l_phys_port_name[IFNAMSIZ];
+ struct nl_data *l_phys_switch_id;
+ int l_ns_fd;
+ pid_t l_ns_pid;
+ struct rtnl_link_vf *l_vf_list;
+};
+
+struct rtnl_nh_encap {
+ struct nh_encap_ops *ops;
+ void *priv; /* private data for encap type */
+};
+
+struct rtnl_nexthop {
+ uint8_t rtnh_flags;
+ uint8_t rtnh_flag_mask;
+ uint8_t rtnh_weight;
+ /* 1 byte spare */
+ uint32_t rtnh_ifindex;
+ struct nl_addr *rtnh_gateway;
+ uint32_t ce_mask; /* HACK to support attr macros */
+ struct nl_list_head rtnh_list;
+ uint32_t rtnh_realms;
+ struct nl_addr *rtnh_newdst;
+ struct nl_addr *rtnh_via;
+ struct rtnl_nh_encap *rtnh_encap;
+};
+
+struct rtnl_ratespec {
+ uint64_t rs_rate64;
+ uint16_t rs_overhead;
+ int16_t rs_cell_align;
+ uint16_t rs_mpu;
+ uint8_t rs_cell_log;
+};
+
+#define TCKINDSIZ 32
+
+#define NL_TC_GENERIC(pre) \
+ NLHDR_COMMON \
+ uint32_t pre##_family; \
+ uint32_t pre##_ifindex; \
+ uint32_t pre##_handle; \
+ uint32_t pre##_parent; \
+ uint32_t pre##_info; \
+ uint32_t pre##_mtu; \
+ uint32_t pre##_mpu; \
+ uint32_t pre##_overhead; \
+ uint32_t pre##_linktype; \
+ char pre##_kind[TCKINDSIZ]; \
+ struct nl_data *pre##_opts; \
+ 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_tc_ops *pre##_ops; \
+ enum rtnl_tc_type pre##_type; \
+ uint32_t pre##_chain
+
+struct rtnl_tc {
+ NL_TC_GENERIC(tc);
+};
+
+struct rtnl_qdisc {
+ NL_TC_GENERIC(q);
+};
+
+struct rtnl_act {
+ NL_TC_GENERIC(c);
+ struct rtnl_act *a_next;
+};
+
+/*****************************************************************************/
+
+static inline void rtnl_copy_ratespec(struct rtnl_ratespec *dst,
+ struct tc_ratespec *src)
+{
+ dst->rs_cell_log = src->cell_log;
+ dst->rs_overhead = src->overhead;
+ dst->rs_cell_align = src->cell_align;
+ dst->rs_mpu = src->mpu;
+ dst->rs_rate64 = src->rate;
+}
+
+static inline void rtnl_rcopy_ratespec(struct tc_ratespec *dst,
+ struct rtnl_ratespec *src)
+{
+ dst->cell_log = src->rs_cell_log;
+ dst->overhead = src->rs_overhead;
+ dst->cell_align = src->rs_cell_align;
+ dst->mpu = src->rs_mpu;
+ dst->rate = src->rs_rate64 > 0xFFFFFFFFull ? 0xFFFFFFFFull :
+ (uint32_t)src->rs_rate64;
+}
+
+/*****************************************************************************/
+
+static inline int build_sysconf_path(char **strp, const char *filename)
+{
+ char *sysconfdir;
+
+ sysconfdir = getenv("NLSYSCONFDIR");
+
+ if (!sysconfdir)
+ sysconfdir = SYSCONFDIR;
+
+ return asprintf(strp, "%s/%s", sysconfdir, filename);
+}
+
+/*****************************************************************************/
+
+static inline int rtnl_tc_calc_txtime64(int bufsize, uint64_t rate)
+{
+ return ((double)bufsize / (double)rate) * 1000000.0;
+}
+
+static inline int rtnl_tc_calc_bufsize64(int txtime, uint64_t rate)
+{
+ return ((double)txtime * (double)rate) / 1000000.0;
+}
+
+#endif /* __LIB_ROUTE_NL_ROUTE_H__ */
diff --git a/lib/route/pktloc.c b/lib/route/pktloc.c
index 599e5930..7f320d9b 100644
--- a/lib/route/pktloc.c
+++ b/lib/route/pktloc.c
@@ -25,12 +25,16 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <sys/stat.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/pktloc.h>
+#include "nl-route.h"
+
#include "pktloc_syntax.h"
#include "pktloc_grammar.h"
@@ -242,7 +246,7 @@ void rtnl_pktloc_foreach(void (*cb)(struct rtnl_pktloc *, void *), void *arg)
cb(loc, arg);
}
-static int __init pktloc_init(void)
+static int _nl_init pktloc_init(void)
{
int i;
diff --git a/lib/route/pktloc_grammar.l b/lib/route/pktloc_grammar.l
index ab592d1b..2db229d1 100644
--- a/lib/route/pktloc_grammar.l
+++ b/lib/route/pktloc_grammar.l
@@ -1,10 +1,10 @@
%{
- #include <netlink-private/netlink.h>
- #include <netlink-private/tc.h>
+ #include <linux/tc_ematch/tc_em_cmp.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/pktloc.h>
- #include <linux/tc_ematch/tc_em_cmp.h>
+
#include "pktloc_syntax.h"
int pktloc_get_column(yyscan_t);
diff --git a/lib/route/pktloc_syntax.y b/lib/route/pktloc_syntax.y
index 3c9326fe..661463a4 100644
--- a/lib/route/pktloc_syntax.y
+++ b/lib/route/pktloc_syntax.y
@@ -1,9 +1,9 @@
%{
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/pktloc.h>
+
+#include "nl-route.h"
%}
%locations
diff --git a/lib/route/qdisc.c b/lib/route/qdisc.c
index 62c4390a..67ea358d 100644
--- a/lib/route/qdisc.c
+++ b/lib/route/qdisc.c
@@ -9,16 +9,17 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/link.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/classifier.h>
+#include "tc-api.h"
+
static struct nl_cache_ops rtnl_qdisc_ops;
static struct nl_object_ops qdisc_obj_ops;
@@ -587,13 +588,13 @@ static struct nl_object_ops qdisc_obj_ops = {
.oo_id_attrs = (TCA_ATTR_IFINDEX | TCA_ATTR_HANDLE),
};
-static void __init qdisc_init(void)
+static void _nl_init qdisc_init(void)
{
rtnl_tc_type_register(&qdisc_ops);
nl_cache_mngt_register(&rtnl_qdisc_ops);
}
-static void __exit qdisc_exit(void)
+static void _nl_exit qdisc_exit(void)
{
nl_cache_mngt_unregister(&rtnl_qdisc_ops);
rtnl_tc_type_unregister(&qdisc_ops);
diff --git a/lib/route/qdisc/blackhole.c b/lib/route/qdisc/blackhole.c
index c24507af..8d8f4bab 100644
--- a/lib/route/qdisc/blackhole.c
+++ b/lib/route/qdisc/blackhole.c
@@ -9,21 +9,23 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
+
+#include "tc-api.h"
static struct rtnl_tc_ops blackhole_ops = {
.to_kind = "blackhole",
.to_type = RTNL_TC_TYPE_QDISC,
};
-static void __init blackhole_init(void)
+static void _nl_init blackhole_init(void)
{
rtnl_tc_register(&blackhole_ops);
}
-static void __exit blackhole_exit(void)
+static void _nl_exit blackhole_exit(void)
{
rtnl_tc_unregister(&blackhole_ops);
}
diff --git a/lib/route/qdisc/cbq.c b/lib/route/qdisc/cbq.c
index 62af8235..b9a66960 100644
--- a/lib/route/qdisc/cbq.c
+++ b/lib/route/qdisc/cbq.c
@@ -3,17 +3,27 @@
* Copyright (c) 2003-2011 Thomas Graf <tgraf@suug.ch>
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/link.h>
#include <netlink/route/qdisc/cbq.h>
#include <netlink/route/cls/police.h>
+#include "tc-api.h"
+
+struct rtnl_cbq {
+ struct tc_cbq_lssopt cbq_lss;
+ struct tc_ratespec cbq_rate;
+ struct tc_cbq_wrropt cbq_wrr;
+ struct tc_cbq_ovl cbq_ovl;
+ struct tc_cbq_fopt cbq_fopt;
+ struct tc_cbq_police cbq_police;
+};
+
/**
* @ingroup qdisc
* @ingroup class
@@ -183,13 +193,13 @@ static struct rtnl_tc_ops cbq_class_ops = {
},
};
-static void __init cbq_init(void)
+static void _nl_init cbq_init(void)
{
rtnl_tc_register(&cbq_qdisc_ops);
rtnl_tc_register(&cbq_class_ops);
}
-static void __exit cbq_exit(void)
+static void _nl_exit cbq_exit(void)
{
rtnl_tc_unregister(&cbq_qdisc_ops);
rtnl_tc_unregister(&cbq_class_ops);
diff --git a/lib/route/qdisc/dsmark.c b/lib/route/qdisc/dsmark.c
index 07f938c7..f5718f9c 100644
--- a/lib/route/qdisc/dsmark.c
+++ b/lib/route/qdisc/dsmark.c
@@ -10,16 +10,30 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/qdisc.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/class.h>
#include <netlink/route/qdisc/dsmark.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_dsmark_qdisc {
+ uint16_t qdm_indices;
+ uint16_t qdm_default_index;
+ uint32_t qdm_set_tc_index;
+ uint32_t qdm_mask;
+};
+
+struct rtnl_dsmark_class {
+ uint8_t cdm_bmask;
+ uint8_t cdm_value;
+ uint32_t cdm_mask;
+};
+
#define SCH_DSMARK_ATTR_INDICES 0x1
#define SCH_DSMARK_ATTR_DEFAULT_INDEX 0x2
#define SCH_DSMARK_ATTR_SET_TC_INDEX 0x4
@@ -392,13 +406,13 @@ static struct rtnl_tc_ops dsmark_class_ops = {
.to_msg_fill = dsmark_class_msg_fill,
};
-static void __init dsmark_init(void)
+static void _nl_init dsmark_init(void)
{
rtnl_tc_register(&dsmark_qdisc_ops);
rtnl_tc_register(&dsmark_class_ops);
}
-static void __exit dsmark_exit(void)
+static void _nl_exit dsmark_exit(void)
{
rtnl_tc_unregister(&dsmark_qdisc_ops);
rtnl_tc_unregister(&dsmark_class_ops);
diff --git a/lib/route/qdisc/fifo.c b/lib/route/qdisc/fifo.c
index dc6d1895..99768037 100644
--- a/lib/route/qdisc/fifo.c
+++ b/lib/route/qdisc/fifo.c
@@ -23,15 +23,21 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/fifo.h>
#include <netlink/utils.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_fifo {
+ uint32_t qf_limit;
+ uint32_t qf_mask;
+};
+
#define SCH_FIFO_ATTR_LIMIT 1
/** @endcond */
@@ -148,13 +154,13 @@ static struct rtnl_tc_ops bfifo_ops = {
.to_msg_fill = fifo_msg_fill,
};
-static void __init fifo_init(void)
+static void _nl_init fifo_init(void)
{
rtnl_tc_register(&pfifo_ops);
rtnl_tc_register(&bfifo_ops);
}
-static void __exit fifo_exit(void)
+static void _nl_exit fifo_exit(void)
{
rtnl_tc_unregister(&pfifo_ops);
rtnl_tc_unregister(&bfifo_ops);
diff --git a/lib/route/qdisc/fq_codel.c b/lib/route/qdisc/fq_codel.c
index 34f6b444..a44ab222 100644
--- a/lib/route/qdisc/fq_codel.c
+++ b/lib/route/qdisc/fq_codel.c
@@ -11,15 +11,26 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/fq_codel.h>
#include <netlink/utils.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_fq_codel {
+ int fq_limit;
+ uint32_t fq_target;
+ uint32_t fq_interval;
+ int fq_flows;
+ uint32_t fq_quantum;
+ int fq_ecn;
+ uint32_t fq_mask;
+};
+
#define SCH_FQ_CODEL_ATTR_TARGET 0x1
#define SCH_FQ_CODEL_ATTR_LIMIT 0x2
#define SCH_FQ_CODEL_ATTR_INTERVAL 0x4
@@ -358,12 +369,12 @@ static struct rtnl_tc_ops fq_codel_ops = {
.to_msg_fill = fq_codel_msg_fill,
};
-static void __init fq_codel_init(void)
+static void _nl_init fq_codel_init(void)
{
rtnl_tc_register(&fq_codel_ops);
}
-static void __exit fq_codel_exit(void)
+static void _nl_exit fq_codel_exit(void)
{
rtnl_tc_unregister(&fq_codel_ops);
}
diff --git a/lib/route/qdisc/hfsc.c b/lib/route/qdisc/hfsc.c
index 0167e97e..49c24c7d 100644
--- a/lib/route/qdisc/hfsc.c
+++ b/lib/route/qdisc/hfsc.c
@@ -10,18 +10,31 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/link.h>
#include <netlink/route/qdisc/hfsc.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_hfsc_qdisc {
+ uint32_t qh_defcls;
+ uint32_t qh_mask;
+};
+
+struct rtnl_hfsc_class {
+ struct tc_service_curve ch_rsc;
+ struct tc_service_curve ch_fsc;
+ struct tc_service_curve ch_usc;
+ uint32_t ch_mask;
+};
+
#define SCH_HFSC_CLS_HAS_RSC 0x001
#define SCH_HFSC_CLS_HAS_FSC 0x002
#define SCH_HFSC_CLS_HAS_USC 0x004
@@ -330,13 +343,13 @@ static struct rtnl_tc_ops hfsc_class_ops = {
.to_msg_fill = hfsc_class_msg_fill,
};
-static void __init hfsc_init(void)
+static void _nl_init hfsc_init(void)
{
rtnl_tc_register(&hfsc_qdisc_ops);
rtnl_tc_register(&hfsc_class_ops);
}
-static void __exit hfsc_exit(void)
+static void _nl_exit hfsc_exit(void)
{
rtnl_tc_unregister(&hfsc_qdisc_ops);
rtnl_tc_unregister(&hfsc_class_ops);
diff --git a/lib/route/qdisc/htb.c b/lib/route/qdisc/htb.c
index ebe38f90..28061b90 100644
--- a/lib/route/qdisc/htb.c
+++ b/lib/route/qdisc/htb.c
@@ -12,18 +12,37 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/link.h>
#include <netlink/route/qdisc/htb.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_htb_qdisc {
+ uint32_t qh_rate2quantum;
+ uint32_t qh_defcls;
+ uint32_t qh_mask;
+ uint32_t qh_direct_pkts;
+};
+
+struct rtnl_htb_class {
+ uint32_t ch_prio;
+ struct rtnl_ratespec ch_rate;
+ struct rtnl_ratespec ch_ceil;
+ uint32_t ch_rbuffer;
+ uint32_t ch_cbuffer;
+ uint32_t ch_quantum;
+ uint32_t ch_mask;
+ uint32_t ch_level;
+};
+
#define SCH_HTB_HAS_RATE2QUANTUM 0x01
#define SCH_HTB_HAS_DEFCLS 0x02
@@ -727,13 +746,13 @@ static struct rtnl_tc_ops htb_class_ops = {
.to_msg_fill = htb_class_msg_fill,
};
-static void __init htb_init(void)
+static void _nl_init htb_init(void)
{
rtnl_tc_register(&htb_qdisc_ops);
rtnl_tc_register(&htb_class_ops);
}
-static void __exit htb_exit(void)
+static void _nl_exit htb_exit(void)
{
rtnl_tc_unregister(&htb_qdisc_ops);
rtnl_tc_unregister(&htb_class_ops);
diff --git a/lib/route/qdisc/ingress.c b/lib/route/qdisc/ingress.c
index 73d2440e..5363c262 100644
--- a/lib/route/qdisc/ingress.c
+++ b/lib/route/qdisc/ingress.c
@@ -10,13 +10,14 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/utils.h>
+#include "tc-api.h"
+
struct dumb {
uint32_t foo;
};
@@ -45,12 +46,12 @@ static struct rtnl_tc_ops ingress_ops = {
.to_msg_fill = dumb_msg_fill,
};
-static void __init ingress_init(void)
+static void _nl_init ingress_init(void)
{
rtnl_tc_register(&ingress_ops);
}
-static void __exit ingress_exit(void)
+static void _nl_exit ingress_exit(void)
{
rtnl_tc_unregister(&ingress_ops);
}
diff --git a/lib/route/qdisc/mqprio.c b/lib/route/qdisc/mqprio.c
index c1654041..5e9d08f8 100644
--- a/lib/route/qdisc/mqprio.c
+++ b/lib/route/qdisc/mqprio.c
@@ -3,15 +3,29 @@
* Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/mqprio.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_mqprio {
+ uint8_t qm_num_tc;
+ uint8_t qm_prio_map[TC_QOPT_BITMASK + 1];
+ uint8_t qm_hw;
+ uint16_t qm_count[TC_QOPT_MAX_QUEUE];
+ uint16_t qm_offset[TC_QOPT_MAX_QUEUE];
+ uint16_t qm_mode;
+ uint16_t qm_shaper;
+ uint64_t qm_min_rate[TC_QOPT_MAX_QUEUE];
+ uint64_t qm_max_rate[TC_QOPT_MAX_QUEUE];
+ uint32_t qm_mask;
+};
+
#define SCH_MQPRIO_ATTR_NUMTC (1 << 0)
#define SCH_MQPRIO_ATTR_PRIOMAP (1 << 1)
#define SCH_MQPRIO_ATTR_HW (1 << 2)
@@ -591,12 +605,12 @@ static struct rtnl_tc_ops mqprio_ops = {
.to_msg_fill = mqprio_msg_fill,
};
-static void __init mqprio_init(void)
+static void _nl_init mqprio_init(void)
{
rtnl_tc_register(&mqprio_ops);
}
-static void __exit mqprio_exit(void)
+static void _nl_exit mqprio_exit(void)
{
rtnl_tc_unregister(&mqprio_ops);
}
diff --git a/lib/route/qdisc/netem.c b/lib/route/qdisc/netem.c
index 0ca1d571..6dde4f02 100644
--- a/lib/route/qdisc/netem.c
+++ b/lib/route/qdisc/netem.c
@@ -12,17 +12,52 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/netem.h>
-#include "netlink-private/utils.h"
+#include "tc-api.h"
+#include "nl-priv-dynamic-core/nl-core.h"
/** @cond SKIP */
+struct rtnl_netem_corr {
+ uint32_t nmc_delay;
+ uint32_t nmc_loss;
+ uint32_t nmc_duplicate;
+};
+
+struct rtnl_netem_reo {
+ uint32_t nmro_probability;
+ uint32_t nmro_correlation;
+};
+
+struct rtnl_netem_crpt {
+ uint32_t nmcr_probability;
+ uint32_t nmcr_correlation;
+};
+
+struct rtnl_netem_dist {
+ int16_t *dist_data;
+ size_t dist_size;
+};
+
+struct rtnl_netem {
+ uint32_t qnm_latency;
+ uint32_t qnm_limit;
+ uint32_t qnm_loss;
+ uint32_t qnm_gap;
+ uint32_t qnm_duplicate;
+ uint32_t qnm_jitter;
+ uint32_t qnm_mask;
+ struct rtnl_netem_corr qnm_corr;
+ struct rtnl_netem_reo qnm_ro;
+ struct rtnl_netem_crpt qnm_crpt;
+ struct rtnl_netem_dist qnm_dist;
+};
+
#define SCH_NETEM_ATTR_LATENCY 0x0001
#define SCH_NETEM_ATTR_LIMIT 0x0002
#define SCH_NETEM_ATTR_LOSS 0x0004
@@ -686,7 +721,7 @@ int rtnl_netem_get_duplicate(struct rtnl_qdisc *qdisc)
* Set packet duplication correlation probability of netem qdisc.
* @arg qdisc Netem qdisc to be modified.
* @arg prob New packet duplication correlation probability.
- * @return 0 on sucess or a negative error code.
+ * @return 0 on success or a negative error code.
*/
void rtnl_netem_set_duplicate_correlation(struct rtnl_qdisc *qdisc, int prob)
{
@@ -979,12 +1014,12 @@ static struct rtnl_tc_ops netem_ops = {
.to_msg_fill_raw = netem_msg_fill_raw,
};
-static void __init netem_init(void)
+static void _nl_init netem_init(void)
{
rtnl_tc_register(&netem_ops);
}
-static void __exit netem_exit(void)
+static void _nl_exit netem_exit(void)
{
rtnl_tc_unregister(&netem_ops);
}
diff --git a/lib/route/qdisc/plug.c b/lib/route/qdisc/plug.c
index 38c1c1aa..f0108020 100644
--- a/lib/route/qdisc/plug.c
+++ b/lib/route/qdisc/plug.c
@@ -54,13 +54,19 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc/plug.h>
+#include "tc-api.h"
+
+struct rtnl_plug {
+ int action;
+ uint32_t limit;
+};
+
static int plug_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
struct rtnl_plug *plug = data;
@@ -158,12 +164,12 @@ static struct rtnl_tc_ops plug_ops = {
.to_msg_fill = plug_msg_fill,
};
-static void __init plug_init(void)
+static void _nl_init plug_init(void)
{
rtnl_tc_register(&plug_ops);
}
-static void __exit plug_exit(void)
+static void _nl_exit plug_exit(void)
{
rtnl_tc_unregister(&plug_ops);
}
diff --git a/lib/route/qdisc/prio.c b/lib/route/qdisc/prio.c
index 28242a08..e7338453 100644
--- a/lib/route/qdisc/prio.c
+++ b/lib/route/qdisc/prio.c
@@ -20,15 +20,22 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/prio.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_prio {
+ uint32_t qp_bands;
+ uint8_t qp_priomap[TC_PRIO_MAX + 1];
+ uint32_t qp_mask;
+};
+
#define SCH_PRIO_ATTR_BANDS 1
#define SCH_PRIO_ATTR_PRIOMAP 2
/** @endcond */
@@ -273,13 +280,13 @@ static struct rtnl_tc_ops pfifo_fast_ops = {
.to_msg_fill = prio_msg_fill,
};
-static void __init prio_init(void)
+static void _nl_init prio_init(void)
{
rtnl_tc_register(&prio_ops);
rtnl_tc_register(&pfifo_fast_ops);
}
-static void __exit prio_exit(void)
+static void _nl_exit prio_exit(void)
{
rtnl_tc_unregister(&prio_ops);
rtnl_tc_unregister(&pfifo_fast_ops);
diff --git a/lib/route/qdisc/red.c b/lib/route/qdisc/red.c
index ccab9471..e793b780 100644
--- a/lib/route/qdisc/red.c
+++ b/lib/route/qdisc/red.c
@@ -10,15 +10,27 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/red.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_red {
+ uint32_t qr_limit;
+ uint32_t qr_qth_min;
+ uint32_t qr_qth_max;
+ uint8_t qr_flags;
+ uint8_t qr_wlog;
+ uint8_t qr_plog;
+ uint8_t qr_scell_log;
+ uint32_t qr_mask;
+};
+
#define RED_ATTR_LIMIT 0x01
#define RED_ATTR_QTH_MIN 0x02
#define RED_ATTR_QTH_MAX 0x04
@@ -171,12 +183,12 @@ static struct rtnl_tc_ops red_ops = {
.to_msg_fill = red_msg_fill,
};
-static void __init red_init(void)
+static void _nl_init red_init(void)
{
rtnl_tc_register(&red_ops);
}
-static void __exit red_exit(void)
+static void _nl_exit red_exit(void)
{
rtnl_tc_unregister(&red_ops);
}
diff --git a/lib/route/qdisc/sfq.c b/lib/route/qdisc/sfq.c
index f52452e1..43798893 100644
--- a/lib/route/qdisc/sfq.c
+++ b/lib/route/qdisc/sfq.c
@@ -17,15 +17,25 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc/sfq.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_sfq {
+ uint32_t qs_quantum;
+ uint32_t qs_perturb;
+ uint32_t qs_limit;
+ uint32_t qs_divisor;
+ uint32_t qs_flows;
+ uint32_t qs_mask;
+};
+
#define SCH_SFQ_ATTR_QUANTUM 0x01
#define SCH_SFQ_ATTR_PERTURB 0x02
#define SCH_SFQ_ATTR_LIMIT 0x04
@@ -237,12 +247,12 @@ static struct rtnl_tc_ops sfq_ops = {
.to_msg_fill = sfq_msg_fill,
};
-static void __init sfq_init(void)
+static void _nl_init sfq_init(void)
{
rtnl_tc_register(&sfq_ops);
}
-static void __exit sfq_exit(void)
+static void _nl_exit sfq_exit(void)
{
rtnl_tc_unregister(&sfq_ops);
}
diff --git a/lib/route/qdisc/tbf.c b/lib/route/qdisc/tbf.c
index ba8e304e..67996eb5 100644
--- a/lib/route/qdisc/tbf.c
+++ b/lib/route/qdisc/tbf.c
@@ -9,18 +9,30 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
-#include <netlink-private/route/tc-api.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/class.h>
#include <netlink/route/link.h>
#include <netlink/route/qdisc/tbf.h>
+#include "tc-api.h"
+
/** @cond SKIP */
+struct rtnl_tbf {
+ uint32_t qt_limit;
+ struct rtnl_ratespec qt_rate;
+ uint32_t qt_rate_bucket;
+ uint32_t qt_rate_txtime;
+ struct rtnl_ratespec qt_peakrate;
+ uint32_t qt_peakrate_bucket;
+ uint32_t qt_peakrate_txtime;
+ uint32_t qt_mask;
+};
+
#define TBF_ATTR_LIMIT 0x01
#define TBF_ATTR_RATE 0x02
#define TBF_ATTR_PEAKRATE 0x10
@@ -441,12 +453,12 @@ static struct rtnl_tc_ops tbf_tc_ops = {
.to_msg_fill = tbf_msg_fill,
};
-static void __init tbf_init(void)
+static void _nl_init tbf_init(void)
{
rtnl_tc_register(&tbf_tc_ops);
}
-static void __exit tbf_exit(void)
+static void _nl_exit tbf_exit(void)
{
rtnl_tc_unregister(&tbf_tc_ops);
}
diff --git a/lib/route/route.c b/lib/route/route.c
index fcc7459c..0a16ff4f 100644
--- a/lib/route/route.c
+++ b/lib/route/route.c
@@ -10,8 +10,8 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/nl-auto.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
@@ -20,6 +20,11 @@
#include <netlink/route/route.h>
#include <netlink/route/link.h>
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+#include "nl-aux-route/nl-route.h"
+
static struct nl_cache_ops rtnl_route_ops;
static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
@@ -215,12 +220,12 @@ static struct nl_cache_ops rtnl_route_ops = {
.co_obj_ops = &route_obj_ops,
};
-static void __init route_init(void)
+static void _nl_init route_init(void)
{
nl_cache_mngt_register(&rtnl_route_ops);
}
-static void __exit route_exit(void)
+static void _nl_exit route_exit(void)
{
nl_cache_mngt_unregister(&rtnl_route_ops);
}
diff --git a/lib/route/route_obj.c b/lib/route/route_obj.c
index 9441b77a..ce68259c 100644
--- a/lib/route/route_obj.c
+++ b/lib/route/route_obj.c
@@ -24,9 +24,10 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/utils.h>
-#include <netlink-private/route/nexthop-encap.h>
+#include "nl-default.h"
+
+#include <linux/in_route.h>
+
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
@@ -36,9 +37,40 @@
#include <netlink/route/route.h>
#include <netlink/route/link.h>
#include <netlink/route/nexthop.h>
-#include <linux/in_route.h>
+
+#include "nl-route.h"
+#include "nl-aux-route/nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nexthop-encap.h"
/** @cond SKIP */
+struct rtnl_route {
+ NLHDR_COMMON
+
+ uint8_t rt_family;
+ uint8_t rt_dst_len;
+ uint8_t rt_src_len;
+ uint8_t rt_tos;
+ uint8_t rt_protocol;
+ uint8_t rt_scope;
+ uint8_t rt_type;
+ uint8_t rt_nmetrics;
+ uint8_t rt_ttl_propagate;
+ uint32_t rt_flags;
+ struct nl_addr *rt_dst;
+ struct nl_addr *rt_src;
+ uint32_t rt_table;
+ uint32_t rt_iif;
+ uint32_t rt_prio;
+ uint32_t rt_metrics[RTAX_MAX];
+ uint32_t rt_metrics_mask;
+ uint32_t rt_nr_nh;
+ struct nl_addr *rt_pref_src;
+ struct nl_list_head rt_nexthops;
+ struct rtnl_rtcacheinfo rt_cacheinfo;
+ uint32_t rt_flag_mask;
+};
+
#define ROUTE_ATTR_FAMILY 0x000001
#define ROUTE_ATTR_TOS 0x000002
#define ROUTE_ATTR_TABLE 0x000004
@@ -145,7 +177,8 @@ static void route_dump_line(struct nl_object *a, struct nl_dump_params *p)
nl_dump(p, "cache ");
if (!(r->ce_mask & ROUTE_ATTR_DST) ||
- nl_addr_get_len(r->rt_dst) == 0)
+ (nl_addr_get_prefixlen(r->rt_dst) == 0 &&
+ nl_addr_get_len(r->rt_dst) > 0 && nl_addr_iszero(r->rt_dst)))
nl_dump(p, "default ");
else
nl_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
@@ -311,7 +344,7 @@ static void route_keygen(struct nl_object *obj, uint32_t *hashkey,
uint32_t rt_table;
uint32_t rt_prio;
char rt_addr[0];
- } __attribute__((packed)) *rkey = NULL;
+ } _nl_packed *rkey = NULL;
#ifdef NL_DEBUG
char buf[INET6_ADDRSTRLEN+5];
#endif
@@ -368,22 +401,21 @@ static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b,
int i, found;
uint64_t diff = 0;
-#define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
-
- diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family);
- diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos);
- diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table);
- diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol);
- diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope);
- diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type);
- diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio);
- diff |= ROUTE_DIFF(DST, nl_addr_cmp(a->rt_dst, b->rt_dst));
- diff |= ROUTE_DIFF(SRC, nl_addr_cmp(a->rt_src, b->rt_src));
- diff |= ROUTE_DIFF(IIF, a->rt_iif != b->rt_iif);
- diff |= ROUTE_DIFF(PREF_SRC, nl_addr_cmp(a->rt_pref_src,
- b->rt_pref_src));
- diff |= ROUTE_DIFF(TTL_PROPAGATE,
- a->rt_ttl_propagate != b->rt_ttl_propagate);
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(ROUTE_ATTR_FAMILY, a->rt_family != b->rt_family);
+ diff |= _DIFF(ROUTE_ATTR_TOS, a->rt_tos != b->rt_tos);
+ diff |= _DIFF(ROUTE_ATTR_TABLE, a->rt_table != b->rt_table);
+ diff |= _DIFF(ROUTE_ATTR_PROTOCOL, a->rt_protocol != b->rt_protocol);
+ diff |= _DIFF(ROUTE_ATTR_SCOPE, a->rt_scope != b->rt_scope);
+ diff |= _DIFF(ROUTE_ATTR_TYPE, a->rt_type != b->rt_type);
+ diff |= _DIFF(ROUTE_ATTR_PRIO, a->rt_prio != b->rt_prio);
+ diff |= _DIFF(ROUTE_ATTR_DST, nl_addr_cmp(a->rt_dst, b->rt_dst));
+ diff |= _DIFF(ROUTE_ATTR_SRC, nl_addr_cmp(a->rt_src, b->rt_src));
+ diff |= _DIFF(ROUTE_ATTR_IIF, a->rt_iif != b->rt_iif);
+ diff |= _DIFF(ROUTE_ATTR_PREF_SRC,
+ nl_addr_cmp(a->rt_pref_src, b->rt_pref_src));
+ diff |= _DIFF(ROUTE_ATTR_TTL_PROPAGATE,
+ a->rt_ttl_propagate != b->rt_ttl_propagate);
if (flags & LOOSE_COMPARISON) {
nl_list_for_each_entry(nh_b, &b->rt_nexthops, rtnh_list) {
@@ -405,10 +437,10 @@ static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b,
if (a->rt_metrics_mask & (1 << i) &&
(!(b->rt_metrics_mask & (1 << i)) ||
a->rt_metrics[i] != b->rt_metrics[i]))
- diff |= ROUTE_DIFF(METRICS, 1);
+ diff |= _DIFF(ROUTE_ATTR_METRICS, 1);
}
- diff |= ROUTE_DIFF(FLAGS,
+ diff |= _DIFF(ROUTE_ATTR_FLAGS,
(a->rt_flags ^ b->rt_flags) & b->rt_flag_mask);
} else {
if (a->rt_nr_nh != b->rt_nr_nh)
@@ -446,23 +478,22 @@ static uint64_t route_compare(struct nl_object *_a, struct nl_object *_b,
for (i = 0; i < RTAX_MAX - 1; i++) {
if ((a->rt_metrics_mask & (1 << i)) ^
(b->rt_metrics_mask & (1 << i)))
- diff |= ROUTE_DIFF(METRICS, 1);
+ diff |= _DIFF(ROUTE_ATTR_METRICS, 1);
else
- diff |= ROUTE_DIFF(METRICS,
+ diff |= _DIFF(ROUTE_ATTR_METRICS,
a->rt_metrics[i] != b->rt_metrics[i]);
}
- diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags);
+ diff |= _DIFF(ROUTE_ATTR_FLAGS, a->rt_flags != b->rt_flags);
}
out:
return diff;
nh_mismatch:
- diff |= ROUTE_DIFF(MULTIPATH, 1);
+ diff |= _DIFF(ROUTE_ATTR_MULTIPATH, 1);
goto out;
-
-#undef ROUTE_DIFF
+#undef _DIFF
}
static int route_update(struct nl_object *old_obj, struct nl_object *new_obj)
@@ -1156,9 +1187,23 @@ int rtnl_route_parse(struct nlmsghdr *nlh, struct rtnl_route **result)
if (!(dst = nl_addr_alloc_attr(tb[RTA_DST], family)))
return -NLE_NOMEM;
} else {
- if (!(dst = nl_addr_alloc(0)))
+ int len;
+
+ switch (family) {
+ case AF_INET:
+ len = 4;
+ break;
+
+ case AF_INET6:
+ len = 16;
+ break;
+ default:
+ len = 0;
+ break;
+ }
+
+ if (!(dst = nl_addr_build(family, NULL, len)))
return -NLE_NOMEM;
- nl_addr_set_family(dst, rtm->rtm_family);
}
nl_addr_set_prefixlen(dst, rtm->rtm_dst_len);
diff --git a/lib/route/route_utils.c b/lib/route/route_utils.c
index 2a196f22..04e52b4c 100644
--- a/lib/route/route_utils.c
+++ b/lib/route/route_utils.c
@@ -31,12 +31,15 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/route.h>
-
+
+#include "nl-priv-dynamic-core/nl-core.h"
+
/**
* @name Routing Table Identifier Translations
* @{
@@ -49,7 +52,7 @@ static int add_routing_table_name(long id, const char *name)
return __trans_list_add(id, name, &table_names);
}
-static void __init init_routing_table_names(void)
+static void _nl_init init_routing_table_names(void)
{
add_routing_table_name(RT_TABLE_UNSPEC, "unspec");
add_routing_table_name(RT_TABLE_COMPAT, "compat");
@@ -58,7 +61,7 @@ static void __init init_routing_table_names(void)
add_routing_table_name(RT_TABLE_LOCAL, "local");
}
-static void __exit release_routing_table_names(void)
+static void _nl_exit release_routing_table_names(void)
{
__trans_list_clear(&table_names);
}
@@ -95,7 +98,7 @@ static int add_proto_name(long id, const char *name)
return __trans_list_add(id, name, &proto_names);
}
-static void __init init_proto_names(void)
+static void _nl_init init_proto_names(void)
{
add_proto_name(RTPROT_UNSPEC, "unspec");
add_proto_name(RTPROT_REDIRECT, "redirect");
@@ -104,7 +107,7 @@ static void __init init_proto_names(void)
add_proto_name(RTPROT_STATIC, "static");
}
-static void __exit release_proto_names(void)
+static void _nl_exit release_proto_names(void)
{
__trans_list_clear(&proto_names);
}
diff --git a/lib/route/rtnl.c b/lib/route/rtnl.c
index f28ebf36..142c4c4e 100644
--- a/lib/route/rtnl.c
+++ b/lib/route/rtnl.c
@@ -8,11 +8,14 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
+#include "nl-priv-dynamic-core/nl-core.h"
+
/**
* @name Sending
* @{
diff --git a/lib/route/rule.c b/lib/route/rule.c
index b3a60e14..6e7c0849 100644
--- a/lib/route/rule.c
+++ b/lib/route/rule.c
@@ -10,15 +10,44 @@
* @{
*/
-#include <netlink-private/netlink.h>
+#include "nl-default.h"
+
+#include <linux/fib_rules.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/rule.h>
-#include <inttypes.h>
-#include <linux/fib_rules.h>
+
+#include "nl-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
/** @cond SKIP */
+struct rtnl_rule {
+ NLHDR_COMMON
+ uint8_t r_family;
+ uint8_t r_action;
+ uint8_t r_dsfield; /* ipv4 only */
+ uint8_t r_l3mdev;
+ uint8_t r_protocol; /* protocol that installed rule */
+ uint8_t r_ip_proto; /* IP/IPv6 protocol */
+ uint32_t r_table;
+ uint32_t r_flags;
+ uint32_t r_prio;
+ uint32_t r_mark;
+ uint32_t r_mask;
+ uint32_t r_goto;
+ uint32_t r_flow; /* ipv4 only */
+ struct nl_addr *r_src;
+ struct nl_addr *r_dst;
+ char r_iifname[IFNAMSIZ];
+ char r_oifname[IFNAMSIZ];
+
+ struct fib_rule_port_range r_sport;
+ struct fib_rule_port_range r_dport;
+};
+
#define RULE_ATTR_FAMILY 0x000001
#define RULE_ATTR_TABLE 0x000002
#define RULE_ATTR_ACTION 0x000004
@@ -320,23 +349,21 @@ static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
struct rtnl_rule *b = (struct rtnl_rule *) _b;
uint64_t diff = 0;
-#define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
-
- diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
- diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
- diff |= RULE_DIFF(ACTION, a->r_action != b->r_action);
- diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname));
- diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname));
- diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
- diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
- diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask);
- diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto);
- diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
- diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
- diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
- diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow);
-
-#undef RULE_DIFF
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(RULE_ATTR_FAMILY, a->r_family != b->r_family);
+ diff |= _DIFF(RULE_ATTR_TABLE, a->r_table != b->r_table);
+ diff |= _DIFF(RULE_ATTR_ACTION, a->r_action != b->r_action);
+ diff |= _DIFF(RULE_ATTR_IIFNAME, strcmp(a->r_iifname, b->r_iifname));
+ diff |= _DIFF(RULE_ATTR_OIFNAME, strcmp(a->r_oifname, b->r_oifname));
+ diff |= _DIFF(RULE_ATTR_PRIO, a->r_prio != b->r_prio);
+ diff |= _DIFF(RULE_ATTR_MARK, a->r_mark != b->r_mark);
+ diff |= _DIFF(RULE_ATTR_MASK, a->r_mask != b->r_mask);
+ diff |= _DIFF(RULE_ATTR_GOTO, a->r_goto != b->r_goto);
+ diff |= _DIFF(RULE_ATTR_SRC, nl_addr_cmp(a->r_src, b->r_src));
+ diff |= _DIFF(RULE_ATTR_DST, nl_addr_cmp(a->r_dst, b->r_dst));
+ diff |= _DIFF(RULE_ATTR_DSFIELD, a->r_dsfield != b->r_dsfield);
+ diff |= _DIFF(RULE_ATTR_FLOW, a->r_flow != b->r_flow);
+#undef _DIFF
return diff;
}
@@ -538,7 +565,7 @@ int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
* sends the request to the kernel and waits for the next ACK to be
* received and thus blocks until the request has been fullfilled.
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
{
@@ -593,7 +620,7 @@ int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
* sends the request to the kernel and waits for the next ACK to be
* received and thus blocks until the request has been fullfilled.
*
- * @return 0 on sucess or a negative error if an error occured.
+ * @return 0 on success or a negative error if an error occured.
*/
int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
{
@@ -981,12 +1008,12 @@ static struct nl_cache_ops rtnl_rule_ops = {
.co_groups = rule_groups,
};
-static void __init rule_init(void)
+static void _nl_init rule_init(void)
{
nl_cache_mngt_register(&rtnl_rule_ops);
}
-static void __exit rule_exit(void)
+static void _nl_exit rule_exit(void)
{
nl_cache_mngt_unregister(&rtnl_rule_ops);
}
diff --git a/lib/route/tc-api.h b/lib/route/tc-api.h
new file mode 100644
index 00000000..43c4a283
--- /dev/null
+++ b/lib/route/tc-api.h
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: LGPL-2.1-only */
+/*
+ * Copyright (c) 2011-2013 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>
+
+#include "nl-route.h"
+#include "nl-priv-dynamic-route/nl-priv-dynamic-route.h"
+#include "nl-priv-dynamic-core/nl-core.h"
+#include "nl-priv-dynamic-core/cache-api.h"
+
+/*****************************************************************************/
+
+#define TCA_ATTR_HANDLE 0x0001
+#define TCA_ATTR_PARENT 0x0002
+#define TCA_ATTR_IFINDEX 0x0004
+#define TCA_ATTR_KIND 0x0008
+#define TCA_ATTR_FAMILY 0x0010
+#define TCA_ATTR_INFO 0x0020
+#define TCA_ATTR_OPTS 0x0040
+#define TCA_ATTR_STATS 0x0080
+#define TCA_ATTR_XSTATS 0x0100
+#define TCA_ATTR_LINK 0x0200
+#define TCA_ATTR_MTU 0x0400
+#define TCA_ATTR_MPU 0x0800
+#define TCA_ATTR_OVERHEAD 0x1000
+#define TCA_ATTR_LINKTYPE 0x2000
+#define TCA_ATTR_CHAIN 0x4000
+#define TCA_ATTR_MAX TCA_ATTR_CHAIN
+
+extern int tca_parse(struct nlattr **, int, struct rtnl_tc *,
+ const struct nla_policy *);
+
+#define RTNL_TC_RTABLE_SIZE 256
+
+static inline void *tca_xstats(struct rtnl_tc *tca)
+{
+ return tca->tc_xstats->d_data;
+}
+
+extern struct nl_af_group tc_groups[];
+
+/*****************************************************************************/
+
+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 *);
+};
+
+void *rtnl_tc_data_peek(struct rtnl_tc *tc);
+
+/*****************************************************************************/
+
+/* WARNING: the following symbols are wrongly exported in libnl-route-3
+ * library. They are private API, but leaked. */
+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 uint64_t rtnl_tc_compare(struct nl_object *,
+ struct nl_object *,
+ uint64_t, int);
+
+extern void * rtnl_tc_data(struct rtnl_tc *);
+extern void * rtnl_tc_data_check(struct rtnl_tc *,
+ struct rtnl_tc_ops *, int *);
+
+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 *);
+
+
+extern int rtnl_tc_build_rate_table(struct rtnl_tc *tc, struct rtnl_ratespec *,
+ uint32_t *);
+
+/*****************************************************************************/
+
+#endif
diff --git a/lib/route/tc.c b/lib/route/tc.c
index a06a4789..a2fd5674 100644
--- a/lib/route/tc.c
+++ b/lib/route/tc.c
@@ -9,16 +9,20 @@
* @{
*/
-#include <netlink-private/netlink.h>
-#include <netlink-private/tc.h>
+#include "nl-default.h"
+
+#include <linux/if_arp.h>
+#include <linux/gen_stats.h>
+
+#include <linux/atm.h>
+
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/route/rtnl.h>
#include <netlink/route/link.h>
#include <netlink/route/tc.h>
-#include <netlink-private/route/tc-api.h>
-#include "netlink-private/utils.h"
+#include "tc-api.h"
/** @cond SKIP */
@@ -105,11 +109,11 @@ int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc)
return err;
if (tbs[TCA_STATS_BASIC]) {
- struct gnet_stats_basic *bs;
+ struct gnet_stats_basic bs;
- bs = nla_data(tbs[TCA_STATS_BASIC]);
- tc->tc_stats[RTNL_TC_BYTES] = bs->bytes;
- tc->tc_stats[RTNL_TC_PACKETS] = bs->packets;
+ memcpy(&bs, nla_data(tbs[TCA_STATS_BASIC]), sizeof(bs));
+ tc->tc_stats[RTNL_TC_BYTES] = bs.bytes;
+ tc->tc_stats[RTNL_TC_PACKETS] = bs.packets;
}
if (tbs[TCA_STATS_RATE_EST]) {
@@ -142,16 +146,17 @@ int rtnl_tc_msg_parse(struct nlmsghdr *n, struct rtnl_tc *tc)
goto compat_xstats;
} else {
if (tb[TCA_STATS]) {
- struct tc_stats *st = nla_data(tb[TCA_STATS]);
-
- 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;
+ struct tc_stats st;
+
+ memcpy(&st, nla_data(tb[TCA_STATS]), sizeof(st));
+ 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;
tc->ce_mask |= TCA_ATTR_STATS;
}
@@ -666,14 +671,14 @@ int rtnl_tc_calc_bufsize(int txtime, int rate)
/**
* Calculate the binary logarithm for a specific cell size
* @arg cell_size Size of cell, must be a power of two.
- * @return Binary logirhtm of cell size or a negative error code.
+ * @return Binary logarithm of cell size or a negative error code.
*/
int rtnl_tc_calc_cell_log(int cell_size)
{
int i;
for (i = 0; i < 32; i++)
- if ((1 << i) == cell_size)
+ if ((((uint32_t)1u) << i) == cell_size)
return i;
return -NLE_INVAL;
@@ -971,14 +976,12 @@ uint64_t rtnl_tc_compare(struct nl_object *aobj, struct nl_object *bobj,
struct rtnl_tc *b = TC_CAST(bobj);
uint64_t 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
+#define _DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ATTR, a, b, EXPR)
+ diff |= _DIFF(TCA_ATTR_HANDLE, a->tc_handle != b->tc_handle);
+ diff |= _DIFF(TCA_ATTR_PARENT, a->tc_parent != b->tc_parent);
+ diff |= _DIFF(TCA_ATTR_IFINDEX, a->tc_ifindex != b->tc_ifindex);
+ diff |= _DIFF(TCA_ATTR_KIND, strcmp(a->tc_kind, b->tc_kind));
+#undef _DIFF
return diff;
}
@@ -1019,7 +1022,7 @@ int rtnl_tc_register(struct rtnl_tc_ops *ops)
/*
* 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
+ * separate _nl_init would required correct ordering of init
* functions
*/
if (!init) {