mirror_iproute2/tc/m_ife.c
Matteo Croce 8589eb4efd treewide: refactor help messages
Every tool in the iproute2 package have one or more function to show
an help message to the user. Some of these functions print the help
line by line with a series of printf call, e.g. ip/xfrm_state.c does
60 fprintf calls.
If we group all the calls to a single one and just concatenate strings,
we save a lot of libc calls and thus object size. The size difference
of the compiled binaries calculated with bloat-o-meter is:

        ip/ip:
        add/remove: 0/0 grow/shrink: 5/15 up/down: 103/-4796 (-4693)
        Total: Before=672591, After=667898, chg -0.70%
        ip/rtmon:
        add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-54 (-54)
        Total: Before=48879, After=48825, chg -0.11%
        tc/tc:
        add/remove: 0/2 grow/shrink: 31/10 up/down: 882/-6133 (-5251)
        Total: Before=351912, After=346661, chg -1.49%
        bridge/bridge:
        add/remove: 0/0 grow/shrink: 0/1 up/down: 0/-459 (-459)
        Total: Before=70502, After=70043, chg -0.65%
        misc/lnstat:
        add/remove: 0/1 grow/shrink: 1/0 up/down: 48/-486 (-438)
        Total: Before=9960, After=9522, chg -4.40%
        tipc/tipc:
        add/remove: 0/0 grow/shrink: 1/1 up/down: 18/-62 (-44)
        Total: Before=79182, After=79138, chg -0.06%

While at it, indent some strings which were starting at column 0,
and use tabs where possible, to have a consistent style across helps.

Signed-off-by: Matteo Croce <mcroce@redhat.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
2019-05-20 14:35:07 -07:00

337 lines
8.4 KiB
C

