Fix build break in 64bit architectures
[platform/upstream/iproute2.git] / tc / m_skbedit.c
1 /*
2  * m_skbedit.c          SKB Editing module
3  *
4  * Copyright (c) 2008, Intel Corporation.
5  *
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.
9  *
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
13  * more details.
14  *
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>.
17  *
18  * Authors:     Alexander Duyck <alexander.h.duyck@intel.com>
19  *
20  */
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include "utils.h"
27 #include "tc_util.h"
28 #include <linux/tc_act/tc_skbedit.h>
29 #include <linux/if_packet.h>
30
31 static void explain(void)
32 {
33         fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
34                 "QM = queue_mapping QUEUE_MAPPING\n"
35                 "PM = priority PRIORITY\n"
36                 "MM = mark MARK[/MASK]\n"
37                 "PT = ptype PACKETYPE\n"
38                 "IF = inheritdsfield\n"
39                 "PACKETYPE = is one of:\n"
40                 "  host, otherhost, broadcast, multicast\n"
41                 "QUEUE_MAPPING = device transmit queue to use\n"
42                 "PRIORITY = classID to assign to priority field\n"
43                 "MARK = firewall mark to set\n"
44                 "MASK = mask applied to firewall mark (0xffffffff by default)\n"
45                 "note: inheritdsfield maps DS field to skb->priority\n");
46 }
47
48 static void
49 usage(void)
50 {
51         explain();
52         exit(-1);
53 }
54
55 static int
56 parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
57               struct nlmsghdr *n)
58 {
59         int argc = *argc_p;
60         char **argv = *argv_p;
61         int ok = 0;
62         struct rtattr *tail;
63         unsigned int tmp;
64         __u16 queue_mapping, ptype;
65         __u32 flags = 0, priority, mark, mask;
66         __u64 pure_flags = 0;
67         struct tc_skbedit sel = { 0 };
68
69         if (matches(*argv, "skbedit") != 0)
70                 return -1;
71
72         NEXT_ARG();
73
74         while (argc > 0) {
75                 if (matches(*argv, "queue_mapping") == 0) {
76                         flags |= SKBEDIT_F_QUEUE_MAPPING;
77                         NEXT_ARG();
78                         if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
79                                 fprintf(stderr, "Illegal queue_mapping\n");
80                                 return -1;
81                         }
82                         queue_mapping = tmp;
83                         ok++;
84                 } else if (matches(*argv, "priority") == 0) {
85                         flags |= SKBEDIT_F_PRIORITY;
86                         NEXT_ARG();
87                         if (get_tc_classid(&priority, *argv)) {
88                                 fprintf(stderr, "Illegal priority\n");
89                                 return -1;
90                         }
91                         ok++;
92                 } else if (matches(*argv, "mark") == 0) {
93                         char *slash;
94
95                         NEXT_ARG();
96                         slash = strchr(*argv, '/');
97                         if (slash)
98                                 *slash = '\0';
99
100                         flags |= SKBEDIT_F_MARK;
101                         if (get_u32(&mark, *argv, 0)) {
102                                 fprintf(stderr, "Illegal mark\n");
103                                 return -1;
104                         }
105
106                         if (slash) {
107                                 if (get_u32(&mask, slash + 1, 0)) {
108                                         fprintf(stderr, "Illegal mask\n");
109                                         return -1;
110                                 }
111                                 flags |= SKBEDIT_F_MASK;
112                         }
113                         ok++;
114                 } else if (matches(*argv, "ptype") == 0) {
115
116                         NEXT_ARG();
117                         if (matches(*argv, "host") == 0) {
118                                 ptype = PACKET_HOST;
119                         } else if (matches(*argv, "broadcast") == 0) {
120                                 ptype = PACKET_BROADCAST;
121                         } else if (matches(*argv, "multicast") == 0) {
122                                 ptype = PACKET_MULTICAST;
123                         } else if (matches(*argv, "otherhost") == 0) {
124                                 ptype = PACKET_OTHERHOST;
125                         } else {
126                                 fprintf(stderr, "Illegal ptype (%s)\n",
127                                         *argv);
128                                 return -1;
129                         }
130                         flags |= SKBEDIT_F_PTYPE;
131                         ok++;
132                 } else if (matches(*argv, "inheritdsfield") == 0) {
133                         pure_flags |= SKBEDIT_F_INHERITDSFIELD;
134                         ok++;
135                 } else if (matches(*argv, "help") == 0) {
136                         usage();
137                 } else {
138                         break;
139                 }
140                 argc--;
141                 argv++;
142         }
143
144         parse_action_control_dflt(&argc, &argv, &sel.action,
145                                   false, TC_ACT_PIPE);
146
147         if (argc) {
148                 if (matches(*argv, "index") == 0) {
149                         NEXT_ARG();
150                         if (get_u32(&sel.index, *argv, 10)) {
151                                 fprintf(stderr, "skbedit: Illegal \"index\"\n");
152                                 return -1;
153                         }
154                         argc--;
155                         argv++;
156                         ok++;
157                 }
158         }
159
160         if (!ok) {
161                 explain();
162                 return -1;
163         }
164
165
166         tail = addattr_nest(n, MAX_MSG, tca_id);
167         addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
168         if (flags & SKBEDIT_F_QUEUE_MAPPING)
169                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
170                           &queue_mapping, sizeof(queue_mapping));
171         if (flags & SKBEDIT_F_PRIORITY)
172                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
173                           &priority, sizeof(priority));
174         if (flags & SKBEDIT_F_MARK)
175                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
176                           &mark, sizeof(mark));
177         if (flags & SKBEDIT_F_MASK)
178                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_MASK,
179                           &mask, sizeof(mask));
180         if (flags & SKBEDIT_F_PTYPE)
181                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
182                           &ptype, sizeof(ptype));
183         if (pure_flags != 0)
184                 addattr64(n, MAX_MSG, TCA_SKBEDIT_FLAGS, pure_flags);
185         addattr_nest_end(n, tail);
186
187         *argc_p = argc;
188         *argv_p = argv;
189         return 0;
190 }
191
192 static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
193 {
194         struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
195
196         SPRINT_BUF(b1);
197         __u32 priority;
198         __u16 ptype;
199         struct tc_skbedit *p;
200
201         if (arg == NULL)
202                 return -1;
203
204         parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
205
206         if (tb[TCA_SKBEDIT_PARMS] == NULL) {
207                 fprintf(stderr, "Missing skbedit parameters\n");
208                 return -1;
209         }
210         p = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
211
212         print_string(PRINT_ANY, "kind", "%s ", "skbedit");
213
214         if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
215                 print_uint(PRINT_ANY, "queue_mapping", "queue_mapping %u",
216                            rta_getattr_u16(tb[TCA_SKBEDIT_QUEUE_MAPPING]));
217         }
218         if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
219                 priority = rta_getattr_u32(tb[TCA_SKBEDIT_PRIORITY]);
220                 print_string(PRINT_ANY, "priority", " priority %s",
221                              sprint_tc_classid(priority, b1));
222         }
223         if (tb[TCA_SKBEDIT_MARK] != NULL) {
224                 print_uint(PRINT_ANY, "mark", " mark %u",
225                            rta_getattr_u32(tb[TCA_SKBEDIT_MARK]));
226         }
227         if (tb[TCA_SKBEDIT_MASK]) {
228                 print_hex(PRINT_ANY, "mask", "/%#x",
229                           rta_getattr_u32(tb[TCA_SKBEDIT_MASK]));
230         }
231         if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
232                 ptype = rta_getattr_u16(tb[TCA_SKBEDIT_PTYPE]);
233                 if (ptype == PACKET_HOST)
234                         print_string(PRINT_ANY, "ptype", " ptype %s", "host");
235                 else if (ptype == PACKET_BROADCAST)
236                         print_string(PRINT_ANY, "ptype", " ptype %s",
237                                      "broadcast");
238                 else if (ptype == PACKET_MULTICAST)
239                         print_string(PRINT_ANY, "ptype", " ptype %s",
240                                      "multicast");
241                 else if (ptype == PACKET_OTHERHOST)
242                         print_string(PRINT_ANY, "ptype", " ptype %s",
243                                      "otherhost");
244                 else
245                         print_uint(PRINT_ANY, "ptype", " ptype %u", ptype);
246         }
247         if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
248                 __u64 flags = rta_getattr_u64(tb[TCA_SKBEDIT_FLAGS]);
249
250                 if (flags & SKBEDIT_F_INHERITDSFIELD)
251                         print_null(PRINT_ANY, "inheritdsfield", " %s",
252                                      "inheritdsfield");
253         }
254
255         print_action_control(f, " ", p->action, "");
256
257         print_string(PRINT_FP, NULL, "%s", _SL_);
258         print_uint(PRINT_ANY, "index", "\t index %u", p->index);
259         print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
260         print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
261
262         if (show_stats) {
263                 if (tb[TCA_SKBEDIT_TM]) {
264                         struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
265
266                         print_tm(f, tm);
267                 }
268         }
269
270         print_string(PRINT_FP, NULL, "%s", _SL_);
271
272         return 0;
273 }
274
275 struct action_util skbedit_action_util = {
276         .id = "skbedit",
277         .parse_aopt = parse_skbedit,
278         .print_aopt = print_skbedit,
279 };