mirror_iproute2/ip/iplink_vlan.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

286 lines
7.1 KiB
C

/*
* iplink_vlan.c VLAN device support
*
* This program is free software; you can redistribute 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: Patrick McHardy <kaber@trash.net>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/if_vlan.h>
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
static void print_explain(FILE *f)
{
fprintf(f,
"Usage: ... vlan id VLANID\n"
" [ protocol VLANPROTO ]\n"
" [ reorder_hdr { on | off } ]\n"
" [ gvrp { on | off } ]\n"
" [ mvrp { on | off } ]\n"
" [ loose_binding { on | off } ]\n"
" [ bridge_binding { on | off } ]\n"
" [ ingress-qos-map QOS-MAP ]\n"
" [ egress-qos-map QOS-MAP ]\n"
"\n"
"VLANID := 0-4095\n"
"VLANPROTO: [ 802.1Q | 802.1ad ]\n"
"QOS-MAP := [ QOS-MAP ] QOS-MAPPING\n"
"QOS-MAPPING := FROM:TO\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static int on_off(const char *msg, const char *arg)
{
fprintf(stderr, "Error: argument of \"%s\" must be \"on\" or \"off\", not \"%s\"\n", msg, arg);
return -1;
}
static int vlan_parse_qos_map(int *argcp, char ***argvp, struct nlmsghdr *n,
int attrtype)
{
int argc = *argcp;
char **argv = *argvp;
struct ifla_vlan_qos_mapping m;
struct rtattr *tail;
tail = addattr_nest(n, 1024, attrtype);
while (argc > 0) {
char *colon = strchr(*argv, ':');
if (!colon)
break;
*colon = '\0';
if (get_u32(&m.from, *argv, 0))
return 1;
if (get_u32(&m.to, colon + 1, 0))
return 1;
argc--, argv++;
addattr_l(n, 1024, IFLA_VLAN_QOS_MAPPING, &m, sizeof(m));
}
addattr_nest_end(n, tail);
*argcp = argc;
*argvp = argv;
return 0;
}
static int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
struct ifla_vlan_flags flags = { 0 };
__u16 id, proto;
while (argc > 0) {
if (matches(*argv, "protocol") == 0) {
NEXT_ARG();
if (ll_proto_a2n(&proto, *argv))
invarg("protocol is invalid", *argv);
addattr_l(n, 1024, IFLA_VLAN_PROTOCOL, &proto, 2);
} else if (matches(*argv, "id") == 0) {
NEXT_ARG();
if (get_u16(&id, *argv, 0))
invarg("id is invalid", *argv);
addattr_l(n, 1024, IFLA_VLAN_ID, &id, 2);
} else if (matches(*argv, "reorder_hdr") == 0) {
NEXT_ARG();
flags.mask |= VLAN_FLAG_REORDER_HDR;
if (strcmp(*argv, "on") == 0)
flags.flags |= VLAN_FLAG_REORDER_HDR;
else if (strcmp(*argv, "off") == 0)
flags.flags &= ~VLAN_FLAG_REORDER_HDR;
else
return on_off("reorder_hdr", *argv);
} else if (matches(*argv, "gvrp") == 0) {
NEXT_ARG();
flags.mask |= VLAN_FLAG_GVRP;
if (strcmp(*argv, "on") == 0)
flags.flags |= VLAN_FLAG_GVRP;
else if (strcmp(*argv, "off") == 0)
flags.flags &= ~VLAN_FLAG_GVRP;
else
return on_off("gvrp", *argv);
} else if (matches(*argv, "mvrp") == 0) {
NEXT_ARG();
flags.mask |= VLAN_FLAG_MVRP;
if (strcmp(*argv, "on") == 0)
flags.flags |= VLAN_FLAG_MVRP;
else if (strcmp(*argv, "off") == 0)
flags.flags &= ~VLAN_FLAG_MVRP;
else
return on_off("mvrp", *argv);
} else if (matches(*argv, "loose_binding") == 0) {
NEXT_ARG();
flags.mask |= VLAN_FLAG_LOOSE_BINDING;
if (strcmp(*argv, "on") == 0)
flags.flags |= VLAN_FLAG_LOOSE_BINDING;
else if (strcmp(*argv, "off") == 0)
flags.flags &= ~VLAN_FLAG_LOOSE_BINDING;
else
return on_off("loose_binding", *argv);
} else if (matches(*argv, "bridge_binding") == 0) {
NEXT_ARG();
flags.mask |= VLAN_FLAG_BRIDGE_BINDING;
if (strcmp(*argv, "on") == 0)
flags.flags |= VLAN_FLAG_BRIDGE_BINDING;
else if (strcmp(*argv, "off") == 0)
flags.flags &= ~VLAN_FLAG_BRIDGE_BINDING;
else
return on_off("bridge_binding", *argv);
} else if (matches(*argv, "ingress-qos-map") == 0) {
NEXT_ARG();
if (vlan_parse_qos_map(&argc, &argv, n,
IFLA_VLAN_INGRESS_QOS))
invarg("invalid ingress-qos-map", *argv);
continue;
} else if (matches(*argv, "egress-qos-map") == 0) {
NEXT_ARG();
if (vlan_parse_qos_map(&argc, &argv, n,
IFLA_VLAN_EGRESS_QOS))
invarg("invalid egress-qos-map", *argv);
continue;
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "vlan: unknown command \"%s\"?\n", *argv);
explain();
return -1;
}
argc--, argv++;
}
if (flags.mask)
addattr_l(n, 1024, IFLA_VLAN_FLAGS, &flags, sizeof(flags));
return 0;
}
static void vlan_print_map(FILE *f,
const char *name_json,
const char *name_fp,
struct rtattr *attr)
{
struct ifla_vlan_qos_mapping *m;
struct rtattr *i;
int rem;
open_json_array(PRINT_JSON, name_json);
print_string(PRINT_FP, NULL, "\n %s { ", name_fp);
rem = RTA_PAYLOAD(attr);
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
m = RTA_DATA(i);
if (is_json_context()) {
open_json_object(NULL);
print_uint(PRINT_JSON, "from", NULL, m->from);
print_uint(PRINT_JSON, "to", NULL, m->to);
close_json_object();
} else {
fprintf(f, "%u:%u ", m->from, m->to);
}
}
close_json_array(PRINT_JSON, NULL);
print_string(PRINT_FP, NULL, "%s ", "}");
}
static void vlan_print_flags(FILE *fp, __u32 flags)
{
open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
#define _PF(f) if (flags & VLAN_FLAG_##f) { \
flags &= ~VLAN_FLAG_##f; \
print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
}
_PF(REORDER_HDR);
_PF(GVRP);
_PF(MVRP);
_PF(LOOSE_BINDING);
_PF(BRIDGE_BINDING);
#undef _PF
if (flags)
print_hex(PRINT_ANY, NULL, "%x", flags);
close_json_array(PRINT_ANY, "> ");
}
static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
struct ifla_vlan_flags *flags;
SPRINT_BUF(b1);
if (!tb)
return;
if (tb[IFLA_VLAN_PROTOCOL] &&
RTA_PAYLOAD(tb[IFLA_VLAN_PROTOCOL]) < sizeof(__u16))
return;
if (!tb[IFLA_VLAN_ID] ||
RTA_PAYLOAD(tb[IFLA_VLAN_ID]) < sizeof(__u16))
return;
if (tb[IFLA_VLAN_PROTOCOL])
print_string(PRINT_ANY,
"protocol",
"protocol %s ",
ll_proto_n2a(
rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
b1, sizeof(b1)));
else
print_string(PRINT_ANY, "protocol", "protocol %s ", "802.1q");
print_uint(PRINT_ANY,
"id",
"id %u ",
rta_getattr_u16(tb[IFLA_VLAN_ID]));
if (tb[IFLA_VLAN_FLAGS]) {
if (RTA_PAYLOAD(tb[IFLA_VLAN_FLAGS]) < sizeof(*flags))
return;
flags = RTA_DATA(tb[IFLA_VLAN_FLAGS]);
vlan_print_flags(f, flags->flags);
}
if (tb[IFLA_VLAN_INGRESS_QOS])
vlan_print_map(f,
"ingress_qos",
"ingress-qos-map",
tb[IFLA_VLAN_INGRESS_QOS]);
if (tb[IFLA_VLAN_EGRESS_QOS])
vlan_print_map(f,
"egress_qos",
"egress-qos-map",
tb[IFLA_VLAN_EGRESS_QOS]);
}
static void vlan_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util vlan_link_util = {
.id = "vlan",
.maxattr = IFLA_VLAN_MAX,
.parse_opt = vlan_parse_opt,
.print_opt = vlan_print_opt,
.print_help = vlan_print_help,
};