<commit_before>/*
 * lib/route/sch/tbf.c		TBF Qdisc
 *
 *	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) 2003-2008 <NAME> <<EMAIL>>
 */

/**
 * @ingroup qdisc_api
 * @defgroup tbf Token Bucket Filter (TBF)
 * @{
 */

#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/route/tc.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc-modules.h>
#include <netlink/route/class.h>
#include <netlink/route/class-modules.h>
#include <netlink/route/link.h>
#include <netlink/route/sch/tbf.h>

/** @cond SKIP */
#define TBF_ATTR_LIMIT			0x01
#define TBF_ATTR_RATE			0x02
#define TBF_ATTR_PEAKRATE		0x10
#define TBF_ATTR_MPU			0x80
/** @endcond */

static inline struct rtnl_tbf *tbf_qdisc(struct rtnl_qdisc *qdisc)
{
	return (struct rtnl_tbf *) qdisc->q_subdata;
}

static inline struct rtnl_tbf *tbf_alloc(struct rtnl_qdisc *qdisc)
{
	if (!qdisc->q_subdata)
		qdisc->q_subdata = calloc(1, sizeof(struct rtnl_tbf));

	return tbf_qdisc(qdisc);
}

static struct nla_policy tbf_policy[TCA_TBF_MAX+1] = {
	[TCA_TBF_PARMS]	= { .minlen = sizeof(struct tc_tbf_qopt) },
};

static int tbf_msg_parser(struct rtnl_qdisc *q)
{
	int err;
	struct nlattr *tb[TCA_TBF_MAX + 1];
	struct rtnl_tbf *tbf;

	err = tca_parse(tb, TCA_TBF_MAX, (struct rtnl_tca *) q, tbf_policy);
	if (err < 0)
		return err;
	
	tbf = tbf_alloc(q);
	if (!tbf)
		return -NLE_NOMEM;

	if (tb[TCA_TBF_PARMS]) {
		struct tc_tbf_qopt opts;
		int bufsize;

		nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts));
		tbf->qt_limit = opts.limit;
		tbf->qt_mpu = opts.rate.mpu;
	
		rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate);
		tbf->qt_rate_txtime = opts.buffer;
		bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer),
					       opts.rate.rate);
		tbf->qt_rate_bucket = bufsize;

		rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate);
		tbf->qt_peakrate_txtime = opts.mtu;
		bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu),
					       opts.peakrate.rate);
		tbf->qt_peakrate_bucket = bufsize;

		tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_MPU | TBF_ATTR_RATE |
				TBF_ATTR_PEAKRATE);
	}

	return 0;
}

static void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
{
	double r, rbit, lim;
	char *ru, *rubit, *limu;
	struct rtnl_tbf *tbf = tbf_qdisc(qdisc);

	if (!tbf)
		return;

	r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru);
	rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit);
	lim = nl_cancel_down_bytes(tbf->qt_limit, &limu);

	nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s",
		r, ru, rbit, rubit, lim, limu);
}

static void tbf_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
{
	struct rtnl_tbf *tbf = tbf_qdisc(qdisc);

	if (!tbf)
		return;

	if (1) {
		char *bu, *cu;
		double bs = nl_cancel_down_bytes(tbf->qt_rate_bucket, &bu);
		double cl = nl_cancel_down_bytes(1 << tbf->qt_rate.rs_cell_log,
						 &cu);

		nl_dump(p, "mpu %u rate-bucket-size %1.f%s "
			   "rate-cell-size %.1f%s\n",
			tbf->qt_mpu, bs, bu, cl, cu);

	}

	if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
		char *pru, *prbu, *bsu, *clu;
		double pr, prb, bs, cl;
		
		pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru);
		prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu);
		bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu);
		cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log,
					 &clu);

		nl_dump_line(p, "    peak-rate %.2f%s/s (%.0f%s) "
				"bucket-size %.1f%s cell-size %.1f%s",
				"latency %.1f%s",
			     pr, pru, prb, prbu, bs, bsu, cl, clu);
	}
}

