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
     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