2 * m_skbedit.c SKB Editing module
4 * Copyright (c) 2008, Intel Corporation.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, see <http://www.gnu.org/licenses>.
18 * Authors: Alexander Duyck <alexander.h.duyck@intel.com>
28 #include <linux/tc_act/tc_skbedit.h>
29 #include <linux/if_packet.h>
31 static void explain(void)
33 fprintf(stderr
, "Usage: ... skbedit <[QM] [PM] [MM] [PT]>\n"
34 "QM = queue_mapping QUEUE_MAPPING\n"
35 "PM = priority PRIORITY\n"
37 "PT = ptype PACKETYPE\n"
38 "PACKETYPE = is one of:\n"
39 " host, otherhost, broadcast, multicast\n"
40 "QUEUE_MAPPING = device transmit queue to use\n"
41 "PRIORITY = classID to assign to priority field\n"
42 "MARK = firewall mark to set\n");
53 parse_skbedit(struct action_util
*a
, int *argc_p
, char ***argv_p
, int tca_id
,
57 char **argv
= *argv_p
;
61 __u16 queue_mapping
, ptype
;
62 __u32 flags
= 0, priority
, mark
;
63 struct tc_skbedit sel
= { 0 };
65 if (matches(*argv
, "skbedit") != 0)
71 if (matches(*argv
, "queue_mapping") == 0) {
72 flags
|= SKBEDIT_F_QUEUE_MAPPING
;
74 if (get_unsigned(&tmp
, *argv
, 10) || tmp
> 65535) {
75 fprintf(stderr
, "Illegal queue_mapping\n");
80 } else if (matches(*argv
, "priority") == 0) {
81 flags
|= SKBEDIT_F_PRIORITY
;
83 if (get_tc_classid(&priority
, *argv
)) {
84 fprintf(stderr
, "Illegal priority\n");
88 } else if (matches(*argv
, "mark") == 0) {
89 flags
|= SKBEDIT_F_MARK
;
91 if (get_u32(&mark
, *argv
, 0)) {
92 fprintf(stderr
, "Illegal mark\n");
96 } else if (matches(*argv
, "ptype") == 0) {
99 if (matches(*argv
, "host") == 0) {
101 } else if (matches(*argv
, "broadcast") == 0) {
102 ptype
= PACKET_BROADCAST
;
103 } else if (matches(*argv
, "multicast") == 0) {
104 ptype
= PACKET_MULTICAST
;
105 } else if (matches(*argv
, "otherhost") == 0) {
106 ptype
= PACKET_OTHERHOST
;
108 fprintf(stderr
, "Illegal ptype (%s)\n",
112 flags
|= SKBEDIT_F_PTYPE
;
114 } else if (matches(*argv
, "help") == 0) {
123 sel
.action
= TC_ACT_PIPE
;
124 if (argc
&& !action_a2n(*argv
, &sel
.action
, false))
128 if (matches(*argv
, "index") == 0) {
130 if (get_u32(&sel
.index
, *argv
, 10)) {
131 fprintf(stderr
, "Pedit: Illegal \"index\"\n");
146 tail
= NLMSG_TAIL(n
);
147 addattr_l(n
, MAX_MSG
, tca_id
, NULL
, 0);
148 addattr_l(n
, MAX_MSG
, TCA_SKBEDIT_PARMS
, &sel
, sizeof(sel
));
149 if (flags
& SKBEDIT_F_QUEUE_MAPPING
)
150 addattr_l(n
, MAX_MSG
, TCA_SKBEDIT_QUEUE_MAPPING
,
151 &queue_mapping
, sizeof(queue_mapping
));
152 if (flags
& SKBEDIT_F_PRIORITY
)
153 addattr_l(n
, MAX_MSG
, TCA_SKBEDIT_PRIORITY
,
154 &priority
, sizeof(priority
));
155 if (flags
& SKBEDIT_F_MARK
)
156 addattr_l(n
, MAX_MSG
, TCA_SKBEDIT_MARK
,
157 &mark
, sizeof(mark
));
158 if (flags
& SKBEDIT_F_PTYPE
)
159 addattr_l(n
, MAX_MSG
, TCA_SKBEDIT_PTYPE
,
160 &ptype
, sizeof(ptype
));
161 tail
->rta_len
= (char *)NLMSG_TAIL(n
) - (char *)tail
;
168 static int print_skbedit(struct action_util
*au
, FILE *f
, struct rtattr
*arg
)
170 struct rtattr
*tb
[TCA_SKBEDIT_MAX
+ 1];
175 __u16
*queue_mapping
, *ptype
;
176 struct tc_skbedit
*p
= NULL
;
181 parse_rtattr_nested(tb
, TCA_SKBEDIT_MAX
, arg
);
183 if (tb
[TCA_SKBEDIT_PARMS
] == NULL
) {
184 fprintf(f
, "[NULL skbedit parameters]");
187 p
= RTA_DATA(tb
[TCA_SKBEDIT_PARMS
]);
189 fprintf(f
, " skbedit");
191 if (tb
[TCA_SKBEDIT_QUEUE_MAPPING
] != NULL
) {
192 queue_mapping
= RTA_DATA(tb
[TCA_SKBEDIT_QUEUE_MAPPING
]);
193 fprintf(f
, " queue_mapping %u", *queue_mapping
);
195 if (tb
[TCA_SKBEDIT_PRIORITY
] != NULL
) {
196 priority
= RTA_DATA(tb
[TCA_SKBEDIT_PRIORITY
]);
197 fprintf(f
, " priority %s", sprint_tc_classid(*priority
, b1
));
199 if (tb
[TCA_SKBEDIT_MARK
] != NULL
) {
200 mark
= RTA_DATA(tb
[TCA_SKBEDIT_MARK
]);
201 fprintf(f
, " mark %d", *mark
);
203 if (tb
[TCA_SKBEDIT_PTYPE
] != NULL
) {
204 ptype
= RTA_DATA(tb
[TCA_SKBEDIT_PTYPE
]);
205 if (*ptype
== PACKET_HOST
)
206 fprintf(f
, " ptype host");
207 else if (*ptype
== PACKET_BROADCAST
)
208 fprintf(f
, " ptype broadcast");
209 else if (*ptype
== PACKET_MULTICAST
)
210 fprintf(f
, " ptype multicast");
211 else if (*ptype
== PACKET_OTHERHOST
)
212 fprintf(f
, " ptype otherhost");
214 fprintf(f
, " ptype %d", *ptype
);
217 fprintf(f
, "\n\t index %u ref %d bind %d",
218 p
->index
, p
->refcnt
, p
->bindcnt
);
221 if (tb
[TCA_SKBEDIT_TM
]) {
222 struct tcf_t
*tm
= RTA_DATA(tb
[TCA_SKBEDIT_TM
]);
233 struct action_util skbedit_action_util
= {
235 .parse_aopt
= parse_skbedit
,
236 .print_aopt
= print_skbedit
,