Home | History | Annotate | Download | only in tc
      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 tc_skbedit *sel;
    164 	struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
    165 	SPRINT_BUF(b1);
    166 	__u32 *priority;
    167 	__u32 *mark;
    168 	__u16 *queue_mapping;
    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 
    180 	sel = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
    181 
    182 	fprintf(f, " skbedit");
    183 
    184 	if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
    185 		queue_mapping = RTA_DATA(tb[TCA_SKBEDIT_QUEUE_MAPPING]);
    186 		fprintf(f, " queue_mapping %u", *queue_mapping);
    187 	}
    188 	if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
    189 		priority = RTA_DATA(tb[TCA_SKBEDIT_PRIORITY]);
    190 		fprintf(f, " priority %s", sprint_tc_classid(*priority, b1));
    191 	}
    192 	if (tb[TCA_SKBEDIT_MARK] != NULL) {
    193 		mark = RTA_DATA(tb[TCA_SKBEDIT_MARK]);
    194 		fprintf(f, " mark %d", *mark);
    195 	}
    196 
    197 	if (show_stats) {
    198 		if (tb[TCA_SKBEDIT_TM]) {
    199 			struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
    200 			print_tm(f, tm);
    201 		}
    202 	}
    203 
    204 	return 0;
    205 }
    206 
    207 struct action_util skbedit_action_util = {
    208 	.id = "skbedit",
    209 	.parse_aopt = parse_skbedit,
    210 	.print_aopt = print_skbedit,
    211 };
    212