lib/qdisc: merge branch 'westermo/qdisc-mqprio'

https://github.com/thom311/libnl/pull/196
This commit is contained in:
Thomas Haller 2018-10-10 10:50:41 +02:00
commit ebcfdc28b8
7 changed files with 1103 additions and 97 deletions

View File

@ -23,11 +23,12 @@ DISTCHECK_CONFIGURE_FLAGS = \
pkgconfig_DATA = \
libnl-3.0.pc \
libnl-route-3.0.pc \
libnl-genl-3.0.pc \
libnl-idiag-3.0.pc \
libnl-nf-3.0.pc \
libnl-route-3.0.pc \
libnl-xfrm-3.0.pc \
libnl-idiag-3.0.pc
$(NULL)
warn_cppflags = \
-Wall \
@ -63,24 +64,28 @@ libnlinclude_netlink_HEADERS = \
include/netlink/socket.h \
include/netlink/types.h \
include/netlink/utils.h \
include/netlink/version.h
include/netlink/version.h \
$(NULL)
libnlinclude_netlink_fib_lookupdir = $(libnlincludedir)/netlink/fib_lookup
libnlinclude_netlink_fib_lookup_HEADERS = \
include/netlink/fib_lookup/lookup.h \
include/netlink/fib_lookup/request.h
include/netlink/fib_lookup/request.h \
$(NULL)
libnlinclude_netlink_genldir = $(libnlincludedir)/netlink/genl
libnlinclude_netlink_genl_HEADERS = \
include/netlink/genl/ctrl.h \
include/netlink/genl/family.h \
include/netlink/genl/genl.h \
include/netlink/genl/mngt.h
include/netlink/genl/mngt.h \
$(NULL)
libnlinclude_netlink_idiagdir = $(libnlincludedir)/netlink/idiag
libnlinclude_netlink_idiag_HEADERS = \
include/netlink/idiag/idiagnl.h \
include/netlink/idiag/meminfo.h \
include/netlink/idiag/msg.h \
include/netlink/idiag/req.h \
include/netlink/idiag/vegasinfo.h
include/netlink/idiag/vegasinfo.h \
$(NULL)
libnlinclude_netlink_netfilterdir = $(libnlincludedir)/netlink/netfilter
libnlinclude_netlink_netfilter_HEADERS = \
include/netlink/netfilter/ct.h \
@ -90,7 +95,8 @@ libnlinclude_netlink_netfilter_HEADERS = \
include/netlink/netfilter/netfilter.h \
include/netlink/netfilter/nfnl.h \
include/netlink/netfilter/queue.h \
include/netlink/netfilter/queue_msg.h
include/netlink/netfilter/queue_msg.h \
$(NULL)
libnlinclude_netlink_routedir = $(libnlincludedir)/netlink/route
libnlinclude_netlink_route_HEADERS = \
include/netlink/route/action.h \
@ -108,33 +114,38 @@ libnlinclude_netlink_route_HEADERS = \
include/netlink/route/rtnl.h \
include/netlink/route/rule.h \
include/netlink/route/tc-api.h \
include/netlink/route/tc.h
include/netlink/route/tc.h \
$(NULL)
libnlinclude_netlink_route_actdir = $(libnlincludedir)/netlink/route/act
libnlinclude_netlink_route_act_HEADERS = \
include/netlink/route/act/gact.h \
include/netlink/route/act/mirred.h \
include/netlink/route/act/skbedit.h
include/netlink/route/act/skbedit.h \
$(NULL)
libnlinclude_netlink_route_clsdir = $(libnlincludedir)/netlink/route/cls
libnlinclude_netlink_route_cls_HEADERS = \
include/netlink/route/cls/basic.h \
include/netlink/route/cls/cgroup.h \
include/netlink/route/cls/ematch.h \
include/netlink/route/cls/fw.h \
include/netlink/route/cls/matchall.h \
include/netlink/route/cls/police.h \
include/netlink/route/cls/u32.h \
include/netlink/route/cls/matchall.h
$(NULL)
libnlinclude_netlink_route_cls_ematchdir = $(libnlincludedir)/netlink/route/cls/ematch
libnlinclude_netlink_route_cls_ematch_HEADERS = \
include/netlink/route/cls/ematch/cmp.h \
include/netlink/route/cls/ematch/meta.h \
include/netlink/route/cls/ematch/nbyte.h \
include/netlink/route/cls/ematch/text.h
include/netlink/route/cls/ematch/text.h \
$(NULL)
libnlinclude_netlink_route_linkdir = $(libnlincludedir)/netlink/route/link
libnlinclude_netlink_route_link_HEADERS = \
include/netlink/route/link/api.h \
include/netlink/route/link/bonding.h \
include/netlink/route/link/bridge.h \
include/netlink/route/link/can.h \
include/netlink/route/link/geneve.h \
include/netlink/route/link/inet.h \
include/netlink/route/link/inet6.h \
include/netlink/route/link/info-api.h \
@ -153,7 +164,7 @@ libnlinclude_netlink_route_link_HEADERS = \
include/netlink/route/link/vlan.h \
include/netlink/route/link/vrf.h \
include/netlink/route/link/vxlan.h \
include/netlink/route/link/geneve.h
$(NULL)
libnlinclude_netlink_route_qdiscdir = $(libnlincludedir)/netlink/route/qdisc
libnlinclude_netlink_route_qdisc_HEADERS = \
include/netlink/route/qdisc/cbq.h \
@ -162,12 +173,14 @@ libnlinclude_netlink_route_qdisc_HEADERS = \
include/netlink/route/qdisc/fq_codel.h \
include/netlink/route/qdisc/hfsc.h \
include/netlink/route/qdisc/htb.h \
include/netlink/route/qdisc/mqprio.h \
include/netlink/route/qdisc/netem.h \
include/netlink/route/qdisc/plug.h \
include/netlink/route/qdisc/prio.h \
include/netlink/route/qdisc/red.h \
include/netlink/route/qdisc/sfq.h \
include/netlink/route/qdisc/tbf.h
include/netlink/route/qdisc/tbf.h \
$(NULL)
libnlinclude_netlink_xfrmdir = $(libnlincludedir)/netlink/xfrm
libnlinclude_netlink_xfrm_HEADERS = \
include/netlink/xfrm/ae.h \
@ -175,7 +188,8 @@ libnlinclude_netlink_xfrm_HEADERS = \
include/netlink/xfrm/sa.h \
include/netlink/xfrm/selector.h \
include/netlink/xfrm/sp.h \
include/netlink/xfrm/template.h
include/netlink/xfrm/template.h \
$(NULL)
if ENABLE_CLI
libnlinclude_netlink_clidir = $(libnlincludedir)/netlink/cli
@ -191,7 +205,8 @@ libnlinclude_netlink_cli_HEADERS = \
include/netlink/cli/route.h \
include/netlink/cli/rule.h \
include/netlink/cli/tc.h \
include/netlink/cli/utils.h
include/netlink/cli/utils.h \
$(NULL)
endif
noinst_HEADERS = \
@ -252,7 +267,8 @@ noinst_HEADERS = \
include/netlink-private/socket.h \
include/netlink-private/tc.h \
include/netlink-private/types.h \
include/netlink-private/utils.h
include/netlink-private/utils.h \
$(NULL)
###############################################################################
@ -284,10 +300,11 @@ lib/route/cls/ematch_syntax.c: lib/route/cls/ematch_syntax.y lib/route/cls/.dirs
$(AM_V_GEN) $(YACC) -d $(YFLAGS) -o $@ $<
grammar_files_sources = \
lib/route/cls/ematch_grammar.c \
lib/route/cls/ematch_syntax.c \
lib/route/pktloc_grammar.c \
lib/route/pktloc_syntax.c \
lib/route/cls/ematch_grammar.c \
lib/route/cls/ematch_syntax.c
$(NULL)
grammar_files_headers = $(grammar_files_sources:%.c=%.h)
@ -296,10 +313,11 @@ CLEANFILES += \
$(grammar_files_headers)
EXTRA_DIST += \
lib/route/cls/ematch_grammar.l \
lib/route/cls/ematch_syntax.y \
lib/route/pktloc_grammar.l \
lib/route/pktloc_syntax.y \
lib/route/cls/ematch_grammar.l \
lib/route/cls/ematch_syntax.y
$(NULL)
###############################################################################
@ -324,15 +342,16 @@ lib_libnl_3_la_SOURCES = \
lib/data.c \
lib/error.c \
lib/handlers.c \
lib/hash.c \
lib/hashtable.c \
lib/mpls.c \
lib/msg.c \
lib/nl.c \
lib/object.c \
lib/socket.c \
lib/utils.c \
lib/version.c \
lib/hash.c \
lib/hashtable.c \
lib/mpls.c
$(NULL)
EXTRA_lib_libnl_3_la_DEPENDENCIES = \
libnl-3.sym
lib_libnl_3_la_CPPFLAGS = \
@ -353,8 +372,8 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/addr.c \
lib/route/class.c \
lib/route/classid.c \
lib/route/cls/basic.c \
lib/route/cls.c \
lib/route/cls/basic.c \
lib/route/cls/cgroup.c \
lib/route/cls/ematch.c \
lib/route/cls/ematch/cmp.c \
@ -363,18 +382,19 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/cls/ematch/nbyte.c \
lib/route/cls/ematch/text.c \
lib/route/cls/fw.c \
lib/route/cls/mall.c \
lib/route/cls/police.c \
lib/route/cls/u32.c \
lib/route/cls/mall.c \
lib/route/link.c \
lib/route/link/api.c \
lib/route/link/bonding.c \
lib/route/link/bridge.c \
lib/route/link.c \
lib/route/link/can.c \
lib/route/link/dummy.c \
lib/route/link/geneve.c \
lib/route/link/ifb.c \
lib/route/link/inet6.c \
lib/route/link/inet.c \
lib/route/link/inet6.c \
lib/route/link/ip6tnl.c \
lib/route/link/ipgre.c \
lib/route/link/ipip.c \
@ -389,7 +409,6 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/link/vlan.c \
lib/route/link/vrf.c \
lib/route/link/vxlan.c \
lib/route/link/geneve.c \
lib/route/neigh.c \
lib/route/neightbl.c \
lib/route/netconf.c \
@ -397,8 +416,8 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/nexthop_encap.c \
lib/route/nh_encap_mpls.c \
lib/route/pktloc.c \
lib/route/qdisc/blackhole.c \
lib/route/qdisc.c \
lib/route/qdisc/blackhole.c \
lib/route/qdisc/cbq.c \
lib/route/qdisc/dsmark.c \
lib/route/qdisc/fifo.c \
@ -406,6 +425,7 @@ lib_libnl_route_3_la_SOURCES = \
lib/route/qdisc/hfsc.c \
lib/route/qdisc/htb.c \
lib/route/qdisc/ingress.c \
lib/route/qdisc/mqprio.c \
lib/route/qdisc/netem.c \
lib/route/qdisc/plug.c \
lib/route/qdisc/prio.c \
@ -436,11 +456,12 @@ $(lib_libnl_route_3_la_OBJECTS): $(grammar_files_headers)
lib_LTLIBRARIES += lib/libnl-idiag-3.la
lib_libnl_idiag_3_la_SOURCES = \
lib/idiag/idiag.c \
lib/idiag/idiag_meminfo_obj.c \
lib/idiag/idiag_vegasinfo_obj.c \
lib/idiag/idiag_msg_obj.c \
lib/idiag/idiag_req_obj.c \
lib/idiag/idiag.c
lib/idiag/idiag_vegasinfo_obj.c \
$(NULL)
EXTRA_lib_libnl_idiag_3_la_DEPENDENCIES = \
libnl-idiag-3.sym
lib_libnl_idiag_3_la_CPPFLAGS = \
@ -457,7 +478,8 @@ lib_libnl_genl_3_la_SOURCES = \
lib/genl/ctrl.c \
lib/genl/family.c \
lib/genl/genl.c \
lib/genl/mngt.c
lib/genl/mngt.c \
$(NULL)
EXTRA_lib_libnl_genl_3_la_DEPENDENCIES = \
libnl-genl-3.sym
lib_libnl_genl_3_la_CPPFLAGS = \
@ -473,6 +495,8 @@ lib_LTLIBRARIES += lib/libnl-nf-3.la
lib_libnl_nf_3_la_SOURCES = \
lib/netfilter/ct.c \
lib/netfilter/ct_obj.c \
lib/netfilter/exp.c \
lib/netfilter/exp_obj.c \
lib/netfilter/log.c \
lib/netfilter/log_msg.c \
lib/netfilter/log_msg_obj.c \
@ -483,8 +507,7 @@ lib_libnl_nf_3_la_SOURCES = \
lib/netfilter/queue_msg.c \
lib/netfilter/queue_msg_obj.c \
lib/netfilter/queue_obj.c \
lib/netfilter/exp.c \
lib/netfilter/exp_obj.c
$(NULL)
lib_libnl_nf_3_la_CPPFLAGS = \
$(lib_cppflags)
EXTRA_lib_libnl_nf_3_la_DEPENDENCIES = \
@ -504,7 +527,8 @@ lib_libnl_xfrm_3_la_SOURCES = \
lib/xfrm/sa.c \
lib/xfrm/selector.c \
lib/xfrm/sp.c \
lib/xfrm/template.c
lib/xfrm/template.c \
$(NULL)
lib_libnl_xfrm_3_la_CPPFLAGS = \
$(lib_cppflags)
lib_libnl_xfrm_3_la_LDFLAGS = \
@ -517,7 +541,8 @@ lib_libnl_xfrm_3_la_LIBADD = \
lib_cli_ltlibraries_cls = \
lib/cli/cls/basic.la \
lib/cli/cls/cgroup.la
lib/cli/cls/cgroup.la \
$(NULL)
lib_cli_ltlibraries_qdisc = \
lib/cli/qdisc/bfifo.la \
lib/cli/qdisc/blackhole.la \
@ -526,7 +551,8 @@ lib_cli_ltlibraries_qdisc = \
lib/cli/qdisc/htb.la \
lib/cli/qdisc/ingress.la \
lib/cli/qdisc/pfifo.la \
lib/cli/qdisc/plug.la
lib/cli/qdisc/plug.la \
$(NULL)
if ENABLE_CLI
pkglib_clsdir = $(pkglibdir)/cli/cls
@ -575,18 +601,19 @@ check_LTLIBRARIES += src/lib/libnl-cli-3.la
endif
src_lib_libnl_cli_3_la_SOURCES = \
src/lib/utils.c \
src/lib/addr.c \
src/lib/ct.c \
src/lib/link.c \
src/lib/neigh.c \
src/lib/rule.c \
src/lib/route.c \
src/lib/tc.c \
src/lib/qdisc.c \
src/lib/class.c \
src/lib/cls.c \
src/lib/exp.c
src/lib/ct.c \
src/lib/exp.c \
src/lib/link.c \
src/lib/neigh.c \
src/lib/qdisc.c \
src/lib/route.c \
src/lib/rule.c \
src/lib/tc.c \
src/lib/utils.c \
$(NULL)
EXTRA_src_lib_libnl_cli_3_la_DEPENDENCIES = \
libnl-cli-3.sym
src_lib_libnl_cli_3_la_CPPFLAGS = \
@ -605,7 +632,8 @@ src_lib_libnl_cli_3_la_LIBADD = \
lib/libnl-route-3.la \
lib/libnl-nf-3.la \
lib/libnl-genl-3.la \
-ldl
-ldl \
$(NULL)
###############################################################################
@ -623,7 +651,8 @@ src_ldadd = \
lib/libnl-nf-3.la \
lib/libnl-genl-3.la \
lib/libnl-route-3.la \
lib/libnl-idiag-3.la
lib/libnl-idiag-3.la \
$(NULL)
cli_programs = \
src/genl-ctrl-list \
@ -895,11 +924,12 @@ check_programs += tests/check-all
endif
tests_check_all_SOURCES = \
tests/util.h \
tests/check-all.c \
tests/check-addr.c \
tests/check-all.c \
tests/check-attr.c \
tests/check-ematch-tree-clone.c
tests/check-ematch-tree-clone.c \
tests/util.h \
$(NULL)
tests_check_all_CPPFLAGS = \
$(tests_cppflags) \
@ -912,12 +942,13 @@ tests_check_all_LDADD = \
###############################################################################
dist_man8_MANS = \
man/genl-ctrl-list.8 \
man/nl-classid-lookup.8 \
man/nl-pktloc-lookup.8 \
man/nl-qdisc-add.8 \
man/nl-qdisc-delete.8 \
man/nl-qdisc-list.8 \
man/genl-ctrl-list.8
$(NULL)
###############################################################################
@ -980,4 +1011,5 @@ EXTRA_DIST += \
libnl-idiag-3.sym \
libnl-nf-3.sym \
libnl-route-3.sym \
libnl-xfrm-3.sym
libnl-xfrm-3.sym \
$(NULL)

