lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 28 Mar 2019 02:35:38 -0700
From:   Eric Dumazet <eric.dumazet@...il.com>
To:     Olga Albisser <olgabnd@...il.com>, netdev@...r.kernel.org
Cc:     Olga Albisser <olga@...isser.org>,
        Koen De Schepper <koen.de_schepper@...ia-bell-labs.com>,
        Oliver Tilmans <olivier.tilmans@...ia-bell-labs.com>,
        Bob Briscoe <research@...briscoe.net>,
        Henrik Steen <henrist@...rist.net>
Subject: Re: [PATCHv3 net-next] sched: add dualpi2 scheduler module



On 03/28/2019 01:12 AM, Olga Albisser wrote:
> DUALPI2 provides extremely low latency & loss to traffic that uses a
> scalable congestion controller (e.g. L4S, DCTCP) without degrading the
> performance of 'classic' traffic (e.g. Reno, Cubic etc.). It is intended
> to be the reference implementation of the IETF's DualQ Coupled AQM.
> 
> The qdisc provides two queues called low latency and classic. It
> classifies packets based on the ECN field in their IP headers. By default
> it directs non-ECN and ECT(0) into the Classic queue and ECT(1) and CE
> into the low latency queue, as per the IETF spec.
> 
> There is an AQM in each queue.
> * The Classic AQM is called PI2, which is similar to the PIE AQM but more
> responsive and simpler. Classic traffic requires a decent target queue
> (default 15ms for Internet deployment) to fully utilize the link.
> * The low latency AQM is, by default, a simple very shallow ECN marking
> threshold similar to that used for DCTCP.
> 
> The DualQ isolates the extremely low queuing delay of the Low Latency
> queue from the larger delay of the 'Classic' queue. However, from a
> bandwidth perspective, flows in either queue will share out the link
> capacity as if there was just a single queue. This bandwidth pooling
> effect is achieved by coupling together the drop and ECN-marking
> probabilities of the two AQMs.
> 
> The PI2 AQM has two main parameters in addition to its target delay. All
> the defaults are suitable for any Internet setting, but it can be
> reconfigured for a Data Centre setting. The integral gain factor alpha is
> used to slowly correct any persistent standing queue error from the
> target delay, while the proportional gain factor beta is used to quickly
> compensate for queue changes (growth or shrinkage).
> 
> Internally, the output of a simple linear Proportional Integral (PI)
> controller is used for both queues. This output is squared to calculate
> the drop or ECN-marking probability of the classic queue. This
> counterbalances the square-root rate equation of Reno/Cubic, which is the
> trick that balances flow rates across the queues. For the ECN-marking
> probability of the low latency queue, the output of the base AQM is
> multiplied by a coupling parameter k . This determines the balance
> between the flow rates in each queue. The default setting makes the flow
> rates roughly equal, which should be generally applicable.
> 
> If DUALPI2 AQM has detected overload (when excessive non-responsive
> traffic is sent), it will switch to signalling congestion solely using
> drop, irrespective of the ECN field, or alternatively it can be
> configured to limit the drop probability and let the queue grow and
> eventually overflow (like tail-drop).
> 

What changes are in v3 exactly ?

Please include the changes in changelog to ease code review.

Otherwise we have to look again at the whole thing.

More comments inline

