From 2265da08e838f2ac0187b8c4e4a55387b21da976 Mon Sep 17 00:00:00 2001 From: "osdl.net!shemminger" <osdl.net!shemminger> Date: Mon, 30 Aug 2004 21:20:10 +0000 Subject: [PATCH] (Logical change 1.75) --- tc/m_gact.c | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 253 insertions(+) diff --git a/tc/m_gact.c b/tc/m_gact.c index e69de29..01f9400 100644 --- a/tc/m_gact.c +++ b/tc/m_gact.c @@ -0,0 +1,253 @@ +/* + * m_gact.c generic actions module + * + * This program is free software; you can distribute 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, or (at your option) any later version. + * + * Authors: J Hadi Salim (hadi@cyberus.ca) + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <syslog.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> + +#include "utils.h" +#include "tc_util.h" +#include <linux/tc_act/tc_gact.h> + +/* define to turn on probablity stuff */ + +#ifdef CONFIG_GACT_PROB +static const char *prob_n2a(int p) +{ + if (p == PGACT_NONE) + return "none"; + if (p == PGACT_NETRAND) + return "netrand"; + if (p == PGACT_DETERM) + return "determ"; + return "none"; +} +#endif + +static void +explain(void) +{ +#ifdef CONFIG_GACT_PROB + fprintf(stderr, "Usage: ... gact <ACTION> [RAND] [INDEX]\n"); + fprintf(stderr, + "Where: ACTION := reclassify | drop | continue | pass " + "RAND := random <RANDTYPE> <ACTION> <VAL>" + "RANDTYPE := netrand | determ" + "VAL : = value not exceeding 10000" + "INDEX := index value used" + "\n"); +#else + fprintf(stderr, "Usage: ... gact <ACTION> [INDEX]\n"); + fprintf(stderr, + "Where: ACTION := reclassify | drop | continue | pass " + "INDEX := index value used" + "\n"); +#endif +} + +#define usage() return(-1) + +int +get_act(char ***argv_p) +{ + char **argv = *argv_p; + + if (matches(*argv, "reclassify") == 0) { + return TC_ACT_RECLASSIFY; + } else if (matches(*argv, "drop") == 0 || matches(*argv, "shot") == 0) { + return TC_ACT_SHOT; + } else if (matches(*argv, "continue") == 0) { + return TC_ACT_UNSPEC; + } else if (matches(*argv, "pipe") == 0) { + return TC_ACT_PIPE; + } else if (matches(*argv, "pass") == 0 || matches(*argv, "ok") == 0) { + return TC_ACT_OK; + } else { + fprintf(stderr,"bad action type %s\n",*argv); + return -10; + } +} + +int +parse_gact(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) +{ + int argc = *argc_p; + char **argv = *argv_p; + int ok = 0; + int action = TC_POLICE_RECLASSIFY; + struct tc_gact p; +#ifdef CONFIG_GACT_PROB + int rd = 0; + struct tc_gact_p pp; +#endif + struct rtattr *tail; + + memset(&p, 0, sizeof (p)); + p.action = TC_POLICE_RECLASSIFY; + + if (argc < 0) + return -1; + + + if (matches(*argv, "gact") == 0) { + ok++; + } else { + action = get_act(&argv); + if (action != -10) { + p.action = action; + ok++; + } else { + explain(); + return action; + } + } + + if (ok) { + argc--; + argv++; + } + +#ifdef CONFIG_GACT_PROB + if (ok && argc > 0) { + if (matches(*argv, "random") == 0) { + rd = 1; + NEXT_ARG(); + if (matches(*argv, "netrand") == 0) { + NEXT_ARG(); + pp.ptype = PGACT_NETRAND; + } else if (matches(*argv, "determ") == 0) { + NEXT_ARG(); + pp.ptype = PGACT_DETERM; + } else { + fprintf(stderr, "Illegal \"random type\"\n"); + return -1; + } + + action = get_act(&argv); + if (action != -10) { /* FIXME */ + pp.paction = action; + } else { + explain(); + return -1; + } + argc--; + argv++; + if (get_u16(&pp.pval, *argv, 10)) { + fprintf(stderr, "Illegal probability val 0x%x\n",pp.pval); + return -1; + } + if (pp.pval > 10000) { + fprintf(stderr, "Illegal probability val 0x%x\n",pp.pval); + return -1; + } + argc--; + argv++; + } + } +#endif + + if (argc > 0) { + if (matches(*argv, "index") == 0) { + NEXT_ARG(); + if (get_u32(&p.index, *argv, 10)) { + fprintf(stderr, "Illegal \"index\"\n"); + return -1; + } + argc--; + argv++; + ok++; + } + } + + if (!ok) + return -1; + + tail = (struct rtattr *) (((void *) n) + NLMSG_ALIGN(n->nlmsg_len)); + addattr_l(n, MAX_MSG, tca_id, NULL, 0); + addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof (p)); +#ifdef CONFIG_GACT_PROB + if (rd) { + addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof (pp)); + } +#endif + tail->rta_len = + (((void *) n) + NLMSG_ALIGN(n->nlmsg_len)) - (void *) tail; + + *argc_p = argc; + *argv_p = argv; + return 0; +} + +int +print_gact(struct action_util *au,FILE * f, struct rtattr *arg) +{ + SPRINT_BUF(b1); +#ifdef CONFIG_GACT_PROB + SPRINT_BUF(b2); + struct tc_gact_p *pp = NULL; + struct tc_gact_p pp_dummy; +#endif + struct tc_gact *p = NULL; + struct rtattr *tb[TCA_GACT_MAX + 1]; + + if (arg == NULL) + return -1; + + memset(tb, 0, sizeof (tb)); + parse_rtattr(tb, TCA_GACT_MAX, RTA_DATA(arg), RTA_PAYLOAD(arg)); + + if (tb[TCA_GACT_PARMS] == NULL) { + fprintf(f, "[NULL gact parameters]"); + return -1; + } + p = RTA_DATA(tb[TCA_GACT_PARMS]); + + fprintf(f, "gact action %s", action_n2a(p->action, b1, sizeof (b1))); +#ifdef CONFIG_GACT_PROB + if (NULL != tb[TCA_GACT_PROB]) { + pp = RTA_DATA(tb[TCA_GACT_PROB]); + } else { + /* need to keep consistent output */ + memset(&pp_dummy, 0, sizeof (pp_dummy)); + pp = &pp_dummy; + } + fprintf(f, "\n\t random type %s %s val %d",prob_n2a(pp->ptype), action_n2a(pp->paction, b2, sizeof (b2)), pp->pval); +#endif + fprintf(f, "\n\t index %d ref %d bind %d",p->index, p->refcnt, p->bindcnt); + if (show_stats) { + if (tb[TCA_GACT_TM]) { + struct tcf_t *tm = RTA_DATA(tb[TCA_GACT_TM]); + print_tm(f,tm); + } + } + fprintf(f, "\n "); + return 0; +} + +int +gact_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats) +{ + return 0; +} + +struct action_util gact_util = { + .id = "gact", + .parse_aopt = parse_gact, + .print_aopt = print_gact, + .print_xstats = gact_print_xstats, +}; -- 2.30.9