View File

@ -1,3 +1,4 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
#ifndef __LINUX_PKT_SCHED_H
#define __LINUX_PKT_SCHED_H
@ -30,7 +31,7 @@
*/
struct tc_stats {
__u64 bytes; /* NUmber of enqueues bytes */
__u64 bytes; /* Number of enqueued bytes */
__u32 packets; /* Number of enqueued packets */
__u32 drops; /* Packets dropped because of lack of resources */
__u32 overlimits; /* Number of throttle events when this
@ -72,6 +73,11 @@ struct tc_estimator {
#define TC_H_UNSPEC (0U)
#define TC_H_ROOT (0xFFFFFFFFU)
#define TC_H_INGRESS (0xFFFFFFF1U)
#define TC_H_CLSACT TC_H_INGRESS
#define TC_H_MIN_PRIORITY 0xFFE0U
#define TC_H_MIN_INGRESS 0xFFF2U
#define TC_H_MIN_EGRESS 0xFFF3U
struct tc_ratespec {
unsigned char cell_log;
@ -135,17 +141,17 @@ struct tc_multiq_qopt {
#define TCQ_PLUG_LIMIT 3
struct tc_plug_qopt {
/* TCQ_PLUG_BUFFER: Inset a plug into the queue and
* buffer any incoming packets
* TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
* to beginning of the next plug.
* TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
* Stop buffering packets until the next TCQ_PLUG_BUFFER
* command is received (just act as a pass-thru queue).
* TCQ_PLUG_LIMIT: Increase/decrease queue size
*/
int action;
__u32 limit;
/* TCQ_PLUG_BUFFER: Inset a plug into the queue and
* buffer any incoming packets
* TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
* to beginning of the next plug.
* TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
* Stop buffering packets until the next TCQ_PLUG_BUFFER
* command is received (just act as a pass-thru queue).
* TCQ_PLUG_LIMIT: Increase/decrease queue size
*/
int action;
__u32 limit;
};
/* TBF section */
@ -163,6 +169,11 @@ enum {
TCA_TBF_PARMS,
TCA_TBF_RTAB,
TCA_TBF_PTAB,
TCA_TBF_RATE64,
TCA_TBF_PRATE64,
TCA_TBF_BURST,
TCA_TBF_PBURST,
TCA_TBF_PAD,
__TCA_TBF_MAX,
};
@ -183,25 +194,44 @@ struct tc_sfq_qopt {
unsigned flows; /* Maximal number of flows */
};
struct tc_sfqred_stats {
__u32 prob_drop; /* Early drops, below max threshold */
__u32 forced_drop; /* Early drops, after max threshold */
__u32 prob_mark; /* Marked packets, below max threshold */
__u32 forced_mark; /* Marked packets, after max threshold */
__u32 prob_mark_head; /* Marked packets, below max threshold */
__u32 forced_mark_head;/* Marked packets, after max threshold */
};
struct tc_sfq_qopt_v1 {
struct tc_sfq_qopt v0;
unsigned int depth; /* max number of packets per flow */
unsigned int headdrop;
/* SFQRED parameters */
__u32 limit; /* HARD maximal flow queue length (bytes) */
__u32 qth_min; /* Min average length threshold (bytes) */
__u32 qth_max; /* Max average length threshold (bytes) */
unsigned char Wlog; /* log(W) */
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
unsigned char Scell_log; /* cell size for idle damping */
unsigned char flags;
__u32 max_P; /* probability, high resolution */
/* SFQRED stats */
struct tc_sfqred_stats stats;
};
struct tc_sfq_xstats {
__s32 allot;
};
/*
* NOTE: limit, divisor and flows are hardwired to code at the moment.
*
* limit=flows=128, divisor=1024;
*
* The only reason for this is efficiency, it is possible
* to change these parameters in compile time.
*/
/* RED section */
enum {
TCA_RED_UNSPEC,
TCA_RED_PARMS,
TCA_RED_STAB,
TCA_RED_MAX_P,
__TCA_RED_MAX,
};
@ -215,8 +245,9 @@ struct tc_red_qopt {
unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */
unsigned char Scell_log; /* cell size for idle damping */
unsigned char flags;
#define TC_RED_ECN 1
#define TC_RED_HARDDROP 2
#define TC_RED_ECN 1
#define TC_RED_HARDDROP 2
#define TC_RED_ADAPTATIVE 4
};
struct tc_red_xstats {
@ -235,7 +266,9 @@ enum {
TCA_GRED_PARMS,
TCA_GRED_STAB,
TCA_GRED_DPS,
__TCA_GRED_MAX,
TCA_GRED_MAX_P,
TCA_GRED_LIMIT,
__TCA_GRED_MAX,
};
#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
@ -274,6 +307,7 @@ enum {
TCA_CHOKE_UNSPEC,
TCA_CHOKE_PARMS,
TCA_CHOKE_STAB,
TCA_CHOKE_MAX_P,
__TCA_CHOKE_MAX,
};
@ -318,7 +352,7 @@ struct tc_htb_glob {
__u32 debug; /* debug flags */
/* stats */
__u32 direct_pkts; /* count of non shapped packets */
__u32 direct_pkts; /* count of non shaped packets */
};
enum {
TCA_HTB_UNSPEC,
@ -326,6 +360,10 @@ enum {
TCA_HTB_INIT,
TCA_HTB_CTAB,
TCA_HTB_RTAB,
TCA_HTB_DIRECT_QLEN,
TCA_HTB_RATE64,
TCA_HTB_CEIL64,
TCA_HTB_PAD,
__TCA_HTB_MAX,
};
@ -462,21 +500,6 @@ enum {
#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1)
/* fq_codel section */
enum {
TCA_FQ_CODEL_UNSPEC,
TCA_FQ_CODEL_TARGET,
TCA_FQ_CODEL_LIMIT,
TCA_FQ_CODEL_INTERVAL,
TCA_FQ_CODEL_ECN,
TCA_FQ_CODEL_FLOWS,
TCA_FQ_CODEL_QUANTUM,
__TCA_FQ_CODEL_MAX
};
#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
/* ATM section */
enum {
@ -501,6 +524,13 @@ enum {
TCA_NETEM_REORDER,
TCA_NETEM_CORRUPT,
TCA_NETEM_LOSS,
TCA_NETEM_RATE,
TCA_NETEM_ECN,
TCA_NETEM_RATE64,
TCA_NETEM_PAD,
TCA_NETEM_LATENCY64,
TCA_NETEM_JITTER64,
TCA_NETEM_SLOT,
__TCA_NETEM_MAX,
};
@ -531,6 +561,20 @@ struct tc_netem_corrupt {
__u32 correlation;
};
struct tc_netem_rate {
__u32 rate; /* byte/s */
__s32 packet_overhead;
__u32 cell_size;
__s32 cell_overhead;
};
struct tc_netem_slot {
__s64 min_delay; /* nsec */
__s64 max_delay;
__s32 max_packets;
__s32 max_bytes;
};
enum {
NETEM_LOSS_UNSPEC,
NETEM_LOSS_GI, /* General Intuitive - 4 state model */
@ -539,7 +583,7 @@ enum {
};
#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
/* State transition probablities for 4 state model */
/* State transition probabilities for 4 state model */
struct tc_netem_gimodel {
__u32 p13;
__u32 p31;
@ -577,6 +621,30 @@ struct tc_drr_stats {
#define TC_QOPT_BITMASK 15
#define TC_QOPT_MAX_QUEUE 16
enum {
TC_MQPRIO_HW_OFFLOAD_NONE, /* no offload requested */
TC_MQPRIO_HW_OFFLOAD_TCS, /* offload TCs, no queue counts */
__TC_MQPRIO_HW_OFFLOAD_MAX
};
#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
enum {
TC_MQPRIO_MODE_DCB,
TC_MQPRIO_MODE_CHANNEL,
__TC_MQPRIO_MODE_MAX
};
#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)
enum {
TC_MQPRIO_SHAPER_DCB,
TC_MQPRIO_SHAPER_BW_RATE, /* Add new shapers below */
__TC_MQPRIO_SHAPER_MAX
};
#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
struct tc_mqprio_qopt {
__u8 num_tc;
__u8 prio_tc_map[TC_QOPT_BITMASK + 1];
@ -585,6 +653,22 @@ struct tc_mqprio_qopt {
__u16 offset[TC_QOPT_MAX_QUEUE];
};
#define TC_MQPRIO_F_MODE 0x1
#define TC_MQPRIO_F_SHAPER 0x2
#define TC_MQPRIO_F_MIN_RATE 0x4
#define TC_MQPRIO_F_MAX_RATE 0x8
enum {
TCA_MQPRIO_UNSPEC,
TCA_MQPRIO_MODE,
TCA_MQPRIO_SHAPER,
TCA_MQPRIO_MIN_RATE64,
TCA_MQPRIO_MAX_RATE64,
__TCA_MQPRIO_MAX,
};
#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)
/* SFB */
enum {
@ -639,4 +723,207 @@ struct tc_qfq_stats {
__u32 lmax;
};
/* CODEL */
enum {
TCA_CODEL_UNSPEC,
TCA_CODEL_TARGET,
TCA_CODEL_LIMIT,
TCA_CODEL_INTERVAL,
TCA_CODEL_ECN,
TCA_CODEL_CE_THRESHOLD,
__TCA_CODEL_MAX
};
#define TCA_CODEL_MAX (__TCA_CODEL_MAX - 1)
struct tc_codel_xstats {
__u32 maxpacket; /* largest packet we've seen so far */
__u32 count; /* how many drops we've done since the last time we
* entered dropping state
*/
__u32 lastcount; /* count at entry to dropping state */
__u32 ldelay; /* in-queue delay seen by most recently dequeued packet */
__s32 drop_next; /* time to drop next packet */
__u32 drop_overlimit; /* number of time max qdisc packet limit was hit */
__u32 ecn_mark; /* number of packets we ECN marked instead of dropped */
__u32 dropping; /* are we in dropping state ? */
__u32 ce_mark; /* number of CE marked packets because of ce_threshold */
};
/* FQ_CODEL */
enum {
TCA_FQ_CODEL_UNSPEC,
TCA_FQ_CODEL_TARGET,
TCA_FQ_CODEL_LIMIT,
TCA_FQ_CODEL_INTERVAL,
TCA_FQ_CODEL_ECN,
TCA_FQ_CODEL_FLOWS,
TCA_FQ_CODEL_QUANTUM,
TCA_FQ_CODEL_CE_THRESHOLD,
TCA_FQ_CODEL_DROP_BATCH_SIZE,
TCA_FQ_CODEL_MEMORY_LIMIT,
__TCA_FQ_CODEL_MAX
};
#define TCA_FQ_CODEL_MAX (__TCA_FQ_CODEL_MAX - 1)
enum {
TCA_FQ_CODEL_XSTATS_QDISC,
TCA_FQ_CODEL_XSTATS_CLASS,
};
struct tc_fq_codel_qd_stats {
__u32 maxpacket; /* largest packet we've seen so far */
__u32 drop_overlimit; /* number of time max qdisc
* packet limit was hit
*/
__u32 ecn_mark; /* number of packets we ECN marked
* instead of being dropped
*/
__u32 new_flow_count; /* number of time packets
* created a 'new flow'
*/
__u32 new_flows_len; /* count of flows in new list */
__u32 old_flows_len; /* count of flows in old list */
__u32 ce_mark; /* packets above ce_threshold */
__u32 memory_usage; /* in bytes */
__u32 drop_overmemory;
};
struct tc_fq_codel_cl_stats {
__s32 deficit;
__u32 ldelay; /* in-queue delay seen by most recently
* dequeued packet
*/
__u32 count;
__u32 lastcount;
__u32 dropping;
__s32 drop_next;
};
struct tc_fq_codel_xstats {
__u32 type;
union {
struct tc_fq_codel_qd_stats qdisc_stats;
struct tc_fq_codel_cl_stats class_stats;
};
};
/* FQ */
enum {
TCA_FQ_UNSPEC,
TCA_FQ_PLIMIT, /* limit of total number of packets in queue */
TCA_FQ_FLOW_PLIMIT, /* limit of packets per flow */
TCA_FQ_QUANTUM, /* RR quantum */
TCA_FQ_INITIAL_QUANTUM, /* RR quantum for new flow */
TCA_FQ_RATE_ENABLE, /* enable/disable rate limiting */
TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */
TCA_FQ_FLOW_MAX_RATE, /* per flow max rate */
TCA_FQ_BUCKETS_LOG, /* log2(number of buckets) */
TCA_FQ_FLOW_REFILL_DELAY, /* flow credit refill delay in usec */
TCA_FQ_ORPHAN_MASK, /* mask applied to orphaned skb hashes */
TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */
__TCA_FQ_MAX
};
#define TCA_FQ_MAX (__TCA_FQ_MAX - 1)
struct tc_fq_qd_stats {
__u64 gc_flows;
__u64 highprio_packets;
__u64 tcp_retrans;
__u64 throttled;
__u64 flows_plimit;
__u64 pkts_too_long;
__u64 allocation_errors;
__s64 time_next_delayed_flow;
__u32 flows;
__u32 inactive_flows;
__u32 throttled_flows;
__u32 unthrottle_latency_ns;
};
/* Heavy-Hitter Filter */
enum {
TCA_HHF_UNSPEC,
TCA_HHF_BACKLOG_LIMIT,
TCA_HHF_QUANTUM,
TCA_HHF_HH_FLOWS_LIMIT,
TCA_HHF_RESET_TIMEOUT,
TCA_HHF_ADMIT_BYTES,
TCA_HHF_EVICT_TIMEOUT,
TCA_HHF_NON_HH_WEIGHT,
__TCA_HHF_MAX
};
#define TCA_HHF_MAX (__TCA_HHF_MAX - 1)
struct tc_hhf_xstats {
__u32 drop_overlimit; /* number of times max qdisc packet limit
* was hit
*/
__u32 hh_overlimit; /* number of times max heavy-hitters was hit */
__u32 hh_tot_count; /* number of captured heavy-hitters so far */
__u32 hh_cur_count; /* number of current heavy-hitters */
};
/* PIE */
enum {
TCA_PIE_UNSPEC,
TCA_PIE_TARGET,
TCA_PIE_LIMIT,
TCA_PIE_TUPDATE,
TCA_PIE_ALPHA,
TCA_PIE_BETA,
TCA_PIE_ECN,
TCA_PIE_BYTEMODE,
__TCA_PIE_MAX
};
#define TCA_PIE_MAX (__TCA_PIE_MAX - 1)
struct tc_pie_xstats {
__u32 prob; /* current probability */
__u32 delay; /* current delay in ms */
__u32 avg_dq_rate; /* current average dq_rate in bits/pie_time */
__u32 packets_in; /* total number of packets enqueued */
__u32 dropped; /* packets dropped due to pie_action */
__u32 overlimit; /* dropped due to lack of space in queue */
__u32 maxq; /* maximum queue size */
__u32 ecn_mark; /* packets marked with ecn*/
};
/* CBS */
struct tc_cbs_qopt {
__u8 offload;
__u8 _pad[3];
__s32 hicredit;
__s32 locredit;
__s32 idleslope;
__s32 sendslope;
};
enum {
TCA_CBS_UNSPEC,
TCA_CBS_PARMS,
__TCA_CBS_MAX,
};
#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
#endif

View File

@ -679,6 +679,20 @@ struct rtnl_prio
uint32_t qp_mask;
};
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;
};
struct rtnl_tbf
{
uint32_t qt_limit;

View File

@ -0,0 +1,48 @@
/*
* lib/route/qdisc/mqprio.c MQPRIO Qdisc/Class
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
*/
#ifndef NETLINK_MQPRIO_H_
#define NETLINK_MQPRIO_H_
#include <netlink/netlink.h>
#include <netlink/route/qdisc.h>
#ifdef __cplusplus
extern "C" {
#endif
extern int rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc *qdisc, int num_tc);
extern int rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc *qdisc);
extern int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
int len);
extern uint8_t *rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc *qdisc);
extern int rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc *qdisc, int offload);
extern int rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc *qdisc);
extern int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[],
uint16_t offset[], int len);
extern int rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc *qdisc, uint16_t *count,
uint16_t *offset);
extern int rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc *qdisc, uint16_t mode);
extern int rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc *qdisc);
extern int rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc *qdisc, uint16_t shaper);
extern int rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc *qdisc);
extern int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[],
int len);
extern int rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc *qdisc, uint64_t *min);
extern int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[],
int len);
extern int rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc *qdisc, uint64_t *max);
#ifdef __cplusplus
}
#endif
#endif /* NETLINK_MQPRIO_H_ */

