m_skbedit.c revision f72a7aab0ce946ca1133cc8b6b7fcb088fbb1d96
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
31static void
32explain(void)
33{
34	fprintf(stderr, "Usage: ... skbedit "
35			"queue_mapping QUEUE_MAPPING | priority PRIORITY \n"
36			"QUEUE_MAPPING = device transmit queue to use\n"
37			"PRIORITY = classID to assign to priority field\n");
38}
39
40static void
41usage(void)
42{
43	explain();
44	exit(-1);
45}
46
47static int
48parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
49	      struct nlmsghdr *n)
50{
51	struct tc_skbedit sel;
52	int argc = *argc_p;
53	char **argv = *argv_p;
54	int ok = 0;
55	struct rtattr *tail;
56	unsigned int tmp;
57	__u16 queue_mapping;
58	__u32 flags = 0, priority;
59
60	if (matches(*argv, "skbedit") != 0)
61		return -1;
62
63	NEXT_ARG();
64
65	while (argc > 0) {
66		if (matches(*argv, "queue_mapping") == 0) {
67			flags |= SKBEDIT_F_QUEUE_MAPPING;
68			NEXT_ARG();
69			if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
70				fprintf(stderr, "Illegal queue_mapping\n");
71				return -1;
72			}
73			queue_mapping = tmp;
74			ok++;
75		} else if (matches(*argv, "priority") == 0) {
76			flags |= SKBEDIT_F_PRIORITY;
77			NEXT_ARG();
78			if (get_tc_classid(&priority, *argv)) {
79				fprintf(stderr, "Illegal priority\n");
80				return -1;
81			}
82			ok++;
83		} else if (matches(*argv, "help") == 0) {
84			usage();
85		} else {
86			break;
87		}
88		argc--;
89		argv++;
90	}
91
92	if (argc) {
93		if (matches(*argv, "reclassify") == 0) {
94			sel.action = TC_ACT_RECLASSIFY;
95			NEXT_ARG();
96		} else if (matches(*argv, "pipe") == 0) {
97			sel.action = TC_ACT_PIPE;
98			NEXT_ARG();
99		} else if (matches(*argv, "drop") == 0 ||
100			matches(*argv, "shot") == 0) {
101			sel.action = TC_ACT_SHOT;
102			NEXT_ARG();
103		} else if (matches(*argv, "continue") == 0) {
104			sel.action = TC_ACT_UNSPEC;
105			NEXT_ARG();
106		} else if (matches(*argv, "pass") == 0) {
107			sel.action = TC_ACT_OK;
108			NEXT_ARG();
109		}
110	}
111
112	if (argc) {
113		if (matches(*argv, "index") == 0) {
114			NEXT_ARG();
115			if (get_u32(&sel.index, *argv, 10)) {
116				fprintf(stderr, "Pedit: Illegal \"index\"\n");
117				return -1;
118			}
119			argc--;
120			argv++;
121			ok++;
122		}
123	}
124
125	if (!ok) {
126		explain();
127		return -1;
128	}
129
130
131	tail = NLMSG_TAIL(n);
132	addattr_l(n, MAX_MSG, tca_id, NULL, 0);
133	addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
134	if (flags & SKBEDIT_F_QUEUE_MAPPING)
135		addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
136			  &queue_mapping, sizeof(queue_mapping));
137	if (flags & SKBEDIT_F_PRIORITY)
138		addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
139			  &priority, sizeof(priority));
140	tail->rta_len = (char *)NLMSG_TAIL(n) - (char *)tail;
141
142	*argc_p = argc;
143	*argv_p = argv;
144	return 0;
145}
146
147static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
148{
149	struct tc_skbedit *sel;
150	struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
151	SPRINT_BUF(b1);
152	__u32 *priority;
153	__u16 *queue_mapping;
154
155	if (arg == NULL)
156		return -1;
157
158	parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
159
160	if (tb[TCA_SKBEDIT_PARMS] == NULL) {
161		fprintf(f, "[NULL skbedit parameters]");
162		return -1;
163	}
164
165	sel = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
166
167	fprintf(f, " skbedit");
168
169	if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
170		queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
171		fprintf(f, " queue_mapping %u", *queue_mapping);
172	}
173	if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
174		priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]);
175		fprintf(f, " priority %s", sprint_tc_classid(*priority, b1));
176	}
177
178	if (show_stats) {
179		if (tb[TCA_SKBEDIT_TM]) {
180			struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
181			print_tm(f, tm);
182		}
183	}
184
185	return 0;
186}
187
188struct action_util skbedit_action_util = {
189	.id = "skbedit",
190	.parse_aopt = parse_skbedit,
191	.print_aopt = print_skbedit,
192};
193