diff options
author | Stephen Hemminger <stephen@networkplumber.org> | 2017-11-28 09:53:28 -0800 |
---|---|---|
committer | Stephen Hemminger <stephen@networkplumber.org> | 2017-11-28 09:53:28 -0800 |
commit | f6351157b94b3589e1bb1348bc114a465769f10f (patch) | |
tree | 0516bebc390b737ff85dcf3589e856367d7d3d8c | |
parent | b2a2d9530c889324f788d463893f0d457acb31da (diff) | |
parent | 615634c30e5b673367b6f31c527b227a37692beb (diff) | |
download | iproute2-f6351157b94b3589e1bb1348bc114a465769f10f.tar.gz |
Merge branch 'master' into net-next
144 files changed, 1134 insertions, 589 deletions
@@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 # Top level Makefile for iproute2 ifeq ($(VERBOSE),0) diff --git a/bridge/Makefile b/bridge/Makefile index b2ae0a4e..c6b7d08d 100644 --- a/bridge/Makefile +++ b/bridge/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o include ../config.mk diff --git a/bridge/br_common.h b/bridge/br_common.h index 01447ddc..f07c7d1c 100644 --- a/bridge/br_common.h +++ b/bridge/br_common.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + #define MDB_RTA(r) \ ((struct rtattr *)(((char *)(r)) + RTA_ALIGN(sizeof(struct br_mdb_entry)))) diff --git a/bridge/bridge.c b/bridge/bridge.c index 6658cb8f..48fe1c8b 100644 --- a/bridge/bridge.c +++ b/bridge/bridge.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Get/set/delete bridge with netlink * diff --git a/bridge/fdb.c b/bridge/fdb.c index 1ab1fb71..376713b6 100644 --- a/bridge/fdb.c +++ b/bridge/fdb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Get/set/delete fdb table with netlink * diff --git a/bridge/link.c b/bridge/link.c index 65ca47e1..e2371d0d 100644 --- a/bridge/link.c +++ b/bridge/link.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/bridge/mdb.c b/bridge/mdb.c index f38e326e..7b7b81f4 100644 --- a/bridge/mdb.c +++ b/bridge/mdb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Get mdb table with netlink */ diff --git a/bridge/vlan.c b/bridge/vlan.c index 0f78a9e8..69fb5425 100644 --- a/bridge/vlan.c +++ b/bridge/vlan.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -1,4 +1,5 @@ #! /bin/bash +# SPDX-License-Identifier: GPL-2.0 # This is not an autoconf generated configure # INCLUDE=${1:-"$PWD/include"} diff --git a/devlink/Makefile b/devlink/Makefile index 3b2067d6..3afda65e 100644 --- a/devlink/Makefile +++ b/devlink/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include ../config.mk ifeq ($(HAVE_MNL),y) diff --git a/examples/bpf/bpf_tailcall.c b/examples/bpf/bpf_tailcall.c index 1a30426c..161eb606 100644 --- a/examples/bpf/bpf_tailcall.c +++ b/examples/bpf/bpf_tailcall.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include "../../include/bpf_api.h" #define ENTRY_INIT 3 diff --git a/genl/Makefile b/genl/Makefile index de1635e4..2b7a45b6 100644 --- a/genl/Makefile +++ b/genl/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 GENLOBJ=genl.o include ../config.mk diff --git a/genl/genl_utils.h b/genl/genl_utils.h index 85b51830..6e6f4450 100644 --- a/genl/genl_utils.h +++ b/genl/genl_utils.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TC_UTIL_H_ #define _TC_UTIL_H_ 1 diff --git a/genl/static-syms.c b/genl/static-syms.c index 0bc80743..47c4092c 100644 --- a/genl/static-syms.c +++ b/genl/static-syms.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This file creates a dummy version of dynamic loading * for environments where dynamic linking diff --git a/include/bpf_api.h b/include/bpf_api.h index d1324719..89d3488d 100644 --- a/include/bpf_api.h +++ b/include/bpf_api.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __BPF_API__ #define __BPF_API__ diff --git a/include/bpf_elf.h b/include/bpf_elf.h index 406c3087..a8e360f3 100644 --- a/include/bpf_elf.h +++ b/include/bpf_elf.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __BPF_ELF__ #define __BPF_ELF__ diff --git a/include/bpf_scm.h b/include/bpf_scm.h index 122d59fc..669f0538 100644 --- a/include/bpf_scm.h +++ b/include/bpf_scm.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __BPF_SCM__ #define __BPF_SCM__ diff --git a/include/bpf_util.h b/include/bpf_util.h index e818221d..219beb40 100644 --- a/include/bpf_util.h +++ b/include/bpf_util.h @@ -56,13 +56,29 @@ struct bpf_cfg_ops { void (*ebpf_cb)(void *nl, int fd, const char *annotation); }; +enum bpf_mode { + CBPF_BYTECODE, + CBPF_FILE, + EBPF_OBJECT, + EBPF_PINNED, + BPF_MODE_MAX, +}; + struct bpf_cfg_in { const char *object; const char *section; const char *uds; + enum bpf_prog_type type; + enum bpf_mode mode; + __u32 ifindex; + bool verbose; int argc; char **argv; - struct sock_filter *ops; + struct sock_filter opcodes[BPF_MAXINSNS]; + union { + int n_opcodes; + int prog_fd; + }; }; /* ALU ops on registers, bpf_add|sub|...: dst_reg += src_reg */ @@ -244,8 +260,11 @@ struct bpf_cfg_in { .off = 0, \ .imm = 0 }) -int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg, - const struct bpf_cfg_ops *ops, void *nl); +int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops); +int bpf_load_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops, + void *nl); +int bpf_parse_and_load_common(struct bpf_cfg_in *cfg, + const struct bpf_cfg_ops *ops, void *nl); const char *bpf_prog_to_default_section(enum bpf_prog_type type); diff --git a/include/color.h b/include/color.h index 7fd685d0..f6c351b7 100644 --- a/include/color.h +++ b/include/color.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __COLOR_H__ #define __COLOR_H__ 1 diff --git a/include/dlfcn.h b/include/dlfcn.h index f15bc2c7..1d8890ad 100644 --- a/include/dlfcn.h +++ b/include/dlfcn.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * Stub dlfcn implementation for systems that lack shared library support * but obviously can still reference compiled-in symbols. diff --git a/include/ip6tables.h b/include/ip6tables.h index 5f1c5b65..bfb28682 100644 --- a/include/ip6tables.h +++ b/include/ip6tables.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IP6TABLES_USER_H #define _IP6TABLES_USER_H diff --git a/include/iptables.h b/include/iptables.h index 78c10abd..78bc378e 100644 --- a/include/iptables.h +++ b/include/iptables.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IPTABLES_USER_H #define _IPTABLES_USER_H diff --git a/include/iptables/internal.h b/include/iptables/internal.h index 62a8ecb9..1fd13725 100644 --- a/include/iptables/internal.h +++ b/include/iptables/internal.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef IPTABLES_INTERNAL_H #define IPTABLES_INTERNAL_H 1 diff --git a/include/libgenl.h b/include/libgenl.h index 2dbb4b36..cd13f476 100644 --- a/include/libgenl.h +++ b/include/libgenl.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LIBGENL_H__ #define __LIBGENL_H__ diff --git a/include/libiptc/ipt_kernel_headers.h b/include/libiptc/ipt_kernel_headers.h index a5963e94..3d2a2a32 100644 --- a/include/libiptc/ipt_kernel_headers.h +++ b/include/libiptc/ipt_kernel_headers.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* This is the userspace/kernel interface for Generic IP Chains, required for libc6. */ #ifndef _FWCHAINS_KERNEL_HEADERS_H diff --git a/include/libiptc/libip6tc.h b/include/libiptc/libip6tc.h index 9aed80a0..cd588de7 100644 --- a/include/libiptc/libip6tc.h +++ b/include/libiptc/libip6tc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LIBIP6TC_H #define _LIBIP6TC_H /* Library which manipulates firewall rules. Version 0.2. */ diff --git a/include/libiptc/libiptc.h b/include/libiptc/libiptc.h index 24cdbdb7..1bfe4e18 100644 --- a/include/libiptc/libiptc.h +++ b/include/libiptc/libiptc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LIBIPTC_H #define _LIBIPTC_H /* Library which manipulates filtering rules. */ diff --git a/include/libiptc/libxtc.h b/include/libiptc/libxtc.h index 37010188..1e9596a6 100644 --- a/include/libiptc/libxtc.h +++ b/include/libiptc/libxtc.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LIBXTC_H #define _LIBXTC_H /* Library which manipulates filtering rules. */ diff --git a/include/libiptc/xtcshared.h b/include/libiptc/xtcshared.h index 773ebc4c..278a58f4 100644 --- a/include/libiptc/xtcshared.h +++ b/include/libiptc/xtcshared.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LIBXTC_SHARED_H #define _LIBXTC_SHARED_H 1 diff --git a/include/libnetlink.h b/include/libnetlink.h index 77b62605..a4d83b9e 100644 --- a/include/libnetlink.h +++ b/include/libnetlink.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LIBNETLINK_H__ #define __LIBNETLINK_H__ 1 diff --git a/include/list.h b/include/list.h index 5b529dc6..5af737c7 100644 --- a/include/list.h +++ b/include/list.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LIST_H__ #define __LIST_H__ 1 /* List and hash list stuff from kernel */ diff --git a/include/ll_map.h b/include/ll_map.h index 949bfc3e..c8474e6e 100644 --- a/include/ll_map.h +++ b/include/ll_map.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LL_MAP_H__ #define __LL_MAP_H__ 1 diff --git a/include/names.h b/include/names.h index 6fed5818..3e5d3b14 100644 --- a/include/names.h +++ b/include/names.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef DB_NAMES_H_ #define DB_NAMES_H_ 1 diff --git a/include/namespace.h b/include/namespace.h index 51324b21..aed7ce08 100644 --- a/include/namespace.h +++ b/include/namespace.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __NAMESPACE_H__ #define __NAMESPACE_H__ 1 diff --git a/include/rt_names.h b/include/rt_names.h index 921be060..62ebbd6a 100644 --- a/include/rt_names.h +++ b/include/rt_names.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef RT_NAMES_H_ #define RT_NAMES_H_ 1 diff --git a/include/rtm_map.h b/include/rtm_map.h index d6e5885c..f85e52c4 100644 --- a/include/rtm_map.h +++ b/include/rtm_map.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __RTM_MAP_H__ #define __RTM_MAP_H__ 1 diff --git a/include/utils.h b/include/utils.h index 10749fbe..d3895d56 100644 --- a/include/utils.h +++ b/include/utils.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __UTILS_H__ #define __UTILS_H__ 1 @@ -88,6 +89,8 @@ int get_prefix(inet_prefix *dst, char *arg, int family); int mask2bits(__u32 netmask); int get_addr_ila(__u64 *val, const char *arg); +int read_prop(const char *dev, char *prop, long *value); +int parse_percent(double *val, const char *str); int get_hex(char c); int get_integer(int *val, const char *arg, int base); int get_unsigned(unsigned *val, const char *arg, int base); diff --git a/include/xt-internal.h b/include/xt-internal.h index b8ea67da..89c73e4f 100644 --- a/include/xt-internal.h +++ b/include/xt-internal.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _XTABLES_INTERNAL_H #define _XTABLES_INTERNAL_H 1 diff --git a/include/xtables.h b/include/xtables.h index 978ae0d1..b48c3166 100644 --- a/include/xtables.h +++ b/include/xtables.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _XTABLES_H #define _XTABLES_H diff --git a/ip/Makefile b/ip/Makefile index 5a1c7ad2..a653c1bd 100644 --- a/ip/Makefile +++ b/ip/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \ rtm_map.o iptunnel.o ip6tunnel.o tunnel.o ipneigh.o ipntable.o iplink.o \ ipmaddr.o ipmonitor.o ipmroute.o ipprefix.o iptuntap.o iptoken.o \ @@ -1,4 +1,5 @@ #! /bin/bash +# SPDX-License-Identifier: GPL-2.0 CheckForwarding () { local sbase fwd diff --git a/ip/ila_common.h b/ip/ila_common.h index 04c6c2ed..f99c2672 100644 --- a/ip/ila_common.h +++ b/ip/ila_common.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ILA_COMMON_H_ #define _ILA_COMMON_H_ diff --git a/ip/ip_common.h b/ip/ip_common.h index 4b8b0a71..3203f0cd 100644 --- a/ip/ip_common.h +++ b/ip/ip_common.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _IP_COMMON_H_ #define _IP_COMMON_H_ diff --git a/ip/iplink.c b/ip/iplink.c index 2c51ef7d..0a8eb56f 100644 --- a/ip/iplink.c +++ b/ip/iplink.c @@ -631,8 +631,8 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, bool offload = strcmp(*argv, "xdpoffload") == 0; NEXT_ARG(); - if (xdp_parse(&argc, &argv, req, generic, drv, - offload)) + if (xdp_parse(&argc, &argv, req, dev_index, + generic, drv, offload)) exit(-1); } else if (strcmp(*argv, "netns") == 0) { NEXT_ARG(); diff --git a/ip/iplink_dummy.c b/ip/iplink_dummy.c index cf78ea5b..cba22955 100644 --- a/ip/iplink_dummy.c +++ b/ip/iplink_dummy.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/ip/iplink_ifb.c b/ip/iplink_ifb.c index d7dc8f98..a2a7301f 100644 --- a/ip/iplink_ifb.c +++ b/ip/iplink_ifb.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/ip/iplink_nlmon.c b/ip/iplink_nlmon.c index 51d5919a..6ffb9101 100644 --- a/ip/iplink_nlmon.c +++ b/ip/iplink_nlmon.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/ip/iplink_team.c b/ip/iplink_team.c index 6225268d..58f955a4 100644 --- a/ip/iplink_team.c +++ b/ip/iplink_team.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/ip/iplink_vcan.c b/ip/iplink_vcan.c index b7ae15f0..74a1505b 100644 --- a/ip/iplink_vcan.c +++ b/ip/iplink_vcan.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdlib.h> diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c index a0530dda..661eaa79 100644 --- a/ip/iplink_vxlan.c +++ b/ip/iplink_vxlan.c @@ -345,7 +345,7 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, return -1; } - if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) { + if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID) && !set_op) { fprintf(stderr, "vxlan: missing virtual network identifier\n"); return -1; } @@ -367,7 +367,8 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, "Use 'dstport 0' to get default and quiet this message\n"); } - addattr32(n, 1024, IFLA_VXLAN_ID, vni); + if (VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) + addattr32(n, 1024, IFLA_VXLAN_ID, vni); if (gaddr) addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4); else if (daddr) diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c index 2d2953aa..6eeb820a 100644 --- a/ip/iplink_xdp.c +++ b/ip/iplink_xdp.c @@ -48,10 +48,11 @@ static int xdp_delete(struct xdp_req *xdp) return 0; } -int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic, - bool drv, bool offload) +int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex, + bool generic, bool drv, bool offload) { struct bpf_cfg_in cfg = { + .type = BPF_PROG_TYPE_XDP, .argc = *argc, .argv = *argv, }; @@ -59,6 +60,12 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic, .req = req, }; + if (offload) { + if (!ifindex) + incomplete_command(); + cfg.ifindex = ifindex; + } + if (!force) xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST; if (generic) @@ -74,7 +81,7 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic, return xdp_delete(&xdp); } - if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp)) + if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &xdp)) return -1; *argc = cfg.argc; diff --git a/ip/ipnetns.c b/ip/ipnetns.c index 1fa53986..059a4220 100644 --- a/ip/ipnetns.c +++ b/ip/ipnetns.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define _ATFILE_SOURCE #include <sys/types.h> #include <sys/stat.h> diff --git a/ip/iproute_lwtunnel.c b/ip/iproute_lwtunnel.c index 27266171..740da7c6 100644 --- a/ip/iproute_lwtunnel.c +++ b/ip/iproute_lwtunnel.c @@ -886,6 +886,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len, int attr, const enum bpf_prog_type bpf_type) { struct bpf_cfg_in cfg = { + .type = bpf_type, .argc = *argcp, .argv = *argvp, }; @@ -897,7 +898,7 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len, int err; nest = rta_nest(rta, len, attr); - err = bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, &x); + err = bpf_parse_and_load_common(&cfg, &bpf_cb_ops, &x); if (err < 0) { fprintf(stderr, "Failed to parse eBPF program: %s\n", strerror(-err)); diff --git a/ip/iproute_lwtunnel.h b/ip/iproute_lwtunnel.h index b82b58ad..be003cea 100644 --- a/ip/iproute_lwtunnel.h +++ b/ip/iproute_lwtunnel.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __LWTUNNEL_H__ #define __LETUNNEL_H__ 1 diff --git a/ip/iptuntap.c b/ip/iptuntap.c index b46e452f..09f2be24 100644 --- a/ip/iptuntap.c +++ b/ip/iptuntap.c @@ -223,38 +223,6 @@ static int do_del(int argc, char **argv) return tap_del_ioctl(&ifr); } -static int read_prop(char *dev, char *prop, long *value) -{ - char fname[IFNAMSIZ+25], buf[80], *endp; - ssize_t len; - int fd; - long result; - - sprintf(fname, "/sys/class/net/%s/%s", dev, prop); - fd = open(fname, O_RDONLY); - if (fd < 0) { - if (strcmp(prop, "tun_flags")) - fprintf(stderr, "open %s: %s\n", fname, - strerror(errno)); - return -1; - } - len = read(fd, buf, sizeof(buf)-1); - close(fd); - if (len < 0) { - fprintf(stderr, "read %s: %s", fname, strerror(errno)); - return -1; - } - - buf[len] = 0; - result = strtol(buf, &endp, 0); - if (*endp != '\n') { - fprintf(stderr, "Failed to parse %s\n", fname); - return -1; - } - *value = result; - return 0; -} - static void print_flags(long flags) { if (flags & IFF_TUN) diff --git a/ip/link_gre.c b/ip/link_gre.c index 35782caa..43cb1af6 100644 --- a/ip/link_gre.c +++ b/ip/link_gre.c @@ -276,7 +276,8 @@ get_failed: if (uval > 255) invarg("TTL must be <= 255\n", *argv); ttl = uval; - } + } else + ttl = 0; } else if (!matches(*argv, "tos") || !matches(*argv, "tclass") || !matches(*argv, "dsfield")) { diff --git a/ip/link_gre6.c b/ip/link_gre6.c index 50c1b804..0a82eaec 100644 --- a/ip/link_gre6.c +++ b/ip/link_gre6.c @@ -372,7 +372,7 @@ get_failed: } else { __u8 uval; - if (get_u8(&uval, *argv, 0) < -1) + if (get_u8(&uval, *argv, 0)) invarg("invalid ELIM", *argv); encap_limit = uval; flags &= ~IP6_TNL_F_IGN_ENCAP_LIMIT; @@ -1,4 +1,5 @@ #! /bin/sh +# SPDX-License-Identifier: GPL-2.0 if [ -z "$*" ] ; then exec ip -4 ro flush scope global type unicast @@ -1,5 +1,5 @@ #!/bin/sh -#$Id$ +# SPDX-License-Identifier: GPL-2.0 # # Script created by: Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 @@ -1,4 +1,5 @@ #! /bin/bash +# SPDX-License-Identifier: GPL-2.0 exec tr "[\\\\]" "[ ]" diff --git a/ip/static-syms.c b/ip/static-syms.c index 0bc80743..47c4092c 100644 --- a/ip/static-syms.c +++ b/ip/static-syms.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This file creates a dummy version of dynamic loading * for environments where dynamic linking @@ -1,10 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __XDP__ #define __XDP__ #include "utils.h" -int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic, - bool drv, bool offload); +int xdp_parse(int *argc, char ***argv, struct iplink_req *req, __u32 ifindex, + bool generic, bool drv, bool offload); void xdp_dump(FILE *fp, struct rtattr *tb, bool link, bool details); #endif /* __XDP__ */ diff --git a/lib/Makefile b/lib/Makefile index 0fbdf4c3..7b34ed5f 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include ../config.mk CFLAGS += -fPIC @@ -113,10 +113,10 @@ const char *bpf_prog_to_default_section(enum bpf_prog_type type) #ifdef HAVE_ELF static int bpf_obj_open(const char *path, enum bpf_prog_type type, - const char *sec, bool verbose); + const char *sec, __u32 ifindex, bool verbose); #else static int bpf_obj_open(const char *path, enum bpf_prog_type type, - const char *sec, bool verbose) + const char *sec, __u32 ifindex, bool verbose) { fprintf(stderr, "No ELF library support compiled in.\n"); errno = ENOSYS; @@ -805,16 +805,7 @@ static int bpf_obj_pinned(const char *pathname, enum bpf_prog_type type) return prog_fd; } -enum bpf_mode { - CBPF_BYTECODE, - CBPF_FILE, - EBPF_OBJECT, - EBPF_PINNED, - BPF_MODE_MAX, -}; - -static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, - struct bpf_cfg_in *cfg, const bool *opt_tbl) +static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl) { const char *file, *section, *uds_name; bool verbose = false; @@ -827,20 +818,20 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, if (opt_tbl[CBPF_BYTECODE] && (matches(*argv, "bytecode") == 0 || strcmp(*argv, "bc") == 0)) { - *mode = CBPF_BYTECODE; + cfg->mode = CBPF_BYTECODE; } else if (opt_tbl[CBPF_FILE] && (matches(*argv, "bytecode-file") == 0 || strcmp(*argv, "bcf") == 0)) { - *mode = CBPF_FILE; + cfg->mode = CBPF_FILE; } else if (opt_tbl[EBPF_OBJECT] && (matches(*argv, "object-file") == 0 || strcmp(*argv, "obj") == 0)) { - *mode = EBPF_OBJECT; + cfg->mode = EBPF_OBJECT; } else if (opt_tbl[EBPF_PINNED] && (matches(*argv, "object-pinned") == 0 || matches(*argv, "pinned") == 0 || matches(*argv, "fd") == 0)) { - *mode = EBPF_PINNED; + cfg->mode = EBPF_PINNED; } else { fprintf(stderr, "What mode is \"%s\"?\n", *argv); return -1; @@ -848,11 +839,11 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, NEXT_ARG(); file = section = uds_name = NULL; - if (*mode == EBPF_OBJECT || *mode == EBPF_PINNED) { + if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) { file = *argv; NEXT_ARG_FWD(); - if (*type == BPF_PROG_TYPE_UNSPEC) { + if (cfg->type == BPF_PROG_TYPE_UNSPEC) { if (argc > 0 && matches(*argv, "type") == 0) { NEXT_ARG(); for (i = 0; i < ARRAY_SIZE(__bpf_prog_meta); @@ -861,30 +852,30 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, continue; if (!matches(*argv, __bpf_prog_meta[i].type)) { - *type = i; + cfg->type = i; break; } } - if (*type == BPF_PROG_TYPE_UNSPEC) { + if (cfg->type == BPF_PROG_TYPE_UNSPEC) { fprintf(stderr, "What type is \"%s\"?\n", *argv); return -1; } NEXT_ARG_FWD(); } else { - *type = BPF_PROG_TYPE_SCHED_CLS; + cfg->type = BPF_PROG_TYPE_SCHED_CLS; } } - section = bpf_prog_to_default_section(*type); + section = bpf_prog_to_default_section(cfg->type); if (argc > 0 && matches(*argv, "section") == 0) { NEXT_ARG(); section = *argv; NEXT_ARG_FWD(); } - if (__bpf_prog_meta[*type].may_uds_export) { + if (__bpf_prog_meta[cfg->type].may_uds_export) { uds_name = getenv(BPF_ENV_UDS); if (argc > 0 && !uds_name && matches(*argv, "export") == 0) { @@ -902,53 +893,63 @@ static int bpf_parse(enum bpf_prog_type *type, enum bpf_mode *mode, PREV_ARG(); } - if (*mode == CBPF_BYTECODE || *mode == CBPF_FILE) - ret = bpf_ops_parse(argc, argv, cfg->ops, *mode == CBPF_FILE); - else if (*mode == EBPF_OBJECT) - ret = bpf_obj_open(file, *type, section, verbose); - else if (*mode == EBPF_PINNED) - ret = bpf_obj_pinned(file, *type); - else + if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE) { + ret = bpf_ops_parse(argc, argv, cfg->opcodes, + cfg->mode == CBPF_FILE); + cfg->n_opcodes = ret; + } else if (cfg->mode == EBPF_OBJECT) { + ret = 0; /* program will be loaded by load stage */ + } else if (cfg->mode == EBPF_PINNED) { + ret = bpf_obj_pinned(file, cfg->type); + cfg->prog_fd = ret; + } else { return -1; + } cfg->object = file; cfg->section = section; cfg->uds = uds_name; cfg->argc = argc; cfg->argv = argv; + cfg->verbose = verbose; return ret; } -static int bpf_parse_opt_tbl(enum bpf_prog_type type, struct bpf_cfg_in *cfg, - const struct bpf_cfg_ops *ops, void *nl, - const bool *opt_tbl) +static int bpf_do_load(struct bpf_cfg_in *cfg) +{ + if (cfg->mode == EBPF_OBJECT) { + cfg->prog_fd = bpf_obj_open(cfg->object, cfg->type, + cfg->section, cfg->ifindex, + cfg->verbose); + return cfg->prog_fd; + } + return 0; +} + +int bpf_load_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops, + void *nl) { - struct sock_filter opcodes[BPF_MAXINSNS]; char annotation[256]; - enum bpf_mode mode; int ret; - cfg->ops = opcodes; - ret = bpf_parse(&type, &mode, cfg, opt_tbl); - cfg->ops = NULL; + ret = bpf_do_load(cfg); if (ret < 0) return ret; - if (mode == CBPF_BYTECODE || mode == CBPF_FILE) - ops->cbpf_cb(nl, opcodes, ret); - if (mode == EBPF_OBJECT || mode == EBPF_PINNED) { + if (cfg->mode == CBPF_BYTECODE || cfg->mode == CBPF_FILE) + ops->cbpf_cb(nl, cfg->opcodes, cfg->n_opcodes); + if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) { snprintf(annotation, sizeof(annotation), "%s:[%s]", - basename(cfg->object), mode == EBPF_PINNED ? + basename(cfg->object), cfg->mode == EBPF_PINNED ? "*fsobj" : cfg->section); - ops->ebpf_cb(nl, ret, annotation); + ops->ebpf_cb(nl, cfg->prog_fd, annotation); } return 0; } -int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg, - const struct bpf_cfg_ops *ops, void *nl) +int bpf_parse_common(struct bpf_cfg_in *cfg, const struct bpf_cfg_ops *ops) { bool opt_tbl[BPF_MODE_MAX] = {}; @@ -962,12 +963,23 @@ int bpf_parse_common(enum bpf_prog_type type, struct bpf_cfg_in *cfg, opt_tbl[EBPF_PINNED] = true; } - return bpf_parse_opt_tbl(type, cfg, ops, nl, opt_tbl); + return bpf_do_parse(cfg, opt_tbl); +} + +int bpf_parse_and_load_common(struct bpf_cfg_in *cfg, + const struct bpf_cfg_ops *ops, void *nl) +{ + int ret; + + ret = bpf_parse_common(cfg, ops); + if (ret < 0) + return ret; + + return bpf_load_common(cfg, ops, nl); } int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) { - enum bpf_prog_type type = BPF_PROG_TYPE_UNSPEC; const bool opt_tbl[BPF_MODE_MAX] = { [EBPF_OBJECT] = true, [EBPF_PINNED] = true, @@ -978,17 +990,24 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) .size_value = sizeof(int), }; struct bpf_cfg_in cfg = { + .type = BPF_PROG_TYPE_UNSPEC, .argc = argc, .argv = argv, }; struct bpf_map_ext ext = {}; int ret, prog_fd, map_fd; - enum bpf_mode mode; uint32_t map_key; - prog_fd = bpf_parse(&type, &mode, &cfg, opt_tbl); - if (prog_fd < 0) - return prog_fd; + ret = bpf_do_parse(&cfg, opt_tbl); + if (ret < 0) + return ret; + + ret = bpf_do_load(&cfg); + if (ret < 0) + return ret; + + prog_fd = cfg.prog_fd; + if (key) { map_key = *key; } else { @@ -1000,7 +1019,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) } } - map_fd = bpf_obj_get(map_path, type); + map_fd = bpf_obj_get(map_path, cfg.type); if (map_fd < 0) { fprintf(stderr, "Couldn\'t retrieve pinned map \'%s\': %s\n", map_path, strerror(errno)); @@ -1010,7 +1029,7 @@ int bpf_graft_map(const char *map_path, uint32_t *key, int argc, char **argv) ret = bpf_map_selfcheck_pinned(map_fd, &test, &ext, offsetof(struct bpf_elf_map, max_elem), - type); + cfg.type); if (ret < 0) { fprintf(stderr, "Map \'%s\' self-check failed!\n", map_path); goto out_map; @@ -1047,9 +1066,10 @@ int bpf_prog_detach_fd(int target_fd, enum bpf_attach_type type) return bpf(BPF_PROG_DETACH, &attr, sizeof(attr)); } -int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, - size_t size_insns, const char *license, char *log, - size_t size_log) +static int bpf_prog_load_dev(enum bpf_prog_type type, + const struct bpf_insn *insns, size_t size_insns, + const char *license, __u32 ifindex, + char *log, size_t size_log) { union bpf_attr attr = {}; @@ -1057,6 +1077,7 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, attr.insns = bpf_ptr_to_u64(insns); attr.insn_cnt = size_insns / sizeof(struct bpf_insn); attr.license = bpf_ptr_to_u64(license); + attr.prog_ifindex = ifindex; if (size_log > 0) { attr.log_buf = bpf_ptr_to_u64(log); @@ -1067,6 +1088,14 @@ int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, return bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); } +int bpf_prog_load(enum bpf_prog_type type, const struct bpf_insn *insns, + size_t size_insns, const char *license, char *log, + size_t size_log) +{ + return bpf_prog_load_dev(type, insns, size_insns, license, 0, + log, size_log); +} + #ifdef HAVE_ELF struct bpf_elf_prog { enum bpf_prog_type type; @@ -1102,6 +1131,7 @@ struct bpf_elf_ctx { int sec_maps; char license[ELF_MAX_LICENSE_LEN]; enum bpf_prog_type type; + __u32 ifindex; bool verbose; struct bpf_elf_st stat; struct bpf_hash_entry *ht[256]; @@ -1474,8 +1504,9 @@ static int bpf_prog_attach(const char *section, int tries = 0, fd; retry: errno = 0; - fd = bpf_prog_load(prog->type, prog->insns, prog->size, - prog->license, ctx->log, ctx->log_size); + fd = bpf_prog_load_dev(prog->type, prog->insns, prog->size, + prog->license, ctx->ifindex, + ctx->log, ctx->log_size); if (fd < 0 || ctx->verbose) { /* The verifier log is pretty chatty, sometimes so chatty * on larger programs, that we could fail to dump everything @@ -2403,7 +2434,8 @@ static void bpf_get_cfg(struct bpf_elf_ctx *ctx) } static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, - enum bpf_prog_type type, bool verbose) + enum bpf_prog_type type, __u32 ifindex, + bool verbose) { int ret = -EINVAL; @@ -2415,6 +2447,7 @@ static int bpf_elf_ctx_init(struct bpf_elf_ctx *ctx, const char *pathname, bpf_get_cfg(ctx); ctx->verbose = verbose; ctx->type = type; + ctx->ifindex = ifindex; ctx->obj_fd = open(pathname, O_RDONLY); if (ctx->obj_fd < 0) @@ -2506,12 +2539,12 @@ static void bpf_elf_ctx_destroy(struct bpf_elf_ctx *ctx, bool failure) static struct bpf_elf_ctx __ctx; static int bpf_obj_open(const char *pathname, enum bpf_prog_type type, - const char *section, bool verbose) + const char *section, __u32 ifindex, bool verbose) { struct bpf_elf_ctx *ctx = &__ctx; int fd = 0, ret; - ret = bpf_elf_ctx_init(ctx, pathname, type, verbose); + ret = bpf_elf_ctx_init(ctx, pathname, type, ifindex, verbose); if (ret < 0) { fprintf(stderr, "Cannot initialize ELF context!\n"); return ret; diff --git a/lib/color.c b/lib/color.c index 8d049a01..a13a4930 100644 --- a/lib/color.c +++ b/lib/color.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <stdarg.h> #include <stdlib.h> diff --git a/lib/dnet_ntop.c b/lib/dnet_ntop.c index 112dc0d9..17d960e3 100644 --- a/lib/dnet_ntop.c +++ b/lib/dnet_ntop.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <errno.h> #include <string.h> #include <sys/types.h> diff --git a/lib/dnet_pton.c b/lib/dnet_pton.c index 73857562..1cf54e51 100644 --- a/lib/dnet_pton.c +++ b/lib/dnet_pton.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <errno.h> #include <string.h> #include <sys/types.h> @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <sys/wait.h> #include <stdio.h> #include <errno.h> diff --git a/lib/ipx_ntop.c b/lib/ipx_ntop.c index 5f646b3e..80b8a34e 100644 --- a/lib/ipx_ntop.c +++ b/lib/ipx_ntop.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <errno.h> #include <sys/types.h> #include <sys/socket.h> diff --git a/lib/ipx_pton.c b/lib/ipx_pton.c index 071a775e..a97c1c1b 100644 --- a/lib/ipx_pton.c +++ b/lib/ipx_pton.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <errno.h> #include <string.h> #include <sys/types.h> diff --git a/lib/libgenl.c b/lib/libgenl.c index bb5fbb5f..f2ce698f 100644 --- a/lib/libgenl.c +++ b/lib/libgenl.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * libgenl.c GENL library */ diff --git a/lib/mpls_ntop.c b/lib/mpls_ntop.c index 5902f503..f8d89f42 100644 --- a/lib/mpls_ntop.c +++ b/lib/mpls_ntop.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + #include <errno.h> #include <string.h> #include <sys/types.h> diff --git a/lib/mpls_pton.c b/lib/mpls_pton.c index 6d2e6a69..065374eb 100644 --- a/lib/mpls_pton.c +++ b/lib/mpls_pton.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + #include <errno.h> #include <string.h> #include <sys/types.h> diff --git a/lib/utils.c b/lib/utils.c index 48cead19..7ced8c06 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -38,6 +38,74 @@ int resolve_hosts; int timestamp_short; +int read_prop(const char *dev, char *prop, long *value) +{ + char fname[128], buf[80], *endp, *nl; + FILE *fp; + long result; + int ret; + + ret = snprintf(fname, sizeof(fname), "/sys/class/net/%s/%s", + dev, prop); + + if (ret <= 0 || ret >= sizeof(fname)) { + fprintf(stderr, "could not build pathname for property\n"); + return -1; + } + + fp = fopen(fname, "r"); + if (fp == NULL) { + fprintf(stderr, "fopen %s: %s\n", fname, strerror(errno)); + return -1; + } + + if (!fgets(buf, sizeof(buf), fp)) { + fprintf(stderr, "property \"%s\" in file %s is currently unknown\n", prop, fname); + fclose(fp); + goto out; + } + + nl = strchr(buf, '\n'); + if (nl) + *nl = '\0'; + + fclose(fp); + result = strtol(buf, &endp, 0); + + if (*endp || buf == endp) { + fprintf(stderr, "value \"%s\" in file %s is not a number\n", + buf, fname); + goto out; + } + + if ((result == LONG_MAX || result == LONG_MIN) && errno == ERANGE) { + fprintf(stderr, "strtol %s: %s", fname, strerror(errno)); + goto out; + } + + *value = result; + return 0; +out: + fprintf(stderr, "Failed to parse %s\n", fname); + return -1; +} + +/* Parse a percent e.g: '30%' + * return: 0 = ok, -1 = error, 1 = out of range + */ +int parse_percent(double *val, const char *str) +{ + char *p; + + *val = strtod(str, &p) / 100.; + if (*val == HUGE_VALF || *val == HUGE_VALL) + return 1; + if (*val == 0.0 || (*p && strcmp(p, "%"))) + return -1; + + return 0; +} + int get_hex(char c) { if (c >= 'A' && c <= 'F') diff --git a/man/Makefile b/man/Makefile index 749faa11..6b095ee4 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 INSTALL=install INSTALLDIR=install -m 0755 -d INSTALLMAN=install -m 0644 diff --git a/man/man3/Makefile b/man/man3/Makefile index a98741de..e3d3e607 100644 --- a/man/man3/Makefile +++ b/man/man3/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 MAN3PAGES = $(wildcard *.3) all: diff --git a/man/man7/Makefile b/man/man7/Makefile index 689fc713..1a8d5219 100644 --- a/man/man7/Makefile +++ b/man/man7/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 MAN7PAGES = $(wildcard *.7) all: diff --git a/man/man8/Makefile b/man/man8/Makefile index 12af66be..932ba1f3 100644 --- a/man/man8/Makefile +++ b/man/man8/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 TARGETS = ip-address.8 ip-link.8 ip-route.8 MAN8PAGES = $(TARGETS) $(filter-out $(TARGETS),$(wildcard *.8)) diff --git a/man/man8/tc.8 b/man/man8/tc.8 index f96911ae..ff071b33 100644 --- a/man/man8/tc.8 +++ b/man/man8/tc.8 @@ -74,7 +74,8 @@ tc \- show / manipulate traffic control settings \fB\-r\fR[\fIaw\fR] | \fB\-p\fR[\fIretty\fR] | \fB\-i\fR[\fIec\fR] | -\fB\-g\fR[\fIraph\fR] } +\fB\-g\fR[\fIraph\fR] | +\fB\-j\fR[\fIjson\fR] } .SH DESCRIPTION .B Tc @@ -443,7 +444,10 @@ see the man pages for individual qdiscs. RATES Bandwidths or rates. These parameters accept a floating point number, possibly followed by -a unit (both SI and IEC units supported). +either a unit (both SI and IEC units supported), or a float followed by a '%' +character to specify the rate as a percentage of the device's speed +(e.g. 5%, 99.5%). Warning: specifying the rate as a percentage means a fraction +of the current speed; if the speed changes, the value will not be recalculated. .RS .TP bit or a bare number @@ -659,6 +663,10 @@ option was specified. Classes can be filtered only by option. .TP +.BR "\-j", " \-json" +Display results in JSON format. + +.TP .BR "\-nm" , " \-name" resolve class name from .B /etc/iproute2/tc_cls diff --git a/misc/Makefile b/misc/Makefile index d02616e3..34ef6b21 100644 --- a/misc/Makefile +++ b/misc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 SSOBJ=ss.o ssfilter.o LNSTATOBJ=lnstat.o lnstat_util.o diff --git a/misc/lnstat.h b/misc/lnstat.h index 83dad970..199eb54a 100644 --- a/misc/lnstat.h +++ b/misc/lnstat.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LNSTAT_H #define _LNSTAT_H diff --git a/misc/ssfilter.h b/misc/ssfilter.h index dfc5b938..f5b0bc8a 100644 --- a/misc/ssfilter.h +++ b/misc/ssfilter.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define SSF_DCOND 0 #define SSF_SCOND 1 #define SSF_OR 2 diff --git a/netem/Makefile b/netem/Makefile index 43418527..ba4c5a76 100644 --- a/netem/Makefile +++ b/netem/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include ../config.mk DISTGEN = maketable normal pareto paretonormal diff --git a/rdma/Makefile b/rdma/Makefile index 1b5aa50b..c8966bfd 100644 --- a/rdma/Makefile +++ b/rdma/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include ../config.mk ifeq ($(HAVE_MNL),y) diff --git a/tc/Makefile b/tc/Makefile index 24bd3e2e..3716dd6a 100644 --- a/tc/Makefile +++ b/tc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 TCOBJ= tc.o tc_qdisc.o tc_class.o tc_filter.o tc_util.o tc_monitor.o \ tc_exec.o m_police.o m_estimator.o m_action.o m_ematch.o \ emp_ematch.yacc.o emp_ematch.lex.o diff --git a/tc/emp_ematch.l b/tc/emp_ematch.l index d9b45be1..dc106759 100644 --- a/tc/emp_ematch.l +++ b/tc/emp_ematch.l @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ %{ #include "emp_ematch.yacc.h" #include "m_ematch.h" @@ -82,6 +82,7 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle, unsigned int bpf_flags = 0; struct bpf_cfg_in cfg = {}; bool seen_run = false; + bool skip_sw = false; struct rtattr *tail; int ret = 0; @@ -101,13 +102,20 @@ static int bpf_parse_opt(struct filter_util *qu, char *handle, while (argc > 0) { if (matches(*argv, "run") == 0) { NEXT_ARG(); + + if (seen_run) + duparg("run", *argv); opt_bpf: seen_run = true; + cfg.type = bpf_type; cfg.argc = argc; cfg.argv = argv; - if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n)) + if (bpf_parse_common(&cfg, &bpf_cb_ops) < 0) { + fprintf(stderr, + "Unable to parse bpf command line\n"); return -1; + } argc = cfg.argc; argv = cfg.argv; @@ -131,6 +139,7 @@ opt_bpf: bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_HW; } else if (matches(*argv, "skip_sw") == 0) { bpf_gen_flags |= TCA_CLS_FLAGS_SKIP_SW; + skip_sw = true; } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_BPF_ACT, n)) { @@ -160,6 +169,13 @@ opt_bpf: NEXT_ARG_FWD(); } + if (skip_sw) + cfg.ifindex = t->tcm_ifindex; + if (bpf_load_common(&cfg, &bpf_cb_ops, n) < 0) { + fprintf(stderr, "Unable to load program\n"); + return -1; + } + if (bpf_gen_flags) addattr32(n, MAX_MSG, TCA_BPF_FLAGS_GEN, bpf_gen_flags); if (bpf_flags) diff --git a/tc/f_flower.c b/tc/f_flower.c index 9cad6c85..5a4ec832 100644 --- a/tc/f_flower.c +++ b/tc/f_flower.c @@ -1037,89 +1037,105 @@ static int __mask_bits(char *addr, size_t len) return bits; } -static void flower_print_eth_addr(FILE *f, char *name, - struct rtattr *addr_attr, +static void flower_print_eth_addr(char *name, struct rtattr *addr_attr, struct rtattr *mask_attr) { + SPRINT_BUF(namefrm); + SPRINT_BUF(out); SPRINT_BUF(b1); + size_t done; int bits; if (!addr_attr || RTA_PAYLOAD(addr_attr) != ETH_ALEN) return; - fprintf(f, "\n %s %s", name, ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN, - 0, b1, sizeof(b1))); - if (!mask_attr || RTA_PAYLOAD(mask_attr) != ETH_ALEN) - return; - bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN); - if (bits < 0) - fprintf(f, "/%s", ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN, - 0, b1, sizeof(b1))); - else if (bits < ETH_ALEN * 8) - fprintf(f, "/%d", bits); + done = sprintf(out, "%s", + ll_addr_n2a(RTA_DATA(addr_attr), ETH_ALEN, + 0, b1, sizeof(b1))); + if (mask_attr && RTA_PAYLOAD(mask_attr) == ETH_ALEN) { + bits = __mask_bits(RTA_DATA(mask_attr), ETH_ALEN); + if (bits < 0) + sprintf(out + done, "/%s", + ll_addr_n2a(RTA_DATA(mask_attr), ETH_ALEN, + 0, b1, sizeof(b1))); + else if (bits < ETH_ALEN * 8) + sprintf(out + done, "/%d", bits); + } + + sprintf(namefrm, "\n %s %%s", name); + print_string(PRINT_ANY, name, namefrm, out); } -static void flower_print_eth_type(FILE *f, __be16 *p_eth_type, +static void flower_print_eth_type(__be16 *p_eth_type, struct rtattr *eth_type_attr) { + SPRINT_BUF(out); __be16 eth_type; if (!eth_type_attr) return; eth_type = rta_getattr_u16(eth_type_attr); - fprintf(f, "\n eth_type "); if (eth_type == htons(ETH_P_IP)) - fprintf(f, "ipv4"); + sprintf(out, "ipv4"); else if (eth_type == htons(ETH_P_IPV6)) - fprintf(f, "ipv6"); + sprintf(out, "ipv6"); else if (eth_type == htons(ETH_P_ARP)) - fprintf(f, "arp"); + sprintf(out, "arp"); else if (eth_type == htons(ETH_P_RARP)) - fprintf(f, "rarp"); + sprintf(out, "rarp"); else - fprintf(f, "%04x", ntohs(eth_type)); + sprintf(out, "%04x", ntohs(eth_type)); + + print_string(PRINT_ANY, "eth_type", "\n eth_type %s", out); *p_eth_type = eth_type; } -static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto, +static void flower_print_ip_proto(__u8 *p_ip_proto, struct rtattr *ip_proto_attr) { + SPRINT_BUF(out); __u8 ip_proto; if (!ip_proto_attr) return; ip_proto = rta_getattr_u8(ip_proto_attr); - fprintf(f, "\n ip_proto "); if (ip_proto == IPPROTO_TCP) - fprintf(f, "tcp"); + sprintf(out, "tcp"); else if (ip_proto == IPPROTO_UDP) - fprintf(f, "udp"); + sprintf(out, "udp"); else if (ip_proto == IPPROTO_SCTP) - fprintf(f, "sctp"); + sprintf(out, "sctp"); else if (ip_proto == IPPROTO_ICMP) - fprintf(f, "icmp"); + sprintf(out, "icmp"); else if (ip_proto == IPPROTO_ICMPV6) - fprintf(f, "icmpv6"); + sprintf(out, "icmpv6"); else - fprintf(f, "%02x", ip_proto); + sprintf(out, "%02x", ip_proto); + + print_string(PRINT_ANY, "ip_proto", "\n ip_proto %s", out); *p_ip_proto = ip_proto; } -static void flower_print_ip_attr(FILE *f, char *name, - struct rtattr *key_attr, +static void flower_print_ip_attr(char *name, struct rtattr *key_attr, struct rtattr *mask_attr) { + SPRINT_BUF(namefrm); + SPRINT_BUF(out); + size_t done; + if (!key_attr) return; - fprintf(f, "\n %s %x", name, rta_getattr_u8(key_attr)); - if (!mask_attr) - return; - fprintf(f, "/%x", rta_getattr_u8(mask_attr)); + done = sprintf(out, "%x", rta_getattr_u8(key_attr)); + if (mask_attr) + sprintf(out + done, "/%x", rta_getattr_u8(mask_attr)); + + sprintf(namefrm, "\n %s %%x", name); + print_string(PRINT_ANY, name, namefrm, out); } -static void flower_print_matching_flags(FILE *f, char *name, +static void flower_print_matching_flags(char *name, enum flower_matching_flags type, struct rtattr *attr, struct rtattr *mask_attr) @@ -1139,20 +1155,28 @@ static void flower_print_matching_flags(FILE *f, char *name, if (type != flags_str[i].type) continue; if (mtf_mask & flags_str[i].flag) { - if (++count == 1) - fprintf(f, "\n %s ", name); - else - fprintf(f, "/"); + if (++count == 1) { + print_string(PRINT_FP, NULL, "\n %s ", name); + open_json_object(name); + } else { + print_string(PRINT_FP, NULL, "/", NULL); + } + print_bool(PRINT_JSON, flags_str[i].string, NULL, + mtf & flags_str[i].flag); if (mtf & flags_str[i].flag) - fprintf(f, "%s", flags_str[i].string); + print_string(PRINT_FP, NULL, "%s", + flags_str[i].string); else - fprintf(f, "no%s", flags_str[i].string); + print_string(PRINT_FP, NULL, "no%s", + flags_str[i].string); } } + if (count) + close_json_object(); } -static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type, +static void flower_print_ip_addr(char *name, __be16 eth_type, struct rtattr *addr4_attr, struct rtattr *mask4_attr, struct rtattr *addr6_attr, @@ -1160,6 +1184,9 @@ static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type, { struct rtattr *addr_attr; struct rtattr *mask_attr; + SPRINT_BUF(namefrm); + SPRINT_BUF(out); + size_t done; int family; size_t len; int bits; @@ -1179,56 +1206,75 @@ static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type, } if (!addr_attr || RTA_PAYLOAD(addr_attr) != len) return; - fprintf(f, "\n %s %s", name, rt_addr_n2a_rta(family, addr_attr)); if (!mask_attr || RTA_PAYLOAD(mask_attr) != len) return; + done = sprintf(out, "%s", rt_addr_n2a_rta(family, addr_attr)); bits = __mask_bits(RTA_DATA(mask_attr), len); if (bits < 0) - fprintf(f, "/%s", rt_addr_n2a_rta(family, mask_attr)); + sprintf(out + done, "/%s", rt_addr_n2a_rta(family, mask_attr)); else if (bits < len * 8) - fprintf(f, "/%d", bits); + sprintf(out + done, "/%d", bits); + + sprintf(namefrm, "\n %s %%s", name); + print_string(PRINT_ANY, name, namefrm, out); } -static void flower_print_ip4_addr(FILE *f, char *name, - struct rtattr *addr_attr, +static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr, struct rtattr *mask_attr) { - return flower_print_ip_addr(f, name, htons(ETH_P_IP), + return flower_print_ip_addr(name, htons(ETH_P_IP), addr_attr, mask_attr, 0, 0); } -static void flower_print_port(FILE *f, char *name, struct rtattr *attr) +static void flower_print_port(char *name, struct rtattr *attr) { - if (attr) - fprintf(f, "\n %s %d", name, rta_getattr_be16(attr)); + SPRINT_BUF(namefrm); + + if (!attr) + return; + + sprintf(namefrm,"\n %s %%u", name); + print_uint(PRINT_ANY, name, namefrm, rta_getattr_be16(attr)); } -static void flower_print_tcp_flags(FILE *f, char *name, - struct rtattr *flags_attr, - struct rtattr *mask_attr) +static void flower_print_tcp_flags(char *name, struct rtattr *flags_attr, + struct rtattr *mask_attr) { + SPRINT_BUF(namefrm); + SPRINT_BUF(out); + size_t done; + if (!flags_attr) return; - fprintf(f, "\n %s %x", name, rta_getattr_be16(flags_attr)); - if (!mask_attr) - return; - fprintf(f, "/%x", rta_getattr_be16(mask_attr)); + + done = sprintf(out, "%x", rta_getattr_be16(flags_attr)); + if (mask_attr) + sprintf(out + done, "%x", rta_getattr_be16(flags_attr)); + + sprintf(namefrm, "\n %s %%s", name); + print_string(PRINT_ANY, name, namefrm, out); } -static void flower_print_key_id(FILE *f, const char *name, - struct rtattr *attr) +static void flower_print_key_id(const char *name, struct rtattr *attr) { - if (attr) - fprintf(f, "\n %s %d", name, rta_getattr_be32(attr)); + SPRINT_BUF(namefrm); + + if (!attr) + return; + + sprintf(namefrm,"\n %s %%u", name); + print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr)); } -static void flower_print_masked_u8(FILE *f, const char *name, - struct rtattr *attr, +static void flower_print_masked_u8(const char *name, struct rtattr *attr, struct rtattr *mask_attr, const char *(*value_to_str)(__u8 value)) { const char *value_str = NULL; __u8 value, mask; + SPRINT_BUF(namefrm); + SPRINT_BUF(out); + size_t done; if (!attr) return; @@ -1238,39 +1284,39 @@ static void flower_print_masked_u8(FILE *f, const char *name, if (mask == UINT8_MAX && value_to_str) value_str = value_to_str(value); - fprintf(f, "\n %s ", name); - if (value_str) - fputs(value_str, f); + done = sprintf(out, "%s", value_str); else - fprintf(f, "%d", value); + done = sprintf(out, "%d", value); if (mask != UINT8_MAX) - fprintf(f, "/%d", mask); + sprintf(out + done, "/%d", mask); + + sprintf(namefrm,"\n %s %%s", name); + print_string(PRINT_ANY, name, namefrm, out); } -static void flower_print_u8(FILE *f, const char *name, struct rtattr *attr) +static void flower_print_u8(const char *name, struct rtattr *attr) { - flower_print_masked_u8(f, name, attr, NULL, NULL); + flower_print_masked_u8(name, attr, NULL, NULL); } -static void flower_print_u32(FILE *f, const char *name, struct rtattr *attr) +static void flower_print_u32(const char *name, struct rtattr *attr) { - __u32 value; + SPRINT_BUF(namefrm); if (!attr) return; - value = rta_getattr_u32(attr); - - fprintf(f, "\n %s %d", name, value); + sprintf(namefrm,"\n %s %%u", name); + print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr)); } -static void flower_print_arp_op(FILE *f, const char *name, +static void flower_print_arp_op(const char *name, struct rtattr *op_attr, struct rtattr *mask_attr) { - flower_print_masked_u8(f, name, op_attr, mask_attr, + flower_print_masked_u8(name, op_attr, mask_attr, flower_print_arp_op_to_name); } @@ -1288,7 +1334,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, parse_rtattr_nested(tb, TCA_FLOWER_MAX, opt); if (handle) - fprintf(f, "handle 0x%x ", handle); + print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle); if (tb[TCA_FLOWER_CLASSID]) { __u32 h = rta_getattr_u32(tb[TCA_FLOWER_CLASSID]); @@ -1296,56 +1342,62 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, if (TC_H_MIN(h) < TC_H_MIN_PRIORITY || TC_H_MIN(h) > (TC_H_MIN_PRIORITY + TC_QOPT_MAX_QUEUE - 1)) { SPRINT_BUF(b1); - fprintf(f, "classid %s ", sprint_tc_classid(h, b1)); + print_string(PRINT_ANY, "classid", "classid %s ", + sprint_tc_classid(h, b1)); } else { - fprintf(f, "hw_tc %u ", - TC_H_MIN(h) - TC_H_MIN_PRIORITY); + print_uint(PRINT_ANY, "hw_tc", "hw_tc %u ", + TC_H_MIN(h) - TC_H_MIN_PRIORITY); } } if (tb[TCA_FLOWER_INDEV]) { struct rtattr *attr = tb[TCA_FLOWER_INDEV]; - fprintf(f, "\n indev %s", rta_getattr_str(attr)); + print_string(PRINT_ANY, "indev", "\n indev %s", + rta_getattr_str(attr)); } + open_json_object("keys"); + if (tb[TCA_FLOWER_KEY_VLAN_ID]) { struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID]; - fprintf(f, "\n vlan_id %d", rta_getattr_u16(attr)); + print_uint(PRINT_ANY, "vlan_id", "\n vlan_id %u", + rta_getattr_u16(attr)); } if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) { struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO]; - fprintf(f, "\n vlan_prio %d", rta_getattr_u8(attr)); + print_uint(PRINT_ANY, "vlan_prio", "\n vlan_prio %d", + rta_getattr_u8(attr)); } - flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST], + flower_print_eth_addr("dst_mac", tb[TCA_FLOWER_KEY_ETH_DST], tb[TCA_FLOWER_KEY_ETH_DST_MASK]); - flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC], + flower_print_eth_addr("src_mac", tb[TCA_FLOWER_KEY_ETH_SRC], tb[TCA_FLOWER_KEY_ETH_SRC_MASK]); - flower_print_eth_type(f, ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]); - flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]); + flower_print_eth_type(ð_type, tb[TCA_FLOWER_KEY_ETH_TYPE]); + flower_print_ip_proto(&ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]); - flower_print_ip_attr(f, "ip_tos", tb[TCA_FLOWER_KEY_IP_TOS], + flower_print_ip_attr("ip_tos", tb[TCA_FLOWER_KEY_IP_TOS], tb[TCA_FLOWER_KEY_IP_TOS_MASK]); - flower_print_ip_attr(f, "ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL], + flower_print_ip_attr("ip_ttl", tb[TCA_FLOWER_KEY_IP_TTL], tb[TCA_FLOWER_KEY_IP_TTL_MASK]); - flower_print_u32(f, "mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]); - flower_print_u8(f, "mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]); - flower_print_u8(f, "mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]); - flower_print_u8(f, "mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]); + flower_print_u32("mpls_label", tb[TCA_FLOWER_KEY_MPLS_LABEL]); + flower_print_u8("mpls_tc", tb[TCA_FLOWER_KEY_MPLS_TC]); + flower_print_u8("mpls_bos", tb[TCA_FLOWER_KEY_MPLS_BOS]); + flower_print_u8("mpls_ttl", tb[TCA_FLOWER_KEY_MPLS_TTL]); - flower_print_ip_addr(f, "dst_ip", eth_type, + flower_print_ip_addr("dst_ip", eth_type, tb[TCA_FLOWER_KEY_IPV4_DST], tb[TCA_FLOWER_KEY_IPV4_DST_MASK], tb[TCA_FLOWER_KEY_IPV6_DST], tb[TCA_FLOWER_KEY_IPV6_DST_MASK]); - flower_print_ip_addr(f, "src_ip", eth_type, + flower_print_ip_addr("src_ip", eth_type, tb[TCA_FLOWER_KEY_IPV4_SRC], tb[TCA_FLOWER_KEY_IPV4_SRC_MASK], tb[TCA_FLOWER_KEY_IPV6_SRC], @@ -1353,12 +1405,12 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_DST); if (nl_type >= 0) - flower_print_port(f, "dst_port", tb[nl_type]); + flower_print_port("dst_port", tb[nl_type]); nl_type = flower_port_attr_type(ip_proto, FLOWER_ENDPOINT_SRC); if (nl_type >= 0) - flower_print_port(f, "src_port", tb[nl_type]); + flower_print_port("src_port", tb[nl_type]); - flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS], + flower_print_tcp_flags("tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS], tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]); nl_type = flower_icmp_attr_type(eth_type, ip_proto, @@ -1366,7 +1418,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, FLOWER_ICMP_FIELD_TYPE); if (nl_type >= 0 && nl_mask_type >= 0) - flower_print_masked_u8(f, "icmp_type", tb[nl_type], + flower_print_masked_u8("icmp_type", tb[nl_type], tb[nl_mask_type], NULL); nl_type = flower_icmp_attr_type(eth_type, ip_proto, @@ -1374,21 +1426,21 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, FLOWER_ICMP_FIELD_CODE); if (nl_type >= 0 && nl_mask_type >= 0) - flower_print_masked_u8(f, "icmp_code", tb[nl_type], + flower_print_masked_u8("icmp_code", tb[nl_type], tb[nl_mask_type], NULL); - flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP], + flower_print_ip4_addr("arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP], tb[TCA_FLOWER_KEY_ARP_SIP_MASK]); - flower_print_ip4_addr(f, "arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP], + flower_print_ip4_addr("arp_tip", tb[TCA_FLOWER_KEY_ARP_TIP], tb[TCA_FLOWER_KEY_ARP_TIP_MASK]); - flower_print_arp_op(f, "arp_op", tb[TCA_FLOWER_KEY_ARP_OP], + flower_print_arp_op("arp_op", tb[TCA_FLOWER_KEY_ARP_OP], tb[TCA_FLOWER_KEY_ARP_OP_MASK]); - flower_print_eth_addr(f, "arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA], + flower_print_eth_addr("arp_sha", tb[TCA_FLOWER_KEY_ARP_SHA], tb[TCA_FLOWER_KEY_ARP_SHA_MASK]); - flower_print_eth_addr(f, "arp_tha", tb[TCA_FLOWER_KEY_ARP_THA], + flower_print_eth_addr("arp_tha", tb[TCA_FLOWER_KEY_ARP_THA], tb[TCA_FLOWER_KEY_ARP_THA_MASK]); - flower_print_ip_addr(f, "enc_dst_ip", + flower_print_ip_addr("enc_dst_ip", tb[TCA_FLOWER_KEY_ENC_IPV4_DST_MASK] ? htons(ETH_P_IP) : htons(ETH_P_IPV6), tb[TCA_FLOWER_KEY_ENC_IPV4_DST], @@ -1396,7 +1448,7 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, tb[TCA_FLOWER_KEY_ENC_IPV6_DST], tb[TCA_FLOWER_KEY_ENC_IPV6_DST_MASK]); - flower_print_ip_addr(f, "enc_src_ip", + flower_print_ip_addr("enc_src_ip", tb[TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK] ? htons(ETH_P_IP) : htons(ETH_P_IPV6), tb[TCA_FLOWER_KEY_ENC_IPV4_SRC], @@ -1404,29 +1456,28 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, tb[TCA_FLOWER_KEY_ENC_IPV6_SRC], tb[TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK]); - flower_print_key_id(f, "enc_key_id", - tb[TCA_FLOWER_KEY_ENC_KEY_ID]); + flower_print_key_id("enc_key_id", tb[TCA_FLOWER_KEY_ENC_KEY_ID]); - flower_print_port(f, "enc_dst_port", - tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]); + flower_print_port("enc_dst_port", tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]); - flower_print_matching_flags(f, "ip_flags", - FLOWER_IP_FLAGS, + flower_print_matching_flags("ip_flags", FLOWER_IP_FLAGS, tb[TCA_FLOWER_KEY_FLAGS], tb[TCA_FLOWER_KEY_FLAGS_MASK]); + close_json_object(); + if (tb[TCA_FLOWER_FLAGS]) { __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]); if (flags & TCA_CLS_FLAGS_SKIP_HW) - fprintf(f, "\n skip_hw"); + print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true); if (flags & TCA_CLS_FLAGS_SKIP_SW) - fprintf(f, "\n skip_sw"); + print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true); if (flags & TCA_CLS_FLAGS_IN_HW) - fprintf(f, "\n in_hw"); + print_bool(PRINT_ANY, "in_hw", "\n in_hw", true); else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) - fprintf(f, "\n not_in_hw"); + print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true); } if (tb[TCA_FLOWER_ACT]) diff --git a/tc/f_matchall.c b/tc/f_matchall.c index 183f2611..5ebd0415 100644 --- a/tc/f_matchall.c +++ b/tc/f_matchall.c @@ -121,11 +121,11 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f, parse_rtattr_nested(tb, TCA_MATCHALL_MAX, opt); if (handle) - fprintf(f, "handle 0x%x ", handle); + print_uint(PRINT_ANY, "handle", "handle 0x%x ", handle); if (tb[TCA_MATCHALL_CLASSID]) { SPRINT_BUF(b1); - fprintf(f, "flowid %s ", + print_string(PRINT_ANY, "flowid", "flowid %s ", sprint_tc_classid(rta_getattr_u32(tb[TCA_MATCHALL_CLASSID]), b1)); } @@ -133,14 +133,14 @@ static int matchall_print_opt(struct filter_util *qu, FILE *f, __u32 flags = rta_getattr_u32(tb[TCA_MATCHALL_FLAGS]); if (flags & TCA_CLS_FLAGS_SKIP_HW) - fprintf(f, "\n skip_hw"); + print_bool(PRINT_ANY, "skip_hw", "\n skip_hw", true); if (flags & TCA_CLS_FLAGS_SKIP_SW) - fprintf(f, "\n skip_sw"); + print_bool(PRINT_ANY, "skip_sw", "\n skip_sw", true); if (flags & TCA_CLS_FLAGS_IN_HW) - fprintf(f, "\n in_hw"); + print_bool(PRINT_ANY, "in_hw", "\n in_hw", true); else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) - fprintf(f, "\n not_in_hw"); + print_bool(PRINT_ANY, "not_in_hw", "\n not_in_hw", true); } if (tb[TCA_MATCHALL_ACT]) diff --git a/tc/f_rsvp.c b/tc/f_rsvp.c index 02028b4b..1ce37340 100644 --- a/tc/f_rsvp.c +++ b/tc/f_rsvp.c @@ -169,7 +169,8 @@ done: } -static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) +static int rsvp_parse_opt(struct filter_util *qu, char *handle, int argc, + char **argv, struct nlmsghdr *n) { int family = strcmp(qu->id, "rsvp") == 0 ? AF_INET : AF_INET6; struct tc_rsvp_pinfo pinfo = {}; diff --git a/tc/f_tcindex.c b/tc/f_tcindex.c index 4cd7859f..749273db 100644 --- a/tc/f_tcindex.c +++ b/tc/f_tcindex.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * f_tcindex.c Traffic control index filter * diff --git a/tc/m_action.c b/tc/m_action.c index 0dce97f0..13f942bf 100644 --- a/tc/m_action.c +++ b/tc/m_action.c @@ -11,10 +11,11 @@ * TODO: * - parse to be passed a filedescriptor for logging purposes * -*/ + */ #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include <unistd.h> #include <fcntl.h> #include <sys/socket.h> @@ -41,7 +42,7 @@ static void act_usage(void) * with any action .so from the old days. But if someone really * does that, they would know how to fix this .. * - */ + */ fprintf(stderr, "usage: tc actions <ACTSPECOP>*\n"); fprintf(stderr, "Where: \tACTSPECOP := ACR | GD | FL\n" @@ -68,16 +69,19 @@ static int print_noaopt(struct action_util *au, FILE *f, struct rtattr *opt) return 0; } -static int parse_noaopt(struct action_util *au, int *argc_p, char ***argv_p, int code, struct nlmsghdr *n) +static int parse_noaopt(struct action_util *au, int *argc_p, + char ***argv_p, int code, struct nlmsghdr *n) { int argc = *argc_p; char **argv = *argv_p; - if (argc) { - fprintf(stderr, "Unknown action \"%s\", hence option \"%s\" is unparsable\n", au->id, *argv); - } else { + if (argc) + fprintf(stderr, + "Unknown action \"%s\", hence option \"%s\" is unparsable\n", + au->id, *argv); + else fprintf(stderr, "Unknown action \"%s\"\n", au->id); - } + return -1; } @@ -135,18 +139,14 @@ noexist: return a; } -static int +static bool new_cmd(char **argv) { - if ((matches(*argv, "change") == 0) || + return (matches(*argv, "change") == 0) || (matches(*argv, "replace") == 0) || (matches(*argv, "delete") == 0) || (matches(*argv, "get") == 0) || - (matches(*argv, "add") == 0)) - return 1; - - return 0; - + (matches(*argv, "add") == 0); } int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) @@ -154,7 +154,7 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) int argc = *argc_p; char **argv = *argv_p; struct rtattr *tail, *tail2; - char k[16]; + char k[FILTER_NAMESZ]; int act_ck_len = 0; int ok = 0; int eap = 0; /* expect action parameters */ @@ -179,9 +179,8 @@ int parse_action(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) argv++; eap = 1; #ifdef CONFIG_GACT - if (!gact_ld) { + if (!gact_ld) get_action_kind("gact"); - } #endif continue; } else if (strcmp(*argv, "flowid") == 0) { @@ -207,9 +206,9 @@ done0: goto done; } - if (a == NULL) { + if (a == NULL) goto bad_val; - } + tail = NLMSG_TAIL(n); addattr_l(n, MAX_MSG, ++prio, NULL, 0); @@ -268,7 +267,8 @@ done: return 0; bad_val: /* no need to undo things, returning from here should - * cause enough pain */ + * cause enough pain + */ fprintf(stderr, "parse_action: bad value (%d:%s)!\n", argc, *argv); return -1; } @@ -301,18 +301,19 @@ static int tc_print_one_action(FILE *f, struct rtattr *arg) return err; if (show_stats && tb[TCA_ACT_STATS]) { - - fprintf(f, "\tAction statistics:\n"); + print_string(PRINT_FP, NULL, "\tAction statistics:\n", NULL); + open_json_object("stats"); print_tcstats2_attr(f, tb[TCA_ACT_STATS], "\t", NULL); - if (tb[TCA_ACT_COOKIE]) { - int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]); - char b1[strsz * 2 + 1]; + close_json_object(); + print_string(PRINT_FP, NULL, "\n", NULL); + } + if (tb[TCA_ACT_COOKIE]) { + int strsz = RTA_PAYLOAD(tb[TCA_ACT_COOKIE]); + char b1[strsz * 2 + 1]; - fprintf(f, "\n\tcookie len %d %s ", strsz, - hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]), - strsz, b1, sizeof(b1))); - } - fprintf(f, "\n"); + print_string(PRINT_ANY, "cookie", "\tcookie %s\n", + hexstring_n2a(RTA_DATA(tb[TCA_ACT_COOKIE]), + strsz, b1, sizeof(b1))); } return 0; @@ -363,15 +364,21 @@ tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts) if (tab_flush && NULL != tb[0] && NULL == tb[1]) return tc_print_action_flush(f, tb[0]); + open_json_array(PRINT_JSON, "actions"); for (i = 0; i < tot_acts; i++) { if (tb[i]) { - fprintf(f, "\n\taction order %d: ", i); + open_json_object(NULL); + print_uint(PRINT_ANY, "order", + "\n\taction order %u: ", i); if (tc_print_one_action(f, tb[i]) < 0) { - fprintf(f, "Error printing action\n"); + print_string(PRINT_FP, NULL, + "Error printing action\n", NULL); } + close_json_object(); } } + close_json_object(); return 0; } @@ -429,9 +436,10 @@ int print_action(const struct sockaddr_nl *who, return 0; } -static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p) +static int tc_action_gd(int cmd, unsigned int flags, + int *argc_p, char ***argv_p) { - char k[16]; + char k[FILTER_NAMESZ]; struct action_util *a = NULL; int argc = *argc_p; char **argv = *argv_p; @@ -485,7 +493,8 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p argc -= 1; argv += 1; if (argc <= 0) { - fprintf(stderr, "Error: no index specified action: %s\n", k); + fprintf(stderr, + "Error: no index specified action: %s\n", k); ret = -1; goto bad_val; } @@ -500,7 +509,8 @@ static int tc_action_gd(int cmd, unsigned int flags, int *argc_p, char ***argv_p argc -= 1; argv += 1; } else { - fprintf(stderr, "Error: no index specified action: %s\n", k); + fprintf(stderr, + "Error: no index specified action: %s\n", k); ret = -1; goto bad_val; } @@ -536,7 +546,8 @@ bad_val: return ret; } -static int tc_action_modify(int cmd, unsigned int flags, int *argc_p, char ***argv_p) +static int tc_action_modify(int cmd, unsigned int flags, + int *argc_p, char ***argv_p) { int argc = *argc_p; char **argv = *argv_p; @@ -581,7 +592,7 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event) char **argv = *argv_p; __u32 msec_since = 0; int argc = *argc_p; - char k[16]; + char k[FILTER_NAMESZ]; struct { struct nlmsghdr n; struct tcamsg t; @@ -597,9 +608,9 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event) strncpy(k, *argv, sizeof(k) - 1); #ifdef CONFIG_GACT - if (!gact_ld) { + if (!gact_ld) get_action_kind("gact"); - } + #endif a = get_action_kind(k); if (a == NULL) { @@ -637,10 +648,12 @@ static int tc_act_list_or_flush(int *argc_p, char ***argv_p, int event) addattr32(&req.n, MAX_MSG, TCA_ROOT_TIME_DELTA, msec_since); tail4->rta_len = (void *) NLMSG_TAIL(&req.n) - (void *) tail4; } - msg_size = NLMSG_ALIGN(req.n.nlmsg_len) - NLMSG_ALIGN(sizeof(struct nlmsghdr)); + msg_size = NLMSG_ALIGN(req.n.nlmsg_len) + - NLMSG_ALIGN(sizeof(struct nlmsghdr)); if (event == RTM_GETACTION) { - if (rtnl_dump_request(&rth, event, (void *)&req.t, msg_size) < 0) { + if (rtnl_dump_request(&rth, event, + (void *)&req.t, msg_size) < 0) { perror("Cannot send dump request"); return 1; } @@ -674,10 +687,14 @@ int do_action(int argc, char **argv) while (argc > 0) { if (matches(*argv, "add") == 0) { - ret = tc_action_modify(RTM_NEWACTION, NLM_F_EXCL|NLM_F_CREATE, &argc, &argv); + ret = tc_action_modify(RTM_NEWACTION, + NLM_F_EXCL | NLM_F_CREATE, + &argc, &argv); } else if (matches(*argv, "change") == 0 || matches(*argv, "replace") == 0) { - ret = tc_action_modify(RTM_NEWACTION, NLM_F_CREATE|NLM_F_REPLACE, &argc, &argv); + ret = tc_action_modify(RTM_NEWACTION, + NLM_F_CREATE | NLM_F_REPLACE, + &argc, &argv); } else if (matches(*argv, "delete") == 0) { argc -= 1; argv += 1; @@ -686,8 +703,9 @@ int do_action(int argc, char **argv) argc -= 1; argv += 1; ret = tc_action_gd(RTM_GETACTION, 0, &argc, &argv); - } else if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 - || matches(*argv, "lst") == 0) { + } else if (matches(*argv, "list") == 0 || + matches(*argv, "show") == 0 || + matches(*argv, "lst") == 0) { if (argc <= 2) { act_usage(); return -1; @@ -711,7 +729,9 @@ int do_action(int argc, char **argv) act_usage(); return -1; } else { - fprintf(stderr, "Command \"%s\" is unknown, try \"tc actions help\".\n", *argv); + fprintf(stderr, + "Command \"%s\" is unknown, try \"tc actions help\".\n", + *argv); return -1; } @@ -96,12 +96,16 @@ static int bpf_parse_opt(struct action_util *a, int *ptr_argc, char ***ptr_argv, while (argc > 0) { if (matches(*argv, "run") == 0) { NEXT_ARG(); + + if (seen_run) + duparg("run", *argv); opt_bpf: seen_run = true; + cfg.type = bpf_type; cfg.argc = argc; cfg.argv = argv; - if (bpf_parse_common(bpf_type, &cfg, &bpf_cb_ops, n)) + if (bpf_parse_and_load_common(&cfg, &bpf_cb_ops, n)) return -1; argc = cfg.argc; diff --git a/tc/m_ematch.h b/tc/m_ematch.h index 81456aac..fa6e214a 100644 --- a/tc/m_ematch.h +++ b/tc/m_ematch.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef __TC_EMATCH_H_ #define __TC_EMATCH_H_ diff --git a/tc/m_gact.c b/tc/m_gact.c index efe992f0..e7d91dab 100644 --- a/tc/m_gact.c +++ b/tc/m_gact.c @@ -115,17 +115,21 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p, &pp.paction, false) == -1) usage(); if (get_u16(&pp.pval, *argv, 10)) { - fprintf(stderr, "Illegal probability val 0x%x\n", pp.pval); + fprintf(stderr, + "Illegal probability val 0x%x\n", + pp.pval); return -1; } if (pp.pval > 10000) { - fprintf(stderr, "Illegal probability val 0x%x\n", pp.pval); + fprintf(stderr, + "Illegal probability val 0x%x\n", + pp.pval); return -1; } argc--; argv++; } else if (matches(*argv, "help") == 0) { - usage(); + usage(); } } #endif @@ -140,7 +144,7 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p, argc--; argv++; } else if (matches(*argv, "help") == 0) { - usage(); + usage(); } } @@ -148,9 +152,8 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p, addattr_l(n, MAX_MSG, tca_id, NULL, 0); addattr_l(n, MAX_MSG, TCA_GACT_PARMS, &p, sizeof(p)); #ifdef CONFIG_GACT_PROB - if (rd) { + if (rd) addattr_l(n, MAX_MSG, TCA_GACT_PROB, &pp, sizeof(pp)); - } #endif tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail; @@ -160,7 +163,7 @@ parse_gact(struct action_util *a, int *argc_p, char ***argv_p, } static int -print_gact(struct action_util *au, FILE * f, struct rtattr *arg) +print_gact(struct action_util *au, FILE *f, struct rtattr *arg) { #ifdef CONFIG_GACT_PROB struct tc_gact_p *pp = NULL; @@ -175,12 +178,12 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg) parse_rtattr_nested(tb, TCA_GACT_MAX, arg); if (tb[TCA_GACT_PARMS] == NULL) { - fprintf(f, "[NULL gact parameters]"); + print_string(PRINT_FP, NULL, "%s", "[NULL gact parameters]"); return -1; } p = RTA_DATA(tb[TCA_GACT_PARMS]); - fprintf(f, "gact "); + print_string(PRINT_ANY, "kind", "%s ", "gact"); print_action_control(f, "action ", p->action, ""); #ifdef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB] != NULL) { @@ -190,12 +193,16 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg) memset(&pp_dummy, 0, sizeof(pp_dummy)); pp = &pp_dummy; } - fprintf(f, "\n\t random type %s", prob_n2a(pp->ptype)); + open_json_object("prob"); + print_string(PRINT_ANY, "random_type", "\n\t random type %s", + prob_n2a(pp->ptype)); print_action_control(f, " ", pp->paction, " "); - fprintf(f, "val %d", pp->pval); + print_int(PRINT_ANY, "val", "val %d", pp->pval); + close_json_object(); #endif - fprintf(f, "\n\t index %u ref %d bind %d", p->index, p->refcnt, - p->bindcnt); + print_uint(PRINT_ANY, "index", "\n\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_GACT_TM]) { struct tcf_t *tm = RTA_DATA(tb[TCA_GACT_TM]); @@ -203,7 +210,7 @@ print_gact(struct action_util *au, FILE * f, struct rtattr *arg) print_tm(f, tm); } } - fprintf(f, "\n "); + print_string(PRINT_FP, NULL, "%s", "\n"); return 0; } @@ -286,7 +286,7 @@ static int parse_ipt(struct action_util *a, int *argc_p, int rargc = *argc_p; char **argv = *argv_p; int argc = 0, iargc = 0; - char k[16]; + char k[FILTER_NAMESZ]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; diff --git a/tc/m_mirred.c b/tc/m_mirred.c index d0b7a46a..3870d3a4 100644 --- a/tc/m_mirred.c +++ b/tc/m_mirred.c @@ -28,13 +28,13 @@ static void explain(void) { - fprintf(stderr, "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n"); - fprintf(stderr, "where:\n"); - fprintf(stderr, "\tDIRECTION := <ingress | egress>\n"); - fprintf(stderr, "\tACTION := <mirror | redirect>\n"); - fprintf(stderr, "\tINDEX is the specific policy instance id\n"); - fprintf(stderr, "\tDEVICENAME is the devicename\n"); - + fprintf(stderr, + "Usage: mirred <DIRECTION> <ACTION> [index INDEX] <dev DEVICENAME>\n" + "where:\n" + "\tDIRECTION := <ingress | egress>\n" + "\tACTION := <mirror | redirect>\n" + "\tINDEX is the specific policy instance id\n" + "\tDEVICENAME is the devicename\n"); } static void @@ -60,6 +60,34 @@ static const char *mirred_n2a(int action) } } +static const char *mirred_direction(int action) +{ + switch (action) { + case TCA_EGRESS_REDIR: + case TCA_EGRESS_MIRROR: + return "egress"; + case TCA_INGRESS_REDIR: + case TCA_INGRESS_MIRROR: + return "ingress"; + default: + return "unknown"; + } +} + +static const char *mirred_action(int action) +{ + switch (action) { + case TCA_EGRESS_REDIR: + case TCA_INGRESS_REDIR: + return "redirect"; + case TCA_EGRESS_MIRROR: + case TCA_INGRESS_MIRROR: + return "mirror"; + default: + return "unknown"; + } +} + static int parse_direction(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) @@ -70,7 +98,7 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, int ok = 0, iok = 0, mirror = 0, redir = 0, ingress = 0, egress = 0; struct tc_mirred p = {}; struct rtattr *tail; - char d[16] = {}; + char d[IFNAMSIZ] = {}; while (argc > 0) { @@ -79,7 +107,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, } else if (!egress && matches(*argv, "egress") == 0) { egress = 1; if (ingress) { - fprintf(stderr, "Can't have both egress and ingress\n"); + fprintf(stderr, + "Can't have both egress and ingress\n"); return -1; } NEXT_ARG(); @@ -88,7 +117,8 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, } else if (!ingress && matches(*argv, "ingress") == 0) { ingress = 1; if (egress) { - fprintf(stderr, "Can't have both ingress and egress\n"); + fprintf(stderr, + "Can't have both ingress and egress\n"); return -1; } NEXT_ARG(); @@ -109,30 +139,35 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, break; } } else if (!ok) { - fprintf(stderr, "was expecting egress or ingress (%s)\n", *argv); + fprintf(stderr, + "was expecting egress or ingress (%s)\n", + *argv); break; } else if (!mirror && matches(*argv, "mirror") == 0) { mirror = 1; if (redir) { - fprintf(stderr, "Can't have both mirror and redir\n"); + fprintf(stderr, + "Can't have both mirror and redir\n"); return -1; } p.eaction = egress ? TCA_EGRESS_MIRROR : - TCA_INGRESS_MIRROR; + TCA_INGRESS_MIRROR; p.action = TC_ACT_PIPE; ok++; } else if (!redir && matches(*argv, "redirect") == 0) { redir = 1; if (mirror) { - fprintf(stderr, "Can't have both mirror and redir\n"); + fprintf(stderr, + "Can't have both mirror and redir\n"); return -1; } p.eaction = egress ? TCA_EGRESS_REDIR : - TCA_INGRESS_REDIR; + TCA_INGRESS_REDIR; p.action = TC_ACT_STOLEN; ok++; - } else if ((redir || mirror) && matches(*argv, "dev") == 0) { + } else if ((redir || mirror) && + matches(*argv, "dev") == 0) { NEXT_ARG(); if (strlen(d)) duparg("dev", *argv); @@ -149,18 +184,16 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, NEXT_ARG(); } - if (!ok && !iok) { + if (!ok && !iok) return -1; - } - - if (d[0]) { int idx; ll_init_map(&rth); - if ((idx = ll_name_to_index(d)) == 0) { + idx = ll_name_to_index(d); + if (idx == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", d); return -1; } @@ -176,16 +209,17 @@ parse_direction(struct action_util *a, int *argc_p, char ***argv_p, if (iok && matches(*argv, "index") == 0) { fprintf(stderr, "mirred: Illegal double index\n"); return -1; - } else { - if (matches(*argv, "index") == 0) { - NEXT_ARG(); - if (get_u32(&p.index, *argv, 10)) { - fprintf(stderr, "mirred: Illegal \"index\"\n"); - return -1; - } - argc--; - argv++; + } + + if (matches(*argv, "index") == 0) { + NEXT_ARG(); + if (get_u32(&p.index, *argv, 10)) { + fprintf(stderr, + "mirred: Illegal \"index\"\n"); + return -1; } + argc--; + argv++; } } @@ -242,7 +276,7 @@ parse_mirred(struct action_util *a, int *argc_p, char ***argv_p, } static int -print_mirred(struct action_util *au, FILE * f, struct rtattr *arg) +print_mirred(struct action_util *au, FILE *f, struct rtattr *arg) { struct tc_mirred *p; struct rtattr *tb[TCA_MIRRED_MAX + 1]; @@ -254,27 +288,29 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg) parse_rtattr_nested(tb, TCA_MIRRED_MAX, arg); if (tb[TCA_MIRRED_PARMS] == NULL) { - fprintf(f, "[NULL mirred parameters]"); + print_string(PRINT_FP, NULL, "%s", "[NULL mirred parameters]"); return -1; } p = RTA_DATA(tb[TCA_MIRRED_PARMS]); - /* - ll_init_map(&rth); - */ - - - if ((dev = ll_index_to_name(p->ifindex)) == 0) { + dev = ll_index_to_name(p->ifindex); + if (dev == 0) { fprintf(stderr, "Cannot find device %d\n", p->ifindex); return -1; } - fprintf(f, "mirred (%s to device %s)", mirred_n2a(p->eaction), dev); + print_string(PRINT_ANY, "kind", "%s ", "mirred"); + print_string(PRINT_FP, NULL, "(%s", mirred_n2a(p->eaction)); + print_string(PRINT_JSON, "mirred_action", NULL, + mirred_action(p->eaction)); + print_string(PRINT_JSON, "direction", NULL, + mirred_direction(p->eaction)); + print_string(PRINT_ANY, "to_dev", " to device %s)", dev); print_action_control(f, " ", p->action, ""); - fprintf(f, "\n "); - fprintf(f, "\tindex %u ref %d bind %d", p->index, p->refcnt, - p->bindcnt); + print_uint(PRINT_ANY, "index", "\n \tindex %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_MIRRED_TM]) { @@ -283,7 +319,7 @@ print_mirred(struct action_util *au, FILE * f, struct rtattr *arg) print_tm(f, tm); } } - fprintf(f, "\n "); + print_string(PRINT_FP, NULL, "%s", "\n "); return 0; } diff --git a/tc/m_pedit.c b/tc/m_pedit.c index a6da9536..26549eee 100644 --- a/tc/m_pedit.c +++ b/tc/m_pedit.c @@ -524,7 +524,7 @@ static int parse_munge(int *argc_p, char ***argv_p, struct m_pedit_sel *sel) res = parse_offset(&argc, &argv, sel, &tkey); goto done; } else { - char k[16]; + char k[FILTER_NAMESZ]; struct m_pedit_util *p = NULL; strncpy(k, *argv, sizeof(k) - 1); diff --git a/tc/m_vlan.c b/tc/m_vlan.c index cccb4996..161759fd 100644 --- a/tc/m_vlan.c +++ b/tc/m_vlan.c @@ -27,13 +27,14 @@ static const char * const action_names[] = { static void explain(void) { - fprintf(stderr, "Usage: vlan pop\n"); - fprintf(stderr, " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"); - fprintf(stderr, " vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"); - fprintf(stderr, " VLANPROTO is one of 802.1Q or 802.1AD\n"); - fprintf(stderr, " with default: 802.1Q\n"); - fprintf(stderr, " CONTROL := reclassify | pipe | drop | continue | pass |\n"); - fprintf(stderr, " goto chain <CHAIN_INDEX>\n"); + fprintf(stderr, + "Usage: vlan pop\n" + " vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n" + " vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n" + " VLANPROTO is one of 802.1Q or 802.1AD\n" + " with default: 802.1Q\n" + " CONTROL := reclassify | pipe | drop | continue | pass |\n" + " goto chain <CHAIN_INDEX>\n"); } static void usage(void) @@ -47,6 +48,14 @@ static bool has_push_attribs(int action) return action == TCA_VLAN_ACT_PUSH || action == TCA_VLAN_ACT_MODIFY; } +static void unexpected(const char *arg) +{ + fprintf(stderr, + "unexpected \"%s\" - action already specified\n", + arg); + explain(); +} + static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n) { @@ -70,57 +79,42 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p, while (argc > 0) { if (matches(*argv, "pop") == 0) { if (action) { - fprintf(stderr, "unexpected \"%s\" - action already specified\n", - *argv); - explain(); + unexpected(*argv); return -1; } action = TCA_VLAN_ACT_POP; } else if (matches(*argv, "push") == 0) { if (action) { - fprintf(stderr, "unexpected \"%s\" - action already specified\n", - *argv); - explain(); + unexpected(*argv); return -1; } action = TCA_VLAN_ACT_PUSH; } else if (matches(*argv, "modify") == 0) { if (action) { - fprintf(stderr, "unexpected \"%s\" - action already specified\n", - *argv); - explain(); + unexpected(*argv); return -1; } action = TCA_VLAN_ACT_MODIFY; } else if (matches(*argv, "id") == 0) { - if (!has_push_attribs(action)) { - fprintf(stderr, "\"%s\" is only valid for push/modify\n", - *argv); - explain(); - return -1; - } + if (!has_push_attribs(action)) + invarg("only valid for push/modify", *argv); + NEXT_ARG(); if (get_u16(&id, *argv, 0)) invarg("id is invalid", *argv); id_set = 1; } else if (matches(*argv, "protocol") == 0) { - if (!has_push_attribs(action)) { - fprintf(stderr, "\"%s\" is only valid for push/modify\n", - *argv); - explain(); - return -1; - } + if (!has_push_attribs(action)) + invarg("only valid for push/modify", *argv); + NEXT_ARG(); if (ll_proto_a2n(&proto, *argv)) invarg("protocol is invalid", *argv); proto_set = 1; } else if (matches(*argv, "priority") == 0) { - if (!has_push_attribs(action)) { - fprintf(stderr, "\"%s\" is only valid for push/modify\n", - *argv); - explain(); - return -1; - } + if (!has_push_attribs(action)) + invarg("only valid for push/modify", *argv); + NEXT_ARG(); if (get_u8(&prio, *argv, 0) || (prio & ~0x7)) invarg("prio is invalid", *argv); @@ -195,39 +189,40 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg) parse_rtattr_nested(tb, TCA_VLAN_MAX, arg); if (!tb[TCA_VLAN_PARMS]) { - fprintf(f, "[NULL vlan parameters]"); + print_string(PRINT_FP, NULL, "%s", "[NULL vlan parameters]"); return -1; } parm = RTA_DATA(tb[TCA_VLAN_PARMS]); - fprintf(f, " vlan"); + print_string(PRINT_ANY, "kind", "%s ", "vlan"); + print_string(PRINT_ANY, "vlan_action", " %s", + action_names[parm->v_action]); switch (parm->v_action) { - case TCA_VLAN_ACT_POP: - fprintf(f, " pop"); - break; case TCA_VLAN_ACT_PUSH: case TCA_VLAN_ACT_MODIFY: - fprintf(f, " %s", action_names[parm->v_action]); if (tb[TCA_VLAN_PUSH_VLAN_ID]) { val = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); - fprintf(f, " id %u", val); + print_uint(PRINT_ANY, "id", " id %u", val); } if (tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]) { - fprintf(f, " protocol %s", - ll_proto_n2a(rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]), - b1, sizeof(b1))); + __u16 proto; + + proto = rta_getattr_u16(tb[TCA_VLAN_PUSH_VLAN_PROTOCOL]); + print_string(PRINT_ANY, "protocol", " protocol %s", + ll_proto_n2a(proto, b1, sizeof(b1))); } if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) { val = rta_getattr_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]); - fprintf(f, " priority %u", val); + print_uint(PRINT_ANY, "priority", " priority %u", val); } break; } print_action_control(f, " ", parm->action, ""); - fprintf(f, "\n\t index %u ref %d bind %d", parm->index, parm->refcnt, - parm->bindcnt); + print_uint(PRINT_ANY, "index", "\n\t index %u", parm->index); + print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt); + print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt); if (show_stats) { if (tb[TCA_VLAN_TM]) { @@ -237,7 +232,7 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg) } } - fprintf(f, "\n "); + print_string(PRINT_FP, NULL, "%s", "\n"); return 0; } @@ -154,7 +154,7 @@ static int parse_ipt(struct action_util *a, int *argc_p, int c; char **argv = *argv_p; int argc; - char k[16]; + char k[FILTER_NAMESZ]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; diff --git a/tc/m_xt_old.c b/tc/m_xt_old.c index 4e56e267..21d90877 100644 --- a/tc/m_xt_old.c +++ b/tc/m_xt_old.c @@ -213,7 +213,7 @@ static int parse_ipt(struct action_util *a, int *argc_p, int rargc = *argc_p; char **argv = *argv_p; int argc = 0, iargc = 0; - char k[16]; + char k[FILTER_NAMESZ]; int size = 0; int iok = 0, ok = 0; __u32 hook = 0, index = 0; @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * q_atm.c ATM. * @@ -26,7 +27,8 @@ #define MAX_HDR_LEN 64 -static int atm_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int atm_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { if (argc) { fprintf(stderr, "Usage: atm\n"); @@ -44,7 +46,7 @@ static void explain(void) static int atm_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct sockaddr_atmsvc addr = {}; struct atm_qos qos; @@ -46,7 +46,7 @@ static void explain1(char *arg) } -static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { struct tc_ratespec r = {}; struct tc_cbq_lssopt lss = {}; @@ -62,7 +62,12 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl if (matches(*argv, "bandwidth") == 0 || matches(*argv, "rate") == 0) { NEXT_ARG(); - if (get_rate(&r.rate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&r.rate, *argv, dev)) { + explain1("bandwidth"); + return -1; + } + } else if (get_rate(&r.rate, *argv)) { explain1("bandwidth"); return -1; } @@ -176,7 +181,7 @@ static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl return 0; } -static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int wrr_ok = 0, fopt_ok = 0; struct tc_ratespec r = {}; @@ -196,13 +201,23 @@ static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str while (argc > 0) { if (matches(*argv, "rate") == 0) { NEXT_ARG(); - if (get_rate(&r.rate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&r.rate, *argv, dev)) { + explain1("rate"); + return -1; + } + } else if (get_rate(&r.rate, *argv)) { explain1("rate"); return -1; } } else if (matches(*argv, "bandwidth") == 0) { NEXT_ARG(); - if (get_rate(&bndw, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&bndw, *argv, dev)) { + explain1("bandwidth"); + return -1; + } + } else if (get_rate(&bndw, *argv)) { explain1("bandwidth"); return -1; } @@ -34,7 +34,8 @@ static void explain1(const char *arg, const char *val) fprintf(stderr, "cbs: illegal value for \"%s\": \"%s\"\n", arg, val); } -static int cbs_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int cbs_parse_opt(struct qdisc_util *qu, int argc, + char **argv, struct nlmsghdr *n, const char *dev) { struct tc_cbs_qopt opt = {}; struct rtattr *tail; diff --git a/tc/q_choke.c b/tc/q_choke.c index 726914b2..50ac4ad4 100644 --- a/tc/q_choke.c +++ b/tc/q_choke.c @@ -31,7 +31,7 @@ static void explain(void) } static int choke_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct tc_red_qopt opt = {}; unsigned int burst = 0; @@ -53,7 +53,12 @@ static int choke_parse_opt(struct qdisc_util *qu, int argc, char **argv, } } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); - if (get_rate(&rate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&rate, *argv, dev)) { + fprintf(stderr, "Illegal \"bandwidth\"\n"); + return -1; + } + } else if (get_rate(&rate, *argv)) { fprintf(stderr, "Illegal \"bandwidth\"\n"); return -1; } diff --git a/tc/q_clsact.c b/tc/q_clsact.c index e2a1a710..341f653f 100644 --- a/tc/q_clsact.c +++ b/tc/q_clsact.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #include <stdio.h> #include <string.h> @@ -10,7 +11,7 @@ static void explain(void) } static int clsact_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { if (argc > 0) { fprintf(stderr, "What is \"%s\"?\n", *argv); diff --git a/tc/q_codel.c b/tc/q_codel.c index 253629ef..62d6dd68 100644 --- a/tc/q_codel.c +++ b/tc/q_codel.c @@ -58,7 +58,7 @@ static void explain(void) } static int codel_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { unsigned int limit = 0; unsigned int target = 0; @@ -33,7 +33,8 @@ static void explain2(void) } -static int drr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int drr_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { while (argc) { if (strcmp(*argv, "help") == 0) { @@ -49,7 +50,7 @@ static int drr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl } static int drr_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct rtattr *tail; __u32 tmp; diff --git a/tc/q_dsmark.c b/tc/q_dsmark.c index 0aab387d..967fd892 100644 --- a/tc/q_dsmark.c +++ b/tc/q_dsmark.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * q_dsmark.c Differentiated Services field marking. * @@ -25,7 +26,7 @@ static void explain(void) static int dsmark_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct rtattr *tail; __u16 ind; @@ -84,7 +85,7 @@ static void explain_class(void) static int dsmark_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct rtattr *tail; __u8 tmp; diff --git a/tc/q_fifo.c b/tc/q_fifo.c index c3e90886..5fd6c1b1 100644 --- a/tc/q_fifo.c +++ b/tc/q_fifo.c @@ -27,7 +27,8 @@ static void explain(void) fprintf(stderr, "Usage: ... <[p|b]fifo | pfifo_head_drop> [ limit NUMBER ]\n"); } -static int fifo_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int fifo_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { int ok = 0; struct tc_fifo_qopt opt = {}; @@ -71,7 +71,7 @@ static unsigned int ilog2(unsigned int val) } static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { unsigned int plimit; unsigned int flow_plimit; @@ -118,7 +118,12 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, } } else if (strcmp(*argv, "maxrate") == 0) { NEXT_ARG(); - if (get_rate(&maxrate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&maxrate, *argv, dev)) { + fprintf(stderr, "Illegal \"maxrate\"\n"); + return -1; + } + } else if (get_rate(&maxrate, *argv)) { fprintf(stderr, "Illegal \"maxrate\"\n"); return -1; } @@ -132,7 +137,12 @@ static int fq_parse_opt(struct qdisc_util *qu, int argc, char **argv, set_low_rate_threshold = true; } else if (strcmp(*argv, "defrate") == 0) { NEXT_ARG(); - if (get_rate(&defrate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&defrate, *argv, dev)) { + fprintf(stderr, "Illegal \"defrate\"\n"); + return -1; + } + } else if (get_rate(&defrate, *argv)) { fprintf(stderr, "Illegal \"defrate\"\n"); return -1; } diff --git a/tc/q_fq_codel.c b/tc/q_fq_codel.c index 1eac1403..fd1f59c8 100644 --- a/tc/q_fq_codel.c +++ b/tc/q_fq_codel.c @@ -56,7 +56,7 @@ static void explain(void) } static int fq_codel_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { unsigned int limit = 0; unsigned int flows = 0; @@ -173,44 +173,51 @@ static int fq_codel_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt if (tb[TCA_FQ_CODEL_LIMIT] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_LIMIT]) >= sizeof(__u32)) { limit = rta_getattr_u32(tb[TCA_FQ_CODEL_LIMIT]); - fprintf(f, "limit %up ", limit); + print_uint(PRINT_ANY, "limit", "limit %up ", limit); } if (tb[TCA_FQ_CODEL_FLOWS] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_FLOWS]) >= sizeof(__u32)) { flows = rta_getattr_u32(tb[TCA_FQ_CODEL_FLOWS]); - fprintf(f, "flows %u ", flows); + print_uint(PRINT_ANY, "flows", "flows %u ", flows); } if (tb[TCA_FQ_CODEL_QUANTUM] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_QUANTUM]) >= sizeof(__u32)) { quantum = rta_getattr_u32(tb[TCA_FQ_CODEL_QUANTUM]); - fprintf(f, "quantum %u ", quantum); + print_uint(PRINT_ANY, "quantum", "quantum %u ", quantum); } if (tb[TCA_FQ_CODEL_TARGET] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_TARGET]) >= sizeof(__u32)) { target = rta_getattr_u32(tb[TCA_FQ_CODEL_TARGET]); - fprintf(f, "target %s ", sprint_time(target, b1)); + print_uint(PRINT_JSON, "target", NULL, target); + print_string(PRINT_FP, NULL, "target %s ", + sprint_time(target, b1)); } if (tb[TCA_FQ_CODEL_CE_THRESHOLD] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_CE_THRESHOLD]) >= sizeof(__u32)) { ce_threshold = rta_getattr_u32(tb[TCA_FQ_CODEL_CE_THRESHOLD]); - fprintf(f, "ce_threshold %s ", sprint_time(ce_threshold, b1)); + print_uint(PRINT_JSON, "ce_threshold", NULL, ce_threshold); + print_string(PRINT_FP, NULL, "ce_threshold %s ", + sprint_time(ce_threshold, b1)); } if (tb[TCA_FQ_CODEL_INTERVAL] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_INTERVAL]) >= sizeof(__u32)) { interval = rta_getattr_u32(tb[TCA_FQ_CODEL_INTERVAL]); - fprintf(f, "interval %s ", sprint_time(interval, b1)); + print_uint(PRINT_JSON, "interval", NULL, interval); + print_string(PRINT_FP, NULL, "interval %s ", + sprint_time(interval, b1)); } if (tb[TCA_FQ_CODEL_MEMORY_LIMIT] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_MEMORY_LIMIT]) >= sizeof(__u32)) { memory_limit = rta_getattr_u32(tb[TCA_FQ_CODEL_MEMORY_LIMIT]); - - fprintf(f, "memory_limit %s ", sprint_size(memory_limit, b1)); + print_uint(PRINT_JSON, "memory_limit", NULL, memory_limit); + print_string(PRINT_FP, NULL, "memory_limit %s ", + sprint_size(memory_limit, b1)); } if (tb[TCA_FQ_CODEL_ECN] && RTA_PAYLOAD(tb[TCA_FQ_CODEL_ECN]) >= sizeof(__u32)) { ecn = rta_getattr_u32(tb[TCA_FQ_CODEL_ECN]); if (ecn) - fprintf(f, "ecn "); + print_bool(PRINT_ANY, "ecn", "ecn ", true); } return 0; diff --git a/tc/q_gred.c b/tc/q_gred.c index 2eb906d0..5b5761ee 100644 --- a/tc/q_gred.c +++ b/tc/q_gred.c @@ -116,7 +116,7 @@ static int init_gred(struct qdisc_util *qu, int argc, char **argv, /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */ -static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int ok = 0; struct tc_gred_qopt opt = { 0 }; @@ -199,7 +199,12 @@ static int gred_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct n ok++; } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); - if (get_rate(&rate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&rate, *argv, dev)) { + fprintf(stderr, "Illegal \"bandwidth\"\n"); + return -1; + } + } else if (get_rate(&rate, *argv)) { fprintf(stderr, "Illegal \"bandwidth\"\n"); return -1; } diff --git a/tc/q_hfsc.c b/tc/q_hfsc.c index dc9fed93..c19e87f9 100644 --- a/tc/q_hfsc.c +++ b/tc/q_hfsc.c @@ -23,8 +23,8 @@ #include "utils.h" #include "tc_util.h" -static int hfsc_get_sc(int *, char ***, struct tc_service_curve *); - +static int hfsc_get_sc(int *, char ***, + struct tc_service_curve *, const char *); static void explain_qdisc(void) @@ -70,7 +70,8 @@ explain1(char *arg) } static int -hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { struct tc_hfsc_qopt qopt = {}; @@ -141,7 +142,7 @@ hfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats) static int hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct tc_service_curve rsc = {}, fsc = {}, usc = {}; int rsc_ok = 0, fsc_ok = 0, usc_ok = 0; @@ -150,21 +151,21 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, while (argc > 0) { if (matches(*argv, "rt") == 0) { NEXT_ARG(); - if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { + if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("rt"); return -1; } rsc_ok = 1; } else if (matches(*argv, "ls") == 0) { NEXT_ARG(); - if (hfsc_get_sc(&argc, &argv, &fsc) < 0) { + if (hfsc_get_sc(&argc, &argv, &fsc, dev) < 0) { explain1("ls"); return -1; } fsc_ok = 1; } else if (matches(*argv, "sc") == 0) { NEXT_ARG(); - if (hfsc_get_sc(&argc, &argv, &rsc) < 0) { + if (hfsc_get_sc(&argc, &argv, &rsc, dev) < 0) { explain1("sc"); return -1; } @@ -173,7 +174,7 @@ hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, fsc_ok = 1; } else if (matches(*argv, "ul") == 0) { NEXT_ARG(); - if (hfsc_get_sc(&argc, &argv, &usc) < 0) { + if (hfsc_get_sc(&argc, &argv, &usc, dev) < 0) { explain1("ul"); return -1; } @@ -281,7 +282,8 @@ struct qdisc_util hfsc_qdisc_util = { }; static int -hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc) +hfsc_get_sc1(int *argcp, char ***argvp, + struct tc_service_curve *sc, const char *dev) { char **argv = *argvp; int argc = *argcp; @@ -289,7 +291,12 @@ hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc) if (matches(*argv, "m1") == 0) { NEXT_ARG(); - if (get_rate(&m1, *argv) < 0) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&m1, *argv, dev)) { + explain1("m1"); + return -1; + } + } else if (get_rate(&m1, *argv) < 0) { explain1("m1"); return -1; } @@ -307,7 +314,12 @@ hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc) if (matches(*argv, "m2") == 0) { NEXT_ARG(); - if (get_rate(&m2, *argv) < 0) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&m2, *argv, dev)) { + explain1("m2"); + return -1; + } + } else if (get_rate(&m2, *argv) < 0) { explain1("m2"); return -1; } @@ -324,7 +336,7 @@ hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc) } static int -hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc) +hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc, const char *dev) { char **argv = *argvp; int argc = *argcp; @@ -350,7 +362,12 @@ hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc) if (matches(*argv, "rate") == 0) { NEXT_ARG(); - if (get_rate(&rate, *argv) < 0) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&rate, *argv, dev)) { + explain1("rate"); + return -1; + } + } else if (get_rate(&rate, *argv) < 0) { explain1("rate"); return -1; } @@ -386,10 +403,10 @@ hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc) } static int -hfsc_get_sc(int *argcp, char ***argvp, struct tc_service_curve *sc) +hfsc_get_sc(int *argcp, char ***argvp, struct tc_service_curve *sc, const char *dev) { - if (hfsc_get_sc1(argcp, argvp, sc) < 0 && - hfsc_get_sc2(argcp, argvp, sc) < 0) + if (hfsc_get_sc1(argcp, argvp, sc, dev) < 0 && + hfsc_get_sc2(argcp, argvp, sc, dev) < 0) return -1; if (sc->m1 == 0 && sc->m2 == 0) { @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* q_hhf.c Heavy-Hitter Filter (HHF) * * Copyright (C) 2013 Terry Lam <vtlam@google.com> @@ -25,7 +26,7 @@ static void explain(void) } static int hhf_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { unsigned int limit = 0; unsigned int quantum = 0; @@ -58,8 +58,8 @@ static void explain1(char *arg) explain(); } - -static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int htb_parse_opt(struct qdisc_util *qu, int argc, + char **argv, struct nlmsghdr *n, const char *dev) { unsigned int direct_qlen = ~0U; struct tc_htb_glob opt = { @@ -108,7 +108,7 @@ static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl return 0; } -static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int ok = 0; struct tc_htb_opt opt = {}; @@ -178,7 +178,12 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str fprintf(stderr, "Double \"ceil\" spec\n"); return -1; } - if (get_rate64(&ceil64, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate64(&ceil64, *argv, dev)) { + explain1("ceil"); + return -1; + } + } else if (get_rate64(&ceil64, *argv)) { explain1("ceil"); return -1; } @@ -189,7 +194,12 @@ static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, str fprintf(stderr, "Double \"rate\" spec\n"); return -1; } - if (get_rate64(&rate64, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate64(&rate64, *argv, dev)) { + explain1("rate"); + return -1; + } + } else if (get_rate64(&rate64, *argv)) { explain1("rate"); return -1; } @@ -283,9 +293,10 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) if (RTA_PAYLOAD(tb[TCA_HTB_PARMS]) < sizeof(*hopt)) return -1; if (!hopt->level) { - fprintf(f, "prio %d ", (int)hopt->prio); + print_int(PRINT_ANY, "prio", "prio ", (int)hopt->prio); if (show_details) - fprintf(f, "quantum %d ", (int)hopt->quantum); + print_int(PRINT_ANY, "quantum", "quantum ", + (int)hopt->quantum); } rate64 = hopt->rate.rate; @@ -331,16 +342,21 @@ static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt) gopt = RTA_DATA(tb[TCA_HTB_INIT]); if (RTA_PAYLOAD(tb[TCA_HTB_INIT]) < sizeof(*gopt)) return -1; - fprintf(f, "r2q %d default %x direct_packets_stat %u", - gopt->rate2quantum, gopt->defcls, gopt->direct_pkts); - if (show_details) - fprintf(f, " ver %d.%d", gopt->version >> 16, gopt->version & 0xffff); + print_int(PRINT_ANY, "r2q", "r2q %d", gopt->rate2quantum); + print_uint(PRINT_ANY, "default", " default %u", gopt->defcls); + print_uint(PRINT_ANY, "direct_packets_stat", + " direct_packets_stat %u", gopt->direct_pkts); + if (show_details) { + sprintf(b1, "%d.%d", gopt->version >> 16, gopt->version & 0xffff); + print_string(PRINT_ANY, "ver", " ver %s", b1); + } } if (tb[TCA_HTB_DIRECT_QLEN] && RTA_PAYLOAD(tb[TCA_HTB_DIRECT_QLEN]) >= sizeof(__u32)) { __u32 direct_qlen = rta_getattr_u32(tb[TCA_HTB_DIRECT_QLEN]); - fprintf(f, " direct_qlen %u", direct_qlen); + print_uint(PRINT_ANY, "direct_qlen", " direct_qlen %u", + direct_qlen); } return 0; } diff --git a/tc/q_ingress.c b/tc/q_ingress.c index 31699a81..1e422298 100644 --- a/tc/q_ingress.c +++ b/tc/q_ingress.c @@ -21,7 +21,7 @@ static void explain(void) } static int ingress_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { while (argc > 0) { if (strcmp(*argv, "handle") == 0) { diff --git a/tc/q_mqprio.c b/tc/q_mqprio.c index 99798520..89b46002 100644 --- a/tc/q_mqprio.c +++ b/tc/q_mqprio.c @@ -33,7 +33,7 @@ static void explain(void) } static int mqprio_parse_opt(struct qdisc_util *qu, int argc, - char **argv, struct nlmsghdr *n) + char **argv, struct nlmsghdr *n, const char *dev) { int idx; struct tc_mqprio_qopt opt = { diff --git a/tc/q_multiq.c b/tc/q_multiq.c index ce91fe83..8ad9e0b2 100644 --- a/tc/q_multiq.c +++ b/tc/q_multiq.c @@ -40,7 +40,7 @@ static void explain(void) } static int multiq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct tc_multiq_qopt opt = {}; diff --git a/tc/q_netem.c b/tc/q_netem.c index 82eb46f2..9f9a9b3d 100644 --- a/tc/q_netem.c +++ b/tc/q_netem.c @@ -59,20 +59,6 @@ static void set_percent(__u32 *percent, double per) *percent = rint(per * UINT32_MAX); } -/* Parse either a fraction '.3' or percent '30% - * return: 0 = ok, -1 = error, 1 = out of range - */ -static int parse_percent(double *val, const char *str) -{ - char *p; - - *val = strtod(str, &p) / 100.; - if (*p && strcmp(p, "%")) - return -1; - - return 0; -} - static int get_percent(__u32 *percent, const char *str) { double per; @@ -167,7 +153,7 @@ static int get_ticks(__u32 *ticks, const char *str) } static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { int dist_size = 0; struct rtattr *tail; @@ -396,7 +382,12 @@ static int netem_parse_opt(struct qdisc_util *qu, int argc, char **argv, } else if (matches(*argv, "rate") == 0) { ++present[TCA_NETEM_RATE]; NEXT_ARG(); - if (get_rate64(&rate64, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate64(&rate64, *argv, dev)) { + explain1("rate"); + return -1; + } + } else if (get_rate64(&rate64, *argv)) { explain1("rate"); return -1; } @@ -39,7 +39,7 @@ static void explain(void) #define BETA_MAX 32 static int pie_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { unsigned int limit = 0; unsigned int target = 0; diff --git a/tc/q_prio.c b/tc/q_prio.c index 677e25a3..358cf06c 100644 --- a/tc/q_prio.c +++ b/tc/q_prio.c @@ -27,7 +27,8 @@ static void explain(void) fprintf(stderr, "Usage: ... prio bands NUMBER priomap P1 P2...[multiqueue]\n"); } -static int prio_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int prio_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { int pmap_mode = 0; int idx = 0; @@ -35,7 +35,7 @@ static void explain_class(void) } static int qfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { if (argc > 0) { if (matches(*argv, "help") != 0) @@ -48,7 +48,7 @@ static int qfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, } static int qfq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct rtattr *tail; __u32 tmp; @@ -32,7 +32,8 @@ static void explain(void) fprintf(stderr, " [ecn] [harddrop]\n"); } -static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { struct tc_red_qopt opt = {}; unsigned int burst = 0; @@ -83,7 +84,12 @@ static int red_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl } } else if (strcmp(*argv, "bandwidth") == 0) { NEXT_ARG(); - if (get_rate(&rate, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate(&rate, *argv, dev)) { + fprintf(stderr, "Illegal \"bandwidth\"\n"); + return -1; + } + } else if (get_rate(&rate, *argv)) { fprintf(stderr, "Illegal \"bandwidth\"\n"); return -1; } @@ -28,7 +28,7 @@ static void explain(void) } -static int rr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int rr_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int pmap_mode = 0; int idx = 0; @@ -48,7 +48,7 @@ static int get_prob(__u32 *val, const char *arg) } static int sfb_parse_opt(struct qdisc_util *qu, int argc, char **argv, - struct nlmsghdr *n) + struct nlmsghdr *n, const char *dev) { struct tc_sfb_qopt opt = { .rehash_interval = 600*1000, @@ -34,7 +34,7 @@ static void explain(void) fprintf(stderr, " [ ecn ] [ harddrop ]\n"); } -static int sfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int sfq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { int ok = 0, red = 0; struct tc_sfq_qopt_v1 opt = {}; @@ -35,7 +35,8 @@ static void explain1(const char *arg, const char *val) } -static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, + struct nlmsghdr *n, const char *dev) { int ok = 0; struct tc_tbf_qopt opt = {}; @@ -125,7 +126,12 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl fprintf(stderr, "tbf: duplicate \"rate\" specification\n"); return -1; } - if (get_rate64(&rate64, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate64(&rate64, *argv, dev)) { + explain1("rate", *argv); + return -1; + } + } else if (get_rate64(&rate64, *argv)) { explain1("rate", *argv); return -1; } @@ -136,7 +142,12 @@ static int tbf_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nl fprintf(stderr, "tbf: duplicate \"peakrate\" specification\n"); return -1; } - if (get_rate64(&prate64, *argv)) { + if (strchr(*argv, '%')) { + if (get_percent_rate64(&prate64, *argv, dev)) { + explain1("peakrate", *argv); + return -1; + } + } else if (get_rate64(&prate64, *argv)) { explain1("peakrate", *argv); return -1; } diff --git a/tc/static-syms.c b/tc/static-syms.c index 0bc80743..47c4092c 100644 --- a/tc/static-syms.c +++ b/tc/static-syms.c @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ /* * This file creates a dummy version of dynamic loading * for environments where dynamic linking @@ -41,6 +41,7 @@ int batch_mode; int use_iec; int force; bool use_names; +int json; static char *conf_file; @@ -59,7 +60,7 @@ static int print_noqopt(struct qdisc_util *qu, FILE *f, return 0; } -static int parse_noqopt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n) +static int parse_noqopt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev) { if (argc) { fprintf(stderr, "Unknown qdisc \"%s\", hence option \"%s\" is unparsable\n", qu->id, *argv); @@ -189,7 +190,7 @@ static void usage(void) " tc [-force] -batch filename\n" "where OBJECT := { qdisc | class | filter | action | monitor | exec }\n" " OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -p[retty] | -b[atch] [filename] | -n[etns] name |\n" - " -nm | -nam[es] | { -cf | -conf } path }\n"); + " -nm | -nam[es] | { -cf | -conf } path } | -j[son]\n"); } static int do_cmd(int argc, char **argv) @@ -312,6 +313,8 @@ int main(int argc, char **argv) } else if (matches(argv[1], "-tshort") == 0) { ++timestamp; ++timestamp_short; + } else if (matches(argv[1], "-json") == 0) { + ++json; } else { fprintf(stderr, "Option \"%s\" is unknown, try \"tc -help\".\n", argv[1]); return -1; diff --git a/tc/tc_cbq.h b/tc/tc_cbq.h index 8f956490..fa17d249 100644 --- a/tc/tc_cbq.h +++ b/tc/tc_cbq.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TC_CBQ_H_ #define _TC_CBQ_H_ 1 diff --git a/tc/tc_class.c b/tc/tc_class.c index c4a6a250..1b214b82 100644 --- a/tc/tc_class.c +++ b/tc/tc_class.c @@ -67,8 +67,8 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv) }; struct qdisc_util *q = NULL; struct tc_estimator est = {}; - char d[16] = {}; - char k[16] = {}; + char d[IFNAMSIZ] = {}; + char k[FILTER_NAMESZ] = {}; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { @@ -128,7 +128,7 @@ static int tc_class_modify(int cmd, unsigned int flags, int argc, char **argv) fprintf(stderr, "Error: Qdisc \"%s\" is classless.\n", k); return 1; } - if (q->parse_copt(q, argc, argv, &req.n)) + if (q->parse_copt(q, argc, argv, &req.n, d)) return 1; } else { if (argc) { @@ -388,7 +388,7 @@ int print_class(const struct sockaddr_nl *who, static int tc_class_list(int argc, char **argv) { struct tcmsg t = { .tcm_family = AF_UNSPEC }; - char d[16] = {}; + char d[IFNAMSIZ] = {}; char buf[1024] = {0}; filter_qdisc = 0; diff --git a/tc/tc_common.h b/tc/tc_common.h index a2f38984..264fbdac 100644 --- a/tc/tc_common.h +++ b/tc/tc_common.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #define TCA_BUF_MAX (64*1024) diff --git a/tc/tc_core.h b/tc/tc_core.h index 8a63b79c..1dfa9a4f 100644 --- a/tc/tc_core.h +++ b/tc/tc_core.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TC_CORE_H_ #define _TC_CORE_H_ 1 diff --git a/tc/tc_exec.c b/tc/tc_exec.c index d23a825d..0151af7b 100644 --- a/tc/tc_exec.c +++ b/tc/tc_exec.c @@ -84,7 +84,7 @@ noexist: int do_exec(int argc, char **argv) { struct exec_util *eu; - char kind[16] = {}; + char kind[FILTER_NAMESZ] = {}; if (argc < 1) { fprintf(stderr, "No command given, try \"tc exec help\".\n"); diff --git a/tc/tc_filter.c b/tc/tc_filter.c index d0c967a9..545cc3a1 100644 --- a/tc/tc_filter.c +++ b/tc/tc_filter.c @@ -61,8 +61,8 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv) __u32 chain_index; int chain_index_set = 0; char *fhandle = NULL; - char d[16] = {}; - char k[16] = {}; + char d[IFNAMSIZ] = {}; + char k[FILTER_NAMESZ] = {}; struct tc_estimator est = {}; if (cmd == RTM_NEWTFILTER && flags & NLM_F_CREATE) @@ -160,6 +160,16 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv) if (k[0]) addattr_l(&req.n, sizeof(req), TCA_KIND, k, strlen(k)+1); + if (d[0]) { + ll_init_map(&rth); + + req.t.tcm_ifindex = ll_name_to_index(d); + if (req.t.tcm_ifindex == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", d); + return 1; + } + } + if (q) { if (q->parse_fopt(q, fhandle, argc, argv, &req.n)) return 1; @@ -182,17 +192,6 @@ static int tc_filter_modify(int cmd, unsigned int flags, int argc, char **argv) if (est.ewma_log) addattr_l(&req.n, sizeof(req), TCA_RATE, &est, sizeof(est)); - - if (d[0]) { - ll_init_map(&rth); - - req.t.tcm_ifindex = ll_name_to_index(d); - if (req.t.tcm_ifindex == 0) { - fprintf(stderr, "Cannot find device \"%s\"\n", d); - return 1; - } - } - if (rtnl_talk(&rth, &req.n, NULL) < 0) { fprintf(stderr, "We have an error talking to the kernel\n"); return 2; @@ -237,33 +236,36 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) return -1; } + open_json_object(NULL); + if (n->nlmsg_type == RTM_DELTFILTER) - fprintf(fp, "deleted "); + print_bool(PRINT_ANY, "deleted", "deleted ", true); if (n->nlmsg_type == RTM_NEWTFILTER && (n->nlmsg_flags & NLM_F_CREATE) && !(n->nlmsg_flags & NLM_F_EXCL)) - fprintf(fp, "replaced "); + print_bool(PRINT_ANY, "replaced", "replaced ", true); if (n->nlmsg_type == RTM_NEWTFILTER && (n->nlmsg_flags & NLM_F_CREATE) && (n->nlmsg_flags & NLM_F_EXCL)) - fprintf(fp, "added "); + print_bool(PRINT_ANY, "added", "added ", true); - fprintf(fp, "filter "); + print_string(PRINT_FP, NULL, "filter ", NULL); if (!filter_ifindex || filter_ifindex != t->tcm_ifindex) - fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex)); + print_string(PRINT_ANY, "dev", "dev %s ", + ll_index_to_name(t->tcm_ifindex)); if (!filter_parent || filter_parent != t->tcm_parent) { if (t->tcm_parent == TC_H_ROOT) - fprintf(fp, "root "); + print_bool(PRINT_ANY, "root", "root ", true); else if (t->tcm_parent == TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS)) - fprintf(fp, "ingress "); + print_bool(PRINT_ANY, "ingress", "ingress ", true); else if (t->tcm_parent == TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS)) - fprintf(fp, "egress "); + print_bool(PRINT_ANY, "egress", "egress ", true); else { print_tc_classid(abuf, sizeof(abuf), t->tcm_parent); - fprintf(fp, "parent %s ", abuf); + print_string(PRINT_ANY, "parent", "parent %s ", abuf); } } @@ -274,39 +276,45 @@ int print_filter(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) if (!filter_protocol || filter_protocol != f_proto) { if (f_proto) { SPRINT_BUF(b1); - fprintf(fp, "protocol %s ", - ll_proto_n2a(f_proto, b1, sizeof(b1))); + print_string(PRINT_JSON, "protocol", + "protocol %s ", + ll_proto_n2a(f_proto, b1, sizeof(b1))); } } if (!filter_prio || filter_prio != prio) { if (prio) - fprintf(fp, "pref %u ", prio); + print_uint(PRINT_ANY, "pref", "pref %u ", prio); } } - fprintf(fp, "%s ", rta_getattr_str(tb[TCA_KIND])); + print_string(PRINT_ANY, "kind", "%s ", rta_getattr_str(tb[TCA_KIND])); if (tb[TCA_CHAIN]) { __u32 chain_index = rta_getattr_u32(tb[TCA_CHAIN]); if (!filter_chain_index_set || filter_chain_index != chain_index) - fprintf(fp, "chain %u ", chain_index); + print_uint(PRINT_ANY, "chain", "chain %u ", + chain_index); } q = get_filter_kind(RTA_DATA(tb[TCA_KIND])); if (tb[TCA_OPTIONS]) { + open_json_object("options"); if (q) q->print_fopt(q, fp, tb[TCA_OPTIONS], t->tcm_handle); else - fprintf(fp, "[cannot parse parameters]"); + print_string(PRINT_FP, NULL, + "[cannot parse parameters]", NULL); + close_json_object(); } - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, "\n", NULL); if (show_stats && (tb[TCA_STATS] || tb[TCA_STATS2])) { print_tcstats_attr(fp, tb, " ", NULL); - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, "\n", NULL); } + close_json_object(); fflush(fp); return 0; } @@ -339,8 +347,8 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv) int chain_index_set = 0; __u32 parent_handle = 0; char *fhandle = NULL; - char d[16] = {}; - char k[16] = {}; + char d[IFNAMSIZ] = {}; + char k[FILTER_NAMESZ] = {}; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { @@ -452,10 +460,23 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv) return -1; } + if (d[0]) { + ll_init_map(&rth); + + req.t.tcm_ifindex = ll_name_to_index(d); + if (req.t.tcm_ifindex == 0) { + fprintf(stderr, "Cannot find device \"%s\"\n", d); + return 1; + } + filter_ifindex = req.t.tcm_ifindex; + } else { + fprintf(stderr, "Must specify netdevice \"dev\"\n"); + return -1; + } + if (q->parse_fopt(q, fhandle, argc, argv, &req.n)) return 1; - if (!fhandle) { fprintf(stderr, "Must specify filter \"handle\"\n"); return -1; @@ -470,26 +491,14 @@ static int tc_filter_get(int cmd, unsigned int flags, int argc, char **argv) return -1; } - if (d[0]) { - ll_init_map(&rth); - - req.t.tcm_ifindex = ll_name_to_index(d); - if (req.t.tcm_ifindex == 0) { - fprintf(stderr, "Cannot find device \"%s\"\n", d); - return 1; - } - filter_ifindex = req.t.tcm_ifindex; - } else { - fprintf(stderr, "Must specify netdevice \"dev\"\n"); - return -1; - } - if (rtnl_talk(&rth, &req.n, &answer) < 0) { fprintf(stderr, "We have an error talking to the kernel\n"); return 2; } + new_json_obj(json); print_filter(NULL, answer, (void *)stdout); + delete_json_obj(); free(answer); return 0; @@ -507,7 +516,7 @@ static int tc_filter_list(int argc, char **argv) .t.tcm_parent = TC_H_UNSPEC, .t.tcm_family = AF_UNSPEC, }; - char d[16] = {}; + char d[IFNAMSIZ] = {}; __u32 prio = 0; __u32 protocol = 0; __u32 chain_index; @@ -617,10 +626,12 @@ static int tc_filter_list(int argc, char **argv) return 1; } + new_json_obj(json); if (rtnl_dump_filter(&rth, print_filter, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } + delete_json_obj(); return 0; } diff --git a/tc/tc_qdisc.c b/tc/tc_qdisc.c index fcb75f29..4431d5fd 100644 --- a/tc/tc_qdisc.c +++ b/tc/tc_qdisc.c @@ -49,8 +49,8 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv) struct tc_sizespec szopts; __u16 *data; } stab = {}; - char d[16] = {}; - char k[16] = {}; + char d[IFNAMSIZ] = {}; + char k[FILTER_NAMESZ] = {}; struct { struct nlmsghdr n; struct tcmsg t; @@ -140,7 +140,7 @@ static int tc_qdisc_modify(int cmd, unsigned int flags, int argc, char **argv) if (q) { if (q->parse_qopt) { - if (q->parse_qopt(q, argc, argv, &req.n)) + if (q->parse_qopt(q, argc, argv, &req.n, d)) return 1; } else if (argc) { fprintf(stderr, "qdisc '%s' does not support option parsing\n", k); @@ -227,39 +227,44 @@ int print_qdisc(const struct sockaddr_nl *who, return -1; } + open_json_object(NULL); + if (n->nlmsg_type == RTM_DELQDISC) - fprintf(fp, "deleted "); + print_bool(PRINT_ANY, "deleted", "deleted ", true); if (n->nlmsg_type == RTM_NEWQDISC && (n->nlmsg_flags & NLM_F_CREATE) && (n->nlmsg_flags & NLM_F_REPLACE)) - fprintf(fp, "replaced "); + print_bool(PRINT_ANY, "replaced", "replaced ", true); if (n->nlmsg_type == RTM_NEWQDISC && (n->nlmsg_flags & NLM_F_CREATE) && (n->nlmsg_flags & NLM_F_EXCL)) - fprintf(fp, "added "); - - if (show_raw) - fprintf(fp, "qdisc %s %x:[%08x] ", - rta_getattr_str(tb[TCA_KIND]), - t->tcm_handle >> 16, t->tcm_handle); - else - fprintf(fp, "qdisc %s %x: ", rta_getattr_str(tb[TCA_KIND]), - t->tcm_handle >> 16); + print_bool(PRINT_ANY, "added", "added ", true); + + print_string(PRINT_ANY, "kind", "qdisc %s", + rta_getattr_str(tb[TCA_KIND])); + sprintf(abuf, "%x:", t->tcm_handle >> 16); + print_string(PRINT_ANY, "handle", " %s", abuf); + if (show_raw) { + sprintf(abuf, "[%08x]", t->tcm_handle); + print_string(PRINT_FP, NULL, "%s", abuf); + } + print_string(PRINT_FP, NULL, " ", NULL); if (filter_ifindex == 0) - fprintf(fp, "dev %s ", ll_index_to_name(t->tcm_ifindex)); + print_string(PRINT_ANY, "dev", "dev %s ", + ll_index_to_name(t->tcm_ifindex)); if (t->tcm_parent == TC_H_ROOT) - fprintf(fp, "root "); + print_bool(PRINT_ANY, "root", "root ", true); else if (t->tcm_parent) { print_tc_classid(abuf, sizeof(abuf), t->tcm_parent); - fprintf(fp, "parent %s ", abuf); + print_string(PRINT_ANY, "parent", "parent %s ", abuf); } if (t->tcm_info != 1) - fprintf(fp, "refcnt %d ", t->tcm_info); + print_uint(PRINT_ANY, "refcnt", "refcnt %u ", t->tcm_info); /* pfifo_fast is generic enough to warrant the hardcoding --JHS */ if (strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])) == 0) @@ -267,17 +272,21 @@ int print_qdisc(const struct sockaddr_nl *who, else q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND])); + open_json_object("options"); if (tb[TCA_OPTIONS]) { if (q) q->print_qopt(q, fp, tb[TCA_OPTIONS]); else - fprintf(fp, "[cannot parse qdisc parameters]"); + print_string(PRINT_FP, NULL, + "[cannot parse qdisc parameters]", NULL); } - fprintf(fp, "\n"); + close_json_object(); + + print_string(PRINT_FP, NULL, "\n", NULL); if (show_details && tb[TCA_STAB]) { print_size_table(fp, " ", tb[TCA_STAB]); - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, "\n", NULL); } if (show_stats) { @@ -285,14 +294,15 @@ int print_qdisc(const struct sockaddr_nl *who, if (tb[TCA_STATS] || tb[TCA_STATS2] || tb[TCA_XSTATS]) { print_tcstats_attr(fp, tb, " ", &xstats); - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, "\n", NULL); } if (q && xstats && q->print_xstats) { q->print_xstats(q, fp, xstats); - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, "\n", NULL); } } + close_json_object(); fflush(fp); return 0; } @@ -300,7 +310,7 @@ int print_qdisc(const struct sockaddr_nl *who, static int tc_qdisc_list(int argc, char **argv) { struct tcmsg t = { .tcm_family = AF_UNSPEC }; - char d[16] = {}; + char d[IFNAMSIZ] = {}; bool dump_invisible = false; while (argc > 0) { @@ -360,10 +370,12 @@ static int tc_qdisc_list(int argc, char **argv) return 1; } + new_json_obj(json); if (rtnl_dump_filter(&rth, print_qdisc, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return 1; } + delete_json_obj(); return 0; } diff --git a/tc/tc_red.h b/tc/tc_red.h index 6f6b09e3..88fba58b 100644 --- a/tc/tc_red.h +++ b/tc/tc_red.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TC_RED_H_ #define _TC_RED_H_ 1 diff --git a/tc/tc_util.c b/tc/tc_util.c index 197953ab..18879056 100644 --- a/tc/tc_util.c +++ b/tc/tc_util.c @@ -190,6 +190,69 @@ static const struct rate_suffix { { NULL } }; +int parse_percent_rate(char *rate, const char *str, const char *dev) +{ + long dev_mbit; + int ret; + double perc, rate_mbit; + char *str_perc; + + if (!dev[0]) { + fprintf(stderr, "No device specified; specify device to rate limit by percentage\n"); + return -1; + } + + if (read_prop(dev, "speed", &dev_mbit)) + return -1; + + ret = sscanf(str, "%m[0-9.%]", &str_perc); + if (ret != 1) + goto malf; + + if (parse_percent(&perc, str_perc)) + goto malf; + + free(str_perc); + + if (perc > 1.0 || perc < 0.0) { + fprintf(stderr, "Invalid rate specified; should be between [0,100]%% but is %s\n", str); + return -1; + } + + rate_mbit = perc * dev_mbit; + + ret = snprintf(rate, 20, "%lf", rate_mbit); + if (ret <= 0 || ret >= 20) { + fprintf(stderr, "Unable to parse calculated rate\n"); + return -1; + } + + return 0; + +malf: + fprintf(stderr, "Specified rate value could not be read or is malformed\n"); + return -1; +} + +int get_percent_rate(unsigned int *rate, const char *str, const char *dev) +{ + char r_str[20]; + + if (parse_percent_rate(r_str, str, dev)) + return -1; + + return get_rate(rate, r_str); +} + +int get_percent_rate64(__u64 *rate, const char *str, const char *dev) +{ + char r_str[20]; + + if (parse_percent_rate(r_str, str, dev)) + return -1; + + return get_rate64(rate, r_str); +} int get_rate(unsigned int *rate, const char *str) { @@ -646,12 +709,17 @@ int parse_action_control_slash(int *argc_p, char ***argv_p, void print_action_control(FILE *f, const char *prefix, int action, const char *suffix) { - fprintf(f, "%s%s", prefix, action_n2a(action)); + print_string(PRINT_FP, NULL, "%s", prefix); + open_json_object("control_action"); + print_string(PRINT_ANY, "type", "%s", action_n2a(action)); if (TC_ACT_EXT_CMP(action, TC_ACT_GOTO_CHAIN)) - fprintf(f, " chain %u", action & TC_ACT_EXT_VAL_MASK); + print_uint(PRINT_ANY, "chain", " chain %u", + action & TC_ACT_EXT_VAL_MASK); if (TC_ACT_EXT_CMP(action, TC_ACT_JUMP)) - fprintf(f, " %u", action & TC_ACT_EXT_VAL_MASK); - fprintf(f, "%s", suffix); + print_uint(PRINT_ANY, "jump", " %u", + action & TC_ACT_EXT_VAL_MASK); + close_json_object(); + print_string(PRINT_FP, NULL, "%s", suffix); } int get_linklayer(unsigned int *val, const char *arg) @@ -699,12 +767,21 @@ void print_tm(FILE *f, const struct tcf_t *tm) { int hz = get_user_hz(); - if (tm->install != 0) - fprintf(f, " installed %u sec", (unsigned int)(tm->install/hz)); - if (tm->lastuse != 0) - fprintf(f, " used %u sec", (unsigned int)(tm->lastuse/hz)); - if (tm->expires != 0) - fprintf(f, " expires %u sec", (unsigned int)(tm->expires/hz)); + if (tm->install != 0) { + print_uint(PRINT_JSON, "installed", NULL, tm->install); + print_uint(PRINT_FP, NULL, " installed %u sec", + (unsigned int)(tm->install/hz)); + } + if (tm->lastuse != 0) { + print_uint(PRINT_JSON, "last_used", NULL, tm->lastuse); + print_uint(PRINT_FP, NULL, " used %u sec", + (unsigned int)(tm->lastuse/hz)); + } + if (tm->expires != 0) { + print_uint(PRINT_JSON, "expires", NULL, tm->expires); + print_uint(PRINT_FP, NULL, " expires %u sec", + (unsigned int)(tm->expires/hz)); + } } void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats) @@ -718,16 +795,19 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat struct gnet_stats_basic bs = {0}; memcpy(&bs, RTA_DATA(tbs[TCA_STATS_BASIC]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_BASIC]), sizeof(bs))); - fprintf(fp, "%sSent %llu bytes %u pkt", - prefix, (unsigned long long) bs.bytes, bs.packets); + print_string(PRINT_FP, NULL, "%s", prefix); + print_lluint(PRINT_ANY, "bytes", "Sent %llu bytes", bs.bytes); + print_uint(PRINT_ANY, "packets", " %u pkt", bs.packets); } if (tbs[TCA_STATS_QUEUE]) { struct gnet_stats_queue q = {0}; memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q))); - fprintf(fp, " (dropped %u, overlimits %u requeues %u) ", - q.drops, q.overlimits, q.requeues); + print_uint(PRINT_ANY, "drops", " (dropped %u", q.drops); + print_uint(PRINT_ANY, "overlimits", ", overlimits %u", + q.overlimits); + print_uint(PRINT_ANY, "requeues", " requeues %u) ", q.requeues); } if (tbs[TCA_STATS_RATE_EST64]) { @@ -736,8 +816,11 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat memcpy(&re, RTA_DATA(tbs[TCA_STATS_RATE_EST64]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST64]), sizeof(re))); - fprintf(fp, "\n%srate %s %llupps ", - prefix, sprint_rate(re.bps, b1), re.pps); + print_string(PRINT_FP, NULL, "\n%s", prefix); + print_lluint(PRINT_JSON, "rate", NULL, re.bps); + print_string(PRINT_FP, NULL, "rate %s", + sprint_rate(re.bps, b1)); + print_lluint(PRINT_ANY, "pps", " %llupps", re.pps); } else if (tbs[TCA_STATS_RATE_EST]) { struct gnet_stats_rate_est re = {0}; @@ -745,6 +828,11 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat MIN(RTA_PAYLOAD(tbs[TCA_STATS_RATE_EST]), sizeof(re))); fprintf(fp, "\n%srate %s %upps ", prefix, sprint_rate(re.bps, b1), re.pps); + print_string(PRINT_FP, NULL, "\n%s", prefix); + print_uint(PRINT_JSON, "rate", NULL, re.bps); + print_string(PRINT_FP, NULL, "rate %s", + sprint_rate(re.bps, b1)); + print_uint(PRINT_ANY, "pps", " %upps", re.pps); } if (tbs[TCA_STATS_QUEUE]) { @@ -752,9 +840,12 @@ void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtat memcpy(&q, RTA_DATA(tbs[TCA_STATS_QUEUE]), MIN(RTA_PAYLOAD(tbs[TCA_STATS_QUEUE]), sizeof(q))); if (!tbs[TCA_STATS_RATE_EST]) - fprintf(fp, "\n%s", prefix); - fprintf(fp, "backlog %s %up requeues %u ", - sprint_size(q.backlog, b1), q.qlen, q.requeues); + print_string(PRINT_FP, NULL, "\n%s", prefix); + print_uint(PRINT_JSON, "backlog", NULL, q.backlog); + print_string(PRINT_FP, NULL, "backlog %s", + sprint_size(q.backlog, b1)); + print_uint(PRINT_ANY, "qlen", " %up", q.qlen); + print_uint(PRINT_ANY, "requeues", " requeues %u", q.qlen); } if (xstats) diff --git a/tc/tc_util.h b/tc/tc_util.h index 583a21a8..1218610d 100644 --- a/tc/tc_util.h +++ b/tc/tc_util.h @@ -1,12 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _TC_UTIL_H_ #define _TC_UTIL_H_ 1 #define MAX_MSG 16384 #include <limits.h> +#include <linux/if.h> + #include <linux/pkt_sched.h> #include <linux/pkt_cls.h> #include <linux/gen_stats.h> + #include "tc_core.h" +#include "json_print.h" /* This is the deprecated multiqueue interface */ #ifndef TCA_PRIO_MAX @@ -20,25 +25,27 @@ enum #define TCA_PRIO_MAX (__TCA_PRIO_MAX - 1) #endif +#define FILTER_NAMESZ 16 + struct qdisc_util { struct qdisc_util *next; const char *id; int (*parse_qopt)(struct qdisc_util *qu, int argc, - char **argv, struct nlmsghdr *n); + char **argv, struct nlmsghdr *n, const char *dev); int (*print_qopt)(struct qdisc_util *qu, FILE *f, struct rtattr *opt); int (*print_xstats)(struct qdisc_util *qu, FILE *f, struct rtattr *xstats); int (*parse_copt)(struct qdisc_util *qu, int argc, - char **argv, struct nlmsghdr *n); + char **argv, struct nlmsghdr *n, const char *dev); int (*print_copt)(struct qdisc_util *qu, FILE *f, struct rtattr *opt); }; extern __u16 f_proto; struct filter_util { struct filter_util *next; - char id[16]; + char id[FILTER_NAMESZ]; int (*parse_fopt)(struct filter_util *qu, char *fhandle, int argc, char **argv, struct nlmsghdr *n); int (*print_fopt)(struct filter_util *qu, @@ -47,7 +54,7 @@ struct filter_util { struct action_util { struct action_util *next; - char id[16]; + char id[FILTER_NAMESZ]; int (*parse_aopt)(struct action_util *a, int *argc, char ***argv, int code, struct nlmsghdr *n); int (*print_aopt)(struct action_util *au, FILE *f, struct rtattr *opt); @@ -57,7 +64,7 @@ struct action_util { struct exec_util { struct exec_util *next; - char id[16]; + char id[FILTER_NAMESZ]; int (*parse_eopt)(struct exec_util *eu, int argc, char **argv); }; @@ -66,9 +73,12 @@ const char *get_tc_lib(void); struct qdisc_util *get_qdisc_kind(const char *str); struct filter_util *get_filter_kind(const char *str); +int parse_percent_rate(char *rate, const char *str, const char *dev); int get_qdisc_handle(__u32 *h, const char *str); int get_rate(unsigned int *rate, const char *str); +int get_percent_rate(unsigned int *rate, const char *str, const char *dev); int get_rate64(__u64 *rate, const char *str); +int get_percent_rate64(__u64 *rate, const char *str, const char *dev); int get_size(unsigned int *size, const char *str); int get_size_and_cell(unsigned int *size, int *cell_log, char *str); int get_time(unsigned int *time, const char *str); diff --git a/testsuite/Makefile b/testsuite/Makefile index 055136b5..2a54e5c8 100644 --- a/testsuite/Makefile +++ b/testsuite/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 ## -- Config -- DEV := lo PREFIX := sudo -E unshare -n diff --git a/testsuite/iproute2/Makefile b/testsuite/iproute2/Makefile index ba128aa7..b8a7d515 100644 --- a/testsuite/iproute2/Makefile +++ b/testsuite/iproute2/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 SUBDIRS := $(filter-out Makefile,$(wildcard *)) .PHONY: all configure clean distclean show $(SUBDIRS) diff --git a/testsuite/tools/Makefile b/testsuite/tools/Makefile index 9581de51..f2cdc980 100644 --- a/testsuite/tools/Makefile +++ b/testsuite/tools/Makefile @@ -1,2 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.c $(CC) -o $@ $^ diff --git a/tipc/Makefile b/tipc/Makefile index d3c957e2..abd33ab0 100644 --- a/tipc/Makefile +++ b/tipc/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 include ../config.mk ifeq ($(HAVE_MNL),y) |