xref: /aosp_15_r20/external/iproute2/tc/m_skbedit.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * m_skbedit.c		SKB Editing module
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  * Copyright (c) 2008, Intel Corporation.
5*de1e4e89SAndroid Build Coastguard Worker  *
6*de1e4e89SAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify it
7*de1e4e89SAndroid Build Coastguard Worker  * under the terms and conditions of the GNU General Public License,
8*de1e4e89SAndroid Build Coastguard Worker  * version 2, as published by the Free Software Foundation.
9*de1e4e89SAndroid Build Coastguard Worker  *
10*de1e4e89SAndroid Build Coastguard Worker  * This program is distributed in the hope it will be useful, but WITHOUT
11*de1e4e89SAndroid Build Coastguard Worker  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12*de1e4e89SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13*de1e4e89SAndroid Build Coastguard Worker  * more details.
14*de1e4e89SAndroid Build Coastguard Worker  *
15*de1e4e89SAndroid Build Coastguard Worker  * You should have received a copy of the GNU General Public License
16*de1e4e89SAndroid Build Coastguard Worker  * along with this program; if not, see <http://www.gnu.org/licenses>.
17*de1e4e89SAndroid Build Coastguard Worker  *
18*de1e4e89SAndroid Build Coastguard Worker  * Authors:	Alexander Duyck <[email protected]>
19*de1e4e89SAndroid Build Coastguard Worker  *
20*de1e4e89SAndroid Build Coastguard Worker  */
21*de1e4e89SAndroid Build Coastguard Worker 
22*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
23*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
24*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
25*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
26*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
27*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
28*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_skbedit.h>
29*de1e4e89SAndroid Build Coastguard Worker #include <linux/if_packet.h>
30*de1e4e89SAndroid Build Coastguard Worker 
explain(void)31*de1e4e89SAndroid Build Coastguard Worker static void explain(void)
32*de1e4e89SAndroid Build Coastguard Worker {
33*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n"
34*de1e4e89SAndroid Build Coastguard Worker 		"QM = queue_mapping QUEUE_MAPPING\n"
35*de1e4e89SAndroid Build Coastguard Worker 		"PM = priority PRIORITY\n"
36*de1e4e89SAndroid Build Coastguard Worker 		"MM = mark MARK\n"
37*de1e4e89SAndroid Build Coastguard Worker 		"PT = ptype PACKETYPE\n"
38*de1e4e89SAndroid Build Coastguard Worker 		"PACKETYPE = is one of:\n"
39*de1e4e89SAndroid Build Coastguard Worker 		"  host, otherhost, broadcast, multicast\n"
40*de1e4e89SAndroid Build Coastguard Worker 		"QUEUE_MAPPING = device transmit queue to use\n"
41*de1e4e89SAndroid Build Coastguard Worker 		"PRIORITY = classID to assign to priority field\n"
42*de1e4e89SAndroid Build Coastguard Worker 		"MARK = firewall mark to set\n");
43*de1e4e89SAndroid Build Coastguard Worker }
44*de1e4e89SAndroid Build Coastguard Worker 
45*de1e4e89SAndroid Build Coastguard Worker static void
usage(void)46*de1e4e89SAndroid Build Coastguard Worker usage(void)
47*de1e4e89SAndroid Build Coastguard Worker {
48*de1e4e89SAndroid Build Coastguard Worker 	explain();
49*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
50*de1e4e89SAndroid Build Coastguard Worker }
51*de1e4e89SAndroid Build Coastguard Worker 
52*de1e4e89SAndroid Build Coastguard Worker static int
parse_skbedit(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)53*de1e4e89SAndroid Build Coastguard Worker parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
54*de1e4e89SAndroid Build Coastguard Worker 	      struct nlmsghdr *n)
55*de1e4e89SAndroid Build Coastguard Worker {
56*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
57*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
58*de1e4e89SAndroid Build Coastguard Worker 	int ok = 0;
59*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail;
60*de1e4e89SAndroid Build Coastguard Worker 	unsigned int tmp;
61*de1e4e89SAndroid Build Coastguard Worker 	__u16 queue_mapping, ptype;
62*de1e4e89SAndroid Build Coastguard Worker 	__u32 flags = 0, priority, mark;
63*de1e4e89SAndroid Build Coastguard Worker 	struct tc_skbedit sel = { 0 };
64*de1e4e89SAndroid Build Coastguard Worker 
65*de1e4e89SAndroid Build Coastguard Worker 	if (matches(*argv, "skbedit") != 0)
66*de1e4e89SAndroid Build Coastguard Worker 		return -1;
67*de1e4e89SAndroid Build Coastguard Worker 
68*de1e4e89SAndroid Build Coastguard Worker 	NEXT_ARG();
69*de1e4e89SAndroid Build Coastguard Worker 
70*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
71*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "queue_mapping") == 0) {
72*de1e4e89SAndroid Build Coastguard Worker 			flags |= SKBEDIT_F_QUEUE_MAPPING;
73*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
74*de1e4e89SAndroid Build Coastguard Worker 			if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
75*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal queue_mapping\n");
76*de1e4e89SAndroid Build Coastguard Worker 				return -1;
77*de1e4e89SAndroid Build Coastguard Worker 			}
78*de1e4e89SAndroid Build Coastguard Worker 			queue_mapping = tmp;
79*de1e4e89SAndroid Build Coastguard Worker 			ok++;
80*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "priority") == 0) {
81*de1e4e89SAndroid Build Coastguard Worker 			flags |= SKBEDIT_F_PRIORITY;
82*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
83*de1e4e89SAndroid Build Coastguard Worker 			if (get_tc_classid(&priority, *argv)) {
84*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal priority\n");
85*de1e4e89SAndroid Build Coastguard Worker 				return -1;
86*de1e4e89SAndroid Build Coastguard Worker 			}
87*de1e4e89SAndroid Build Coastguard Worker 			ok++;
88*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "mark") == 0) {
89*de1e4e89SAndroid Build Coastguard Worker 			flags |= SKBEDIT_F_MARK;
90*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
91*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&mark, *argv, 0)) {
92*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal mark\n");
93*de1e4e89SAndroid Build Coastguard Worker 				return -1;
94*de1e4e89SAndroid Build Coastguard Worker 			}
95*de1e4e89SAndroid Build Coastguard Worker 			ok++;
96*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "ptype") == 0) {
97*de1e4e89SAndroid Build Coastguard Worker 
98*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
99*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "host") == 0) {
100*de1e4e89SAndroid Build Coastguard Worker 				ptype = PACKET_HOST;
101*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "broadcast") == 0) {
102*de1e4e89SAndroid Build Coastguard Worker 				ptype = PACKET_BROADCAST;
103*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "multicast") == 0) {
104*de1e4e89SAndroid Build Coastguard Worker 				ptype = PACKET_MULTICAST;
105*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "otherhost") == 0) {
106*de1e4e89SAndroid Build Coastguard Worker 				ptype = PACKET_OTHERHOST;
107*de1e4e89SAndroid Build Coastguard Worker 			} else {
108*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal ptype (%s)\n",
109*de1e4e89SAndroid Build Coastguard Worker 					*argv);
110*de1e4e89SAndroid Build Coastguard Worker 				return -1;
111*de1e4e89SAndroid Build Coastguard Worker 			}
112*de1e4e89SAndroid Build Coastguard Worker 			flags |= SKBEDIT_F_PTYPE;
113*de1e4e89SAndroid Build Coastguard Worker 			ok++;
114*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "help") == 0) {
115*de1e4e89SAndroid Build Coastguard Worker 			usage();
116*de1e4e89SAndroid Build Coastguard Worker 		} else {
117*de1e4e89SAndroid Build Coastguard Worker 			break;
118*de1e4e89SAndroid Build Coastguard Worker 		}
119*de1e4e89SAndroid Build Coastguard Worker 		argc--;
120*de1e4e89SAndroid Build Coastguard Worker 		argv++;
121*de1e4e89SAndroid Build Coastguard Worker 	}
122*de1e4e89SAndroid Build Coastguard Worker 
123*de1e4e89SAndroid Build Coastguard Worker 	parse_action_control_dflt(&argc, &argv, &sel.action,
124*de1e4e89SAndroid Build Coastguard Worker 				  false, TC_ACT_PIPE);
125*de1e4e89SAndroid Build Coastguard Worker 
126*de1e4e89SAndroid Build Coastguard Worker 	if (argc) {
127*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "index") == 0) {
128*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
129*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&sel.index, *argv, 10)) {
130*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Pedit: Illegal \"index\"\n");
131*de1e4e89SAndroid Build Coastguard Worker 				return -1;
132*de1e4e89SAndroid Build Coastguard Worker 			}
133*de1e4e89SAndroid Build Coastguard Worker 			argc--;
134*de1e4e89SAndroid Build Coastguard Worker 			argv++;
135*de1e4e89SAndroid Build Coastguard Worker 			ok++;
136*de1e4e89SAndroid Build Coastguard Worker 		}
137*de1e4e89SAndroid Build Coastguard Worker 	}
138*de1e4e89SAndroid Build Coastguard Worker 
139*de1e4e89SAndroid Build Coastguard Worker 	if (!ok) {
140*de1e4e89SAndroid Build Coastguard Worker 		explain();
141*de1e4e89SAndroid Build Coastguard Worker 		return -1;
142*de1e4e89SAndroid Build Coastguard Worker 	}
143*de1e4e89SAndroid Build Coastguard Worker 
144*de1e4e89SAndroid Build Coastguard Worker 
145*de1e4e89SAndroid Build Coastguard Worker 	tail = NLMSG_TAIL(n);
146*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
147*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
148*de1e4e89SAndroid Build Coastguard Worker 	if (flags & SKBEDIT_F_QUEUE_MAPPING)
149*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
150*de1e4e89SAndroid Build Coastguard Worker 			  &queue_mapping, sizeof(queue_mapping));
151*de1e4e89SAndroid Build Coastguard Worker 	if (flags & SKBEDIT_F_PRIORITY)
152*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
153*de1e4e89SAndroid Build Coastguard Worker 			  &priority, sizeof(priority));
154*de1e4e89SAndroid Build Coastguard Worker 	if (flags & SKBEDIT_F_MARK)
155*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
156*de1e4e89SAndroid Build Coastguard Worker 			  &mark, sizeof(mark));
157*de1e4e89SAndroid Build Coastguard Worker 	if (flags & SKBEDIT_F_PTYPE)
158*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
159*de1e4e89SAndroid Build Coastguard Worker 			  &ptype, sizeof(ptype));
160*de1e4e89SAndroid Build Coastguard Worker 	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
161*de1e4e89SAndroid Build Coastguard Worker 
162*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = argc;
163*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
164*de1e4e89SAndroid Build Coastguard Worker 	return 0;
165*de1e4e89SAndroid Build Coastguard Worker }
166*de1e4e89SAndroid Build Coastguard Worker 
print_skbedit(struct action_util * au,FILE * f,struct rtattr * arg)167*de1e4e89SAndroid Build Coastguard Worker static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
168*de1e4e89SAndroid Build Coastguard Worker {
169*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
170*de1e4e89SAndroid Build Coastguard Worker 
171*de1e4e89SAndroid Build Coastguard Worker 	SPRINT_BUF(b1);
172*de1e4e89SAndroid Build Coastguard Worker 	__u32 *priority;
173*de1e4e89SAndroid Build Coastguard Worker 	__u32 *mark;
174*de1e4e89SAndroid Build Coastguard Worker 	__u16 *queue_mapping, *ptype;
175*de1e4e89SAndroid Build Coastguard Worker 	struct tc_skbedit *p = NULL;
176*de1e4e89SAndroid Build Coastguard Worker 
177*de1e4e89SAndroid Build Coastguard Worker 	if (arg == NULL)
178*de1e4e89SAndroid Build Coastguard Worker 		return -1;
179*de1e4e89SAndroid Build Coastguard Worker 
180*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
181*de1e4e89SAndroid Build Coastguard Worker 
182*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_SKBEDIT_PARMS] == NULL) {
183*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL skbedit parameters]");
184*de1e4e89SAndroid Build Coastguard Worker 		return -1;
185*de1e4e89SAndroid Build Coastguard Worker 	}
186*de1e4e89SAndroid Build Coastguard Worker 	p = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
187*de1e4e89SAndroid Build Coastguard Worker 
188*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, " skbedit");
189*de1e4e89SAndroid Build Coastguard Worker 
190*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
191*de1e4e89SAndroid Build Coastguard Worker 		queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
192*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, " queue_mapping %u", *queue_mapping);
193*de1e4e89SAndroid Build Coastguard Worker 	}
194*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
195*de1e4e89SAndroid Build Coastguard Worker 		priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]);
196*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, " priority %s", sprint_tc_classid(*priority, b1));
197*de1e4e89SAndroid Build Coastguard Worker 	}
198*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_SKBEDIT_MARK] != NULL) {
199*de1e4e89SAndroid Build Coastguard Worker 		mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]);
200*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, " mark %d", *mark);
201*de1e4e89SAndroid Build Coastguard Worker 	}
202*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
203*de1e4e89SAndroid Build Coastguard Worker 		ptype = RTA_DATA(tb[TCA_SKBEDIT_PTYPE]);
204*de1e4e89SAndroid Build Coastguard Worker 		if (*ptype == PACKET_HOST)
205*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ptype host");
206*de1e4e89SAndroid Build Coastguard Worker 		else if (*ptype == PACKET_BROADCAST)
207*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ptype broadcast");
208*de1e4e89SAndroid Build Coastguard Worker 		else if (*ptype == PACKET_MULTICAST)
209*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ptype multicast");
210*de1e4e89SAndroid Build Coastguard Worker 		else if (*ptype == PACKET_OTHERHOST)
211*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ptype otherhost");
212*de1e4e89SAndroid Build Coastguard Worker 		else
213*de1e4e89SAndroid Build Coastguard Worker 			fprintf(f, " ptype %d", *ptype);
214*de1e4e89SAndroid Build Coastguard Worker 	}
215*de1e4e89SAndroid Build Coastguard Worker 
216*de1e4e89SAndroid Build Coastguard Worker 	print_action_control(f, " ", p->action, "");
217*de1e4e89SAndroid Build Coastguard Worker 
218*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n\t index %u ref %d bind %d",
219*de1e4e89SAndroid Build Coastguard Worker 		p->index, p->refcnt, p->bindcnt);
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker 	if (show_stats) {
222*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_SKBEDIT_TM]) {
223*de1e4e89SAndroid Build Coastguard Worker 			struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
224*de1e4e89SAndroid Build Coastguard Worker 
225*de1e4e89SAndroid Build Coastguard Worker 			print_tm(f, tm);
226*de1e4e89SAndroid Build Coastguard Worker 		}
227*de1e4e89SAndroid Build Coastguard Worker 	}
228*de1e4e89SAndroid Build Coastguard Worker 
229*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n ");
230*de1e4e89SAndroid Build Coastguard Worker 
231*de1e4e89SAndroid Build Coastguard Worker 	return 0;
232*de1e4e89SAndroid Build Coastguard Worker }
233*de1e4e89SAndroid Build Coastguard Worker 
234*de1e4e89SAndroid Build Coastguard Worker struct action_util skbedit_action_util = {
235*de1e4e89SAndroid Build Coastguard Worker 	.id = "skbedit",
236*de1e4e89SAndroid Build Coastguard Worker 	.parse_aopt = parse_skbedit,
237*de1e4e89SAndroid Build Coastguard Worker 	.print_aopt = print_skbedit,
238*de1e4e89SAndroid Build Coastguard Worker };
239