// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Codel - The Controlled-Delay Active Queue Management algorithm
 *
 *  Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com>
 *  Copyright (C) 2011-2012 Van Jacobson <van@pollere.net>
 *
 *  Implemented on linux by :
 *  Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net>
 *  Copyright (C) 2012,2015 Eric Dumazet <edumazet@google.com>
 */

#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/prefetch.h>
#include <net/pkt_sched.h>
#include <net/codel.h>
#include <net/codel_impl.h>
#include <net/codel_qdisc.h>


#define DEFAULT_CODEL_LIMIT 1000

struct codel_sched_data {
	struct codel_params	params;
	struct codel_vars	vars;
	struct codel_stats	stats;
	u32			drop_overlimit;
};

/* This is the specific function called from codel_dequeue()
 * to dequeue a packet from queue. Note: backlog is handled in
 * codel, we dont need to reduce it here.
 */
static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx)
{
	struct Qdisc *sch = ctx;
	struct sk_buff *skb = __qdisc_dequeue_head(&sch->q);

	if (skb) {
		sch->qstats.backlog -= qdisc_pkt_len(skb);
		prefetch(&skb->end); /* we'll need skb_shinfo() */
	}
	return skb;
}

static void drop_func(struct sk_buff *skb, void *ctx)
{
	struct Qdisc *sch = ctx;

	qdisc_dequeue_drop(sch, skb, QDISC_DROP_CONGESTED);
	qdisc_qstats_drop(sch);
}

static struct sk_buff *codel_qdisc_dequeue(struct Qdisc *sch)
{
	struct codel_sched_data *q = qdisc_priv(sch);
	struct sk_buff *skb;

	skb = codel_dequeue(sch, &sch->qstats.backlog, &q->params, &q->vars,
			    &q->stats, qdisc_pkt_len, codel_get_enqueue_time,
			    drop_func, dequeue_func);

	if (q->stats.drop_count) {
		qdisc_tree_reduce_backlog(sch, q->stats.drop_count, q->stats.drop_len);
		q->stats.drop_count = 0;
		q->stats.drop_len = 0;
	}
	if (skb)
		qdisc_bstats_update(sch, skb);
	return skb;
}

static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
			       struct sk_buff **to_free)
{
	struct codel_sched_data *q;

	if (likely(qdisc_qlen(sch) < sch->limit)) {
		codel_set_enqueue_time(skb);
		return qdisc_enqueue_tail(skb, sch);
	}
	q = qdisc_priv(sch);
	WRITE_ONCE(q->drop_overlimit, q->drop_overlimit + 1);
	return qdisc_drop_reason(skb, sch, to_free, QDISC_DROP_OVERLIMIT);
}

static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
	[TCA_CODEL_TARGET]	= { .type = NLA_U32 },
	[TCA_CODEL_LIMIT]	= { .type = NLA_U32 },
	[TCA_CODEL_INTERVAL]	= { .type = NLA_U32 },
	[TCA_CODEL_ECN]		= { .type = NLA_U32 },
	[TCA_CODEL_CE_THRESHOLD]= { .type = NLA_U32 },
};

static int codel_change(struct Qdisc *sch, struct nlattr *opt,
			struct netlink_ext_ack *extack)
{
	unsigned int dropped_pkts = 0, dropped_bytes = 0;
	struct codel_sched_data *q = qdisc_priv(sch);
	struct nlattr *tb[TCA_CODEL_MAX + 1];
	int err;

	err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt,
					  codel_policy, NULL);
	if (err < 0)
		return err;

	sch_tree_lock(sch);

	if (tb[TCA_CODEL_TARGET]) {
		u32 target = nla_get_u32(tb[TCA_CODEL_TARGET]);

		WRITE_ONCE(q->params.target,
			   ((u64)target * NSEC_PER_USEC) >> CODEL_SHIFT);
	}

	if (tb[TCA_CODEL_CE_THRESHOLD]) {
		u64 val = nla_get_u32(tb[TCA_CODEL_CE_THRESHOLD]);

		WRITE_ONCE(q->params.ce_threshold,
			   (val * NSEC_PER_USEC) >> CODEL_SHIFT);
	}

	if (tb[TCA_CODEL_INTERVAL]) {
		u32 interval = nla_get_u32(tb[TCA_CODEL_INTERVAL]);

		WRITE_ONCE(q->params.interval,
			   ((u64)interval * NSEC_PER_USEC) >> CODEL_SHIFT);
	}

	if (tb[TCA_CODEL_LIMIT])
		WRITE_ONCE(sch->limit,
			   nla_get_u32(tb[TCA_CODEL_LIMIT]));

	if (tb[TCA_CODEL_ECN])
		WRITE_ONCE(q->params.ecn,
			   !!nla_get_u32(tb[TCA_CODEL_ECN]));

	while (sch->q.qlen > sch->limit) {
		struct sk_buff *skb = qdisc_dequeue_internal(sch, true);

		if (!skb)
			break;

		dropped_pkts++;
		dropped_bytes += qdisc_pkt_len(skb);
		rtnl_qdisc_drop(skb, sch);
	}
	qdisc_tree_reduce_backlog(sch, dropped_pkts, dropped_bytes);

	sch_tree_unlock(sch);
	return 0;
}

