diff options
Diffstat (limited to 'lib/route')
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) { |