/*
* m_ife.c IFE actions module
*
* This program is free software; you can distribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Authors: J Hadi Salim (jhs@mojatatu.com)
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <linux/netdevice.h>
#include "rt_names.h"
#include "utils.h"
#include "tc_util.h"
#include <linux/tc_act/tc_ife.h>
static void ife_explain(void)
{
fprintf(stderr,
"Usage:... ife {decode|encode} [{ALLOW|USE} ATTR] [dst DMAC] [src SMAC] [type TYPE] [CONTROL] [index INDEX]\n"
"\tALLOW := Encode direction. Allows encoding specified metadata\n"
"\t\t e.g \"allow mark\"\n"
"\tUSE := Encode direction. Enforce Static encoding of specified metadata\n"
"\t\t e.g \"use mark 0x12\"\n"
"\tATTR := mark (32-bit), prio (32-bit), tcindex (16-bit)\n"
"\tDMAC := 6 byte Destination MAC address to encode\n"
"\tSMAC := optional 6 byte Source MAC address to encode\n"
"\tTYPE := optional 16 bit ethertype to encode\n"
"\tCONTROL := reclassify|pipe|drop|continue|ok\n"
"\tINDEX := optional IFE table index value used\n"
"encode is used for sending IFE packets\n"
"decode is used for receiving IFE packets\n");
}
static void ife_usage(void)
{
ife_explain();
exit(-1);
}
static int parse_ife(struct action_util *a, int *argc_p, char ***argv_p,
int tca_id, struct nlmsghdr *n)
{
int argc = *argc_p;
char **argv = *argv_p;
int ok = 0;
struct tc_ife p = { 0 };
struct rtattr *tail;
struct rtattr *tail2;
char dbuf[ETH_ALEN];
char sbuf[ETH_ALEN];
__u16 ife_type = 0;
int user_type = 0;
__u32 ife_prio = 0;
__u32 ife_prio_v = 0;
__u32 ife_mark = 0;
__u32 ife_mark_v = 0;
__u16 ife_tcindex = 0;
__u16 ife_tcindex_v = 0;
char *daddr = NULL;
char *saddr = NULL;
if (argc <= 0)
return -1;
while (argc > 0) {
if (matches(*argv, "ife") == 0) {
NEXT_ARG();
continue;
} else if (matches(*argv, "decode") == 0) {
p.flags = IFE_DECODE; /* readability aid */
ok++;
} else if (matches(*argv, "encode") == 0) {
p.flags = IFE_ENCODE;
ok++;
} else if (matches(*argv, "allow") == 0) {
NEXT_ARG();
if (matches(*argv, "mark") == 0) {
ife_mark = IFE_META_SKBMARK;
} else if (matches(*argv, "prio") == 0) {
ife_prio = IFE_META_PRIO;
} else if (matches(*argv, "tcindex") == 0) {
ife_tcindex = IFE_META_TCINDEX;
} else {
invarg("Illegal meta define", *argv);
}
} else if (matches(*argv, "use") == 0) {
NEXT_ARG();
if (matches(*argv, "mark") == 0) {
NEXT_ARG();
if (get_u32(&ife_mark_v, *argv, 0))
invarg("ife mark val is invalid",
*argv);
} else if (matches(*argv, "prio") == 0) {
NEXT_ARG();
if (get_u32(&ife_prio_v, *argv, 0))
invarg("ife prio val is invalid",
*argv);
} else if (matches(*argv, "tcindex") == 0) {
NEXT_ARG();
if (get_u16(&ife_tcindex_v, *argv, 0))
invarg("ife tcindex val is invalid",
*argv);
} else {
invarg("Illegal meta use type", *argv);
}
} else if (matches(*argv, "type") == 0) {
NEXT_ARG();
if (get_u16(&ife_type, *argv, 0))
invarg("ife type is invalid", *argv);
fprintf(stderr, "IFE type 0x%04X\n", ife_type);
user_type = 1;
} else if (matches(*argv, "dst") == 0) {
NEXT_ARG();
daddr = *argv;
if (sscanf(daddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
dbuf, dbuf + 1, dbuf + 2,
dbuf + 3, dbuf + 4, dbuf + 5) != 6) {
invarg("Invalid mac address", *argv);
}
fprintf(stderr, "dst MAC address <%s>\n", daddr);
} else if (matches(*argv, "src") == 0) {
NEXT_ARG();
saddr = *argv;
if (sscanf(saddr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx",
sbuf, sbuf + 1, sbuf + 2,
sbuf + 3, sbuf + 4, sbuf + 5) != 6) {
invarg("Invalid mac address", *argv);
}
fprintf(stderr, "src MAC address <%s>\n", saddr);
} else if (matches(*argv, "help") == 0) {
ife_usage();
} else {
break;
}
argc--;
argv++;
}
parse_action_control_dflt(&argc, &argv, &p.action, false, TC_ACT_PIPE);
if (argc) {
if (matches(*argv, "index") == 0) {
NEXT_ARG();
if (get_u32(&p.index, *argv, 0)) {
fprintf(stderr, "ife: Illegal \"index\"\n");
return -1;
}
ok++;
argc--;
argv++;
}
}
if (!ok) {
fprintf(stderr, "IFE requires decode/encode specified\n");
ife_usage();
}
tail = addattr_nest(n, MAX_MSG, tca_id);
addattr_l(n, MAX_MSG, TCA_IFE_PARMS, &p, sizeof(p));
if (!(p.flags & IFE_ENCODE))
goto skip_encode;
if (daddr)
addattr_l(n, MAX_MSG, TCA_IFE_DMAC, dbuf, ETH_ALEN);
if (user_type)
addattr_l(n, MAX_MSG, TCA_IFE_TYPE, &ife_type, 2);
else
fprintf(stderr, "IFE type 0x%04X\n", ETH_P_IFE);
if (saddr)
addattr_l(n, MAX_MSG, TCA_IFE_SMAC, sbuf, ETH_ALEN);
tail2 = addattr_nest(n, MAX_MSG, TCA_IFE_METALST);
if (ife_mark || ife_mark_v) {
if (ife_mark_v)
addattr_l(n, MAX_MSG, IFE_META_SKBMARK, &ife_mark_v, 4);
else
addattr_l(n, MAX_MSG, IFE_META_SKBMARK, NULL, 0);
}
if (ife_prio || ife_prio_v) {
if (ife_prio_v)
addattr_l(n, MAX_MSG, IFE_META_PRIO, &ife_prio_v, 4);
else
addattr_l(n, MAX_MSG, IFE_META_PRIO, NULL, 0);
}
if (ife_tcindex || ife_tcindex_v) {
if (ife_tcindex_v)
addattr_l(n, MAX_MSG, IFE_META_TCINDEX, &ife_tcindex_v,
2);
else
addattr_l(n, MAX_MSG, IFE_META_TCINDEX, NULL, 0);
}
addattr_nest_end(n, tail2);
skip_encode:
addattr_nest_end(n, tail);
*argc_p = argc;
*argv_p = argv;
return 0;
}
static int print_ife(struct action_util *au, FILE *f, struct rtattr *arg)
{
struct tc_ife *p = NULL;
struct rtattr *tb[TCA_IFE_MAX + 1];
__u16 ife_type = 0;
__u32 mmark = 0;
__u16 mtcindex = 0;
__u32 mprio = 0;
int has_optional = 0;
SPRINT_BUF(b2);
if (arg == NULL)
return -1;
parse_rtattr_nested(tb, TCA_IFE_MAX, arg);
if (tb[TCA_IFE_PARMS] == NULL) {
print_string(PRINT_FP, NULL, "%s", "[NULL ife parameters]");
return -1;
}
p = RTA_DATA(tb[TCA_IFE_PARMS]);
print_string(PRINT_ANY, "kind", "%s ", "ife");
print_string(PRINT_ANY, "mode", "%s ",
p->flags & IFE_ENCODE ? "encode" : "decode");
print_action_control(f, "action ", p->action, " ");
if (tb[TCA_IFE_TYPE]) {
ife_type = rta_getattr_u16(tb[TCA_IFE_TYPE]);
has_optional = 1;
print_0xhex(PRINT_ANY, "type", "type %#llX ", ife_type);
}
if (has_optional)
print_string(PRINT_FP, NULL, "%s\t", _SL_);
if (tb[TCA_IFE_METALST]) {
struct rtattr *metalist[IFE_META_MAX + 1];
int len = 0;
parse_rtattr_nested(metalist, IFE_META_MAX,
tb[TCA_IFE_METALST]);
if (metalist[IFE_META_SKBMARK]) {
len = RTA_PAYLOAD(metalist[IFE_META_SKBMARK]);
if (len) {
mmark = rta_getattr_u32(metalist[IFE_META_SKBMARK]);
print_uint(PRINT_ANY, "mark", "use mark %u ",
mmark);
} else
print_string(PRINT_ANY, "mark", "%s mark ",
"allow");
}
if (metalist[IFE_META_TCINDEX]) {
len = RTA_PAYLOAD(metalist[IFE_META_TCINDEX]);
if (len) {
mtcindex =
rta_getattr_u16(metalist[IFE_META_TCINDEX]);
print_uint(PRINT_ANY, "tcindex",
"use tcindex %u ", mtcindex);
} else
print_string(PRINT_ANY, "tcindex",
"%s tcindex ", "allow");
}
if (metalist[IFE_META_PRIO]) {
len = RTA_PAYLOAD(metalist[IFE_META_PRIO]);
if (len) {
mprio = rta_getattr_u32(metalist[IFE_META_PRIO]);
print_uint(PRINT_ANY, "prio", "use prio %u ",
mprio);
} else
print_string(PRINT_ANY, "prio", "%s prio ",
"allow");
}
}
if (tb[TCA_IFE_DMAC]) {
has_optional = 1;
print_string(PRINT_ANY, "dst", "dst %s ",
ll_addr_n2a(RTA_DATA(tb[TCA_IFE_DMAC]),
RTA_PAYLOAD(tb[TCA_IFE_DMAC]), 0, b2,
sizeof(b2)));
}
if (tb[TCA_IFE_SMAC]) {
has_optional = 1;
print_string(PRINT_ANY, "src", "src %s ",
ll_addr_n2a(RTA_DATA(tb[TCA_IFE_SMAC]),
RTA_PAYLOAD(tb[TCA_IFE_SMAC]), 0, b2,
sizeof(b2)));
}
print_string(PRINT_FP, NULL, "%s", _SL_);
print_uint(PRINT_ANY, "index", "\t index %u", p->index);
print_int(PRINT_ANY, "ref", " ref %d", p->refcnt);
print_int(PRINT_ANY, "bind", " bind %d", p->bindcnt);
if (show_stats) {
if (tb[TCA_IFE_TM]) {
struct tcf_t *tm = RTA_DATA(tb[TCA_IFE_TM]);
print_tm(f, tm);
}
}
print_string(PRINT_FP, NULL, "%s", _SL_);
return 0;
}
struct action_util ife_action_util = {
.id = "ife",
.parse_aopt = parse_ife,
.print_aopt = print_ife,
};