605
lib/route/qdisc/mqprio.c Normal file
View File

@ -0,0 +1,605 @@
/*
* lib/route/qdisc/mqprio.c MQPRIO Qdisc/Class
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2018 Volodymyr Bendiuga <volodymyr.bendiuga@westermo.se>
*/
#include <netlink-private/netlink.h>
#include <netlink-private/tc.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>
/** @cond SKIP */
#define SCH_MQPRIO_ATTR_NUMTC (1 << 0)
#define SCH_MQPRIO_ATTR_PRIOMAP (1 << 1)
#define SCH_MQPRIO_ATTR_HW (1 << 2)
#define SCH_MQPRIO_ATTR_QUEUE (1 << 3)
#define SCH_MQPRIO_ATTR_MODE (1 << 4)
#define SCH_MQPRIO_ATTR_SHAPER (1 << 5)
#define SCH_MQPRIO_ATTR_MIN_RATE (1 << 6)
#define SCH_MQPRIO_ATTR_MAX_RATE (1 << 7)
/** @endcond */
static struct nla_policy mqprio_policy[TCA_MQPRIO_MAX + 1] = {
[TCA_MQPRIO_MODE] = { .minlen = sizeof(uint16_t) },
[TCA_MQPRIO_SHAPER] = { .minlen = sizeof(uint16_t) },
[TCA_MQPRIO_MIN_RATE64] = { .type = NLA_NESTED },
[TCA_MQPRIO_MAX_RATE64] = { .type = NLA_NESTED },
};
static int mqprio_msg_parser(struct rtnl_tc *tc, void *data)
{
struct rtnl_mqprio *mqprio = data;
struct tc_mqprio_qopt *qopt;
struct nlattr *attr;
int len, rem, i, err;
if (tc->tc_opts->d_size < sizeof(*qopt))
return -NLE_INVAL;
qopt = (struct tc_mqprio_qopt *) tc->tc_opts->d_data;
mqprio->qm_num_tc = qopt->num_tc;
mqprio->qm_hw = qopt->hw;
memcpy(mqprio->qm_prio_map, qopt->prio_tc_map,
TC_QOPT_MAX_QUEUE * sizeof(uint8_t));
memcpy(mqprio->qm_count, qopt->count,
TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
memcpy(mqprio->qm_offset, qopt->offset,
TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
mqprio->qm_mask = (SCH_MQPRIO_ATTR_NUMTC | SCH_MQPRIO_ATTR_PRIOMAP |
SCH_MQPRIO_ATTR_QUEUE | SCH_MQPRIO_ATTR_HW);
len = tc->tc_opts->d_size - NLA_ALIGN(sizeof(*qopt));
if (len > 0) {
struct nlattr *tb[TCA_MQPRIO_MAX + 1];
err = nla_parse(tb, TCA_MQPRIO_MAX, (struct nlattr *)
(tc->tc_opts->d_data + NLA_ALIGN(sizeof(*qopt))),
len, mqprio_policy);
if (err < 0)
return err;
if (tb[TCA_MQPRIO_MODE]) {
mqprio->qm_mode = nla_get_u16(tb[TCA_MQPRIO_MODE]);
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE;
}
if (tb[TCA_MQPRIO_SHAPER]) {
mqprio->qm_shaper = nla_get_u16(tb[TCA_MQPRIO_SHAPER]);
mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER;
}
if (tb[TCA_MQPRIO_MIN_RATE64]) {
i = 0;
nla_for_each_nested(attr, tb[TCA_MQPRIO_MIN_RATE64], rem) {
if (nla_type(attr) != TCA_MQPRIO_MIN_RATE64)
return -EINVAL;
if (i >= mqprio->qm_num_tc)
break;
mqprio->qm_min_rate[i] = nla_get_u64(attr);
}
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE;
}
if (tb[TCA_MQPRIO_MAX_RATE64]) {
i = 0;
nla_for_each_nested(attr, tb[TCA_MQPRIO_MAX_RATE64], rem) {
if (nla_type(attr) != TCA_MQPRIO_MAX_RATE64)
return -EINVAL;
if (i >= mqprio->qm_num_tc)
break;
mqprio->qm_max_rate[i] = nla_get_u64(attr);
}
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE;
}
}
return 0;
}
static int mqprio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
{
struct rtnl_mqprio *mqprio = data;
struct tc_mqprio_qopt qopt = { 0 };
struct nlattr *nest = NULL;
int i;
if (!mqprio ||
!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC) ||
!(mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP) ||
!(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE))
return -NLE_INVAL;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
qopt.hw = 0;
else
qopt.hw = mqprio->qm_hw;
qopt.num_tc = mqprio->qm_num_tc;
memcpy(qopt.count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
memcpy(qopt.offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
memcpy(qopt.prio_tc_map, mqprio->qm_prio_map, TC_QOPT_MAX_QUEUE * sizeof(uint8_t));
nlmsg_append(msg, &qopt, sizeof(qopt), NL_DONTPAD);
if (mqprio->qm_hw) {
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE)
NLA_PUT_U16(msg, TCA_MQPRIO_MODE, mqprio->qm_mode);
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)
NLA_PUT_U16(msg, TCA_MQPRIO_SHAPER, mqprio->qm_shaper);
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) {
nest = nla_nest_start(msg, TCA_MQPRIO_MIN_RATE64);
if (!nest)
goto nla_put_failure;
for (i = 0; i < mqprio->qm_num_tc; i++) {
if (nla_put(msg, TCA_MQPRIO_MIN_RATE64,
sizeof(mqprio->qm_min_rate[i]),
&mqprio->qm_min_rate[i]) < 0)
goto nla_nest_cancel;
}
nla_nest_end(msg, nest);
}
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) {
nest = nla_nest_start(msg, TCA_MQPRIO_MAX_RATE64);
if (!nest)
goto nla_put_failure;
for (i = 0; i < mqprio->qm_num_tc; i++) {
if (nla_put(msg, TCA_MQPRIO_MAX_RATE64,
sizeof(mqprio->qm_max_rate[i]),
&mqprio->qm_max_rate[i]) < 0)
goto nla_nest_cancel;
}
nla_nest_end(msg, nest);
}
}
return 0;
nla_nest_cancel:
nla_nest_cancel(msg, nest);
return -NLE_MSGSIZE;
nla_put_failure:
return -NLE_MSGSIZE;
}
static void mqprio_dump_line(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
struct rtnl_mqprio *mqprio = data;
if (mqprio)
nl_dump(p, " num_tc %u", mqprio->qm_num_tc);
}
static void mqprio_dump_details(struct rtnl_tc *tc, void *data,
struct nl_dump_params *p)
{
struct rtnl_mqprio *mqprio = data;
int i;
if (!mqprio)
return;
nl_dump(p, "map [");
for (i = 0; i <= TC_QOPT_BITMASK; i++)
nl_dump(p, "%u%s", mqprio->qm_prio_map[i],
i < TC_QOPT_BITMASK ? " " : "");
nl_dump(p, "]\n");
nl_new_line(p);
}
/**
* @name Attribute Modification
* @{
*/
/**
* Set number of traffic classes.
* @arg qdisc MQPRIO qdisc to be modified.
* @arg num_tc Number of traffic classes to create.
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_num_tc(struct rtnl_qdisc *qdisc, int num_tc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
mqprio->qm_num_tc = num_tc;
mqprio->qm_mask |= SCH_MQPRIO_ATTR_NUMTC;
return 0;
}
/**
* Get number of traffic classes of MQPRIO qdisc.
* @arg qdisc MQPRIO qdisc.
* @return Number of traffic classes or a negative error code.
*/
int rtnl_qdisc_mqprio_get_num_tc(struct rtnl_qdisc *qdisc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC)
return mqprio->qm_num_tc;
else
return -NLE_MISSING_ATTR;
}
/**
* Set priomap of the MQPRIO qdisc.
* @arg qdisc MQPRIO qdisc to be modified.
* @arg priomap New priority mapping.
* @arg len Length of priomap (# of elements).
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_priomap(struct rtnl_qdisc *qdisc, uint8_t priomap[],
int len)
{
struct rtnl_mqprio *mqprio;
int i;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
return -NLE_MISSING_ATTR;
if ((len / sizeof(uint8_t)) > (TC_QOPT_BITMASK+1))
return -NLE_RANGE;
for (i = 0; i <= TC_QOPT_BITMASK; i++) {
if (priomap[i] > mqprio->qm_num_tc)
return -NLE_RANGE;
}
memcpy(mqprio->qm_prio_map, priomap, len * sizeof(uint8_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_PRIOMAP;
return 0;
}
/**
* Get priomap of MQPRIO qdisc.
* @arg qdisc MQPRIO qdisc.
* @return Priority mapping as array of size TC_QOPT_BANDS+1
* or NULL if an error occured.
*/
uint8_t *rtnl_qdisc_mqprio_get_priomap(struct rtnl_qdisc *qdisc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return NULL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_PRIOMAP)
return mqprio->qm_prio_map;
else
return NULL;
}
/**
* Offload to HW or run in SW (default).
* @arg qdisc MQPRIO qdisc to be modified.
* @arg offload 1 - offload to HW, 0 - run in SW only (default).
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_hw_offload(struct rtnl_qdisc *qdisc, int offload)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
switch (offload) {
case 0:
case 1:
mqprio->qm_hw = offload;
break;
default:
return -NLE_INVAL;
}
mqprio->qm_mask |= SCH_MQPRIO_ATTR_HW;
return 0;
}
/**
* Check whether running in HW or SW.
* @arg qdisc MQPRIO qdisc to be modified.
* @return 0 if running in SW, otherwise 1 (HW)
*/
int rtnl_qdisc_mqprio_get_hw_offload(struct rtnl_qdisc *qdisc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_HW)
return mqprio->qm_hw;
return 0;
}
/**
* Set tc queue of the MQPRIO qdisc.
* @arg qdisc MQPRIO qdisc to be modified.
* @arg count count of queue range for each traffic class
* @arg offset offset of queue range for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_queue(struct rtnl_qdisc *qdisc, uint16_t count[],
uint16_t offset[], int len)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_NUMTC))
return -NLE_MISSING_ATTR;
if ((len / sizeof(uint16_t)) > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
memcpy(mqprio->qm_count, count, len * sizeof(uint16_t));
memcpy(mqprio->qm_offset, offset, len * sizeof(uint16_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_QUEUE;
return 0;
}
/**
* Get tc queue of the MQPRIO qdisc.
* @arg qdisc MQPRIO qdisc to be modified.
* @arg count count of queue range for each traffic class
* @arg offset offset of queue range for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_get_queue(struct rtnl_qdisc *qdisc, uint16_t *count,
uint16_t *offset)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_QUEUE))
return -NLE_MISSING_ATTR;
memcpy(count, mqprio->qm_count, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
memcpy(offset, mqprio->qm_offset, TC_QOPT_MAX_QUEUE * sizeof(uint16_t));
return 0;
}
/**
* Set mode of mqprio Qdisc
* @arg qdisc MQPRIO qdisc to be modified.
* @arg mode one of: TC_MQPRIO_MODE_DCB, TC_MQPRIO_MODE_CHANNEL
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_mode(struct rtnl_qdisc *qdisc, uint16_t mode)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
return -NLE_MISSING_ATTR;
mqprio->qm_mode = mode;
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MODE;
return 0;
}
/**
* Get mode of mqprio Qdisc
* @arg qdisc MQPRIO qdisc.
* @return mode on success or negative error code.
*/
int rtnl_qdisc_mqprio_get_mode(struct rtnl_qdisc *qdisc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MODE)
return mqprio->qm_mode;
else
return -NLE_MISSING_ATTR;
}
/**
* Set shaper of mqprio Qdisc
* @arg qdisc MQPRIO qdisc to be modified.
* @arg shaper one of: TC_MQPRIO_SHAPER_DCB, TC_MQPRIO_SHAPER_BW_RATE
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_shaper(struct rtnl_qdisc *qdisc, uint16_t shaper)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_HW))
return -NLE_MISSING_ATTR;
mqprio->qm_shaper = shaper;
mqprio->qm_mask |= SCH_MQPRIO_ATTR_SHAPER;
return 0;
}
/**
* Get shaper of mqprio Qdisc
* @arg qdisc MQPRIO qdisc.
* @return shaper on success or negative error code.
*/
int rtnl_qdisc_mqprio_get_shaper(struct rtnl_qdisc *qdisc)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER)
return mqprio->qm_shaper;
else
return -NLE_MISSING_ATTR;
}
/**
* Set minimum value of bandwidth rate limit for each traffic class
* @arg qdisc MQPRIO qdisc.
* @arg min minimum rate for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_min_rate(struct rtnl_qdisc *qdisc, uint64_t min[], int len)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER))
return -NLE_MISSING_ATTR;
if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
return -NLE_INVAL;
if ((len / sizeof(uint64_t)) > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
memcpy(mqprio->qm_min_rate, min, len * sizeof(uint64_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MIN_RATE;
return 0;
}
/**
* Get minimum value of bandwidth rate limit for each traffic class
* @arg qdisc MQPRIO qdisc.
* @arg min minimum rate for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_get_min_rate(struct rtnl_qdisc *qdisc, uint64_t *min)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MIN_RATE) {
memcpy(min, mqprio->qm_min_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t));
return 0;
}
return -NLE_MISSING_ATTR;
}
/**
* Set maximum value of bandwidth rate limit for each traffic class
* @arg qdisc MQPRIO qdisc.
* @arg max maximum rate for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_set_max_rate(struct rtnl_qdisc *qdisc, uint64_t max[], int len)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data(TC_CAST(qdisc))))
return -NLE_NOMEM;
if (!(mqprio->qm_mask & SCH_MQPRIO_ATTR_SHAPER))
return -NLE_MISSING_ATTR;
if (mqprio->qm_shaper != TC_MQPRIO_SHAPER_BW_RATE)
return -NLE_INVAL;
if ((len / sizeof(uint64_t)) > TC_QOPT_MAX_QUEUE)
return -NLE_RANGE;
memcpy(mqprio->qm_max_rate, max, len * sizeof(uint64_t));
mqprio->qm_mask |= SCH_MQPRIO_ATTR_MAX_RATE;
return 0;
}
/**
* Get maximum value of bandwidth rate limit for each traffic class
* @arg qdisc MQPRIO qdisc.
* @arg min maximum rate for each traffic class
* @return 0 on success or a negative error code.
*/
int rtnl_qdisc_mqprio_get_max_rate(struct rtnl_qdisc *qdisc, uint64_t *max)
{
struct rtnl_mqprio *mqprio;
if (!(mqprio = rtnl_tc_data_peek(TC_CAST(qdisc))))
return -NLE_INVAL;
if (mqprio->qm_mask & SCH_MQPRIO_ATTR_MAX_RATE) {
memcpy(max, mqprio->qm_max_rate, TC_QOPT_MAX_QUEUE * sizeof(uint64_t));
return 0;
}
return -NLE_MISSING_ATTR;
}
/** @} */
static struct rtnl_tc_ops mqprio_ops = {
.to_kind = "mqprio",
.to_type = RTNL_TC_TYPE_QDISC,
.to_size = sizeof(struct rtnl_mqprio),
.to_msg_parser = mqprio_msg_parser,
.to_dump = {
[NL_DUMP_LINE] = mqprio_dump_line,
[NL_DUMP_DETAILS] = mqprio_dump_details,
},
.to_msg_fill = mqprio_msg_fill,
};
static void __init mqprio_init(void)
{
rtnl_tc_register(&mqprio_ops);
}
static void __exit mqprio_exit(void)
{
rtnl_tc_unregister(&mqprio_ops);
}
/** @} */