> Additional details can be found in the draft:
> https://www.ietf.org/id/draft-ietf-tsvwg-aqm-dualq-coupled
> 
> Signed-off-by: Olga Albisser <olga@...isser.org>
> Signed-off-by: Koen De Schepper <koen.de_schepper@...ia-bell-labs.com>
> Signed-off-by: Oliver Tilmans <olivier.tilmans@...ia-bell-labs.com>
> Signed-off-by: Bob Briscoe <research@...briscoe.net>
> Signed-off-by: Henrik Steen <henrist@...rist.net>
> ---
>  include/uapi/linux/pkt_sched.h |  33 ++
>  net/sched/Kconfig              |  18 +
>  net/sched/Makefile             |   1 +
>  net/sched/sch_dualpi2.c        | 688 +++++++++++++++++++++++++++++++++
>  4 files changed, 740 insertions(+)
>  create mode 100644 net/sched/sch_dualpi2.c
> 
> diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
> index 7ee74c3474bf..b845274937f2 100644
> --- a/include/uapi/linux/pkt_sched.h
> +++ b/include/uapi/linux/pkt_sched.h
> @@ -1161,4 +1161,37 @@ enum {
>  
>  #define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
>  
> +/* DUALPI2 */
> +enum {
> +	TCA_DUALPI2_UNSPEC,
> +	TCA_DUALPI2_ALPHA,
> +	TCA_DUALPI2_BETA,
> +	TCA_DUALPI2_DUALQ,
> +	TCA_DUALPI2_ECN,
> +	TCA_DUALPI2_K,
> +	TCA_DUALPI2_L_DROP,
> +	TCA_DUALPI2_ET_PACKETS,
> +	TCA_DUALPI2_L_THRESH,
> +	TCA_DUALPI2_LIMIT,
> +	TCA_DUALPI2_T_SHIFT,
> +	TCA_DUALPI2_T_SPEED,
> +	TCA_DUALPI2_TARGET,
> +	TCA_DUALPI2_TUPDATE,
> +	TCA_DUALPI2_DROP_EARLY,
> +	TCA_DUALPI2_WRR_RATIO,
> +	__TCA_DUALPI2_MAX
> +};
> +
> +#define TCA_DUALPI2_MAX   (__TCA_DUALPI2_MAX - 1)
> +struct tc_dualpi2_xstats {
> +	__u32 prob;             /* current probability */
> +	__u32 delay_c;          /* current delay in C queue */
> +	__u32 delay_l;          /* current delay in L queue */
> +	__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*/
> +};
> +
>  #endif
> diff --git a/net/sched/Kconfig b/net/sched/Kconfig
> index 1b9afdee5ba9..0b0fb11b8c72 100644
> --- a/net/sched/Kconfig
> +++ b/net/sched/Kconfig
> @@ -409,6 +409,24 @@ config NET_SCH_PLUG
>  	  To compile this code as a module, choose M here: the
>  	  module will be called sch_plug.
>  
> +config NET_SCH_DUALPI2
> +        tristate "Dual Queue Proportional Integral Controller Improved with a Square (DUALPI2)"
> +        help
> +
> +	  Say Y here if you want to use the Dual Queue Proportional Integral Controller AQM -
> +          Improved with a square (DUALPI2).
> +          DUALPI2 AQM is a combination of the DUALQ Coupled-AQM with a PI2 base-AQM. The PI2 AQM
> +          is in turn both an extension and a simplification of the PIE AQM. PI2 makes quite some
> +          PIE heuristics unnecessary, while being able to control scalable congestion controls
> +          like DCTCP and TCP-Prague. With PI2, both Reno/Cubic can be used in parallel with DCTCP,
> +          maintaining window fairness. DUALQ provides latency separation between low latency
> +          DCTCP flows and Reno/Cubic flows that need a bigger queue.
> +          For more information, please see
> +          https://www.ietf.org/id/draft-ietf-tsvwg-aqm-dualq-coupled
> +
> +          To compile this driver as a module, choose M here: the module
> +          will be called sch_dualpi2.
> +
>  menuconfig NET_SCH_DEFAULT
>  	bool "Allow override default queue discipline"
>  	---help---
> diff --git a/net/sched/Makefile b/net/sched/Makefile
> index 8a40431d7b5c..383eb9dd1fcc 100644
> --- a/net/sched/Makefile
> +++ b/net/sched/Makefile
> @@ -58,6 +58,7 @@ obj-$(CONFIG_NET_SCH_PIE)	+= sch_pie.o
>  obj-$(CONFIG_NET_SCH_CBS)	+= sch_cbs.o
>  obj-$(CONFIG_NET_SCH_ETF)	+= sch_etf.o
>  obj-$(CONFIG_NET_SCH_TAPRIO)	+= sch_taprio.o
> +obj-$(CONFIG_NET_SCH_DUALPI2)   += sch_dualpi2.o
>  
>  obj-$(CONFIG_NET_CLS_U32)	+= cls_u32.o
>  obj-$(CONFIG_NET_CLS_ROUTE4)	+= cls_route.o
> diff --git a/net/sched/sch_dualpi2.c b/net/sched/sch_dualpi2.c
> new file mode 100644
> index 000000000000..6b696a546492
> --- /dev/null
> +++ b/net/sched/sch_dualpi2.c
> @@ -0,0 +4,691 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (C) 2018 Nokia.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; either version 2
> + * of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * Author: Koen De Schepper <koen.de_schepper@...ia-bell-labs.com>
> + * Author: Olga Albisser <olga@...isser.org>
> + * Author: Henrik Steen <henrist@...rist.net>
> + * Author: Olivier Tilmans <olivier.tilmans@...ia-bell-labs.com>
> + *
> + * DualPI Improved with a Square (dualpi2)
> + * Supports controlling scalable congestion controls (DCTCP, etc...)
> + * Supports DualQ with PI2
> + * Supports L4S ECN identifier
> + *
> + * References:
> + * IETF draft submission:
> + *   http://tools.ietf.org/html/draft-ietf-tsvwg-aqm-dualq-coupled-08
> + * ACM CoNEXT’16, Conference on emerging Networking EXperiments
> + * and Technologies :
> + * "PI2: PI Improved with a Square to support Scalable Congestion Controllers"
> + * IETF draft submission:
> + *   http://tools.ietf.org/html/draft-pan-aqm-pie-00
> + * IEEE  Conference on High Performance Switching and Routing 2013 :
> + * "PIE: A * Lightweight Control Scheme to Address the Bufferbloat Problem"
> + * Partially based on the PIE implementation:
> + * Copyright (C) 2013 Cisco Systems, Inc, 2013.
> + * Author: Vijay Subramanian <vijaynsu@...co.com>
> + * Author: Mythili Prabhu <mysuryan@...co.com>
> + * ECN support is added by Naeem Khademi <naeemk@....uio.no>
> + * University of Oslo, Norway.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/kernel.h>
> +#include <linux/errno.h>
> +#include <linux/skbuff.h>
> +#include <linux/version.h>
> +#include <net/pkt_sched.h>
> +#include <net/inet_ecn.h>
> +#include <net/dsfield.h>
> +
> +#define QUEUE_THRESHOLD 10000
> +#define MAX_PROB  0xffffffff
> +
> +/* parameters used */
> +struct dualpi2_params {
> +	psched_time_t	target;	/* user specified target delay in pschedtime */
> +	u64     tshift;         /* L4S FIFO time shift (in ns) */
> +	u32	tupdate;	/* timer frequency (in jiffies) */
> +	u32	limit;		/* number of packets that can be enqueued */
> +	u32	alpha;		/* alpha and beta are user specified values
> +				 * scaled by factor of 256
> +				 */
> +	u32	beta;		/* and are used for shift relative to 1 */
> +	u32	k;		/* coupling rate between Classic and L4S */
> +	u32	queue_mask:2,	/* Mask on ecn bits to determine if packet
> +				 * goes in l-queue
> +				 * 0 (00): single queue
> +				 * 1 (01): dual queue for ECT(1) and CE
> +				 * 3 (11): dual queue for ECT(0), ECT(1) and CE
> +				 *	  (DCTCP compatibility)
> +				 */
> +		mark_mask:2,	/* Mask on ecn bits to determine marking
> +				 * (instead of dropping)
> +				 * 0 (00): no ecn
> +				 * 3 (11): ecn (marking) support
> +				 */
> +		scal_mask:2,	/* Mask on ecn bits to mark p (instead of p^2)
> +				 * 0 (00): no scalable marking
> +				 * 1 (01): scalable marking for ECT(1)
> +				 * 3 (11): scalable marking for ECT(0) and
> +				 *	  ECT(1) (DCTCP compatibility)
> +				 */
> +		et_packets:1,   /* ecn threshold in packets (1) or us (0) */
> +		drop_early:1,	/* Drop at enqueue */
> +		tspeed:16;      /* L4S FIFO time speed (in bit shifts) */
> +	u32	ecn_thresh;	/* sojourn queue size to mark LL packets */
> +	u32	l_drop;		/* L4S max probability where classic drop is
> +				 * applied to all traffic, if 0 then no drop
> +				 * applied at all (but taildrop) to ECT
> +				 * packets
> +				 */
> +	u32     dequeue_ratio;  /* WRR denominator for dequeues */
> +};
> +
> +/* variables used */
> +struct dualpi2_vars {
> +	psched_time_t   qdelay_c;               /* Classic Q delay */
> +	psched_time_t   qdelay_l;               /* L4S Q delay */
> +	u32		prob;			/* probability scaled as u32 */
> +	u32		alpha;			/* calculated alpha value */
> +	u32		beta;			/* calculated beta value */
> +	u32		deferred_drop_count;
> +	u32		deferred_drop_len;
> +	u32             dequeued_l;             /* Successive L4S dequeues */
> +};
> +
> +/* statistics gathering */
> +struct dualpi2_stats {
> +	u32	packets_in;	/* total number of packets enqueued */
> +	u32	dropped;	/* packets dropped due to dualpi2_action */
> +	u32	overlimit;	/* dropped due to lack of space in queue */
> +	u32	maxq;		/* maximum queue size */
> +	u32	ecn_mark;	/* packets marked with ECN */
> +};
> +
> +/* private data for the Qdisc */
> +struct dualpi2_sched_data {
> +	struct Qdisc *l_queue;
> +	struct Qdisc *sch;
> +	struct dualpi2_vars vars;
> +	struct dualpi2_stats stats;
> +	struct dualpi2_params params;
> +	struct timer_list adapt_timer;
> +};
> +
> +static inline void set_ts_cb(struct sk_buff *skb)
> +{
> +	u64 now = ktime_get_mono_fast_ns();
> 

Do not use this variant in a qdisc.

networking code never has to use NMI safe variant.

-> ktime_get_ns() is the preferred version.

More details in Documentation/core-api/timekeeping.rst

+
> +	memcpy(qdisc_skb_cb(skb)->data, &now, sizeof(u64));
> +}
> +
> +static inline u64 get_ts_cb(struct sk_buff *skb)
> +{
> +	u64 ts = 0;
> +
> +	memcpy(&ts, qdisc_skb_cb(skb)->data, sizeof(u64));



> +	return ts;
> +}
> +
> +static inline u64 skb_sojourn_time(struct sk_buff *skb, u64 reference)
> +{
> +	return skb ? reference - get_ts_cb(skb) : 0;
> +}
> +
> +static inline u32 __dualpi2_vars_from_params(u32 param)
> +{
> +	return (param * (MAX_PROB / PSCHED_TICKS_PER_SEC)) >> 8;

Can this overflow ?

> +}
> +
> +static void dualpi2_calculate_alpha_beta(struct dualpi2_sched_data *q)
> +{
> +	/* input alpha and beta should be in multiples of 1/256 */
> +	q->vars.alpha = __dualpi2_vars_from_params(q->params.alpha);
> +	q->vars.beta = __dualpi2_vars_from_params(q->params.beta);
> +}
> +
> +static void dualpi2_params_init(struct dualpi2_params *params)
> +{
> +	params->alpha = 80;
> +	params->beta = 800;
> +	params->tupdate = usecs_to_jiffies(32 * USEC_PER_MSEC);	/* 32 ms */
> +	params->limit = 10000;
> +	params->target = PSCHED_NS2TICKS(20 * NSEC_PER_MSEC);	/* 20 ms */
> +	params->k = 2;
> +	params->queue_mask = INET_ECN_ECT_1;
> +	params->mark_mask = INET_ECN_MASK;
> +	params->scal_mask = INET_ECN_ECT_1;
> +	params->et_packets = 0;
> +	params->ecn_thresh = 1000;
> +	params->tshift = 40 * NSEC_PER_MSEC;
> +	params->tspeed = 0;
> +	params->l_drop = 0;
> +	params->drop_early = false;
> +	params->dequeue_ratio = 16;
> +}
> +
> +static u32 get_ecn_field(struct sk_buff *skb)
> +{
> +	switch (tc_skb_protocol(skb)) {
> +	case htons(ETH_P_IP):
> +		return ipv4_get_dsfield(ip_hdr(skb)) & INET_ECN_MASK;
> +	case htons(ETH_P_IPV6):
> +		return ipv6_get_dsfield(ipv6_hdr(skb)) & INET_ECN_MASK;
> +	default:
> +		return 0;
> +	}
> +}
> +
> +static bool should_drop(struct Qdisc *sch, struct dualpi2_sched_data *q,
> +			u32 ecn, struct sk_buff *skb)
> +{
> +	u32 mtu = psched_mtu(qdisc_dev(sch));
> +	u64 local_l_prob;
> +	bool overload;
> +	u32 rnd;
> +
> +	/* If we have fewer than 2 mtu-sized packets, disable drop,
> +	 * similar to min_th in RED
> +	 */
> +	if (sch->qstats.backlog < 2 * mtu)
> +		return false;
> +
> +	local_l_prob = (u64)q->vars.prob * q->params.k;
> +	overload = q->params.l_drop && local_l_prob > (u64)q->params.l_drop;
> +
> +	rnd = prandom_u32();
> +	if (!overload && (ecn & q->params.scal_mask)) {
> +		/* do scalable marking */
> +		if (rnd < local_l_prob && INET_ECN_set_ce(skb))
> +			/* mark ecn without a square */
> +			q->stats.ecn_mark++;
> +	} else if (rnd < q->vars.prob) {
> +		/* think twice to drop, so roll again */
> +		rnd = prandom_u32();
> +		if (rnd < q->vars.prob) {
> +			if (!overload &&
> +			    (ecn & q->params.mark_mask) &&
> +			    INET_ECN_set_ce(skb))
> +				/* mark ecn with a square */
> +				q->stats.ecn_mark++;
> +			else
> +				return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static int dualpi2_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
> +				 struct sk_buff **to_free)
> +{
> +	struct dualpi2_sched_data *q = qdisc_priv(sch);
> +	u32 ecn = get_ecn_field(skb);
> +	int err;
> +
> +	/* set to the time the HTQ packet is in the Q */
> +	set_ts_cb(skb);

Why setting the time if the packet is dropped in the following checks ?

Maybe call set_ts_cb() a bit later.

> +
> +	if (unlikely(qdisc_qlen(sch) >= sch->limit)) {
> +		qdisc_qstats_overlimit(sch);
> +		err = NET_XMIT_DROP;
> +		goto drop;
> +	}
> +
> +	/* drop early if configured */
> +	if (q->params.drop_early && should_drop(sch, q, ecn, skb)) {
> +		err = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
> +		goto drop;
> +	}
> +
> +	q->stats.packets_in++;
> +	if (qdisc_qlen(sch) > q->stats.maxq)
> +		q->stats.maxq = qdisc_qlen(sch);
> +
> +	/* decide L4S queue or classic */
> +	if (ecn & q->params.queue_mask) {
> +		sch->q.qlen++; /* otherwise packets are not seen by parent Q */
> +		qdisc_qstats_backlog_inc(sch, skb);
> +		return qdisc_enqueue_tail(skb, q->l_queue);
> +	} else {
> +		return qdisc_enqueue_tail(skb, sch);
> +	}
> +
> +drop:
> +	q->stats.dropped++;
> +	q->vars.deferred_drop_count += 1;
> +	q->vars.deferred_drop_len += qdisc_pkt_len(skb);
> +
> +	qdisc_drop(skb, sch, to_free);
> +	return err;
> +}
> +
> +static const struct nla_policy dualpi2_policy[TCA_DUALPI2_MAX + 1] = {
> +	[TCA_DUALPI2_ALPHA] = {.type = NLA_U32},
> +	[TCA_DUALPI2_BETA] = {.type = NLA_U32},
> +	[TCA_DUALPI2_DUALQ] = {.type = NLA_U32},
> +	[TCA_DUALPI2_ECN] = {.type = NLA_U32},
> +	[TCA_DUALPI2_K] = {.type = NLA_U32},
> +	[TCA_DUALPI2_L_DROP] = {.type = NLA_U32},
> +	[TCA_DUALPI2_ET_PACKETS] = {.type = NLA_U32},
> +	[TCA_DUALPI2_L_THRESH] = {.type = NLA_U32},
> +	[TCA_DUALPI2_LIMIT] = {.type = NLA_U32},
> +	[TCA_DUALPI2_T_SHIFT] = {.type = NLA_U32},
> +	[TCA_DUALPI2_T_SPEED] = {.type = NLA_U16},
> +	[TCA_DUALPI2_TARGET] = {.type = NLA_U32},
> +	[TCA_DUALPI2_TUPDATE] = {.type = NLA_U32},
> +	[TCA_DUALPI2_DROP_EARLY] = {.type = NLA_U32},
> +	[TCA_DUALPI2_WRR_RATIO] = {.type = NLA_U32},
> +};
> +
> +static int dualpi2_change(struct Qdisc *sch, struct nlattr *opt,
> +			  struct netlink_ext_ack *extack)
> +{
> +	struct dualpi2_sched_data *q = qdisc_priv(sch);
> +	struct nlattr *tb[TCA_DUALPI2_MAX + 1];
> +	unsigned int qlen, dropped = 0;
> +	int err;
> +
> +	if (!opt)
> +		return -EINVAL;
> +	err = nla_parse_nested(tb, TCA_DUALPI2_MAX, opt, dualpi2_policy, NULL);
> +	if (err < 0)
> +		return err;
> +
> +	sch_tree_lock(sch);
> +	if (q->l_queue == &noop_qdisc) {
> +		struct Qdisc *child;
> +
> +		child = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
> +					  TC_H_MAKE(sch->handle, 1), extack);
> +		if (child)
> +			q->l_queue = child;
> +	}
> +
> +	if (tb[TCA_DUALPI2_TARGET]) {
> +		u32 target = nla_get_u32(tb[TCA_DUALPI2_TARGET]);
> +
> +		q->params.target = PSCHED_NS2TICKS((u64)target * NSEC_PER_USEC);



For a new qdisc, I would not bother using the legacy PSCHED_NS2TICKS() stuff.

PSCHED_NS2TICKS is deprecated now we have nanosecond resolution almost for free
and more hosts are 64bits.

> +	}
> +
> +	if (tb[TCA_DUALPI2_TUPDATE]) {
> +		u32 tupdate_usecs = nla_get_u32(tb[TCA_DUALPI2_TUPDATE]);
> +
> +		q->params.tupdate = usecs_to_jiffies(tupdate_usecs);
> +	}
> +
> +	if (tb[TCA_DUALPI2_LIMIT]) {
> +		u32 limit = nla_get_u32(tb[TCA_DUALPI2_LIMIT]);
> +
> +		q->params.limit = limit;
> +		sch->limit = limit;
> +	}
> +
> +	if (tb[TCA_DUALPI2_ALPHA])
> +		q->params.alpha = nla_get_u32(tb[TCA_DUALPI2_ALPHA]);

No bound checking on this parameter ?

> +
> +	if (tb[TCA_DUALPI2_BETA])
> +		q->params.beta = nla_get_u32(tb[TCA_DUALPI2_BETA]);

No bound checking on this parameter ?


> +
> +	if (tb[TCA_DUALPI2_DUALQ])
> +		q->params.queue_mask = nla_get_u32(tb[TCA_DUALPI2_DUALQ]);
> +
> +	if (tb[TCA_DUALPI2_ECN]) {
> +		u32 masks = nla_get_u32(tb[TCA_DUALPI2_ECN]);
> +
> +		q->params.mark_mask = (masks >> 2) & INET_ECN_MASK;
> +		q->params.scal_mask = masks & INET_ECN_MASK;
> +	}
> +
> +	if (tb[TCA_DUALPI2_K])
> +		q->params.k = nla_get_u32(tb[TCA_DUALPI2_K]);
> +
> +	if (tb[TCA_DUALPI2_K])
> +		q->params.k = nla_get_u32(tb[TCA_DUALPI2_K]);
> +
> +	if (tb[TCA_DUALPI2_L_THRESH])
> +		/* l_thresh is in us */
> +		q->params.ecn_thresh = nla_get_u32(tb[TCA_DUALPI2_L_THRESH]);
> +
> +	if (tb[TCA_DUALPI2_T_SHIFT]) {
> +		u32 t_shift = nla_get_u32(tb[TCA_DUALPI2_T_SHIFT]);
> +
> +		q->params.tshift = (u64)t_shift * NSEC_PER_USEC;
> +	}
> +
> +	if (tb[TCA_DUALPI2_T_SPEED])
> +		q->params.tspeed = nla_get_u16(tb[TCA_DUALPI2_T_SPEED]);
> +
> +	if (tb[TCA_DUALPI2_L_DROP]) {
> +		u32 l_drop_percent = nla_get_u32(tb[TCA_DUALPI2_L_DROP]);
> +
> +		q->params.l_drop = l_drop_percent * (MAX_PROB / 100);
> +	}
> +
> +	if (tb[TCA_DUALPI2_DROP_EARLY])
> +		q->params.drop_early = nla_get_u32(tb[TCA_DUALPI2_DROP_EARLY]);
> +
> +	if (tb[TCA_DUALPI2_WRR_RATIO])
> +		q->params.dequeue_ratio =
> +			nla_get_u32(tb[TCA_DUALPI2_WRR_RATIO]);
> +
> +	/* Calculate new internal alpha and beta values in case their
> +	 * dependencies are changed
> +	 */
> +	dualpi2_calculate_alpha_beta(q);
> +
> +	/* Drop excess packets if new limit is lower */
> +	qlen = sch->q.qlen;
> +	while (sch->q.qlen > sch->limit) {
> +		struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);
> +
> +		dropped += qdisc_pkt_len(skb);
> +		qdisc_qstats_backlog_dec(sch, skb);
> +		rtnl_qdisc_drop(skb, sch);
> +	}
> +	qdisc_tree_reduce_backlog(sch, qlen - sch->q.qlen, dropped);
> +
> +	sch_tree_unlock(sch);
> +	return 0;
> +}
> +
> +static inline psched_time_t qdelay_in_psched(struct Qdisc *q, u64 now)
> +{
> +	struct sk_buff *skb = qdisc_peek_head(q);
> +
> +	return PSCHED_NS2TICKS(skb_sojourn_time(skb, now));

Same as above : psched_time_t is deprecated.

I believe only CBQ and PIE are still using it.

(psched_get_time() is also deprecated)

> +}
> +
> +static void calculate_probability(struct Qdisc *sch)
> +{
> +	struct dualpi2_sched_data *q = qdisc_priv(sch);
> +	u64 now = ktime_get_mono_fast_ns();

ktime_get_ns()

> +	psched_time_t qdelay_old;
> +	psched_time_t qdelay;
> +	u32 oldprob;
> +	s64 delta;	/* determines the change in probability */
> +


Powered by blists - more mailing lists