iproute2/tc/m_skbedit.c
<<
>>
Prefs
   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@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#include <linux/if_packet.h>
  30
  31static void explain(void)
  32{
  33        fprintf(stderr, "Usage: ... skbedit <[QM] [PM] [MM] [PT] [IF]>\n"
  34                "QM = queue_mapping QUEUE_MAPPING\n"
  35                "PM = priority PRIORITY\n"
  36                "MM = mark MARK[/MASK]\n"
  37                "PT = ptype PACKETYPE\n"
  38                "IF = inheritdsfield\n"
  39                "PACKETYPE = is one of:\n"
  40                "  host, otherhost, broadcast, multicast\n"
  41                "QUEUE_MAPPING = device transmit queue to use\n"
  42                "PRIORITY = classID to assign to priority field\n"
  43                "MARK = firewall mark to set\n"
  44                "MASK = mask applied to firewall mark (0xffffffff by default)\n"
  45                "note: inheritdsfield maps DS field to skb->priority\n");
  46}
  47
  48static void
  49usage(void)
  50{
  51        explain();
  52        exit(-1);
  53}
  54
  55static int
  56parse_skbedit(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
  57              struct nlmsghdr *n)
  58{
  59        int argc = *argc_p;
  60        char **argv = *argv_p;
  61        int ok = 0;
  62        struct rtattr *tail;
  63        unsigned int tmp;
  64        __u16 queue_mapping, ptype;
  65        __u32 flags = 0, priority, mark, mask;
  66        __u64 pure_flags = 0;
  67        struct tc_skbedit sel = { 0 };
  68
  69        if (matches(*argv, "skbedit") != 0)
  70                return -1;
  71
  72        NEXT_ARG();
  73
  74        while (argc > 0) {
  75                if (matches(*argv, "queue_mapping") == 0) {
  76                        flags |= SKBEDIT_F_QUEUE_MAPPING;
  77                        NEXT_ARG();
  78                        if (get_unsigned(&tmp, *argv, 10) || tmp > 65535) {
  79                                fprintf(stderr, "Illegal queue_mapping\n");
  80                                return -1;
  81                        }
  82                        queue_mapping = tmp;
  83                        ok++;
  84                } else if (matches(*argv, "priority") == 0) {
  85                        flags |= SKBEDIT_F_PRIORITY;
  86                        NEXT_ARG();
  87                        if (get_tc_classid(&priority, *argv)) {
  88                                fprintf(stderr, "Illegal priority\n");
  89                                return -1;
  90                        }
  91                        ok++;
  92                } else if (matches(*argv, "mark") == 0) {
  93                        char *slash;
  94
  95                        NEXT_ARG();
  96                        slash = strchr(*argv, '/');
  97                        if (slash)
  98                                *slash = '\0';
  99
 100                        flags |= SKBEDIT_F_MARK;
 101                        if (get_u32(&mark, *argv, 0)) {
 102                                fprintf(stderr, "Illegal mark\n");
 103                                return -1;
 104                        }
 105
 106                        if (slash) {
 107                                if (get_u32(&mask, slash + 1, 0)) {
 108                                        fprintf(stderr, "Illegal mask\n");
 109                                        return -1;
 110                                }
 111                                flags |= SKBEDIT_F_MASK;
 112                        }
 113                        ok++;
 114                } else if (matches(*argv, "ptype") == 0) {
 115
 116                        NEXT_ARG();
 117                        if (matches(*argv, "host") == 0) {
 118                                ptype = PACKET_HOST;
 119                        } else if (matches(*argv, "broadcast") == 0) {
 120                                ptype = PACKET_BROADCAST;
 121                        } else if (matches(*argv, "multicast") == 0) {
 122                                ptype = PACKET_MULTICAST;
 123                        } else if (matches(*argv, "otherhost") == 0) {
 124                                ptype = PACKET_OTHERHOST;
 125                        } else {
 126                                fprintf(stderr, "Illegal ptype (%s)\n",
 127                                        *argv);
 128                                return -1;
 129                        }
 130                        flags |= SKBEDIT_F_PTYPE;
 131                        ok++;
 132                } else if (matches(*argv, "inheritdsfield") == 0) {
 133                        pure_flags |= SKBEDIT_F_INHERITDSFIELD;
 134                        ok++;
 135                } else if (matches(*argv, "help") == 0) {
 136                        usage();
 137                } else {
 138                        break;
 139                }
 140                argc--;
 141                argv++;
 142        }
 143
 144        parse_action_control_dflt(&argc, &argv, &sel.action,
 145                                  false, TC_ACT_PIPE);
 146
 147        if (argc) {
 148                if (matches(*argv, "index") == 0) {
 149                        NEXT_ARG();
 150                        if (get_u32(&sel.index, *argv, 10)) {
 151                                fprintf(stderr, "skbedit: Illegal \"index\"\n");
 152                                return -1;
 153                        }
 154                        argc--;
 155                        argv++;
 156                        ok++;
 157                }
 158        }
 159
 160        if (!ok) {
 161                explain();
 162                return -1;
 163        }
 164
 165
 166        tail = addattr_nest(n, MAX_MSG, tca_id);
 167        addattr_l(n, MAX_MSG, TCA_SKBEDIT_PARMS, &sel, sizeof(sel));
 168        if (flags & SKBEDIT_F_QUEUE_MAPPING)
 169                addattr_l(n, MAX_MSG, TCA_SKBEDIT_QUEUE_MAPPING,
 170                          &queue_mapping, sizeof(queue_mapping));
 171        if (flags & SKBEDIT_F_PRIORITY)
 172                addattr_l(n, MAX_MSG, TCA_SKBEDIT_PRIORITY,
 173                          &priority, sizeof(priority));
 174        if (flags & SKBEDIT_F_MARK)
 175                addattr_l(n, MAX_MSG, TCA_SKBEDIT_MARK,
 176                          &mark, sizeof(mark));
 177        if (flags & SKBEDIT_F_MASK)
 178                addattr_l(n, MAX_MSG, TCA_SKBEDIT_MASK,
 179                          &mask, sizeof(mask));
 180        if (flags & SKBEDIT_F_PTYPE)
 181                addattr_l(n, MAX_MSG, TCA_SKBEDIT_PTYPE,
 182                          &ptype, sizeof(ptype));
 183        if (pure_flags != 0)
 184                addattr64(n, MAX_MSG, TCA_SKBEDIT_FLAGS, pure_flags);
 185        addattr_nest_end(n, tail);
 186
 187        *argc_p = argc;
 188        *argv_p = argv;
 189        return 0;
 190}
 191
 192static int print_skbedit(struct action_util *au, FILE *f, struct rtattr *arg)
 193{
 194        struct rtattr *tb[TCA_SKBEDIT_MAX + 1];
 195
 196        SPRINT_BUF(b1);
 197        __u32 priority;
 198        __u16 ptype;
 199        struct tc_skbedit *p;
 200
 201        print_string(PRINT_ANY, "kind", "%s ", "skbedit");
 202        if (arg == NULL)
 203                return 0;
 204
 205        parse_rtattr_nested(tb, TCA_SKBEDIT_MAX, arg);
 206
 207        if (tb[TCA_SKBEDIT_PARMS] == NULL) {
 208                fprintf(stderr, "Missing skbedit parameters\n");
 209                return -1;
 210        }
 211        p = RTA_DATA(tb[TCA_SKBEDIT_PARMS]);
 212
 213        if (tb[TCA_SKBEDIT_QUEUE_MAPPING] != NULL) {
 214                print_uint(PRINT_ANY, "queue_mapping", "queue_mapping %u",
 215                           rta_getattr_u16(tb[TCA_SKBEDIT_QUEUE_MAPPING]));
 216        }
 217        if (tb[TCA_SKBEDIT_PRIORITY] != NULL) {
 218                priority = rta_getattr_u32(tb[TCA_SKBEDIT_PRIORITY]);
 219                print_string(PRINT_ANY, "priority", " priority %s",
 220                             sprint_tc_classid(priority, b1));
 221        }
 222        if (tb[TCA_SKBEDIT_MARK] != NULL) {
 223                print_uint(PRINT_ANY, "mark", " mark %u",
 224                           rta_getattr_u32(tb[TCA_SKBEDIT_MARK]));
 225        }
 226        if (tb[TCA_SKBEDIT_MASK]) {
 227                print_hex(PRINT_ANY, "mask", "/%#x",
 228                          rta_getattr_u32(tb[TCA_SKBEDIT_MASK]));
 229        }
 230        if (tb[TCA_SKBEDIT_PTYPE] != NULL) {
 231                ptype = rta_getattr_u16(tb[TCA_SKBEDIT_PTYPE]);
 232                if (ptype == PACKET_HOST)
 233                        print_string(PRINT_ANY, "ptype", " ptype %s", "host");
 234                else if (ptype == PACKET_BROADCAST)
 235                        print_string(PRINT_ANY, "ptype", " ptype %s",
 236                                     "broadcast");
 237                else if (ptype == PACKET_MULTICAST)
 238                        print_string(PRINT_ANY, "ptype", " ptype %s",
 239                                     "multicast");
 240                else if (ptype == PACKET_OTHERHOST)
 241                        print_string(PRINT_ANY, "ptype", " ptype %s",
 242                                     "otherhost");
 243                else
 244                        print_uint(PRINT_ANY, "ptype", " ptype %u", ptype);
 245        }
 246        if (tb[TCA_SKBEDIT_FLAGS] != NULL) {
 247                __u64 flags = rta_getattr_u64(tb[TCA_SKBEDIT_FLAGS]);
 248
 249                if (flags & SKBEDIT_F_INHERITDSFIELD)
 250                        print_null(PRINT_ANY, "inheritdsfield", " %s",
 251                                     "inheritdsfield");
 252        }
 253
 254        print_action_control(f, " ", p->action, "");
 255
 256        print_nl();
 257        print_uint(PRINT_ANY, "index", "\t index %u", p->index);
 258        print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
 259        print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
 260
 261        if (show_stats) {
 262                if (tb[TCA_SKBEDIT_TM]) {
 263                        struct tcf_t *tm = RTA_DATA(tb[TCA_SKBEDIT_TM]);
 264
 265                        print_tm(f, tm);
 266                }
 267        }
 268
 269        print_nl();
 270
 271        return 0;
 272}
 273
 274struct action_util skbedit_action_util = {
 275        .id = "skbedit",
 276        .parse_aopt = parse_skbedit,
 277        .print_aopt = print_skbedit,
 278};
 279