View File

@ -202,14 +202,16 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags,
.tcm_handle = tc->tc_handle,
.tcm_parent = tc->tc_parent,
};
int err = -NLE_MSGSIZE;
int err;
msg = nlmsg_alloc_simple(type, flags);
if (!msg)
return -NLE_NOMEM;
if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0)
if (nlmsg_append(msg, &tchdr, sizeof(tchdr), NLMSG_ALIGNTO) < 0) {
err = -NLE_MSGSIZE;
goto nla_put_failure;
}
if (tc->ce_mask & TCA_ATTR_KIND)
NLA_PUT_STRING(msg, TCA_KIND, tc->tc_kind);
@ -220,8 +222,10 @@ int rtnl_tc_msg_build(struct rtnl_tc *tc, int type, int flags,
void *data = rtnl_tc_data(tc);
if (ops->to_msg_fill) {
if (!(opts = nla_nest_start(msg, TCA_OPTIONS)))
if (!(opts = nla_nest_start(msg, TCA_OPTIONS))) {
err = -NLE_NOMEM;
goto nla_put_failure;
}
if ((err = ops->to_msg_fill(tc, data, msg)) < 0)
goto nla_put_failure;

View File

@ -1109,4 +1109,20 @@ global:
rtnl_neigh_get_by_vlan;
rtnl_neigh_get_master;
rtnl_neigh_set_master;
rtnl_qdisc_mqprio_set_num_tc;
rtnl_qdisc_mqprio_get_num_tc;
rtnl_qdisc_mqprio_set_priomap;
rtnl_qdisc_mqprio_get_priomap;
rtnl_qdisc_mqprio_hw_offload;
rtnl_qdisc_mqprio_get_hw_offload;
rtnl_qdisc_mqprio_set_queue;
rtnl_qdisc_mqprio_get_queue;
rtnl_qdisc_mqprio_set_mode;
rtnl_qdisc_mqprio_get_mode;
rtnl_qdisc_mqprio_set_shaper;
rtnl_qdisc_mqprio_get_shaper;
rtnl_qdisc_mqprio_set_min_rate;
rtnl_qdisc_mqprio_get_min_rate;
rtnl_qdisc_mqprio_set_max_rate;
rtnl_qdisc_mqprio_get_max_rate;
} libnl_3_4;