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 (at) 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 rtattr *tb[TCA_SKBEDIT_MAX + 1]; 164 SPRINT_BUF(b1); 165 __u32 *priority; 166 __u32 *mark; 167 __u16 *queue_mapping; 168 169 if (arg == NULL) 170 return -1; 171 172 parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg); 173 174 if (tb[TCA_SKBEDIT_PARMS] == NULL) { 175 fprintf(f, "[NULL skbedit parameters]"); 176 return -1; 177 } 178 179 fprintf(f, " skbedit"); 180 181 if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) { 182 queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]); 183 fprintf(f, " queue_mapping %u", *queue_mapping); 184 } 185 if (tb[TCA_SKBEDIT_PRIORITY] != NULL) { 186 priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]); 187 fprintf(f, " priority %s", sprint_tc_classid(*priority, b1)); 188 } 189 if (tb[TCA_SKBEDIT_MARK] != NULL) { 190 mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]); 191 fprintf(f, " mark %d", *mark); 192 } 193 194 if (show_stats) { 195 if (tb[TCA_SKBEDIT_TM]) { 196 struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]); 197 print_tm(f, tm); 198 } 199 } 200 201 return 0; 202 } 203 204 struct action_util skbedit_action_util = { 205 .id = "skbedit", 206 .parse_aopt = parse_skbedit, 207 .print_aopt = print_skbedit, 208 }; 209