13#include <netlink-private/netlink.h> 
   14#include <netlink-private/tc.h> 
   15#include <netlink/netlink.h> 
   16#include <netlink/cache.h> 
   17#include <netlink/utils.h> 
   18#include <netlink-private/route/tc-api.h> 
   19#include <netlink/route/qdisc.h> 
   20#include <netlink/route/class.h> 
   21#include <netlink/route/link.h> 
   22#include <netlink/route/qdisc/hfsc.h> 
   25#define SCH_HFSC_CLS_HAS_RSC            0x001 
   26#define SCH_HFSC_CLS_HAS_FSC            0x002 
   27#define SCH_HFSC_CLS_HAS_USC            0x004 
   29#define SCH_HFSC_QD_HAS_DEFCLS          0x01 
   32static struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
 
   33        [TCA_HFSC_RSC]  = { .
minlen = 
sizeof(
struct tc_service_curve) },
 
   34        [TCA_HFSC_FSC]  = { .minlen = 
sizeof(
struct tc_service_curve) },
 
   35        [TCA_HFSC_USC]  = { .minlen = 
sizeof(
struct tc_service_curve) },
 
   38static int hfsc_qdisc_msg_parser(
struct rtnl_tc *tc, 
void *data)
 
   40        struct rtnl_hfsc_qdisc *hfsc = data;
 
   41        struct tc_hfsc_qopt *opts;
 
   43        opts = (
struct tc_hfsc_qopt *) tc->tc_opts->d_data;
 
   44        hfsc->qh_defcls = opts->defcls;
 
   45        hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
 
   49static int hfsc_class_msg_parser(
struct rtnl_tc *tc, 
void *data)
 
   51        struct nlattr *tb[TCA_HFSC_MAX + 1];
 
   52        struct rtnl_hfsc_class *hfsc = data;
 
   55        if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0)
 
   58        if (tb[TCA_HFSC_RSC]) {
 
   59                struct tc_service_curve tsc;
 
   61                nla_memcpy(&tsc, tb[TCA_HFSC_RSC], 
sizeof(tsc));
 
   63                hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
 
   66        if (tb[TCA_HFSC_FSC]) {
 
   67                struct tc_service_curve tsc;
 
   69                nla_memcpy(&tsc, tb[TCA_HFSC_FSC], 
sizeof(tsc));
 
   71                hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
 
   74        if (tb[TCA_HFSC_USC]) {
 
   75                struct tc_service_curve tsc;
 
   77                nla_memcpy(&tsc, tb[TCA_HFSC_USC], 
sizeof(tsc));
 
   79                hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
 
   85static void hfsc_qdisc_dump_line(
struct rtnl_tc *tc, 
void *data,
 
   88        struct rtnl_hfsc_qdisc *hfsc = data;
 
   93        if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) {
 
  100static void hfsc_dump_tsc(
struct nl_dump_params *p, 
struct tc_service_curve *tsc)
 
  102        nl_dump(p, 
" m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2);
 
  105static void hfsc_class_dump_line(
struct rtnl_tc *tc, 
void *data,
 
  108        struct rtnl_hfsc_class *hfsc = data;
 
  112        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)
 
  113                hfsc_dump_tsc(p, &hfsc->ch_rsc);
 
  114        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)
 
  115                hfsc_dump_tsc(p, &hfsc->ch_fsc);
 
  116        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)
 
  117                hfsc_dump_tsc(p, &hfsc->ch_usc);
 
  120static void hfsc_class_dump_details(
struct rtnl_tc *tc, 
void *data,
 
  126static int hfsc_qdisc_msg_fill(
struct rtnl_tc *tc, 
void *data,
 
  129        struct rtnl_hfsc_qdisc *hfsc = data;
 
  130        struct tc_hfsc_qopt opts = {0};
 
  135        opts.defcls = hfsc->qh_defcls;
 
  136        return nlmsg_append(msg, &opts, 
sizeof(opts), NL_DONTPAD);
 
  139static int hfsc_class_msg_fill(
struct rtnl_tc *tc, 
void *data,
 
  142        struct rtnl_hfsc_class *hfsc = data;
 
  143        struct tc_service_curve tsc;
 
  148        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) {
 
  150                NLA_PUT(msg, TCA_HFSC_RSC, 
sizeof(tsc), &tsc);
 
  153        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) {
 
  155                NLA_PUT(msg, TCA_HFSC_FSC, 
sizeof(tsc), &tsc);
 
  158        if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) {
 
  160                NLA_PUT(msg, TCA_HFSC_USC, 
sizeof(tsc), &tsc);
 
  169static struct rtnl_tc_ops hfsc_qdisc_ops;
 
  170static struct rtnl_tc_ops hfsc_class_ops;
 
  172static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(
const struct rtnl_qdisc *qdisc, 
int *err)
 
  177static struct rtnl_hfsc_class *hfsc_class_data(
const struct rtnl_class *
class, 
int *err)
 
  198        struct rtnl_hfsc_qdisc *hfsc;
 
  200        if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) &&
 
  201            (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS))
 
  202                return hfsc->qh_defcls;
 
  214        struct rtnl_hfsc_qdisc *hfsc;
 
  217        if (!(hfsc = hfsc_qdisc_data(qdisc, &err)))
 
  220        hfsc->qh_defcls = defcls;
 
  221        hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
 
  226int rtnl_class_hfsc_get_rsc(
const struct rtnl_class *
class, 
struct tc_service_curve *tsc)
 
  228        struct rtnl_hfsc_class *hfsc;
 
  229        int err = -NLE_OPNOTSUPP;
 
  231        if ((hfsc = hfsc_class_data(
class, &err)) &&
 
  232            (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) {
 
  240int rtnl_class_hfsc_set_rsc(
struct rtnl_class *
class, 
const struct tc_service_curve *tsc)
 
  242        struct rtnl_hfsc_class *hfsc;
 
  245        if (!(hfsc = hfsc_class_data(
class, &err)))
 
  249        hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
 
  254int rtnl_class_hfsc_get_fsc(
const struct rtnl_class *
class, 
struct tc_service_curve *tsc)
 
  256        struct rtnl_hfsc_class *hfsc;
 
  257        int err = -NLE_OPNOTSUPP;
 
  259        if ((hfsc = hfsc_class_data(
class, &err)) &&
 
  260            (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) {
 
  268int rtnl_class_hfsc_set_fsc(
struct rtnl_class *
class, 
const struct tc_service_curve *tsc)
 
  270        struct rtnl_hfsc_class *hfsc;
 
  273        if (!(hfsc = hfsc_class_data(
class, &err)))
 
  277        hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
 
  282int rtnl_class_hfsc_get_usc(
const struct rtnl_class *
class, 
struct tc_service_curve *tsc)
 
  284        struct rtnl_hfsc_class *hfsc;
 
  285        int err = -NLE_OPNOTSUPP;
 
  287        if ((hfsc = hfsc_class_data(
class, &err)) &&
 
  288            (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) {
 
  296int rtnl_class_hfsc_set_usc(
struct rtnl_class *
class, 
const struct tc_service_curve *tsc)
 
  298        struct rtnl_hfsc_class *hfsc;
 
  301        if (!(hfsc = hfsc_class_data(
class, &err)))
 
  305        hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
 
  312static struct rtnl_tc_ops hfsc_qdisc_ops = {
 
  314        .to_type                = RTNL_TC_TYPE_QDISC,
 
  315        .to_size                = 
sizeof(
struct rtnl_hfsc_qdisc),
 
  316        .to_msg_parser          = hfsc_qdisc_msg_parser,
 
  318        .to_msg_fill            = hfsc_qdisc_msg_fill,
 
  321static struct rtnl_tc_ops hfsc_class_ops = {
 
  323        .to_type                = RTNL_TC_TYPE_CLASS,
 
  324        .to_size                = 
sizeof(
struct rtnl_hfsc_class),
 
  325        .to_msg_parser          = hfsc_class_msg_parser,
 
  330        .to_msg_fill            = hfsc_class_msg_fill,
 
  333static void __init hfsc_init(
void)
 
  339static void __exit hfsc_exit(
void)
 
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
 
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
 
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
 
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
 
uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc)
Return default class of HFSC qdisc.
 
int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the hfsc qdisc to the specified value.
 
void * rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err)
Check traffic control object type and return private data section.
 
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
 
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
 
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
 
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
 
@ NL_DUMP_LINE
Dump object briefly on one line.
 
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
 
Attribute validation policy.
 
uint16_t minlen
Minimal length of payload required.