]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_skbedit.c
iproute: add DRR support
[mirror_iproute2.git] / tc / m_skbedit.c
CommitLineData
f72a7aab
AD
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};