summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Hemminger <stephen@networkplumber.org>2017-11-28 09:53:28 -0800
committerStephen Hemminger <stephen@networkplumber.org>2017-11-28 09:53:28 -0800
commitf6351157b94b3589e1bb1348bc114a465769f10f (patch)
tree0516bebc390b737ff85dcf3589e856367d7d3d8c
parentb2a2d9530c889324f788d463893f0d457acb31da (diff)
parent615634c30e5b673367b6f31c527b227a37692beb (diff)
downloadiproute2-f6351157b94b3589e1bb1348bc114a465769f10f.tar.gz
Merge branch 'master' into net-next
-rw-r--r--Makefile1
-rw-r--r--bridge/Makefile1
-rw-r--r--bridge/br_common.h2
-rw-r--r--bridge/bridge.c1
-rw-r--r--bridge/fdb.c1
-rw-r--r--bridge/link.c1
-rw-r--r--bridge/mdb.c1
-rw-r--r--bridge/vlan.c1
-rwxr-xr-xconfigure1
-rw-r--r--devlink/Makefile1
-rw-r--r--examples/bpf/bpf_tailcall.c1
-rw-r--r--genl/Makefile1
-rw-r--r--genl/genl_utils.h1
-rw-r--r--genl/static-syms.c1
-rw-r--r--include/bpf_api.h1
-rw-r--r--include/bpf_elf.h1
-rw-r--r--include/bpf_scm.h1
-rw-r--r--include/bpf_util.h25
-rw-r--r--include/color.h1
-rw-r--r--include/dlfcn.h1
-rw-r--r--include/ip6tables.h1
-rw-r--r--include/iptables.h1
-rw-r--r--include/iptables/internal.h1
-rw-r--r--include/libgenl.h1
-rw-r--r--include/libiptc/ipt_kernel_headers.h1
-rw-r--r--include/libiptc/libip6tc.h1
-rw-r--r--include/libiptc/libiptc.h1
-rw-r--r--include/libiptc/libxtc.h1
-rw-r--r--include/libiptc/xtcshared.h1
-rw-r--r--include/libnetlink.h1
-rw-r--r--include/list.h1
-rw-r--r--include/ll_map.h1
-rw-r--r--include/names.h1
-rw-r--r--include/namespace.h1
-rw-r--r--include/rt_names.h1
-rw-r--r--include/rtm_map.h1
-rw-r--r--include/utils.h3
-rw-r--r--include/xt-internal.h1
-rw-r--r--include/xtables.h1
-rw-r--r--ip/Makefile1
-rw-r--r--ip/ifcfg1
-rw-r--r--ip/ila_common.h1
-rw-r--r--ip/ip_common.h1
-rw-r--r--ip/iplink.c4
-rw-r--r--ip/iplink_dummy.c1
-rw-r--r--ip/iplink_ifb.c1
-rw-r--r--ip/iplink_nlmon.c1
-rw-r--r--ip/iplink_team.c1
-rw-r--r--ip/iplink_vcan.c1
-rw-r--r--ip/iplink_vxlan.c5
-rw-r--r--ip/iplink_xdp.c13
-rw-r--r--ip/ipnetns.c1
-rw-r--r--ip/iproute_lwtunnel.c3
-rw-r--r--ip/iproute_lwtunnel.h1
-rw-r--r--ip/iptuntap.c32
-rw-r--r--ip/link_gre.c3
-rw-r--r--ip/link_gre6.c2
-rw-r--r--ip/routef1
-rw-r--r--ip/routel2
-rw-r--r--ip/rtpr1
-rw-r--r--ip/static-syms.c1
-rw-r--r--ip/xdp.h5
-rw-r--r--lib/Makefile1
-rw-r--r--lib/bpf.c155
-rw-r--r--lib/color.c1
-rw-r--r--lib/dnet_ntop.c1
-rw-r--r--lib/dnet_pton.c1
-rw-r--r--lib/exec.c1
-rw-r--r--lib/ipx_ntop.c1
-rw-r--r--lib/ipx_pton.c1
-rw-r--r--lib/libgenl.c1
-rw-r--r--lib/mpls_ntop.c2
-rw-r--r--lib/mpls_pton.c2
-rw-r--r--lib/utils.c68
-rw-r--r--man/Makefile1
-rw-r--r--man/man3/Makefile1
-rw-r--r--man/man7/Makefile1
-rw-r--r--man/man8/Makefile1
-rw-r--r--man/man8/tc.812
-rw-r--r--misc/Makefile1
-rw-r--r--misc/lnstat.h1
-rw-r--r--misc/ssfilter.h1
-rw-r--r--netem/Makefile1
-rw-r--r--rdma/Makefile1
-rw-r--r--tc/Makefile1
-rw-r--r--tc/emp_ematch.l1
-rw-r--r--tc/f_bpf.c18
-rw-r--r--tc/f_flower.c287
-rw-r--r--tc/f_matchall.c12
-rw-r--r--tc/f_rsvp.c3
-rw-r--r--tc/f_tcindex.c1
-rw-r--r--tc/m_action.c114
-rw-r--r--tc/m_bpf.c6
-rw-r--r--tc/m_ematch.h1
-rw-r--r--tc/m_gact.c35
-rw-r--r--tc/m_ipt.c2
-rw-r--r--tc/m_mirred.c122
-rw-r--r--tc/m_pedit.c2
-rw-r--r--tc/m_vlan.c91
-rw-r--r--tc/m_xt.c2
-rw-r--r--tc/m_xt_old.c2
-rw-r--r--tc/q_atm.c6
-rw-r--r--tc/q_cbq.c25
-rw-r--r--tc/q_cbs.c3
-rw-r--r--tc/q_choke.c9
-rw-r--r--tc/q_clsact.c3
-rw-r--r--tc/q_codel.c2
-rw-r--r--tc/q_drr.c5
-rw-r--r--tc/q_dsmark.c5
-rw-r--r--tc/q_fifo.c3
-rw-r--r--tc/q_fq.c16
-rw-r--r--tc/q_fq_codel.c27
-rw-r--r--tc/q_gred.c9
-rw-r--r--tc/q_hfsc.c49
-rw-r--r--tc/q_hhf.c3
-rw-r--r--tc/q_htb.c40
-rw-r--r--tc/q_ingress.c2
-rw-r--r--tc/q_mqprio.c2
-rw-r--r--tc/q_multiq.c2
-rw-r--r--tc/q_netem.c23
-rw-r--r--tc/q_pie.c2
-rw-r--r--tc/q_prio.c3
-rw-r--r--tc/q_qfq.c4
-rw-r--r--tc/q_red.c10
-rw-r--r--tc/q_rr.c2
-rw-r--r--tc/q_sfb.c2
-rw-r--r--tc/q_sfq.c2
-rw-r--r--tc/q_tbf.c17
-rw-r--r--tc/static-syms.c1
-rw-r--r--tc/tc.c7
-rw-r--r--tc/tc_cbq.h1
-rw-r--r--tc/tc_class.c8
-rw-r--r--tc/tc_common.h1
-rw-r--r--tc/tc_core.h1
-rw-r--r--tc/tc_exec.c2
-rw-r--r--tc/tc_filter.c107
-rw-r--r--tc/tc_qdisc.c60
-rw-r--r--tc/tc_red.h1
-rw-r--r--tc/tc_util.c129
-rw-r--r--tc/tc_util.h20
-rw-r--r--testsuite/Makefile1
-rw-r--r--testsuite/iproute2/Makefile1
-rw-r--r--testsuite/tools/Makefile1
-rw-r--r--tipc/Makefile1
144 files changed, 1134 insertions, 589 deletions
diff --git a/Makefile b/Makefile
index 6ad96104..6a51e0db 100644
--- a/Makefile
+++ b/Makefile
@@ -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>
diff --git a/configure b/configure
index f0668ab3..d6832464 100755
--- a/configure
+++ b/configure
@@ -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 \
diff --git a/ip/ifcfg b/ip/ifcfg
index 30a2dc49..851b9215 100644
--- a/ip/ifcfg
+++ b/ip/ifcfg
@@ -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;
diff --git a/ip/routef b/ip/routef
index d266e2d9..c251e7b8 100644
--- a/ip/routef
+++ b/ip/routef
@@ -1,4 +1,5 @@
#! /bin/sh
+# SPDX-License-Identifier: GPL-2.0
if [ -z "$*" ] ; then
exec ip -4 ro flush scope global type unicast
diff --git a/ip/routel b/ip/routel
index 9a30462a..7056886d 100644
--- a/ip/routel
+++ b/ip/routel
@@ -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
diff --git a/ip/rtpr b/ip/rtpr
index c3629fd6..192a476f 100644
--- a/ip/rtpr
+++ b/ip/rtpr
@@ -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
diff --git a/ip/xdp.h b/ip/xdp.h
index 1efd591b..7e10696a 100644
--- a/ip/xdp.h
+++ b/ip/xdp.h
@@ -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
diff --git a/lib/bpf.c b/lib/bpf.c
index fdc28772..d32f1b80 100644
--- a/lib/bpf.c
+++ b/lib/bpf.c
@@ -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>
diff --git a/lib/exec.c b/lib/exec.c
index 97c99120..eb36b59d 100644
--- a/lib/exec.c
+++ b/lib/exec.c
@@ -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"
diff --git a/tc/f_bpf.c b/tc/f_bpf.c
index 3f619d0d..5906f8bb 100644
--- a/tc/f_bpf.c
+++ b/tc/f_bpf.c
@@ -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, &eth_type, tb[TCA_FLOWER_KEY_ETH_TYPE]);
- flower_print_ip_proto(f, &ip_proto, tb[TCA_FLOWER_KEY_IP_PROTO]);
+ flower_print_eth_type(&eth_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;
}
diff --git a/tc/m_bpf.c b/tc/m_bpf.c
index e3d0a2b1..1c1f71cd 100644
--- a/tc/m_bpf.c
+++ b/tc/m_bpf.c
@@ -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;
}
diff --git a/tc/m_ipt.c b/tc/m_ipt.c
index 942b4f23..1c3c240f 100644
--- a/tc/m_ipt.c
+++ b/tc/m_ipt.c
@@ -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;
}
diff --git a/tc/m_xt.c b/tc/m_xt.c
index 0baea33c..a1137be9 100644
--- a/tc/m_xt.c
+++ b/tc/m_xt.c
@@ -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;
diff --git a/tc/q_atm.c b/tc/q_atm.c
index 570e7be5..3ea4cf4e 100644
--- a/tc/q_atm.c
+++ b/tc/q_atm.c
@@ -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;
diff --git a/tc/q_cbq.c b/tc/q_cbq.c
index e00d4e38..d05fe9c8 100644
--- a/tc/q_cbq.c
+++ b/tc/q_cbq.c
@@ -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;
}
diff --git a/tc/q_cbs.c b/tc/q_cbs.c
index ec1cbe83..b5739057 100644
--- a/tc/q_cbs.c
+++ b/tc/q_cbs.c
@@ -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;
diff --git a/tc/q_drr.c b/tc/q_drr.c
index 50623c22..5e541c09 100644
--- a/tc/q_drr.c
+++ b/tc/q_drr.c
@@ -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 = {};
diff --git a/tc/q_fq.c b/tc/q_fq.c
index 49ebeefa..51b5bc36 100644
--- a/tc/q_fq.c
+++ b/tc/q_fq.c
@@ -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) {
diff --git a/tc/q_hhf.c b/tc/q_hhf.c
index d1f15f9a..66c71886 100644
--- a/tc/q_hhf.c
+++ b/tc/q_hhf.c
@@ -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;
diff --git a/tc/q_htb.c b/tc/q_htb.c
index db828523..3fc2acb3 100644
--- a/tc/q_htb.c
+++ b/tc/q_htb.c
@@ -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;
}
diff --git a/tc/q_pie.c b/tc/q_pie.c
index db72add3..b89f53c7 100644
--- a/tc/q_pie.c
+++ b/tc/q_pie.c
@@ -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;
diff --git a/tc/q_qfq.c b/tc/q_qfq.c
index fa270c8a..d70ca1ba 100644
--- a/tc/q_qfq.c
+++ b/tc/q_qfq.c
@@ -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;
diff --git a/tc/q_red.c b/tc/q_red.c
index 1564d6ef..1949558f 100644
--- a/tc/q_red.c
+++ b/tc/q_red.c
@@ -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;
}
diff --git a/tc/q_rr.c b/tc/q_rr.c
index 71ce3ce5..843a4fae 100644
--- a/tc/q_rr.c
+++ b/tc/q_rr.c
@@ -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;
diff --git a/tc/q_sfb.c b/tc/q_sfb.c
index d074e87b..4b366ddd 100644
--- a/tc/q_sfb.c
+++ b/tc/q_sfb.c
@@ -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,
diff --git a/tc/q_sfq.c b/tc/q_sfq.c
index a875abd3..6a1d853b 100644
--- a/tc/q_sfq.c
+++ b/tc/q_sfq.c
@@ -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 = {};
diff --git a/tc/q_tbf.c b/tc/q_tbf.c
index 4955ee49..dfaa5d38 100644
--- a/tc/q_tbf.c
+++ b/tc/q_tbf.c
@@ -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
diff --git a/tc/tc.c b/tc/tc.c
index fa71250d..ad9f07e9 100644
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -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)