xref: /aosp_15_r20/external/iproute2/tc/m_ife.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * m_ife.c	IFE actions module
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *		This program is free software; you can distribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *		modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *		as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *		2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:  J Hadi Salim ([email protected])
10*de1e4e89SAndroid Build Coastguard Worker  *
11*de1e4e89SAndroid Build Coastguard Worker  */
12*de1e4e89SAndroid Build Coastguard Worker 
13*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
14*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
15*de1e4e89SAndroid Build Coastguard Worker #include <unistd.h>
16*de1e4e89SAndroid Build Coastguard Worker #include <syslog.h>
17*de1e4e89SAndroid Build Coastguard Worker #include <fcntl.h>
18*de1e4e89SAndroid Build Coastguard Worker #include <sys/socket.h>
19*de1e4e89SAndroid Build Coastguard Worker #include <netinet/in.h>
20*de1e4e89SAndroid Build Coastguard Worker #include <arpa/inet.h>
21*de1e4e89SAndroid Build Coastguard Worker #include <string.h>
22*de1e4e89SAndroid Build Coastguard Worker #include <linux/netdevice.h>
23*de1e4e89SAndroid Build Coastguard Worker 
24*de1e4e89SAndroid Build Coastguard Worker #include "rt_names.h"
25*de1e4e89SAndroid Build Coastguard Worker #include "utils.h"
26*de1e4e89SAndroid Build Coastguard Worker #include "tc_util.h"
27*de1e4e89SAndroid Build Coastguard Worker #include <linux/tc_act/tc_ife.h>
28*de1e4e89SAndroid Build Coastguard Worker 
ife_explain(void)29*de1e4e89SAndroid Build Coastguard Worker static void ife_explain(void)
30*de1e4e89SAndroid Build Coastguard Worker {
31*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr,
32*de1e4e89SAndroid Build Coastguard Worker 		"Usage:... ife {decode|encode} [{ALLOW|USE} ATTR] [dst DMAC] [src SMAC] [type TYPE] [CONTROL] [index INDEX]\n");
33*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr,
34*de1e4e89SAndroid Build Coastguard Worker 		"\tALLOW := Encode direction. Allows encoding specified metadata\n"
35*de1e4e89SAndroid Build Coastguard Worker 		"\t\t e.g \"allow mark\"\n"
36*de1e4e89SAndroid Build Coastguard Worker 		"\tUSE := Encode direction. Enforce Static encoding of specified metadata\n"
37*de1e4e89SAndroid Build Coastguard Worker 		"\t\t e.g \"use mark 0x12\"\n"
38*de1e4e89SAndroid Build Coastguard Worker 		"\tATTR := mark (32-bit), prio (32-bit), tcindex (16-bit)\n"
39*de1e4e89SAndroid Build Coastguard Worker 		"\tDMAC := 6 byte Destination MAC address to encode\n"
40*de1e4e89SAndroid Build Coastguard Worker 		"\tSMAC := optional 6 byte Source MAC address to encode\n"
41*de1e4e89SAndroid Build Coastguard Worker 		"\tTYPE := optional 16 bit ethertype to encode\n"
42*de1e4e89SAndroid Build Coastguard Worker 		"\tCONTROL := reclassify|pipe|drop|continue|ok\n"
43*de1e4e89SAndroid Build Coastguard Worker 		"\tINDEX := optional IFE table index value used\n");
44*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "encode is used for sending IFE packets\n");
45*de1e4e89SAndroid Build Coastguard Worker 	fprintf(stderr, "decode is used for receiving IFE packets\n");
46*de1e4e89SAndroid Build Coastguard Worker }
47*de1e4e89SAndroid Build Coastguard Worker 
ife_usage(void)48*de1e4e89SAndroid Build Coastguard Worker static void ife_usage(void)
49*de1e4e89SAndroid Build Coastguard Worker {
50*de1e4e89SAndroid Build Coastguard Worker 	ife_explain();
51*de1e4e89SAndroid Build Coastguard Worker 	exit(-1);
52*de1e4e89SAndroid Build Coastguard Worker }
53*de1e4e89SAndroid Build Coastguard Worker 
parse_ife(struct action_util * a,int * argc_p,char *** argv_p,int tca_id,struct nlmsghdr * n)54*de1e4e89SAndroid Build Coastguard Worker static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
55*de1e4e89SAndroid Build Coastguard Worker 		     int tca_id, struct nlmsghdr *n)
56*de1e4e89SAndroid Build Coastguard Worker {
57*de1e4e89SAndroid Build Coastguard Worker 	int argc = *argc_p;
58*de1e4e89SAndroid Build Coastguard Worker 	char **argv = *argv_p;
59*de1e4e89SAndroid Build Coastguard Worker 	int ok = 0;
60*de1e4e89SAndroid Build Coastguard Worker 	struct tc_ife p = { 0 };
61*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail;
62*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tail2;
63*de1e4e89SAndroid Build Coastguard Worker 	char dbuf[ETH_ALEN];
64*de1e4e89SAndroid Build Coastguard Worker 	char sbuf[ETH_ALEN];
65*de1e4e89SAndroid Build Coastguard Worker 	__u16 ife_type = 0;
66*de1e4e89SAndroid Build Coastguard Worker 	int user_type = 0;
67*de1e4e89SAndroid Build Coastguard Worker 	__u32 ife_prio = 0;
68*de1e4e89SAndroid Build Coastguard Worker 	__u32 ife_prio_v = 0;
69*de1e4e89SAndroid Build Coastguard Worker 	__u32 ife_mark = 0;
70*de1e4e89SAndroid Build Coastguard Worker 	__u32 ife_mark_v = 0;
71*de1e4e89SAndroid Build Coastguard Worker 	__u16 ife_tcindex = 0;
72*de1e4e89SAndroid Build Coastguard Worker 	__u16 ife_tcindex_v = 0;
73*de1e4e89SAndroid Build Coastguard Worker 	char *daddr = NULL;
74*de1e4e89SAndroid Build Coastguard Worker 	char *saddr = NULL;
75*de1e4e89SAndroid Build Coastguard Worker 
76*de1e4e89SAndroid Build Coastguard Worker 	if (argc <= 0)
77*de1e4e89SAndroid Build Coastguard Worker 		return -1;
78*de1e4e89SAndroid Build Coastguard Worker 
79*de1e4e89SAndroid Build Coastguard Worker 	while (argc > 0) {
80*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "ife") == 0) {
81*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
82*de1e4e89SAndroid Build Coastguard Worker 			continue;
83*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "decode") == 0) {
84*de1e4e89SAndroid Build Coastguard Worker 			p.flags = IFE_DECODE; /* readability aid */
85*de1e4e89SAndroid Build Coastguard Worker 			ok++;
86*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "encode") == 0) {
87*de1e4e89SAndroid Build Coastguard Worker 			p.flags = IFE_ENCODE;
88*de1e4e89SAndroid Build Coastguard Worker 			ok++;
89*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "allow") == 0) {
90*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
91*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "mark") == 0) {
92*de1e4e89SAndroid Build Coastguard Worker 				ife_mark = IFE_META_SKBMARK;
93*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "prio") == 0) {
94*de1e4e89SAndroid Build Coastguard Worker 				ife_prio = IFE_META_PRIO;
95*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "tcindex") == 0) {
96*de1e4e89SAndroid Build Coastguard Worker 				ife_tcindex = IFE_META_TCINDEX;
97*de1e4e89SAndroid Build Coastguard Worker 			} else {
98*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal meta define <%s>\n",
99*de1e4e89SAndroid Build Coastguard Worker 					*argv);
100*de1e4e89SAndroid Build Coastguard Worker 				return -1;
101*de1e4e89SAndroid Build Coastguard Worker 			}
102*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "use") == 0) {
103*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
104*de1e4e89SAndroid Build Coastguard Worker 			if (matches(*argv, "mark") == 0) {
105*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
106*de1e4e89SAndroid Build Coastguard Worker 				if (get_u32(&ife_mark_v, *argv, 0))
107*de1e4e89SAndroid Build Coastguard Worker 					invarg("ife mark val is invalid",
108*de1e4e89SAndroid Build Coastguard Worker 					       *argv);
109*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "prio") == 0) {
110*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
111*de1e4e89SAndroid Build Coastguard Worker 				if (get_u32(&ife_prio_v, *argv, 0))
112*de1e4e89SAndroid Build Coastguard Worker 					invarg("ife prio val is invalid",
113*de1e4e89SAndroid Build Coastguard Worker 					       *argv);
114*de1e4e89SAndroid Build Coastguard Worker 			} else if (matches(*argv, "tcindex") == 0) {
115*de1e4e89SAndroid Build Coastguard Worker 				NEXT_ARG();
116*de1e4e89SAndroid Build Coastguard Worker 				if (get_u16(&ife_tcindex_v, *argv, 0))
117*de1e4e89SAndroid Build Coastguard Worker 					invarg("ife tcindex val is invalid",
118*de1e4e89SAndroid Build Coastguard Worker 					       *argv);
119*de1e4e89SAndroid Build Coastguard Worker 			} else {
120*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Illegal meta use type <%s>\n",
121*de1e4e89SAndroid Build Coastguard Worker 					*argv);
122*de1e4e89SAndroid Build Coastguard Worker 				return -1;
123*de1e4e89SAndroid Build Coastguard Worker 			}
124*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "type") == 0) {
125*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
126*de1e4e89SAndroid Build Coastguard Worker 			if (get_u16(&ife_type, *argv, 0))
127*de1e4e89SAndroid Build Coastguard Worker 				invarg("ife type is invalid", *argv);
128*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "IFE type 0x%04X\n", ife_type);
129*de1e4e89SAndroid Build Coastguard Worker 			user_type = 1;
130*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "dst") == 0) {
131*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
132*de1e4e89SAndroid Build Coastguard Worker 			daddr = *argv;
133*de1e4e89SAndroid Build Coastguard Worker 			if (sscanf(daddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
134*de1e4e89SAndroid Build Coastguard Worker 				   dbuf, dbuf + 1, dbuf + 2,
135*de1e4e89SAndroid Build Coastguard Worker 				   dbuf + 3, dbuf + 4, dbuf + 5) != 6) {
136*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Invalid mac address %s\n",
137*de1e4e89SAndroid Build Coastguard Worker 					daddr);
138*de1e4e89SAndroid Build Coastguard Worker 			}
139*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "dst MAC address <%s>\n", daddr);
140*de1e4e89SAndroid Build Coastguard Worker 
141*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "src") == 0) {
142*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
143*de1e4e89SAndroid Build Coastguard Worker 			saddr = *argv;
144*de1e4e89SAndroid Build Coastguard Worker 			if (sscanf(saddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
145*de1e4e89SAndroid Build Coastguard Worker 				   sbuf, sbuf + 1, sbuf + 2,
146*de1e4e89SAndroid Build Coastguard Worker 				   sbuf + 3, sbuf + 4, sbuf + 5) != 6) {
147*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "Invalid mac address %s\n",
148*de1e4e89SAndroid Build Coastguard Worker 					saddr);
149*de1e4e89SAndroid Build Coastguard Worker 			}
150*de1e4e89SAndroid Build Coastguard Worker 			fprintf(stderr, "src MAC address <%s>\n", saddr);
151*de1e4e89SAndroid Build Coastguard Worker 		} else if (matches(*argv, "help") == 0) {
152*de1e4e89SAndroid Build Coastguard Worker 			ife_usage();
153*de1e4e89SAndroid Build Coastguard Worker 		} else {
154*de1e4e89SAndroid Build Coastguard Worker 			break;
155*de1e4e89SAndroid Build Coastguard Worker 		}
156*de1e4e89SAndroid Build Coastguard Worker 
157*de1e4e89SAndroid Build Coastguard Worker 		argc--;
158*de1e4e89SAndroid Build Coastguard Worker 		argv++;
159*de1e4e89SAndroid Build Coastguard Worker 	}
160*de1e4e89SAndroid Build Coastguard Worker 
161*de1e4e89SAndroid Build Coastguard Worker 	parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
162*de1e4e89SAndroid Build Coastguard Worker 
163*de1e4e89SAndroid Build Coastguard Worker 	if (argc) {
164*de1e4e89SAndroid Build Coastguard Worker 		if (matches(*argv, "index") == 0) {
165*de1e4e89SAndroid Build Coastguard Worker 			NEXT_ARG();
166*de1e4e89SAndroid Build Coastguard Worker 			if (get_u32(&p.index, *argv, 0)) {
167*de1e4e89SAndroid Build Coastguard Worker 				fprintf(stderr, "ife: Illegal \"index\"\n");
168*de1e4e89SAndroid Build Coastguard Worker 				return -1;
169*de1e4e89SAndroid Build Coastguard Worker 			}
170*de1e4e89SAndroid Build Coastguard Worker 			ok++;
171*de1e4e89SAndroid Build Coastguard Worker 			argc--;
172*de1e4e89SAndroid Build Coastguard Worker 			argv++;
173*de1e4e89SAndroid Build Coastguard Worker 		}
174*de1e4e89SAndroid Build Coastguard Worker 	}
175*de1e4e89SAndroid Build Coastguard Worker 
176*de1e4e89SAndroid Build Coastguard Worker 	if (!ok) {
177*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "IFE requires decode/encode specified\n");
178*de1e4e89SAndroid Build Coastguard Worker 		ife_usage();
179*de1e4e89SAndroid Build Coastguard Worker 	}
180*de1e4e89SAndroid Build Coastguard Worker 
181*de1e4e89SAndroid Build Coastguard Worker 	tail = NLMSG_TAIL(n);
182*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
183*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_IFE_PARMS, &p, sizeof(p));
184*de1e4e89SAndroid Build Coastguard Worker 
185*de1e4e89SAndroid Build Coastguard Worker 	if (!(p.flags & IFE_ENCODE))
186*de1e4e89SAndroid Build Coastguard Worker 		goto skip_encode;
187*de1e4e89SAndroid Build Coastguard Worker 
188*de1e4e89SAndroid Build Coastguard Worker 	if (daddr)
189*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
190*de1e4e89SAndroid Build Coastguard Worker 	if (user_type)
191*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
192*de1e4e89SAndroid Build Coastguard Worker 	else
193*de1e4e89SAndroid Build Coastguard Worker 		fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE);
194*de1e4e89SAndroid Build Coastguard Worker 	if (saddr)
195*de1e4e89SAndroid Build Coastguard Worker 		addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
196*de1e4e89SAndroid Build Coastguard Worker 
197*de1e4e89SAndroid Build Coastguard Worker 	tail2 = NLMSG_TAIL(n);
198*de1e4e89SAndroid Build Coastguard Worker 	addattr_l(n, MAX_MSG, TCA_IFE_METALST, NULL, 0);
199*de1e4e89SAndroid Build Coastguard Worker 	if (ife_mark || ife_mark_v) {
200*de1e4e89SAndroid Build Coastguard Worker 		if (ife_mark_v)
201*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_SKBMARK, &ife_mark_v, 4);
202*de1e4e89SAndroid Build Coastguard Worker 		else
203*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_SKBMARK, NULL, 0);
204*de1e4e89SAndroid Build Coastguard Worker 	}
205*de1e4e89SAndroid Build Coastguard Worker 	if (ife_prio || ife_prio_v) {
206*de1e4e89SAndroid Build Coastguard Worker 		if (ife_prio_v)
207*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_PRIO, &ife_prio_v, 4);
208*de1e4e89SAndroid Build Coastguard Worker 		else
209*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_PRIO, NULL, 0);
210*de1e4e89SAndroid Build Coastguard Worker 	}
211*de1e4e89SAndroid Build Coastguard Worker 	if (ife_tcindex || ife_tcindex_v) {
212*de1e4e89SAndroid Build Coastguard Worker 		if (ife_tcindex_v)
213*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_TCINDEX, &ife_tcindex_v,
214*de1e4e89SAndroid Build Coastguard Worker 				  2);
215*de1e4e89SAndroid Build Coastguard Worker 		else
216*de1e4e89SAndroid Build Coastguard Worker 			addattr_l(n, MAX_MSG, IFE_META_TCINDEX, NULL, 0);
217*de1e4e89SAndroid Build Coastguard Worker 	}
218*de1e4e89SAndroid Build Coastguard Worker 
219*de1e4e89SAndroid Build Coastguard Worker 	tail2->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail2;
220*de1e4e89SAndroid Build Coastguard Worker 
221*de1e4e89SAndroid Build Coastguard Worker skip_encode:
222*de1e4e89SAndroid Build Coastguard Worker 	tail->rta_len = (void *)NLMSG_TAIL(n) - (void *)tail;
223*de1e4e89SAndroid Build Coastguard Worker 
224*de1e4e89SAndroid Build Coastguard Worker 	*argc_p = argc;
225*de1e4e89SAndroid Build Coastguard Worker 	*argv_p = argv;
226*de1e4e89SAndroid Build Coastguard Worker 	return 0;
227*de1e4e89SAndroid Build Coastguard Worker }
228*de1e4e89SAndroid Build Coastguard Worker 
print_ife(struct action_util * au,FILE * f,struct rtattr * arg)229*de1e4e89SAndroid Build Coastguard Worker static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg)
230*de1e4e89SAndroid Build Coastguard Worker {
231*de1e4e89SAndroid Build Coastguard Worker 	struct tc_ife *p = NULL;
232*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[TCA_IFE_MAX + 1];
233*de1e4e89SAndroid Build Coastguard Worker 	__u16 ife_type = 0;
234*de1e4e89SAndroid Build Coastguard Worker 	__u32 mmark = 0;
235*de1e4e89SAndroid Build Coastguard Worker 	__u16 mtcindex = 0;
236*de1e4e89SAndroid Build Coastguard Worker 	__u32 mprio = 0;
237*de1e4e89SAndroid Build Coastguard Worker 	int has_optional = 0;
238*de1e4e89SAndroid Build Coastguard Worker 	SPRINT_BUF(b2);
239*de1e4e89SAndroid Build Coastguard Worker 
240*de1e4e89SAndroid Build Coastguard Worker 	if (arg == NULL)
241*de1e4e89SAndroid Build Coastguard Worker 		return -1;
242*de1e4e89SAndroid Build Coastguard Worker 
243*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, TCA_IFE_MAX, arg);
244*de1e4e89SAndroid Build Coastguard Worker 
245*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IFE_PARMS] == NULL) {
246*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "[NULL ife parameters]");
247*de1e4e89SAndroid Build Coastguard Worker 		return -1;
248*de1e4e89SAndroid Build Coastguard Worker 	}
249*de1e4e89SAndroid Build Coastguard Worker 	p = RTA_DATA(tb[TCA_IFE_PARMS]);
250*de1e4e89SAndroid Build Coastguard Worker 
251*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "ife %s ", p->flags & IFE_ENCODE ? "encode" : "decode");
252*de1e4e89SAndroid Build Coastguard Worker 	print_action_control(f, "action ", p->action, " ");
253*de1e4e89SAndroid Build Coastguard Worker 
254*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IFE_TYPE]) {
255*de1e4e89SAndroid Build Coastguard Worker 		ife_type = rta_getattr_u16(tb[TCA_IFE_TYPE]);
256*de1e4e89SAndroid Build Coastguard Worker 		has_optional = 1;
257*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "type 0x%X ", ife_type);
258*de1e4e89SAndroid Build Coastguard Worker 	}
259*de1e4e89SAndroid Build Coastguard Worker 
260*de1e4e89SAndroid Build Coastguard Worker 	if (has_optional)
261*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "\n\t ");
262*de1e4e89SAndroid Build Coastguard Worker 
263*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IFE_METALST]) {
264*de1e4e89SAndroid Build Coastguard Worker 		struct rtattr *metalist[IFE_META_MAX + 1];
265*de1e4e89SAndroid Build Coastguard Worker 		int len = 0;
266*de1e4e89SAndroid Build Coastguard Worker 
267*de1e4e89SAndroid Build Coastguard Worker 		parse_rtattr_nested(metalist, IFE_META_MAX,
268*de1e4e89SAndroid Build Coastguard Worker 				    tb[TCA_IFE_METALST]);
269*de1e4e89SAndroid Build Coastguard Worker 
270*de1e4e89SAndroid Build Coastguard Worker 		if (metalist[IFE_META_SKBMARK]) {
271*de1e4e89SAndroid Build Coastguard Worker 			len = RTA_PAYLOAD(metalist[IFE_META_SKBMARK]);
272*de1e4e89SAndroid Build Coastguard Worker 			if (len) {
273*de1e4e89SAndroid Build Coastguard Worker 				mmark = rta_getattr_u32(metalist[IFE_META_SKBMARK]);
274*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "use mark %u ", mmark);
275*de1e4e89SAndroid Build Coastguard Worker 			} else
276*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "allow mark ");
277*de1e4e89SAndroid Build Coastguard Worker 		}
278*de1e4e89SAndroid Build Coastguard Worker 
279*de1e4e89SAndroid Build Coastguard Worker 		if (metalist[IFE_META_TCINDEX]) {
280*de1e4e89SAndroid Build Coastguard Worker 			len = RTA_PAYLOAD(metalist[IFE_META_TCINDEX]);
281*de1e4e89SAndroid Build Coastguard Worker 			if (len) {
282*de1e4e89SAndroid Build Coastguard Worker 				mtcindex =
283*de1e4e89SAndroid Build Coastguard Worker 					rta_getattr_u16(metalist[IFE_META_TCINDEX]);
284*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "use tcindex %d ", mtcindex);
285*de1e4e89SAndroid Build Coastguard Worker 			} else
286*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "allow tcindex ");
287*de1e4e89SAndroid Build Coastguard Worker 		}
288*de1e4e89SAndroid Build Coastguard Worker 
289*de1e4e89SAndroid Build Coastguard Worker 		if (metalist[IFE_META_PRIO]) {
290*de1e4e89SAndroid Build Coastguard Worker 			len = RTA_PAYLOAD(metalist[IFE_META_PRIO]);
291*de1e4e89SAndroid Build Coastguard Worker 			if (len) {
292*de1e4e89SAndroid Build Coastguard Worker 				mprio = rta_getattr_u32(metalist[IFE_META_PRIO]);
293*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "use prio %u ", mprio);
294*de1e4e89SAndroid Build Coastguard Worker 			} else
295*de1e4e89SAndroid Build Coastguard Worker 				fprintf(f, "allow prio ");
296*de1e4e89SAndroid Build Coastguard Worker 		}
297*de1e4e89SAndroid Build Coastguard Worker 
298*de1e4e89SAndroid Build Coastguard Worker 	}
299*de1e4e89SAndroid Build Coastguard Worker 
300*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IFE_DMAC]) {
301*de1e4e89SAndroid Build Coastguard Worker 		has_optional = 1;
302*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "dst %s ",
303*de1e4e89SAndroid Build Coastguard Worker 			ll_addr_n2a(RTA_DATA(tb[TCA_IFE_DMAC]),
304*de1e4e89SAndroid Build Coastguard Worker 				    RTA_PAYLOAD(tb[TCA_IFE_DMAC]), 0, b2,
305*de1e4e89SAndroid Build Coastguard Worker 				    sizeof(b2)));
306*de1e4e89SAndroid Build Coastguard Worker 
307*de1e4e89SAndroid Build Coastguard Worker 	}
308*de1e4e89SAndroid Build Coastguard Worker 
309*de1e4e89SAndroid Build Coastguard Worker 	if (tb[TCA_IFE_SMAC]) {
310*de1e4e89SAndroid Build Coastguard Worker 		has_optional = 1;
311*de1e4e89SAndroid Build Coastguard Worker 		fprintf(f, "src %s ",
312*de1e4e89SAndroid Build Coastguard Worker 			ll_addr_n2a(RTA_DATA(tb[TCA_IFE_SMAC]),
313*de1e4e89SAndroid Build Coastguard Worker 				    RTA_PAYLOAD(tb[TCA_IFE_SMAC]), 0, b2,
314*de1e4e89SAndroid Build Coastguard Worker 				    sizeof(b2)));
315*de1e4e89SAndroid Build Coastguard Worker 	}
316*de1e4e89SAndroid Build Coastguard Worker 
317*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt,
318*de1e4e89SAndroid Build Coastguard Worker 		p->bindcnt);
319*de1e4e89SAndroid Build Coastguard Worker 	if (show_stats) {
320*de1e4e89SAndroid Build Coastguard Worker 		if (tb[TCA_IFE_TM]) {
321*de1e4e89SAndroid Build Coastguard Worker 			struct tcf_t *tm = RTA_DATA(tb[TCA_IFE_TM]);
322*de1e4e89SAndroid Build Coastguard Worker 
323*de1e4e89SAndroid Build Coastguard Worker 			print_tm(f, tm);
324*de1e4e89SAndroid Build Coastguard Worker 		}
325*de1e4e89SAndroid Build Coastguard Worker 	}
326*de1e4e89SAndroid Build Coastguard Worker 
327*de1e4e89SAndroid Build Coastguard Worker 	fprintf(f, "\n");
328*de1e4e89SAndroid Build Coastguard Worker 
329*de1e4e89SAndroid Build Coastguard Worker 	return 0;
330*de1e4e89SAndroid Build Coastguard Worker }
331*de1e4e89SAndroid Build Coastguard Worker 
332*de1e4e89SAndroid Build Coastguard Worker struct action_util ife_action_util = {
333*de1e4e89SAndroid Build Coastguard Worker 	.id = "ife",
334*de1e4e89SAndroid Build Coastguard Worker 	.parse_aopt = parse_ife,
335*de1e4e89SAndroid Build Coastguard Worker 	.print_aopt = print_ife,
336*de1e4e89SAndroid Build Coastguard Worker };
337