static int codel_init(struct Qdisc *sch, struct nlattr *opt,
		      struct netlink_ext_ack *extack)
{
	struct codel_sched_data *q = qdisc_priv(sch);

	sch->limit = DEFAULT_CODEL_LIMIT;

	codel_params_init(&q->params);
	codel_vars_init(&q->vars);
	codel_stats_init(&q->stats);
	q->params.mtu = psched_mtu(qdisc_dev(sch));

	if (opt) {
		int err = codel_change(sch, opt, extack);

		if (err)
			return err;
	}

	if (sch->limit >= 1)
		sch->flags |= TCQ_F_CAN_BYPASS;
	else
		sch->flags &= ~TCQ_F_CAN_BYPASS;

	sch->flags |= TCQ_F_DEQUEUE_DROPS;

	return 0;
}

static int codel_dump(struct Qdisc *sch, struct sk_buff *skb)
{
	struct codel_sched_data *q = qdisc_priv(sch);
	codel_time_t ce_threshold;
	struct nlattr *opts;

	opts = nla_nest_start_noflag(skb, TCA_OPTIONS);
	if (opts == NULL)
		goto nla_put_failure;

	if (nla_put_u32(skb, TCA_CODEL_TARGET,
			codel_time_to_us(READ_ONCE(q->params.target))) ||
	    nla_put_u32(skb, TCA_CODEL_LIMIT,
			READ_ONCE(sch->limit)) ||
	    nla_put_u32(skb, TCA_CODEL_INTERVAL,
			codel_time_to_us(READ_ONCE(q->params.interval))) ||
	    nla_put_u32(skb, TCA_CODEL_ECN,
			READ_ONCE(q->params.ecn)))
		goto nla_put_failure;
	ce_threshold = READ_ONCE(q->params.ce_threshold);
	if (ce_threshold != CODEL_DISABLED_THRESHOLD &&
	    nla_put_u32(skb, TCA_CODEL_CE_THRESHOLD,
			codel_time_to_us(ce_threshold)))
		goto nla_put_failure;
	return nla_nest_end(skb, opts);

nla_put_failure:
	nla_nest_cancel(skb, opts);
	return -1;
}

static int codel_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
{
	const struct codel_sched_data *q = qdisc_priv(sch);
	struct tc_codel_xstats st = {
		.maxpacket	= READ_ONCE(q->stats.maxpacket),
		.count		= READ_ONCE(q->vars.count),
		.lastcount	= READ_ONCE(q->vars.lastcount),
		.drop_overlimit = READ_ONCE(q->drop_overlimit),
		.ldelay		= codel_time_to_us(READ_ONCE(q->vars.ldelay)),
		.dropping	= READ_ONCE(q->vars.dropping),
		.ecn_mark	= READ_ONCE(q->stats.ecn_mark),
		.ce_mark	= READ_ONCE(q->stats.ce_mark),
	};

	if (st.dropping) {
		codel_tdiff_t delta = READ_ONCE(q->vars.drop_next) - codel_get_time();

		if (delta >= 0)
			st.drop_next = codel_time_to_us(delta);
		else
			st.drop_next = -codel_time_to_us(-delta);
	}

	return gnet_stats_copy_app(d, &st, sizeof(st));
}

static void codel_reset(struct Qdisc *sch)
{
	struct codel_sched_data *q = qdisc_priv(sch);

	qdisc_reset_queue(sch);
	codel_vars_init(&q->vars);
}

static struct Qdisc_ops codel_qdisc_ops __read_mostly = {
	.id		=	"codel",
	.priv_size	=	sizeof(struct codel_sched_data),

	.enqueue	=	codel_qdisc_enqueue,
	.dequeue	=	codel_qdisc_dequeue,
	.peek		=	qdisc_peek_dequeued,
	.init		=	codel_init,
	.reset		=	codel_reset,
	.change 	=	codel_change,
	.dump		=	codel_dump,
	.dump_stats	=	codel_dump_stats,
	.owner		=	THIS_MODULE,
};
MODULE_ALIAS_NET_SCH("codel");

static int __init codel_module_init(void)
{
	return register_qdisc(&codel_qdisc_ops);
}

static void __exit codel_module_exit(void)
{
	unregister_qdisc(&codel_qdisc_ops);
}

module_init(codel_module_init)
module_exit(codel_module_exit)

MODULE_DESCRIPTION("Controlled Delay queue discipline");
MODULE_AUTHOR("Dave Taht");
MODULE_AUTHOR("Eric Dumazet");
MODULE_LICENSE("Dual BSD/GPL");
