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

387 lines
10 KiB
C

/*
* iplink_geneve.c GENEVE 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: John W. Linville <linville@tuxdriver.com>
*/
#include <stdio.h>
#include "rt_names.h"
#include "utils.h"
#include "ip_common.h"
#define GENEVE_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0)
static void print_explain(FILE *f)
{
fprintf(f,
"Usage: ... geneve id VNI\n"
" remote ADDR\n"
" [ ttl TTL ]\n"
" [ tos TOS ]\n"
" [ df DF ]\n"
" [ flowlabel LABEL ]\n"
" [ dstport PORT ]\n"
" [ [no]external ]\n"
" [ [no]udpcsum ]\n"
" [ [no]udp6zerocsumtx ]\n"
" [ [no]udp6zerocsumrx ]\n"
"\n"
"Where: VNI := 0-16777215\n"
" ADDR := IP_ADDRESS\n"
" TOS := { NUMBER | inherit }\n"
" TTL := { 1..255 | auto | inherit }\n"
" DF := { unset | set | inherit }\n"
" LABEL := 0-1048575\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static void check_duparg(__u64 *attrs, int type, const char *key,
const char *argv)
{
if (!GENEVE_ATTRSET(*attrs, type)) {
*attrs |= (1L << type);
return;
}
duparg2(key, argv);
}
static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
inet_prefix daddr;
__u32 vni = 0;
__u32 label = 0;
__u8 ttl = 0;
__u8 tos = 0;
__u16 dstport = 0;
bool metadata = 0;
__u8 udpcsum = 0;
__u8 udp6zerocsumtx = 0;
__u8 udp6zerocsumrx = 0;
__u64 attrs = 0;
bool set_op = (n->nlmsg_type == RTM_NEWLINK &&
!(n->nlmsg_flags & NLM_F_CREATE));
inet_prefix_reset(&daddr);
while (argc > 0) {
if (!matches(*argv, "id") ||
!matches(*argv, "vni")) {
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_ID, "id", *argv);
if (get_u32(&vni, *argv, 0) ||
vni >= 1u << 24)
invarg("invalid id", *argv);
} else if (!matches(*argv, "remote")) {
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_REMOTE, "remote",
*argv);
get_addr(&daddr, *argv, AF_UNSPEC);
if (!is_addrtype_inet_not_multi(&daddr))
invarg("invalid remote address", *argv);
} else if (!matches(*argv, "ttl") ||
!matches(*argv, "hoplimit")) {
unsigned int uval;
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_TTL, "ttl", *argv);
if (strcmp(*argv, "inherit") == 0) {
addattr8(n, 1024, IFLA_GENEVE_TTL_INHERIT, 1);
} else if (strcmp(*argv, "auto") != 0) {
if (get_unsigned(&uval, *argv, 0))
invarg("invalid TTL", *argv);
if (uval > 255)
invarg("TTL must be <= 255", *argv);
ttl = uval;
}
} else if (!matches(*argv, "tos") ||
!matches(*argv, "dsfield")) {
__u32 uval;
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_TOS, "tos", *argv);
if (strcmp(*argv, "inherit") != 0) {
if (rtnl_dsfield_a2n(&uval, *argv))
invarg("bad TOS value", *argv);
tos = uval;
} else
tos = 1;
} else if (!matches(*argv, "df")) {
enum ifla_geneve_df df;
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_DF, "df", *argv);
if (strcmp(*argv, "unset") == 0)
df = GENEVE_DF_UNSET;
else if (strcmp(*argv, "set") == 0)
df = GENEVE_DF_SET;
else if (strcmp(*argv, "inherit") == 0)
df = GENEVE_DF_INHERIT;
else
invarg("DF must be 'unset', 'set' or 'inherit'",
*argv);
addattr8(n, 1024, IFLA_GENEVE_DF, df);
} else if (!matches(*argv, "label") ||
!matches(*argv, "flowlabel")) {
__u32 uval;
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_LABEL, "flowlabel",
*argv);
if (get_u32(&uval, *argv, 0) ||
(uval & ~LABEL_MAX_MASK))
invarg("invalid flowlabel", *argv);
label = htonl(uval);
} else if (!matches(*argv, "dstport")) {
NEXT_ARG();
check_duparg(&attrs, IFLA_GENEVE_PORT, "dstport",
*argv);
if (get_u16(&dstport, *argv, 0))
invarg("dstport", *argv);
} else if (!matches(*argv, "external")) {
check_duparg(&attrs, IFLA_GENEVE_COLLECT_METADATA,
*argv, *argv);
metadata = true;
} else if (!matches(*argv, "noexternal")) {
check_duparg(&attrs, IFLA_GENEVE_COLLECT_METADATA,
*argv, *argv);
metadata = false;
} else if (!matches(*argv, "udpcsum")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_CSUM, *argv,
*argv);
udpcsum = 1;
} else if (!matches(*argv, "noudpcsum")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_CSUM, *argv,
*argv);
udpcsum = 0;
} else if (!matches(*argv, "udp6zerocsumtx")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
*argv, *argv);
udp6zerocsumtx = 1;
} else if (!matches(*argv, "noudp6zerocsumtx")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_TX,
*argv, *argv);
udp6zerocsumtx = 0;
} else if (!matches(*argv, "udp6zerocsumrx")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
*argv, *argv);
udp6zerocsumrx = 1;
} else if (!matches(*argv, "noudp6zerocsumrx")) {
check_duparg(&attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
*argv, *argv);
udp6zerocsumrx = 0;
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "geneve: unknown command \"%s\"?\n", *argv);
explain();
return -1;
}
argc--, argv++;
}
if (metadata && GENEVE_ATTRSET(attrs, IFLA_GENEVE_ID)) {
fprintf(stderr, "geneve: both 'external' and vni cannot be specified\n");
return -1;
}
if (!metadata) {
/* parameter checking make sense only for full geneve tunnels */
if (!GENEVE_ATTRSET(attrs, IFLA_GENEVE_ID)) {
fprintf(stderr, "geneve: missing virtual network identifier\n");
return -1;
}
/* If we are modifying the geneve device, then we only need the
* ID (VNI) to identify the geneve device, and we do not need
* the remote IP.
*/
if (!set_op && !is_addrtype_inet(&daddr)) {
fprintf(stderr, "geneve: remote link partner not specified\n");
return -1;
}
}
addattr32(n, 1024, IFLA_GENEVE_ID, vni);
if (is_addrtype_inet(&daddr)) {
int type = (daddr.family == AF_INET) ? IFLA_GENEVE_REMOTE :
IFLA_GENEVE_REMOTE6;
addattr_l(n, 1024, type, daddr.data, daddr.bytelen);
}
if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_LABEL))
addattr32(n, 1024, IFLA_GENEVE_LABEL, label);
if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_TTL))
addattr8(n, 1024, IFLA_GENEVE_TTL, ttl);
if (!set_op || GENEVE_ATTRSET(attrs, IFLA_GENEVE_TOS))
addattr8(n, 1024, IFLA_GENEVE_TOS, tos);
if (dstport)
addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport));
if (metadata)
addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA);
if (GENEVE_ATTRSET(attrs, IFLA_GENEVE_UDP_CSUM))
addattr8(n, 1024, IFLA_GENEVE_UDP_CSUM, udpcsum);
if (GENEVE_ATTRSET(attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_TX))
addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_TX, udp6zerocsumtx);
if (GENEVE_ATTRSET(attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_RX))
addattr8(n, 1024, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, udp6zerocsumrx);
return 0;
}
static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 vni;
__u8 ttl = 0;
__u8 tos = 0;
if (!tb)
return;
if (tb[IFLA_GENEVE_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (!tb[IFLA_GENEVE_ID] ||
RTA_PAYLOAD(tb[IFLA_GENEVE_ID]) < sizeof(__u32))
return;
vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]);
print_uint(PRINT_ANY, "id", "id %u ", vni);
if (tb[IFLA_GENEVE_REMOTE]) {
__be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]);
if (addr)
print_string(PRINT_ANY,
"remote",
"remote %s ",
format_host(AF_INET, 4, &addr));
} else if (tb[IFLA_GENEVE_REMOTE6]) {
struct in6_addr addr;
memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
if (!IN6_IS_ADDR_MULTICAST(&addr))
print_string(PRINT_ANY,
"remote6",
"remote %s ",
format_host(AF_INET6,
sizeof(struct in6_addr),
&addr));
}
}
if (tb[IFLA_GENEVE_TTL_INHERIT] &&
rta_getattr_u8(tb[IFLA_GENEVE_TTL_INHERIT])) {
print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
} else if (tb[IFLA_GENEVE_TTL]) {
ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]);
if (is_json_context() || ttl)
print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl);
else
print_string(PRINT_FP, NULL, "ttl %s ", "auto");
}
if (tb[IFLA_GENEVE_TOS])
tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]);
if (tos) {
if (is_json_context() || tos != 1)
print_0xhex(PRINT_ANY, "tos", "tos %#llx ", tos);
else
print_string(PRINT_FP, NULL, "tos %s ", "inherit");
}
if (tb[IFLA_GENEVE_DF]) {
enum ifla_geneve_df df = rta_getattr_u8(tb[IFLA_GENEVE_DF]);
if (df == GENEVE_DF_UNSET)
print_string(PRINT_JSON, "df", "df %s ", "unset");
else if (df == GENEVE_DF_SET)
print_string(PRINT_ANY, "df", "df %s ", "set");
else if (df == GENEVE_DF_INHERIT)
print_string(PRINT_ANY, "df", "df %s ", "inherit");
}
if (tb[IFLA_GENEVE_LABEL]) {
__u32 label = rta_getattr_u32(tb[IFLA_GENEVE_LABEL]);
if (label)
print_0xhex(PRINT_ANY,
"label", "flowlabel %#llx ",
ntohl(label));
}
if (tb[IFLA_GENEVE_PORT])
print_uint(PRINT_ANY,
"port",
"dstport %u ",
rta_getattr_be16(tb[IFLA_GENEVE_PORT]));
if (tb[IFLA_GENEVE_UDP_CSUM]) {
if (is_json_context()) {
print_bool(PRINT_JSON,
"udp_csum",
NULL,
rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]));
} else {
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]))
fputs("no", f);
fputs("udpcsum ", f);
}
}
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) {
if (is_json_context()) {
print_bool(PRINT_JSON,
"udp_zero_csum6_tx",
NULL,
rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]));
} else {
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
fputs("no", f);
fputs("udp6zerocsumtx ", f);
}
}
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) {
if (is_json_context()) {
print_bool(PRINT_JSON,
"udp_zero_csum6_rx",
NULL,
rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]));
} else {
if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
fputs("no", f);
fputs("udp6zerocsumrx ", f);
}
}
}
static void geneve_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util geneve_link_util = {
.id = "geneve",
.maxattr = IFLA_GENEVE_MAX,
.parse_opt = geneve_parse_opt,
.print_opt = geneve_print_opt,
.print_help = geneve_print_help,
};