From e521ea5f5b3486035c235eb7ee180c394edd374d Mon Sep 17 00:00:00 2001 From: "Kiedrzyn, PatrykX" Date: Mon, 23 Nov 2020 09:04:48 +0100 Subject: Add queue lookup mode selection support --- Makefile.am | 2 + include/netlink/route/link/pon.h | 29 ++++ lib/route/link/pon.c | 240 +++++++++++++++++++++++++++++++ libnl-route-3.sym | 4 + 4 files changed, 275 insertions(+) create mode 100644 include/netlink/route/link/pon.h create mode 100644 lib/route/link/pon.c --- a/Makefile.am +++ b/Makefile.am @@ -168,6 +168,7 @@ libnlinclude_netlink_route_link_HEADERS include/netlink/route/link/vlan.h \ include/netlink/route/link/tcont.h \ include/netlink/route/link/gem.h \ + include/netlink/route/link/pon.h \ include/netlink/route/link/pmapper.h \ include/netlink/route/link/vrf.h \ include/netlink/route/link/vxlan.h \ @@ -422,6 +423,7 @@ lib_libnl_route_3_la_SOURCES = \ lib/route/link/vlan.c \ lib/route/link/tcont.c \ lib/route/link/gem.c \ + lib/route/link/pon.c \ lib/route/link/pmapper.c \ lib/route/link/vrf.c \ lib/route/link/vxlan.c \ --- /dev/null +++ b/include/netlink/route/link/pon.h @@ -0,0 +1,29 @@ +/****************************************************************************** + * + * Copyright (c) 2020, MaxLinear, Inc. + * + *****************************************************************************/ + +#ifndef NETLINK_LINK_PON_H_ +#define NETLINK_LINK_PON_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern struct rtnl_link *rtnl_link_pon_alloc(void); + +extern int rtnl_link_is_pon(struct rtnl_link *); + +extern int rtnl_link_pon_set_queue_lookup_mode(struct rtnl_link *, + uint8_t); +extern int rtnl_link_pon_get_queue_lookup_mode(struct rtnl_link *); + +#ifdef __cplusplus +} +#endif + +#endif --- /dev/null +++ b/lib/route/link/pon.c @@ -0,0 +1,240 @@ +/****************************************************************************** + * + * Copyright (c) 2020, MaxLinear, Inc. + * + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define PON_HAS_QUEUE_LOOKUP_MODE (1<<0) + +struct pon_info +{ + uint8_t queue_lookup_mode; + uint32_t mask; +}; + +/* The NetLink messages for the PON device configuration. */ +enum { + IFLA_PON_UNSPEC, + IFLA_PON_QUEUE_LOOKUP_MODE, + IFLA_PON_MAX +}; + +/** @endcond */ + +static struct nla_policy pon_policy[IFLA_PON_MAX+1] = { + [IFLA_PON_QUEUE_LOOKUP_MODE] = { .type = NLA_U8 }, +}; + +static int pon_alloc(struct rtnl_link *link) +{ + struct pon_info *gi; + + if (link->l_info) { + gi = link->l_info; + memset(link->l_info, 0, sizeof(*gi)); + } else { + if ((gi = calloc(1, sizeof(*gi))) == NULL) + return -NLE_NOMEM; + + link->l_info = gi; + } + + return 0; +} + +static int pon_parse(struct rtnl_link *link, struct nlattr *data, + struct nlattr *xstats) +{ + struct nlattr *tb[IFLA_PON_MAX+1]; + struct pon_info *gi; + int err; + + NL_DBG(3, "Parsing PON link info\n"); + + if ((err = nla_parse_nested(tb, IFLA_PON_MAX, data, pon_policy)) < 0) + goto errout; + + if ((err = pon_alloc(link)) < 0) + goto errout; + + gi = link->l_info; + + if (tb[IFLA_PON_QUEUE_LOOKUP_MODE]) { + gi->queue_lookup_mode + = nla_get_u8(tb[IFLA_PON_QUEUE_LOOKUP_MODE]); + gi->mask |= PON_HAS_QUEUE_LOOKUP_MODE; + } + + err = 0; +errout: + return err; +} + +static void pon_free(struct rtnl_link *link) +{ + struct pon_info *gi = link->l_info; + + free(gi); + link->l_info = NULL; +} + +static void pon_dump_line(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct pon_info *gi = link->l_info; + + nl_dump(p, "queue-lookup-mode %d", gi->queue_lookup_mode); +} + +static void pon_dump_details(struct rtnl_link *link, struct nl_dump_params *p) +{ + struct pon_info *gi = link->l_info; + /* TODO: To be extended? */ + + nl_dump(p, "queue-lookup-mode %d", gi->queue_lookup_mode); + nl_dump(p, "\n"); +} + +static int pon_clone(struct rtnl_link *dst, struct rtnl_link *src) +{ + struct pon_info *vdst, *vsrc = src->l_info; + int err; + + dst->l_info = NULL; + if ((err = rtnl_link_set_type(dst, "pon")) < 0) + return err; + vdst = dst->l_info; + + *vdst = *vsrc; + + return 0; +} + +static int pon_put_attrs(struct nl_msg *msg, struct rtnl_link *link) +{ + struct pon_info *gi = link->l_info; + struct nlattr *data; + + if (!(data = nla_nest_start(msg, IFLA_INFO_DATA))) + goto nla_put_failure; + + if (gi->mask & PON_HAS_QUEUE_LOOKUP_MODE) + NLA_PUT_U8(msg, IFLA_PON_QUEUE_LOOKUP_MODE, gi->queue_lookup_mode); + + nla_nest_end(msg, data); + return 0; + +nla_put_failure: + nla_nest_cancel(msg, data); + return -NLE_MSGSIZE; +} + +static struct rtnl_link_info_ops pon_info_ops = { + .io_name = "pon", + .io_alloc = pon_alloc, + .io_parse = pon_parse, + .io_dump = { + [NL_DUMP_LINE] = pon_dump_line, + [NL_DUMP_DETAILS] = pon_dump_details, + }, + .io_clone = pon_clone, + .io_put_attrs = pon_put_attrs, + .io_free = pon_free, +}; + +/** @cond SKIP */ +#define IS_PON_LINK_ASSERT(link) \ + if ((link)->l_info_ops != &pon_info_ops) { \ + APPBUG("Link is not a pon link. set type \"pon\" first."); \ + return -NLE_OPNOTSUPP; \ + } +/** @endcond */ + +/** + * Allocate link object of type PON + * + * @return Allocated link object or NULL. + */ +struct rtnl_link *rtnl_link_pon_alloc(void) +{ + struct rtnl_link *link; + int err; + + if (!(link = rtnl_link_alloc())) + return NULL; + + if ((err = rtnl_link_set_type(link, "pon")) < 0) { + rtnl_link_put(link); + return NULL; + } + + return link; +} + +/** + * Check if link is a PON link + * @arg link Link object + * + * @return True if link is a PON link, otherwise false is returned. + */ +int rtnl_link_is_pon(struct rtnl_link *link) +{ + return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "pon"); +} + +/** + * Set queue lookup mode + * @arg link Link object + * @arg queue_lookup_mode Queue lookup mode + * + * @return 0 on success or a negative error code + */ +int rtnl_link_pon_set_queue_lookup_mode(struct rtnl_link *link, + uint8_t queue_lookup_mode) +{ + struct pon_info *gi = link->l_info; + + IS_PON_LINK_ASSERT(link); + + gi->queue_lookup_mode = queue_lookup_mode; + gi->mask |= PON_HAS_QUEUE_LOOKUP_MODE; + + return 0; +} + +/** + * Get queue lookup mode + * @arg link Link object + * + * @return queue lookup mode, 0 if not set or a negative error code. + */ +int rtnl_link_pon_get_queue_lookup_mode(struct rtnl_link *link) +{ + struct pon_info *gi = link->l_info; + + IS_PON_LINK_ASSERT(link); + + if (gi->mask & PON_HAS_QUEUE_LOOKUP_MODE) + return gi->queue_lookup_mode; + else + return 0; +} + +static void __init pon_init(void) +{ + rtnl_link_register_info(&pon_info_ops); +} + +static void __exit pon_exit(void) +{ + rtnl_link_unregister_info(&pon_info_ops); +} --- a/libnl-route-3.sym +++ b/libnl-route-3.sym @@ -418,6 +418,7 @@ global: rtnl_link_is_can; rtnl_link_is_gem; rtnl_link_is_pmapper; + rtnl_link_is_pon; rtnl_link_is_ip6_tnl; rtnl_link_is_ipgre; rtnl_link_is_ipip; @@ -447,6 +448,9 @@ global: rtnl_link_pmapper_set_pcp_ifindex; rtnl_link_pmapper_get_default_pcp; rtnl_link_pmapper_get_pcp_ifindex; + rtnl_link_pon_alloc; + rtnl_link_pon_get_queue_lookup_mode; + rtnl_link_pon_set_queue_lookup_mode; rtnl_link_release; rtnl_link_release_ifindex; rtnl_link_set_addr;