]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/blob - tc/m_skbedit.c
990b9c7de89d20f09ed9a8fa4c965e3949d0b164
[lisovros/iproute2_canprio.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 along with
16  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
17  * Place - Suite 330, Boston, MA 02111-1307 USA.
18  *
19  * Authors:     Alexander Duyck <alexander.h.duyck@intel.com>
20  *
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include "utils.h"
28 #include "tc_util.h"
29 #include <linux/tc_act/tc_skbedit.h>
30
31 static void
32 explain(void)
33 {
34         fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM]>\n"
35                 "QM = queue_mapping QUEUE_MAPPING\n"
36                 "PM = priority PRIORITY \n"
37                 "MM = mark MARK \n"
38                 "QUEUE_MAPPING = device transmit queue to use\n"
39                 "PRIORITY = classID to assign to priority field\n"
40                 "MARK = firewall mark to set\n");
41 }
42
43 static void
44 usage(void)
45 {
46         explain();
47         exit(-1);
48 }
49
50 static int
51 parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
52               struct nlmsghdr *n)
53 {
54         int argc = *argc_p;
55         char **argv = *argv_p;
56         int ok = 0;
57         struct rtattr *tail;
58         unsigned int tmp;
59         __u16 queue_mapping;
60         __u32 flags = 0, priority, mark;
61         struct tc_skbedit sel = { 0 };
62
63         if (matches(*argv, "skbedit") != 0)
64                 return -1;
65
66         NEXT_ARG();
67
68         while (argc > 0) {
69                 if (matches(*argv, "queue_mapping") == 0) {
70                         flags |= SKBEDIT_F_QUEUE_MAPPING;
71                         NEXT_ARG();
72                         if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
73                                 fprintf(stderr, "Illegal queue_mapping\n");
74                                 return -1;
75                         }
76                         queue_mapping = tmp;
77                         ok++;
78                 } else if (matches(*argv, "priority") == 0) {
79                         flags |= SKBEDIT_F_PRIORITY;
80                         NEXT_ARG();
81                         if (get_tc_classid(&priority, *argv)) {
82                                 fprintf(stderr, "Illegal priority\n");
83                                 return -1;
84                         }
85                         ok++;
86                 } else if (matches(*argv, "mark") == 0) {
87                         flags |= SKBEDIT_F_MARK;
88                         NEXT_ARG();
89                         if (get_u32(&mark, *argv, 0)) {
90                                 fprintf(stderr, "Illegal mark\n");
91                                 return -1;
92                         }
93                         ok++;
94                 } else if (matches(*argv, "help") == 0) {
95                         usage();
96                 } else {
97                         break;
98                 }
99                 argc--;
100                 argv++;
101         }
102
103         if (argc) {
104                 if (matches(*argv, "reclassify") == 0) {
105                         sel.action = TC_ACT_RECLASSIFY;
106                         NEXT_ARG();
107                 } else if (matches(*argv, "pipe") == 0) {
108                         sel.action = TC_ACT_PIPE;
109                         NEXT_ARG();
110                 } else if (matches(*argv, "drop") == 0 ||
111                         matches(*argv, "shot") == 0) {
112                         sel.action = TC_ACT_SHOT;
113                         NEXT_ARG();
114                 } else if (matches(*argv, "continue") == 0) {
115                         sel.action = TC_ACT_UNSPEC;
116                         NEXT_ARG();
117                 } else if (matches(*argv, "pass") == 0) {
118                         sel.action = TC_ACT_OK;
119                         NEXT_ARG();
120                 }
121         }
122
123         if (argc) {
124                 if (matches(*argv, "index") == 0) {
125                         NEXT_ARG();
126                         if (get_u32(&sel.index, *argv, 10)) {
127                                 fprintf(stderr, "Pedit: Illegal \"index\"\n");
128                                 return -1;
129                         }
130                         argc--;
131                         argv++;
132                         ok++;
133                 }
134         }
135
136         if (!ok) {
137                 explain();
138                 return -1;
139         }
140
141
142         tail = NLMSG_TAIL(n);
143         addattr_l(n, MAX_MSG, tca_id, NULL, 0);
144         addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
145         if (flags & SKBEDIT_F_QUEUE_MAPPING)
146                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
147                           &queue_mapping, sizeof(queue_mapping));
148         if (flags & SKBEDIT_F_PRIORITY)
149                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
150                           &priority, sizeof(priority));
151         if (flags & SKBEDIT_F_MARK)
152                 addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
153                           &mark, sizeof(mark));
154         tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
155
156         *argc_p = argc;
157         *argv_p = argv;
158         return 0;
159 }
160
161 static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
162 {
163         struct tc_skbedit *sel;
164         struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
165         SPRINT_BUF(b1);
166         __u32 *priority;
167         __u32 *mark;
168         __u16 *queue_mapping;
169
170         if (arg == NULL)
171                 return -1;
172
173         parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
174
175         if (tb[TCA_SKBEDIT_PARMS] == NULL) {
176                 fprintf(f, "[NULL skbedit parameters]");
177                 return -1;
178         }
179
180         sel = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
181
182         fprintf(f, " skbedit");
183
184         if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
185                 queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
186                 fprintf(f, " queue_mapping %u", *queue_mapping);
187         }
188         if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
189                 priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]);
190                 fprintf(f, " priority %s", sprint_tc_classid(*priority, b1));
191         }
192         if (tb[TCA_SKBEDIT_MARK] != NULL) {
193                 mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]);
194                 fprintf(f, " mark %d", *mark);
195         }
196
197         if (show_stats) {
198                 if (tb[TCA_SKBEDIT_TM]) {
199                         struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
200                         print_tm(f, tm);
201                 }
202         }
203
204         return 0;
205 }
206
207 struct action_util skbedit_action_util = {
208         .id = "skbedit",
209         .parse_aopt = parse_skbedit,
210         .print_aopt = print_skbedit,
211 };