mirror of
				https://git.proxmox.com/git/mirror_iproute2
				synced 2025-10-31 15:31:19 +00:00 
			
		
		
		
	 fa49588973
			
		
	
	
		fa49588973
		
	
	
	
	
		
			
			The following operation fails:
% sudo tc actions add action pipe index 1
% sudo tc filter add dev lo parent ffff: \
       protocol ip pref 10 u32 match ip src 127.0.0.2 \
       flowid 1:10 action gact index 1
Bad action type index
Usage: ... gact <ACTION> [RAND] [INDEX]
Where:  ACTION := reclassify | drop | continue | pass | pipe |
                  goto chain <CHAIN_INDEX> | jump <JUMP_COUNT>
        RAND := random <RANDTYPE> <ACTION> <VAL>
        RANDTYPE := netrand | determ
        VAL : = value not exceeding 10000
        JUMP_COUNT := Absolute jump from start of action list
        INDEX := index value used
However, passing a control action of gact rule during filter binding works:
% sudo tc filter add dev lo parent ffff: \
       protocol ip pref 10 u32 match ip src 127.0.0.2 \
       flowid 1:10 action gact pipe index 1
Binding by reference, i.e. by index, has to consistently work with
any tc action.
Since tc is sensitive to the order of keywords passed on the command line,
we can teach gact to skip parsing arguments as soon as it sees 'gact'
followed by 'index' keyword.
Signed-off-by: Roman Mashak <mrv@mojatatu.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
		
	
			
		
			
				
	
	
		
			222 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * 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 <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: \tACTION := reclassify | drop | continue | pass | pipe |\n"
 | |
| 		"       \t          goto chain <CHAIN_INDEX> | jump <JUMP_COUNT>\n"
 | |
| 			"\tRAND := random <RANDTYPE> <ACTION> <VAL>\n"
 | |
| 			"\tRANDTYPE := netrand | determ\n"
 | |
| 			"\tVAL : = value not exceeding 10000\n"
 | |
| 			"\tJUMP_COUNT := Absolute jump from start of action list\n"
 | |
| 			"\tINDEX := index value used\n"
 | |
| 			"\n");
 | |
| #else
 | |
| 	fprintf(stderr, "Usage: ... gact <ACTION> [INDEX]\n");
 | |
| 	fprintf(stderr,
 | |
| 		"Where: \tACTION := reclassify | drop | continue | pass | pipe |\n"
 | |
| 		"       \t          goto chain <CHAIN_INDEX> | jump <JUMP_COUNT>\n"
 | |
| 		"\tINDEX := index value used\n"
 | |
| 		"\tJUMP_COUNT := Absolute jump from start of action list\n"
 | |
| 		"\n");
 | |
| #endif
 | |
| }
 | |
| 
 | |
| 
 | |
| static void
 | |
| usage(void)
 | |
| {
 | |
| 	explain();
 | |
| 	exit(-1);
 | |
| }
 | |
| 
 | |
| static 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;
 | |
| 	struct tc_gact p = { 0 };
 | |
| #ifdef CONFIG_GACT_PROB
 | |
| 	int rd = 0;
 | |
| 	struct tc_gact_p pp;
 | |
| #endif
 | |
| 	struct rtattr *tail;
 | |
| 
 | |
| 	if (argc < 0)
 | |
| 		return -1;
 | |
| 
 | |
| 	if (!matches(*argv, "gact"))
 | |
| 		NEXT_ARG_FWD();
 | |
| 	/* we're binding existing gact action to filter by index. */
 | |
| 	if (!matches(*argv, "index"))
 | |
| 		goto skip_args;
 | |
| 	if (parse_action_control(&argc, &argv, &p.action, false))
 | |
| 		usage();	/* does not return */
 | |
| 
 | |
| #ifdef CONFIG_GACT_PROB
 | |
| 	if (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;
 | |
| 			}
 | |
| 
 | |
| 			if (parse_action_control(&argc, &argv,
 | |
| 						 &pp.paction, false) == -1)
 | |
| 				usage();
 | |
| 			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++;
 | |
| 		} else if (matches(*argv, "help") == 0) {
 | |
| 			usage();
 | |
| 		}
 | |
| 	}
 | |
| #endif
 | |
| 
 | |
| 	if (argc > 0) {
 | |
| 		if (matches(*argv, "index") == 0) {
 | |
| skip_args:
 | |
| 			NEXT_ARG();
 | |
| 			if (get_u32(&p.index, *argv, 10)) {
 | |
| 				fprintf(stderr, "Illegal \"index\"\n");
 | |
| 				return -1;
 | |
| 			}
 | |
| 			argc--;
 | |
| 			argv++;
 | |
| 		} else if (matches(*argv, "help") == 0) {
 | |
| 			usage();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	tail = addattr_nest(n, MAX_MSG, tca_id);
 | |
| 	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
 | |
| 	addattr_nest_end(n, tail);
 | |
| 
 | |
| 	*argc_p = argc;
 | |
| 	*argv_p = argv;
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int
 | |
| print_gact(struct action_util *au, FILE *f, struct rtattr *arg)
 | |
| {
 | |
| #ifdef CONFIG_GACT_PROB
 | |
| 	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;
 | |
| 
 | |
| 	parse_rtattr_nested(tb, TCA_GACT_MAX, arg);
 | |
| 
 | |
| 	if (tb[TCA_GACT_PARMS] == NULL) {
 | |
| 		print_string(PRINT_FP, NULL, "%s", "[NULL gact parameters]");
 | |
| 		return -1;
 | |
| 	}
 | |
| 	p = RTA_DATA(tb[TCA_GACT_PARMS]);
 | |
| 
 | |
| 	print_string(PRINT_ANY, "kind", "%s ", "gact");
 | |
| 	print_action_control(f, "action ", p->action, "");
 | |
| #ifdef CONFIG_GACT_PROB
 | |
| 	if (tb[TCA_GACT_PROB] != NULL) {
 | |
| 		pp = RTA_DATA(tb[TCA_GACT_PROB]);
 | |
| 	} else {
 | |
| 		/* need to keep consistent output */
 | |
| 		memset(&pp_dummy, 0, sizeof(pp_dummy));
 | |
| 		pp = &pp_dummy;
 | |
| 	}
 | |
| 	open_json_object("prob");
 | |
| 	print_string(PRINT_ANY, "random_type", "\n\t random type %s",
 | |
| 		     prob_n2a(pp->ptype));
 | |
| 	print_action_control(f, " ", pp->paction, " ");
 | |
| 	print_int(PRINT_ANY, "val", "val %d", pp->pval);
 | |
| 	close_json_object();
 | |
| #endif
 | |
| 	print_uint(PRINT_ANY, "index", "\n\t index %u", p->index);
 | |
| 	print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
 | |
| 	print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
 | |
| 	if (show_stats) {
 | |
| 		if (tb[TCA_GACT_TM]) {
 | |
| 			struct tcf_t *tm = RTA_DATA(tb[TCA_GACT_TM]);
 | |
| 
 | |
| 			print_tm(f, tm);
 | |
| 		}
 | |
| 	}
 | |
| 	print_string(PRINT_FP, NULL, "%s", "\n");
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| struct action_util gact_action_util = {
 | |
| 	.id = "gact",
 | |
| 	.parse_aopt = parse_gact,
 | |
| 	.print_aopt = print_gact,
 | |
| };
 |