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 (at) 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 30 static void 31 explain(void) 32 { 33 fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM]>\n" 34 "QM = queue_mapping QUEUE_MAPPING\n" 35 "PM = priority PRIORITY \n" 36 "MM = mark MARK \n" 37 "QUEUE_MAPPING = device transmit queue to use\n" 38 "PRIORITY = classID to assign to priority field\n" 39 "MARK = firewall mark to set\n"); 40 } 41 42 static void 43 usage(void) 44 { 45 explain(); 46 exit(-1); 47 } 48 49 static int 50 parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, 51 struct nlmsghdr *n) 52 { 53 int argc = *argc_p; 54 char **argv = *argv_p; 55 int ok = 0; 56 struct rtattr *tail; 57 unsigned int tmp; 58 __u16 queue_mapping; 59 __u32 flags = 0, priority, mark; 60 struct tc_skbedit sel = { 0 }; 61 62 if (matches(*argv, "skbedit") != 0) 63 return -1; 64 65 NEXT_ARG(); 66 67 while (argc > 0) { 68 if (matches(*argv, "queue_mapping") == 0) { 69 flags |= SKBEDIT_F_QUEUE_MAPPING; 70 NEXT_ARG(); 71 if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) { 72 fprintf(stderr, "Illegal queue_mapping\n"); 73 return -1; 74 } 75 queue_mapping = tmp; 76 ok++; 77 } else if (matches(*argv, "priority") == 0) { 78 flags |= SKBEDIT_F_PRIORITY; 79 NEXT_ARG(); 80 if (get_tc_classid(&priority, *argv)) { 81 fprintf(stderr, "Illegal priority\n"); 82 return -1; 83 } 84 ok++; 85 } else if (matches(*argv, "mark") == 0) { 86 flags |= SKBEDIT_F_MARK; 87 NEXT_ARG(); 88 if (get_u32(&mark, *argv, 0)) { 89 fprintf(stderr, "Illegal mark\n"); 90 return -1; 91 } 92 ok++; 93 } else if (matches(*argv, "help") == 0) { 94 usage(); 95 } else { 96 break; 97 } 98 argc--; 99 argv++; 100 } 101 102 sel.action = TC_ACT_PIPE; 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 rtattr *tb[TCA_SKBEDIT_MAX + 1]; 164 SPRINT_BUF(b1); 165 __u32 *priority; 166 __u32 *mark; 167 __u16 *queue_mapping; 168 struct tc_skbedit *p = NULL; 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 p = RTA_DATA(tb[TCA_SKBEDIT_PARMS]); 180 181 fprintf(f, " skbedit"); 182 183 if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) { 184 queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]); 185 fprintf(f, " queue_mapping %u", *queue_mapping); 186 } 187 if (tb[TCA_SKBEDIT_PRIORITY] != NULL) { 188 priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]); 189 fprintf(f, " priority %s", sprint_tc_classid(*priority, b1)); 190 } 191 if (tb[TCA_SKBEDIT_MARK] != NULL) { 192 mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]); 193 fprintf(f, " mark %d", *mark); 194 } 195 196 fprintf(f, "\n\t index %d ref %d bind %d", p->index, p->refcnt, p->bindcnt); 197 198 if (show_stats) { 199 if (tb[TCA_SKBEDIT_TM]) { 200 struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]); 201 print_tm(f, tm); 202 } 203 } 204 205 fprintf(f, "\n "); 206 207 return 0; 208 } 209 210 struct action_util skbedit_action_util = { 211 .id = "skbedit", 212 .parse_aopt = parse_skbedit, 213 .print_aopt = print_skbedit, 214 }; 215