/*
 * 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.
 *
 * Copyright 2018 Google LLC.
 * Author:	Kan Yan <kyan@google.com>
 *
 */

#include <stdio.h>

#include "utils.h"
#include "tc_util.h"

static const char * const arl_state_names[] = {
	"STABLE",
	"DRAIN",
	"BW_PROBE",
	"LATENCY_PROBE",
	"UNTHROTTLED",
	"UNDEFINED",
};

static void explain(void)
{
	fprintf(stderr, "Usage: ... arl [ limit PACKETS] [ buffer TIME ]");
	fprintf(stderr, " [ minrate KBPS ] [ maxbw KBPS ]\n");
	fprintf(stderr, "               [ latency TIME ] ");
	fprintf(stderr, "[ latency_hysteresis TIME ]\n");
	fprintf(stderr, "[ codel_target TIME ]\n");
	fprintf(stderr, "[ ingress ]\n");
}

static int arl_parse_opt(struct qdisc_util *qu, int argc, char **argv,
			 struct nlmsghdr *n)
{
	unsigned int buffer = 0, limit = 0, latency = 0, latency_hysteresis = 0,
		mode = 0, codel_target = 0;
	__u64 min_rate = 0, max_bw = 0;
	struct rtattr *tail;

	while (argc > 0) {
		if (strcmp(*argv, "buffer") == 0) {
			NEXT_ARG();
			if (get_time(&buffer, *argv)) {
				fprintf(stderr, "Illegal \"buffer\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "minrate") == 0) {
			NEXT_ARG();
			if (get_rate64(&min_rate, *argv)) {
				fprintf(stderr, "Illegal \"minrate\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "maxbw") == 0) {
			NEXT_ARG();
			if (get_rate64(&max_bw, *argv)) {
				fprintf(stderr, "Illegal \"max_bw\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "limit") == 0) {
			NEXT_ARG();
			if (get_unsigned(&limit, *argv, 0)) {
				fprintf(stderr, "Illegal \"limit\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "latency") == 0) {
			NEXT_ARG();
			if (get_time(&latency, *argv)) {
				fprintf(stderr, "Illegal \"latency\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "latency_hysteresis") == 0) {
			NEXT_ARG();
			if (get_time(&latency_hysteresis, *argv)) {
				fprintf(stderr,
					"Illegal \"latency hysteresis\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "codel_target") == 0) {
			NEXT_ARG();
			if (get_time(&codel_target, *argv)) {
				fprintf(stderr, "Illegal \"codel_target\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "ingress") == 0) {
			mode = 1;
		} else if (strcmp(*argv, "help") == 0) {
			explain();
			return -1;
		} else {
			fprintf(stderr, "arl: unknown parameter \"%s\"\n",
				*argv);
			explain();
			return -1;
		}
		argc--; argv++;
	}

	tail = NLMSG_TAIL(n);
	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
	if (buffer)
		addattr_l(n, 1024, TCA_ARL_BUFFER, &buffer, sizeof(__u32));
	if (min_rate)
		addattr_l(n, 1024, TCA_ARL_MIN_RATE, &min_rate, sizeof(__u64));
	if (max_bw)
		addattr_l(n, 1024, TCA_ARL_MAX_BW, &max_bw, sizeof(__u64));
	if (limit)
		addattr_l(n, 1024, TCA_ARL_LIMIT, &limit, sizeof(__u32));
	if (latency)
		addattr_l(n, 1024, TCA_ARL_MAX_LATENCY, &latency,
			  sizeof(__u32));
	if (latency_hysteresis)
		addattr_l(n, 1024, TCA_ARL_LATENCY_HYSTERESIS,
			  &latency_hysteresis, sizeof(__u32));
	if (codel_target)
		addattr_l(n, 1024, TCA_ARL_CODEL_TARGET, &codel_target,
			  sizeof(__u32));
	if (mode)
		addattr_l(n, 1024, TCA_ARL_MODE, &mode, sizeof(__u32));

	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
	return 0;
}

static int arl_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
{
	unsigned int buffer, limit, latency, latency_hysteresis, mode,
		     codel_target;
	__u64 min_rate = 0, max_bw;
	struct rtattr *tb[TCA_ARL_MAX + 1];

	SPRINT_BUF(b1);

	if (opt == NULL)
		return 0;

	parse_rtattr_nested(tb, TCA_ARL_MAX, opt);
	if (tb[TCA_ARL_MIN_RATE] &&
	    RTA_PAYLOAD(tb[TCA_ARL_MIN_RATE]) >= sizeof(__u64)) {
		min_rate = rta_getattr_u64(tb[TCA_ARL_MIN_RATE]);
		fprintf(f, "minrate %s ", sprint_rate(min_rate, b1));
	}

	if (tb[TCA_ARL_BUFFER] &&
	    RTA_PAYLOAD(tb[TCA_ARL_BUFFER]) >= sizeof(__u32)) {
		buffer = rta_getattr_u32(tb[TCA_ARL_BUFFER]);
		fprintf(f, "buffer %s ", sprint_time(buffer, b1));
	}

	if (tb[TCA_ARL_MAX_BW] &&
	    RTA_PAYLOAD(tb[TCA_ARL_MAX_BW]) >= sizeof(__u64)) {
		max_bw = rta_getattr_u64(tb[TCA_ARL_MAX_BW]);
		fprintf(f, "max_bw %s ", sprint_rate(max_bw, b1));
	}

	if (tb[TCA_ARL_LIMIT] &&
	    RTA_PAYLOAD(tb[TCA_ARL_LIMIT]) >= sizeof(__u32)) {
		limit = rta_getattr_u32(tb[TCA_ARL_LIMIT]);
		fprintf(f, "limit %u ", limit);
	}

	if (tb[TCA_ARL_MAX_LATENCY] &&
	    RTA_PAYLOAD(tb[TCA_ARL_MAX_LATENCY]) >= sizeof(__u32)) {
		latency = rta_getattr_u32(tb[TCA_ARL_MAX_LATENCY]);
		fprintf(f, "latency %s ", sprint_time(latency, b1));
	}

	if (tb[TCA_ARL_LATENCY_HYSTERESIS] &&
	    RTA_PAYLOAD(tb[TCA_ARL_LATENCY_HYSTERESIS]) >= sizeof(__u32)) {
		latency_hysteresis =
			rta_getattr_u32(tb[TCA_ARL_LATENCY_HYSTERESIS]);
		fprintf(f, "latency_hysteresis %s ",
			sprint_time(latency_hysteresis, b1));
	}

	if (tb[TCA_ARL_CODEL_TARGET] &&
	    RTA_PAYLOAD(tb[TCA_ARL_CODEL_TARGET]) >= sizeof(__u32)) {
		codel_target = rta_getattr_u32(tb[TCA_ARL_CODEL_TARGET]);
		fprintf(f, "codel_target %s ", sprint_time(codel_target, b1));
	}

	if (tb[TCA_ARL_MODE] &&
	    RTA_PAYLOAD(tb[TCA_ARL_MODE]) >= sizeof(__u32)) {
		mode = rta_getattr_u32(tb[TCA_ARL_MODE]);
		if (mode)
			fprintf(f, "mode ingress");
		else
			fprintf(f, "mode egress");
	}

	return 0;
}

static int arl_print_xstats(struct qdisc_util *qu, FILE *f,
			    struct rtattr *xstats)
{
	struct tc_arl_xstats *st;

	if (xstats == NULL)
		return 0;

	if (RTA_PAYLOAD(xstats) < sizeof(*st))
		return -1;

	st = RTA_DATA(xstats);

	fprintf(f, "state %s base_rate %uKbit current_rate %uKbit latency %uus bw %uKbit",
		arl_state_names[st->state], st->base_rate, st->current_rate,
		st->latency, st->current_bw);
	if (st->max_bw)
		fprintf(f, " max_bw %uKbit", st->max_bw);

	if (st->min_rate)
		fprintf(f, " min_base_rate %uKbit", st->min_rate);

	return 0;
}

struct qdisc_util arl_qdisc_util = {
	.id		= "arl",
	.parse_qopt	= arl_parse_opt,
	.print_qopt	= arl_print_opt,
	.print_xstats	= arl_print_xstats,
};
