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