static struct nl_msg *tbf_get_opts(struct rtnl_qdisc *qdisc)
{
	struct tc_tbf_qopt opts;
	struct rtnl_tbf *tbf;
	struct nl_msg *msg;
	uint32_t rtab[RTNL_TC_RTABLE_SIZE];
	uint32_t ptab[RTNL_TC_RTABLE_SIZE];<commit_msg>invalid comma cause segfault for nl-tctree-list, tbf.c<commit_after>/*
 * lib/route/sch/tbf.c		TBF Qdisc
 *
 *	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) 2003-2008 <NAME> <<EMAIL>>
 */

/**
 * @ingroup qdisc_api
 * @defgroup tbf Token Bucket Filter (TBF)
 * @{
 */

#include <netlink-local.h>
#include <netlink-tc.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/route/tc.h>
#include <netlink/route/qdisc.h>
#include <netlink/route/qdisc-modules.h>
#include <netlink/route/class.h>
#include <netlink/route/class-modules.h>
#include <netlink/route/link.h>
#include <netlink/route/sch/tbf.h>

/** @cond SKIP */
#define TBF_ATTR_LIMIT			0x01
#define TBF_ATTR_RATE			0x02
#define TBF_ATTR_PEAKRATE		0x10
#define TBF_ATTR_MPU			0x80
/** @endcond */

static inline struct rtnl_tbf *tbf_qdisc(struct rtnl_qdisc *qdisc)
{
	return (struct rtnl_tbf *) qdisc->q_subdata;
}

static inline struct rtnl_tbf *tbf_alloc(struct rtnl_qdisc *qdisc)
{
	if (!qdisc->q_subdata)
		qdisc->q_subdata = calloc(1, sizeof(struct rtnl_tbf));

	return tbf_qdisc(qdisc);
}

static struct nla_policy tbf_policy[TCA_TBF_MAX+1] = {
	[TCA_TBF_PARMS]	= { .minlen = sizeof(struct tc_tbf_qopt) },
};

static int tbf_msg_parser(struct rtnl_qdisc *q)
{
	int err;
	struct nlattr *tb[TCA_TBF_MAX + 1];
	struct rtnl_tbf *tbf;

	err = tca_parse(tb, TCA_TBF_MAX, (struct rtnl_tca *) q, tbf_policy);
	if (err < 0)
		return err;
	
	tbf = tbf_alloc(q);
	if (!tbf)
		return -NLE_NOMEM;

	if (tb[TCA_TBF_PARMS]) {
		struct tc_tbf_qopt opts;
		int bufsize;

		nla_memcpy(&opts, tb[TCA_TBF_PARMS], sizeof(opts));
		tbf->qt_limit = opts.limit;
		tbf->qt_mpu = opts.rate.mpu;
	
		rtnl_copy_ratespec(&tbf->qt_rate, &opts.rate);
		tbf->qt_rate_txtime = opts.buffer;
		bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.buffer),
					       opts.rate.rate);
		tbf->qt_rate_bucket = bufsize;

		rtnl_copy_ratespec(&tbf->qt_peakrate, &opts.peakrate);
		tbf->qt_peakrate_txtime = opts.mtu;
		bufsize = rtnl_tc_calc_bufsize(nl_ticks2us(opts.mtu),
					       opts.peakrate.rate);
		tbf->qt_peakrate_bucket = bufsize;

		tbf->qt_mask = (TBF_ATTR_LIMIT | TBF_ATTR_MPU | TBF_ATTR_RATE |
				TBF_ATTR_PEAKRATE);
	}

	return 0;
}

static void tbf_dump_line(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
{
	double r, rbit, lim;
	char *ru, *rubit, *limu;
	struct rtnl_tbf *tbf = tbf_qdisc(qdisc);

	if (!tbf)
		return;

	r = nl_cancel_down_bytes(tbf->qt_rate.rs_rate, &ru);
	rbit = nl_cancel_down_bits(tbf->qt_rate.rs_rate*8, &rubit);
	lim = nl_cancel_down_bytes(tbf->qt_limit, &limu);

	nl_dump(p, " rate %.2f%s/s (%.0f%s) limit %.2f%s",
		r, ru, rbit, rubit, lim, limu);
}

static void tbf_dump_details(struct rtnl_qdisc *qdisc, struct nl_dump_params *p)
{
	struct rtnl_tbf *tbf = tbf_qdisc(qdisc);

	if (!tbf)
		return;

	if (1) {
		char *bu, *cu;
		double bs = nl_cancel_down_bytes(tbf->qt_rate_bucket, &bu);
		double cl = nl_cancel_down_bytes(1 << tbf->qt_rate.rs_cell_log,
						 &cu);

		nl_dump(p, "mpu %u rate-bucket-size %1.f%s "
			   "rate-cell-size %.1f%s\n",
			tbf->qt_mpu, bs, bu, cl, cu);

	}

	if (tbf->qt_mask & TBF_ATTR_PEAKRATE) {
		char *pru, *prbu, *bsu, *clu;
		double pr, prb, bs, cl;
		
		pr = nl_cancel_down_bytes(tbf->qt_peakrate.rs_rate, &pru);
		prb = nl_cancel_down_bits(tbf->qt_peakrate.rs_rate * 8, &prbu);
		bs = nl_cancel_down_bits(tbf->qt_peakrate_bucket, &bsu);
		cl = nl_cancel_down_bits(1 << tbf->qt_peakrate.rs_cell_log,
					 &clu);

		nl_dump_line(p, "    peak-rate %.2f%s/s (%.0f%s) "
				"bucket-size %.1f%s cell-size %.1f%s"
				"latency %.1f%s",
			     pr, pru, prb, prbu, bs, bsu, cl, clu);
	}
}

static struct nl_msg *tbf_get_opts(struct rtnl_qdisc *qdisc)
{
	struct tc_tbf_qopt opts;
	struct rtnl_tbf *tbf;
	struct nl_msg *msg;
	uint32_t rtab[RTNL_TC_RTABLE_SIZE];
	uint32_t ptab[RTNL_TC_RTABLE_SIZE];
{'fraction_non_alphanumeric': 0.1435520079820404, 'fraction_numerical': 0.011973060613619356, 'mean_word_length': 4.268725361366623, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 79, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5902563', 'n_tokens_mistral': 3914, 'n_tokens_neox': 3612, 'n_words': 693}