1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter-feeds.git synced 2025-03-09 15:40:03 +00:00

fix iproute2

This commit is contained in:
suyuan168 2022-04-08 09:10:51 +08:00
parent 4aa9e90a71
commit 1ba4fd626b
23 changed files with 3400 additions and 140 deletions

View file

@ -8,13 +8,12 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=iproute2 PKG_NAME:=iproute2
PKG_RELEASE:=$(AUTORELEASE) PKG_VERSION:=5.0.0
PKG_RELEASE:=2.1
PKG_SOURCE_PROTO:=git
PKG_SOURCE_URL:=git://git.kernel.org/pub/scm/network/iproute2/iproute2.git
PKG_SOURCE_VERSION:=29da83f89f6e1fe528c59131a01f5d43bcd0a000
PKG_VERSION:=5.16.0-$(PKG_SOURCE_VERSION)
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2
PKG_HASH:=df047302a39650ef832c07e8dab5df7a23218cd398bd310c8628e386161d20ba
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_BUILD_DEPENDS:=iptables PKG_BUILD_DEPENDS:=iptables
PKG_LICENSE:=GPL-2.0 PKG_LICENSE:=GPL-2.0
@ -34,8 +33,8 @@ endef
define Package/ip-tiny define Package/ip-tiny
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Routing control utility (minimal) TITLE:=Routing control utility (Minimal)
VARIANT:=iptiny VARIANT:=tiny
DEFAULT_VARIANT:=1 DEFAULT_VARIANT:=1
PROVIDES:=ip PROVIDES:=ip
ALTERNATIVES:=200:/sbin/ip:/usr/libexec/ip-tiny ALTERNATIVES:=200:/sbin/ip:/usr/libexec/ip-tiny
@ -44,92 +43,68 @@ endef
define Package/ip-full define Package/ip-full
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Routing control utility (full) TITLE:=Routing control utility (Full)
VARIANT:=ipfull VARIANT:=full
PROVIDES:=ip PROVIDES:=ip
ALTERNATIVES:=300:/sbin/ip:/usr/libexec/ip-full ALTERNATIVES:=300:/sbin/ip:/usr/libexec/ip-full
DEPENDS:=+libnl-tiny +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl DEPENDS:=+libnl-tiny +libelf +(PACKAGE_devlink||PACKAGE_rdma):libmnl +libcap
endef endef
define Package/tc-tiny define Package/tc
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Traffic control utility (minimal) TITLE:=Traffic control utility
VARIANT:=tctiny VARIANT:=tc
DEFAULT_VARIANT:=1
PROVIDES:=tc PROVIDES:=tc
ALTERNATIVES:=200:/sbin/tc:/usr/libexec/tc-tiny DEPENDS:=+kmod-sched-core +libxtables +libelf +(PACKAGE_devlink||PACKAGE_rdma):libmnl +PACKAGE_ip-full:libcap
DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +(PACKAGE_devlink||PACKAGE_rdma):libmnl
endef
define Package/tc-full
$(call Package/iproute2/Default)
TITLE:=Traffic control utility (full)
VARIANT:=tcfull
PROVIDES:=tc
ALTERNATIVES:=300:/sbin/tc:/usr/libexec/tc-full
DEPENDS:=+kmod-sched-core +libxtables +tc-mod-iptables +libbpf +(PACKAGE_devlink||PACKAGE_rdma):libmnl
endef
define Package/tc-mod-iptables
$(call Package/iproute2/Default)
TITLE:=Traffic control module - iptables action
DEPENDS:=+libxtables
endef endef
define Package/genl define Package/genl
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=General netlink utility frontend TITLE:=General netlink utility frontend
DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
define Package/ip-bridge define Package/ip-bridge
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Bridge configuration utility from iproute2 TITLE:=Bridge configuration utility from iproute2
DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
define Package/ss define Package/ss
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Socket statistics utility TITLE:=Socket statistics utility
DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +kmod-netlink-diag DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
define Package/nstat define Package/nstat
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Network statistics utility TITLE:=Network statistics utility
DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl DEPENDS:=+libnl-tiny +(PACKAGE_devlink||PACKAGE_rdma):libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
define Package/devlink define Package/devlink
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Network devlink utility TITLE:=Network devlink utility
DEPENDS:=+libmnl DEPENDS:=+libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
define Package/rdma define Package/rdma
$(call Package/iproute2/Default) $(call Package/iproute2/Default)
TITLE:=Network rdma utility TITLE:=Network rdma utility
DEPENDS:=+libmnl DEPENDS:=+libmnl +(PACKAGE_tc||PACKAGE_ip-full):libelf +PACKAGE_ip-full:libcap
endef endef
ifeq ($(BUILD_VARIANT),iptiny) ifeq ($(BUILD_VARIANT),tiny)
IP_CONFIG_TINY:=y IP_CONFIG_TINY:=y
LIBBPF_FORCE:=off
endif endif
ifeq ($(BUILD_VARIANT),ipfull) ifeq ($(BUILD_VARIANT),full)
HAVE_ELF:=y HAVE_ELF:=y
LIBBPF_FORCE:=on HAVE_CAP:=y
endif endif
ifeq ($(BUILD_VARIANT),tctiny) ifeq ($(BUILD_VARIANT),tc)
LIBBPF_FORCE:=off
SHARED_LIBS:=y
endif
ifeq ($(BUILD_VARIANT),tcfull)
HAVE_ELF:=y HAVE_ELF:=y
LIBBPF_FORCE:=on
SHARED_LIBS:=y SHARED_LIBS:=y
endif endif
@ -146,31 +121,27 @@ define Build/Configure
> $(PKG_BUILD_DIR)/include/SNAPSHOT.h > $(PKG_BUILD_DIR)/include/SNAPSHOT.h
endef endef
TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto TARGET_CFLAGS += -ffunction-sections -fdata-sections
TARGET_LDFLAGS += -Wl,--gc-sections -Wl,--as-needed TARGET_LDFLAGS += -Wl,--gc-sections
TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny TARGET_CPPFLAGS += -I$(STAGING_DIR)/usr/include/libnl-tiny
MAKE_FLAGS += \ MAKE_FLAGS += \
KERNEL_INCLUDE="$(LINUX_DIR)/user_headers/include" \ KERNEL_INCLUDE="$(LINUX_DIR)/user_headers/include" \
SHARED_LIBS=$(SHARED_LIBS) \ SHARED_LIBS=$(SHARED_LIBS) \
IP_CONFIG_TINY=$(IP_CONFIG_TINY) \ IP_CONFIG_TINY=$(IP_CONFIG_TINY) \
BUILD_VARIANT=$(BUILD_VARIANT) \
LIBBPF_FORCE=$(LIBBPF_FORCE) \
HAVE_ELF=$(HAVE_ELF) \ HAVE_ELF=$(HAVE_ELF) \
HAVE_MNL=$(HAVE_MNL) \ HAVE_MNL=$(HAVE_MNL) \
HAVE_CAP=$(HAVE_CAP) \ HAVE_CAP=$(HAVE_CAP) \
IPT_LIB_DIR=/usr/lib/iptables \ IPT_LIB_DIR=/usr/lib/iptables \
XT_LIB_DIR=/usr/lib/iptables \ XT_LIB_DIR=/usr/lib/iptables \
FPIC="$(FPIC)" \ FPIC="$(FPIC)"
$(if $(findstring c,$(OPENWRT_VERBOSE)),V=1,V='')
define Build/Compile define Build/Compile
+$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS) +$(MAKE_VARS) $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR) $(MAKE_FLAGS)
endef endef
define Build/InstallDev define Build/InstallDev
$(INSTALL_DIR) $(1)/usr/include/iproute2 $(INSTALL_DIR) $(1)/usr/include
$(CP) $(PKG_BUILD_DIR)/include/bpf_elf.h $(1)/usr/include/iproute2
$(CP) $(PKG_BUILD_DIR)/include/{libgenl,libnetlink}.h $(1)/usr/include/ $(CP) $(PKG_BUILD_DIR)/include/{libgenl,libnetlink}.h $(1)/usr/include/
$(INSTALL_DIR) $(1)/usr/lib $(INSTALL_DIR) $(1)/usr/lib
$(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/ $(CP) $(PKG_BUILD_DIR)/lib/libnetlink.a $(1)/usr/lib/
@ -186,19 +157,17 @@ define Package/ip-full/install
$(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-full $(INSTALL_BIN) $(PKG_BUILD_DIR)/ip/ip $(1)/usr/libexec/ip-full
endef endef
define Package/tc-tiny/install define Package/tc/install
$(INSTALL_DIR) $(1)/usr/libexec $(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-tiny $(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/sbin/
endef $(INSTALL_DIR) $(1)/etc/hotplug.d/iface
$(INSTALL_BIN) ./files/15-teql $(1)/etc/hotplug.d/iface/
define Package/tc-full/install $(INSTALL_DIR) $(1)/lib/debug
$(INSTALL_DIR) $(1)/usr/libexec $(INSTALL_BIN) ./files/tc.debug $(1)/lib/debug/tc
$(INSTALL_BIN) $(PKG_BUILD_DIR)/tc/tc $(1)/usr/libexec/tc-full ifeq ($(SHARED_LIBS),y)
endef
define Package/tc-mod-iptables/install
$(INSTALL_DIR) $(1)/usr/lib/tc $(INSTALL_DIR) $(1)/usr/lib/tc
$(CP) $(PKG_BUILD_DIR)/tc/m_xt.so $(1)/usr/lib/tc $(CP) $(PKG_BUILD_DIR)/tc/*.so $(1)/usr/lib/tc
endif
endef endef
define Package/genl/install define Package/genl/install
@ -231,13 +200,9 @@ define Package/rdma/install
$(INSTALL_BIN) $(PKG_BUILD_DIR)/rdma/rdma $(1)/usr/sbin/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/rdma/rdma $(1)/usr/sbin/
endef endef
#$(eval $(call BuildPackage,ip-tiny)) $(eval $(call BuildPackage,ip-tiny))
$(eval $(call BuildPackage,ip-full)) $(eval $(call BuildPackage,ip-full))
# build tc-mod-iptables before its dependents, to avoid $(eval $(call BuildPackage,tc))
# spurious rebuilds when building multiple variants.
$(eval $(call BuildPackage,tc-mod-iptables))
#$(eval $(call BuildPackage,tc-tiny))
$(eval $(call BuildPackage,tc-full))
$(eval $(call BuildPackage,genl)) $(eval $(call BuildPackage,genl))
$(eval $(call BuildPackage,ip-bridge)) $(eval $(call BuildPackage,ip-bridge))
$(eval $(call BuildPackage,ss)) $(eval $(call BuildPackage,ss))

23
iproute2/files/15-teql Normal file
View file

@ -0,0 +1,23 @@
#!/bin/sh
. /lib/functions.sh
if [ "$ACTION" != "ifup" ]; then
exit
fi
config_load network
config_get teql $INTERFACE teql
if [ "$teql" != "" ]; then
logger Adding device $DEVICE to TEQL master $teql
insmod sch_teql
tc qdisc add dev $DEVICE root $teql
# The kernel doesn't let us bring it up until it has at least one
# slave. So bring it up now, if it isn't already.
if ! cat /sys/class/net/$teql/carrier &>/dev/null; then
ifup $teql &
fi
fi

21
iproute2/files/tc.debug Normal file
View file

@ -0,0 +1,21 @@
#!/bin/sh /sbin/sysdebug
#
# Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
for dev in $(ls -1 /sys/class/net/); do
[ -d /sys/class/net/${dev} ] || continue
log tc -s qdisc show dev ${dev}
done

View file

@ -0,0 +1,152 @@
From a7cd7badedcb643dc1adb41edeb4cf8e4d9ec063 Mon Sep 17 00:00:00 2001
From: Stephen Hemminger <stephen@networkplumber.org>
Date: Tue, 19 Mar 2019 10:36:56 -0700
Subject: uapi: add CAKE FWMARK
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
---
include/uapi/linux/pkt_sched.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/uapi/linux/pkt_sched.h b/include/uapi/linux/pkt_sched.h
index 1eb572e..7ee74c3 100644
--- a/include/uapi/linux/pkt_sched.h
+++ b/include/uapi/linux/pkt_sched.h
@@ -1021,6 +1021,7 @@ enum {
TCA_CAKE_INGRESS,
TCA_CAKE_ACK_FILTER,
TCA_CAKE_SPLIT_GSO,
+ TCA_CAKE_FWMARK,
__TCA_CAKE_MAX
};
#define TCA_CAKE_MAX (__TCA_CAKE_MAX - 1)
From 5ebfe1f6fea2bb3bfccf4cf93829516caaa0233d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= <toke@toke.dk>
Date: Mon, 18 Mar 2019 01:30:45 +0100
Subject: [PATCH] q_cake: Add support for setting the fwmark option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This adds support for the newly added fwmark option to CAKE, which allows
overriding the tin selection from the per-packet firewall marks. The fwmark
field is a bitmask that is applied to the fwmark to select the tin.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
man/man8/tc-cake.8 | 16 ++++++++++++++++
tc/q_cake.c | 24 ++++++++++++++++++++++++
2 files changed, 40 insertions(+)
diff --git a/man/man8/tc-cake.8 b/man/man8/tc-cake.8
index eda436e1..8c57eadd 100644
--- a/man/man8/tc-cake.8
+++ b/man/man8/tc-cake.8
@@ -91,6 +91,10 @@ TIME |
LIMIT ]
.br
[
+.BR fwmark
+MASK ]
+.br
+[
.BR ptm
|
.BR atm
@@ -524,6 +528,18 @@ preset on the modern Internet is firmly discouraged.
.br
Voice (CS7, CS6, EF, VA, TOS4), 25% threshold, reduced Codel interval.
+.PP
+.B fwmark
+MASK
+.br
+ This options turns on fwmark-based overriding of CAKE's tin selection.
+If set, the option specifies a bitmask that will be applied to the fwmark
+associated with each packet. If the result of this masking is non-zero, the
+result will be right-shifted by the number of least-significant unset bits in
+the mask value, and the result will be used as a the tin number for that packet.
+This can be used to set policies in a firewall script that will override CAKE's
+built-in tin selection.
+
.SH OTHER PARAMETERS
.B memlimit
LIMIT
diff --git a/tc/q_cake.c b/tc/q_cake.c
index e827e3f1..307a12c0 100644
--- a/tc/q_cake.c
+++ b/tc/q_cake.c
@@ -82,6 +82,7 @@ static void explain(void)
" [ split-gso* | no-split-gso ]\n"
" [ ack-filter | ack-filter-aggressive | no-ack-filter* ]\n"
" [ memlimit LIMIT ]\n"
+" [ fwmark MASK ]\n"
" [ ptm | atm | noatm* ] [ overhead N | conservative | raw* ]\n"
" [ mpu N ] [ ingress | egress* ]\n"
" (* marks defaults)\n");
@@ -106,6 +107,7 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
int autorate = -1;
int ingress = -1;
int overhead = 0;
+ int fwmark = -1;
int wash = -1;
int nat = -1;
int atm = -1;
@@ -332,6 +334,16 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
"Illegal value for \"memlimit\": \"%s\"\n", *argv);
return -1;
}
+ } else if (strcmp(*argv, "fwmark") == 0) {
+ unsigned int fwm;
+
+ NEXT_ARG();
+ if (get_u32(&fwm, *argv, 0)) {
+ fprintf(stderr,
+ "Illegal value for \"fwmark\": \"%s\"\n", *argv);
+ return -1;
+ }
+ fwmark = fwm;
} else if (strcmp(*argv, "help") == 0) {
explain();
return -1;
@@ -376,6 +388,9 @@ static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
if (memlimit)
addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit,
sizeof(memlimit));
+ if (fwmark != -1)
+ addattr_l(n, 1024, TCA_CAKE_FWMARK, &fwmark,
+ sizeof(fwmark));
if (nat != -1)
addattr_l(n, 1024, TCA_CAKE_NAT, &nat, sizeof(nat));
if (wash != -1)
@@ -409,6 +424,7 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
struct rtattr *tb[TCA_CAKE_MAX + 1];
unsigned int interval = 0;
unsigned int memlimit = 0;
+ unsigned int fwmark = 0;
__u64 bandwidth = 0;
int ack_filter = 0;
int split_gso = 0;
@@ -507,6 +523,10 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
RTA_PAYLOAD(tb[TCA_CAKE_RTT]) >= sizeof(__u32)) {
interval = rta_getattr_u32(tb[TCA_CAKE_RTT]);
}
+ if (tb[TCA_CAKE_FWMARK] &&
+ RTA_PAYLOAD(tb[TCA_CAKE_FWMARK]) >= sizeof(__u32)) {
+ fwmark = rta_getattr_u32(tb[TCA_CAKE_FWMARK]);
+ }
if (wash)
print_string(PRINT_FP, NULL, "wash ", NULL);
@@ -559,6 +579,10 @@ static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
sprint_size(memlimit, b1));
}
+ if (fwmark)
+ print_uint(PRINT_FP, NULL, "fwmark 0x%x ", fwmark);
+ print_0xhex(PRINT_JSON, "fwmark", NULL, fwmark);
+
return 0;
}

View file

@ -0,0 +1,589 @@
From dff8eadcab33209e040e77a5d56d5def04808144 Mon Sep 17 00:00:00 2001
From: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Date: Fri, 15 Mar 2019 09:35:37 +0000
Subject: [PATCH] tc: add support for action act_ctinfo
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
ctinfo is a tc action restoring data stored in conntrack marks to
various fields. At present it has two independent modes of operation,
restoration of DSCP into IPv4/v6 diffserv and restoration of conntrack
marks into packet skb marks.
It understands a number of parameters specific to this action in
additional to the usual action syntax. Each operating mode is
independent of the other so all options are optional, however not
specifying at least one mode is a bit pointless.
Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE]
[CONTROL] [index <INDEX>]
DSCP mode
dscp enables copying of a DSCP stored in the conntrack mark into the
ipv4/v6 diffserv field. The mask is a 32bit field and specifies where
in the conntrack mark the DSCP value is located. It must be 6
contiguous bits long. eg. 0xfc000000 would restore the DSCP from the
upper 6 bits of the conntrack mark.
The DSCP copying may be optionally controlled by a statemask. The
statemask is a 32bit field, usually with a single bit set and must not
overlap the dscp mask. The DSCP restore operation will only take place
if the corresponding bit/s in conntrack mark ANDed with the statemask
yield a non zero result.
eg. dscp 0xfc000000 0x01000000 would retrieve the DSCP from the top 6
bits, whilst using bit 25 as a flag to do so. Bit 26 is unused in this
example.
CPMARK mode
cpmark enables copying of the conntrack mark to the packet skb mark. In
this mode it is completely equivalent to the existing act_connmark
action. Additional functionality is provided by the optional mask
parameter, whereby the stored conntrack mark is logically ANDed with the
cpmark mask before being stored into skb mark. This allows shared usage
of the conntrack mark between applications.
eg. cpmark 0x00ffffff would restore only the lower 24 bits of the
conntrack mark, thus may be useful in the event that the upper 8 bits
are used by the DSCP function.
Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE]
[CONTROL] [index <INDEX>]
where :
dscp MASK is the bitmask to restore DSCP
STATEMASK is the bitmask to determine conditional restoring
cpmark MASK mask applied to restored packet mark
ZONE is the conntrack zone
CONTROL := reclassify | pipe | drop | continue | ok |
goto chain <CHAIN_INDEX>
Signed-off-by: Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
include/uapi/linux/pkt_cls.h | 3 +-
include/uapi/linux/tc_act/tc_ctinfo.h | 29 +++
man/man8/tc-ctinfo.8 | 170 ++++++++++++++++
tc/Makefile | 1 +
tc/m_ctinfo.c | 268 ++++++++++++++++++++++++++
5 files changed, 470 insertions(+), 1 deletion(-)
create mode 100644 include/uapi/linux/tc_act/tc_ctinfo.h
create mode 100644 man/man8/tc-ctinfo.8
create mode 100644 tc/m_ctinfo.c
diff --git a/include/uapi/linux/pkt_cls.h b/include/uapi/linux/pkt_cls.h
index 95d0db2a..a6e7e176 100644
--- a/include/uapi/linux/pkt_cls.h
+++ b/include/uapi/linux/pkt_cls.h
@@ -68,7 +68,8 @@ enum {
TCA_ID_UNSPEC=0,
TCA_ID_POLICE=1,
/* other actions go here */
- __TCA_ID_MAX=255
+ TCA_ID_CTINFO=27,
+ __TCA_ID_MAX = 255
};
#define TCA_ID_MAX __TCA_ID_MAX
diff --git a/include/uapi/linux/tc_act/tc_ctinfo.h b/include/uapi/linux/tc_act/tc_ctinfo.h
new file mode 100644
index 00000000..f5f26d95
--- /dev/null
+++ b/include/uapi/linux/tc_act/tc_ctinfo.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __UAPI_TC_CTINFO_H
+#define __UAPI_TC_CTINFO_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+struct tc_ctinfo {
+ tc_gen;
+};
+
+enum {
+ TCA_CTINFO_UNSPEC,
+ TCA_CTINFO_PAD,
+ TCA_CTINFO_TM,
+ TCA_CTINFO_ACT,
+ TCA_CTINFO_ZONE,
+ TCA_CTINFO_PARMS_DSCP_MASK,
+ TCA_CTINFO_PARMS_DSCP_STATEMASK,
+ TCA_CTINFO_PARMS_CPMARK_MASK,
+ TCA_CTINFO_STATS_DSCP_SET,
+ TCA_CTINFO_STATS_DSCP_ERROR,
+ TCA_CTINFO_STATS_CPMARK_SET,
+ __TCA_CTINFO_MAX
+};
+
+#define TCA_CTINFO_MAX (__TCA_CTINFO_MAX - 1)
+
+#endif
diff --git a/man/man8/tc-ctinfo.8 b/man/man8/tc-ctinfo.8
new file mode 100644
index 00000000..096590d1
--- /dev/null
+++ b/man/man8/tc-ctinfo.8
@@ -0,0 +1,170 @@
+.TH "ctinfo action in tc" 8 "4 Jun 2019" "iproute2" "Linux"
+.SH NAME
+ctinfo \- tc connmark processing action
+.SH SYNOPSIS
+.B tc ... action ctinfo
+[
+.B dscp
+MASK [STATEMASK] ] [
+.B cpmark
+[MASK] ] [
+.B zone
+ZONE ] [
+.B CONTROL
+] [
+.B index
+<INDEX>
+]
+
+.SH DESCRIPTION
+CTINFO (Conntrack Information) is a tc action for retrieving data from
+conntrack marks into various fields. At present it has two independent
+processing modes which may be viewed as sub-functions.
+
+DSCP mode copies a DSCP stored in conntrack's connmark into the IPv4/v6 diffserv
+field. The copying may conditionally occur based on a flag also stored in the
+connmark. DSCP mode was designed to assist in restoring packet classifications on
+ingress, classifications which may then be used by qdiscs such as CAKE. It may be
+used in any circumstance where ingress classification needs to be maintained across
+links that otherwise bleach or remap according to their own policies.
+
+CPMARK (copymark) mode copies the conntrack connmark into the packet's mark field. Without
+additional parameters it is functionally completely equivalent to the existing
+connmark action. An optional mask may be specified to mask which bits of the
+connmark are restored. This may be useful when DSCP and CPMARK modes are combined.
+
+Simple statistics (tc -s) on DSCP restores and CPMARK copies are maintained where values for
+set indicate a count of packets altered for that mode. DSCP includes an error count
+where the destination packet's diffserv field was unwriteable.
+.SH PARAMETERS
+.SS DSCP mode parameters:
+.IP mask
+A mask of 6 contiguous bits indicating where the DSCP value is located in the 32 bit
+conntrack mark field. A mask must be provided for this mode. mask is a 32 bit
+unsigned value.
+.IP statemask
+A mask of at least 1 bit indicating where a conditional restore flag is located in the
+32 bit conntrack mark field. The statemask bit/s must NOT overlap the mask bits. The
+DSCP will be restored if the conntrack mark logically ANDed with the statemask yields
+a non-zero result. statemask is an optional unsigned 32 bit value.
+.SS CPMARK mode parameters:
+.IP mask
+Store the logically ANDed result of conntrack mark and mask into the packet's mark
+field. Default is 0xffffffff i.e. the whole mark field. mask is an optional unsigned 32 bit
+value
+.SS Overall action parameters:
+.IP zone
+Specify the conntrack zone when doing conntrack lookups for packets.
+zone is a 16bit unsigned decimal value.
+Default is 0.
+.IP CONTROL
+The following keywords allow to control how the tree of qdisc, classes,
+filters and actions is further traversed after this action.
+.RS
+.TP
+.B reclassify
+Restart with the first filter in the current list.
+.TP
+.B pipe
+Continue with the next action attached to the same filter.
+.TP
+.B drop
+Drop the packet.
+.TP
+.B shot
+synonym for
+.B drop
+.TP
+.B continue
+Continue classification with the next filter in line.
+.TP
+.B pass
+Finish classification process and return to calling qdisc for further packet
+processing. This is the default.
+.RE
+.IP index
+Specify an index for this action in order to being able to identify it in later
+commands. index is a 32bit unsigned decimal value.
+.SH EXAMPLES
+Example showing conditional restoration of DSCP on ingress via an IFB
+.RS
+.EX
+
+#Set up the IFB interface
+.br
+tc qdisc add dev ifb4eth0 handle ffff: ingress
+
+#Put CAKE qdisc on it
+.br
+tc qdisc add dev ifb4eth0 root cake bandwidth 40mbit
+
+#Set interface UP
+.br
+ip link set dev ifb4eth0 up
+
+#Add 2 actions, ctinfo to restore dscp & mirred to redirect the packets to IFB
+.br
+tc filter add dev eth0 parent ffff: protocol all prio 10 u32 \\
+ match u32 0 0 flowid 1:1 action \\
+ ctinfo dscp 0xfc000000 0x01000000 \\
+ mirred egress redirect dev ifb4eth0
+
+tc -s qdisc show dev eth0 ingress
+
+ filter parent ffff: protocol all pref 10 u32 chain 0
+ filter parent ffff: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
+ filter parent ffff: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
+ match 00000000/00000000 at 0
+ action order 1: ctinfo zone 0 pipe
+ index 2 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 72 sec used 0 sec DSCP set 1333 error 0 CPMARK set 0
+ Action statistics:
+ Sent 658484 bytes 1833 pkt (dropped 0, overlimits 0 requeues 0)
+ backlog 0b 0p requeues 0
+
+ action order 2: mirred (Egress Redirect to device ifb4eth0) stolen
+ index 1 ref 1 bind 1 installed 72 sec used 0 sec
+ Action statistics:
+ Sent 658484 bytes 1833 pkt (dropped 0, overlimits 0 requeues 0)
+ backlog 0b 0p requeues 0
+.EE
+.RE
+
+Example showing conditional restoration of DSCP on egress
+
+This may appear nonsensical since iptables marking of egress packets is easy
+to achieve, however the iptables flow classification rules may be extensive
+and so some sort of set once and forget may be useful especially on cpu
+constrained devices.
+.RS
+.EX
+
+# Send unmarked connections to a marking chain which needs to store a DSCP
+and set statemask bit in the connmark
+.br
+iptables -t mangle -A POSTROUTING -o eth0 -m connmark \\
+ --mark 0x00000000/0x01000000 -g CLASS_MARKING_CHAIN
+
+# Apply marked DSCP to the packets
+.br
+tc filter add dev eth0 protocol all prio 10 u32 \\
+ match u32 0 0 flowid 1:1 action \\
+ ctinfo dscp 0xfc000000 0x01000000
+
+tc -s filter show dev eth0
+ filter parent 800e: protocol all pref 10 u32 chain 0
+ filter parent 800e: protocol all pref 10 u32 chain 0 fh 800: ht divisor 1
+ filter parent 800e: protocol all pref 10 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw
+ match 00000000/00000000 at 0
+ action order 1: ctinfo zone 0 pipe
+ index 1 ref 1 bind 1 dscp 0xfc000000 0x01000000 installed 7414 sec used 0 sec DSCP set 53404 error 0 CPMARK set 0
+ Action statistics:
+ Sent 32890260 bytes 120441 pkt (dropped 0, overlimits 0 requeues 0)
+ backlog 0b 0p requeues 0
+.br
+.SH SEE ALSO
+.BR tc (8),
+.BR tc-cake (8)
+.BR tc-connmark (8)
+.BR tc-mirred (8)
+.SH AUTHORS
+ctinfo was written by Kevin Darbyshire-Bryant.
diff --git a/tc/Makefile b/tc/Makefile
index 2edaf2c8..ec93a9a1 100644
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -48,6 +48,7 @@ TCMODULES += m_csum.o
TCMODULES += m_simple.o
TCMODULES += m_vlan.o
TCMODULES += m_connmark.o
+TCMODULES += m_ctinfo.o
TCMODULES += m_bpf.o
TCMODULES += m_tunnel_key.o
TCMODULES += m_sample.o
diff --git a/tc/m_ctinfo.c b/tc/m_ctinfo.c
new file mode 100644
index 00000000..5e451f87
--- /dev/null
+++ b/tc/m_ctinfo.c
@@ -0,0 +1,268 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * m_ctinfo.c netfilter ctinfo mark action
+ *
+ * Copyright (c) 2019 Kevin Darbyshire-Bryant <ldir@darbyshire-bryant.me.uk>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "utils.h"
+#include "tc_util.h"
+#include <linux/tc_act/tc_ctinfo.h>
+
+static void
+explain(void)
+{
+ fprintf(stderr,
+ "Usage: ... ctinfo [dscp mask [statemask]] [cpmark [mask]] [zone ZONE] [CONTROL] [index <INDEX>]\n"
+ "where :\n"
+ "\tdscp MASK bitmask location of stored DSCP\n"
+ "\t STATEMASK bitmask to determine conditional restoring\n"
+ "\tcpmark MASK mask applied to mark on restoration\n"
+ "\tZONE is the conntrack zone\n"
+ "\tCONTROL := reclassify | pipe | drop | continue | ok |\n"
+ "\t goto chain <CHAIN_INDEX>\n");
+}
+
+static void
+usage(void)
+{
+ explain();
+ exit(-1);
+}
+
+static int
+parse_ctinfo(struct action_util *a, int *argc_p, char ***argv_p, int tca_id,
+ struct nlmsghdr *n)
+{
+ unsigned int cpmarkmask = 0, dscpmask = 0, dscpstatemask = 0;
+ struct tc_ctinfo sel = {};
+ unsigned short zone = 0;
+ char **argv = *argv_p;
+ struct rtattr *tail;
+ int argc = *argc_p;
+ int ok = 0;
+ __u8 i;
+
+ while (argc > 0) {
+ if (matches(*argv, "ctinfo") == 0) {
+ ok = 1;
+ NEXT_ARG_FWD();
+ } else if (matches(*argv, "help") == 0) {
+ usage();
+ } else {
+ break;
+ }
+
+ }
+
+ if (!ok) {
+ explain();
+ return -1;
+ }
+
+ if (argc) {
+ if (matches(*argv, "dscp") == 0) {
+ NEXT_ARG();
+ if (get_u32(&dscpmask, *argv, 0)) {
+ fprintf(stderr,
+ "ctinfo: Illegal dscp \"mask\"\n");
+ return -1;
+ }
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG_FWD();
+ if (!get_u32(&dscpstatemask, *argv, 0))
+ NEXT_ARG_FWD(); /* was a statemask */
+ } else {
+ NEXT_ARG_FWD();
+ }
+ }
+ }
+
+ /* cpmark has optional mask parameter, so the next arg might not */
+ /* exist, or it might be the next option, or it may actually be a */
+ /* 32bit mask */
+ if (argc) {
+ if (matches(*argv, "cpmark") == 0) {
+ cpmarkmask = ~0;
+ if (NEXT_ARG_OK()) {
+ NEXT_ARG_FWD();
+ if (!get_u32(&cpmarkmask, *argv, 0))
+ NEXT_ARG_FWD(); /* was a mask */
+ } else {
+ NEXT_ARG_FWD();
+ }
+ }
+ }
+
+ if (argc) {
+ if (matches(*argv, "zone") == 0) {
+ NEXT_ARG();
+ if (get_u16(&zone, *argv, 10)) {
+ fprintf(stderr, "ctinfo: Illegal \"zone\"\n");
+ return -1;
+ }
+ NEXT_ARG_FWD();
+ }
+ }
+
+ parse_action_control_dflt(&argc, &argv, &sel.action,
+ false, TC_ACT_PIPE);
+
+ if (argc) {
+ if (matches(*argv, "index") == 0) {
+ NEXT_ARG();
+ if (get_u32(&sel.index, *argv, 10)) {
+ fprintf(stderr, "ctinfo: Illegal \"index\"\n");
+ return -1;
+ }
+ NEXT_ARG_FWD();
+ }
+ }
+
+ if (dscpmask & dscpstatemask) {
+ fprintf(stderr,
+ "ctinfo: dscp mask & statemask must NOT overlap\n");
+ return -1;
+ }
+
+ i = ffs(dscpmask);
+ if (i && ((~0 & (dscpmask >> (i - 1))) != 0x3f)) {
+ fprintf(stderr,
+ "ctinfo: dscp mask must be 6 contiguous bits long\n");
+ return -1;
+ }
+
+ tail = addattr_nest(n, MAX_MSG, tca_id);
+ addattr_l(n, MAX_MSG, TCA_CTINFO_ACT, &sel, sizeof(sel));
+ addattr16(n, MAX_MSG, TCA_CTINFO_ZONE, zone);
+
+ if (dscpmask)
+ addattr32(n, MAX_MSG,
+ TCA_CTINFO_PARMS_DSCP_MASK, dscpmask);
+
+ if (dscpstatemask)
+ addattr32(n, MAX_MSG,
+ TCA_CTINFO_PARMS_DSCP_STATEMASK, dscpstatemask);
+
+ if (cpmarkmask)
+ addattr32(n, MAX_MSG,
+ TCA_CTINFO_PARMS_CPMARK_MASK, cpmarkmask);
+
+ addattr_nest_end(n, tail);
+
+ *argc_p = argc;
+ *argv_p = argv;
+ return 0;
+}
+
+static void print_ctinfo_stats(FILE *f, struct rtattr *tb[TCA_CTINFO_MAX + 1])
+{
+ struct tcf_t *tm;
+
+ if (tb[TCA_CTINFO_TM]) {
+ tm = RTA_DATA(tb[TCA_CTINFO_TM]);
+
+ print_tm(f, tm);
+ }
+
+ if (tb[TCA_CTINFO_STATS_DSCP_SET])
+ print_lluint(PRINT_ANY, "dscpset", " DSCP set %llu",
+ rta_getattr_u64(tb[TCA_CTINFO_STATS_DSCP_SET]));
+ if (tb[TCA_CTINFO_STATS_DSCP_ERROR])
+ print_lluint(PRINT_ANY, "dscperror", " error %llu",
+ rta_getattr_u64(tb[TCA_CTINFO_STATS_DSCP_ERROR]));
+
+ if (tb[TCA_CTINFO_STATS_CPMARK_SET])
+ print_lluint(PRINT_ANY, "cpmarkset", " CPMARK set %llu",
+ rta_getattr_u64(tb[TCA_CTINFO_STATS_CPMARK_SET]));
+}
+
+static int print_ctinfo(struct action_util *au, FILE *f, struct rtattr *arg)
+{
+ unsigned int cpmarkmask = ~0, dscpmask = 0, dscpstatemask = 0;
+ struct rtattr *tb[TCA_CTINFO_MAX + 1];
+ unsigned short zone = 0;
+ struct tc_ctinfo *ci;
+
+ if (arg == NULL)
+ return -1;
+
+ parse_rtattr_nested(tb, TCA_CTINFO_MAX, arg);
+ if (!tb[TCA_CTINFO_ACT]) {
+ print_string(PRINT_FP, NULL, "%s",
+ "[NULL ctinfo action parameters]");
+ return -1;
+ }
+
+ ci = RTA_DATA(tb[TCA_CTINFO_ACT]);
+
+ if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) {
+ if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_DSCP_MASK]) >=
+ sizeof(__u32))
+ dscpmask = rta_getattr_u32(
+ tb[TCA_CTINFO_PARMS_DSCP_MASK]);
+ else
+ print_string(PRINT_FP, NULL, "%s",
+ "[invalid dscp mask parameter]");
+ }
+
+ if (tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) {
+ if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]) >=
+ sizeof(__u32))
+ dscpstatemask = rta_getattr_u32(
+ tb[TCA_CTINFO_PARMS_DSCP_STATEMASK]);
+ else
+ print_string(PRINT_FP, NULL, "%s",
+ "[invalid dscp statemask parameter]");
+ }
+
+ if (tb[TCA_CTINFO_PARMS_CPMARK_MASK]) {
+ if (RTA_PAYLOAD(tb[TCA_CTINFO_PARMS_CPMARK_MASK]) >=
+ sizeof(__u32))
+ cpmarkmask = rta_getattr_u32(
+ tb[TCA_CTINFO_PARMS_CPMARK_MASK]);
+ else
+ print_string(PRINT_FP, NULL, "%s",
+ "[invalid cpmark mask parameter]");
+ }
+
+ if (tb[TCA_CTINFO_ZONE] && RTA_PAYLOAD(tb[TCA_CTINFO_ZONE]) >=
+ sizeof(__u16))
+ zone = rta_getattr_u16(tb[TCA_CTINFO_ZONE]);
+
+ print_string(PRINT_ANY, "kind", "%s ", "ctinfo");
+ print_hu(PRINT_ANY, "zone", "zone %u", zone);
+ print_action_control(f, " ", ci->action, "");
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ print_uint(PRINT_ANY, "index", "\t index %u", ci->index);
+ print_int(PRINT_ANY, "ref", " ref %d", ci->refcnt);
+ print_int(PRINT_ANY, "bind", " bind %d", ci->bindcnt);
+
+ if (tb[TCA_CTINFO_PARMS_DSCP_MASK]) {
+ print_0xhex(PRINT_ANY, "dscpmask", " dscp %#010llx", dscpmask);
+ print_0xhex(PRINT_ANY, "dscpstatemask", " %#010llx",
+ dscpstatemask);
+ }
+
+ if (tb[TCA_CTINFO_PARMS_CPMARK_MASK])
+ print_0xhex(PRINT_ANY, "cpmark", " cpmark %#010llx",
+ cpmarkmask);
+
+ if (show_stats)
+ print_ctinfo_stats(f, tb);
+
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+
+ return 0;
+}
+
+struct action_util ctinfo_action_util = {
+ .id = "ctinfo",
+ .parse_aopt = parse_ctinfo,
+ .print_aopt = print_ctinfo,
+};
--
2.20.1 (Apple Git-117)

View file

@ -1,6 +1,6 @@
--- a/configure --- a/configure
+++ b/configure +++ b/configure
@@ -34,7 +34,8 @@ int main(int argc, char **argv) { @@ -32,7 +32,8 @@ int main(int argc, char **argv) {
} }
EOF EOF

View file

@ -1,6 +1,6 @@
--- a/tc/Makefile --- a/tc/Makefile
+++ b/tc/Makefile +++ b/tc/Makefile
@@ -128,6 +128,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR @@ -120,6 +120,9 @@ CFLAGS += -DCONFIG_GACT -DCONFIG_GACT_PR
ifneq ($(IPT_LIB_DIR),) ifneq ($(IPT_LIB_DIR),)
CFLAGS += -DIPT_LIB_DIR=\"$(IPT_LIB_DIR)\" CFLAGS += -DIPT_LIB_DIR=\"$(IPT_LIB_DIR)\"
endif endif
@ -8,5 +8,5 @@
+ CFLAGS += -DXT_LIB_DIR=\"$(XT_LIB_DIR)\" + CFLAGS += -DXT_LIB_DIR=\"$(XT_LIB_DIR)\"
+endif +endif
YACC := bison
LEX := flex LEX := flex
CFLAGS += -DYY_NO_INPUT

View file

@ -1,11 +1,6 @@
--- a/misc/Makefile --- a/misc/Makefile
+++ b/misc/Makefile +++ b/misc/Makefile
@@ -2,13 +2,13 @@ @@ -6,9 +6,9 @@ TARGETS=ss nstat ifstat rtacct lnstat
SSOBJ=ss.o ssfilter_check.o ssfilter.tab.o
LNSTATOBJ=lnstat.o lnstat_util.o
-TARGETS=ss nstat ifstat rtacct lnstat
+TARGETS=ss nstat
include ../config.mk include ../config.mk

View file

@ -4,8 +4,8 @@
CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS)
YACCFLAGS = -d -t -v YACCFLAGS = -d -t -v
-SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma dcb man vdpa -SUBDIRS=lib ip tc bridge misc netem genl tipc devlink rdma man
+SUBDIRS=lib ip tc bridge misc genl devlink rdma +SUBDIRS=lib ip tc bridge misc genl tipc devlink rdma man
LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a
LDLIBS += $(LIBNETLINK) LDLIBS += $(LIBNETLINK)

View file

@ -0,0 +1,101 @@
Description: Sync header from iptables
The current versions in several suites have the same content:
- 1.6.1-2 (unstable)
Bug: https://bugs.debian.org/868059
Forwarded: not-needed
Author: Cyril Brulebois <cyril@debamax.com>
Last-Update: 2017-11-22
--- a/include/xtables.h
+++ b/include/xtables.h
@@ -206,9 +206,24 @@ enum xtables_ext_flags {
XTABLES_EXT_ALIAS = 1 << 0,
};
+struct xt_xlate;
+
+struct xt_xlate_mt_params {
+ const void *ip;
+ const struct xt_entry_match *match;
+ int numeric;
+ bool escape_quotes;
+};
+
+struct xt_xlate_tg_params {
+ const void *ip;
+ const struct xt_entry_target *target;
+ int numeric;
+ bool escape_quotes;
+};
+
/* Include file for additions: new matches and targets. */
-struct xtables_match
-{
+struct xtables_match {
/*
* ABI/API version this module requires. Must be first member,
* as the rest of this struct may be subject to ABI changes.
@@ -270,6 +285,10 @@ struct xtables_match
void (*x6_fcheck)(struct xt_fcheck_call *);
const struct xt_option_entry *x6_options;
+ /* Translate iptables to nft */
+ int (*xlate)(struct xt_xlate *xl,
+ const struct xt_xlate_mt_params *params);
+
/* Size of per-extension instance extra "global" scratch space */
size_t udata_size;
@@ -281,8 +300,7 @@ struct xtables_match
unsigned int loaded; /* simulate loading so options are merged properly */
};
-struct xtables_target
-{
+struct xtables_target {
/*
* ABI/API version this module requires. Must be first member,
* as the rest of this struct may be subject to ABI changes.
@@ -347,6 +365,10 @@ struct xtables_target
void (*x6_fcheck)(struct xt_fcheck_call *);
const struct xt_option_entry *x6_options;
+ /* Translate iptables to nft */
+ int (*xlate)(struct xt_xlate *xl,
+ const struct xt_xlate_tg_params *params);
+
size_t udata_size;
/* Ignore these men behind the curtain: */
@@ -407,6 +429,17 @@ struct xtables_globals
#define XT_GETOPT_TABLEEND {.name = NULL, .has_arg = false}
+/*
+ * enum op-
+ *
+ * For writing clean nftables translations code
+ */
+enum xt_op {
+ XT_OP_EQ,
+ XT_OP_NEQ,
+ XT_OP_MAX,
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -549,6 +582,14 @@ extern void xtables_lmap_free(struct xta
extern int xtables_lmap_name2id(const struct xtables_lmap *, const char *);
extern const char *xtables_lmap_id2name(const struct xtables_lmap *, int);
+/* xlate infrastructure */
+struct xt_xlate *xt_xlate_alloc(int size);
+void xt_xlate_free(struct xt_xlate *xl);
+void xt_xlate_add(struct xt_xlate *xl, const char *fmt, ...);
+void xt_xlate_add_comment(struct xt_xlate *xl, const char *comment);
+const char *xt_xlate_get_comment(struct xt_xlate *xl);
+const char *xt_xlate_get(struct xt_xlate *xl);
+
#ifdef XTABLES_INTERNAL
/* Shipped modules rely on this... */

View file

@ -1,6 +1,6 @@
--- a/tc/q_fifo.c --- a/tc/q_fifo.c
+++ b/tc/q_fifo.c +++ b/tc/q_fifo.c
@@ -95,5 +95,6 @@ struct qdisc_util pfifo_head_drop_qdisc_ @@ -99,5 +99,6 @@ struct qdisc_util pfifo_head_drop_qdisc_
struct qdisc_util pfifo_fast_qdisc_util = { struct qdisc_util pfifo_fast_qdisc_util = {
.id = "pfifo_fast", .id = "pfifo_fast",

View file

@ -1,6 +1,6 @@
--- a/configure --- a/configure
+++ b/configure +++ b/configure
@@ -387,7 +387,7 @@ check_selinux() @@ -255,7 +255,7 @@ check_selinux()
check_mnl() check_mnl()
{ {

View file

@ -1,6 +1,6 @@
--- a/configure --- a/configure
+++ b/configure +++ b/configure
@@ -255,7 +255,7 @@ EOF @@ -228,7 +228,7 @@ EOF
check_elf() check_elf()
{ {

View file

@ -1,6 +1,6 @@
--- a/configure --- a/configure
+++ b/configure +++ b/configure
@@ -445,7 +445,7 @@ EOF @@ -313,7 +313,7 @@ EOF
check_cap() check_cap()
{ {

View file

@ -7,5 +7,5 @@
-CFLAGS += -fPIC -CFLAGS += -fPIC
+CFLAGS += $(FPIC) +CFLAGS += $(FPIC)
UTILOBJ = utils.o utils_math.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \ UTILOBJ = utils.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \
inet_proto.o namespace.o json_writer.o json_print.o json_print_math.o \ inet_proto.o namespace.o json_writer.o json_print.o \

View file

@ -0,0 +1,102 @@
--- a/ip/Makefile
+++ b/ip/Makefile
@@ -16,6 +16,13 @@ RTMONOBJ=rtmon.o
include ../config.mk
+STATIC_SYM_FILTER:=
+ifeq ($(IP_CONFIG_TINY),y)
+ STATIC_SYM_FILTER:=iplink_can.c iplink_ipoib.c iplink_vxlan.c
+ CFLAGS += -DIPROUTE2_TINY
+endif
+STATIC_SYM_SOURCES:=$(filter-out $(STATIC_SYM_FILTER),$(wildcard *.c))
+
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
SCRIPTS=ifcfg rtpr routel routef
TARGETS=ip rtmon
@@ -45,7 +52,7 @@ else
ip: static-syms.o
static-syms.o: static-syms.h
-static-syms.h: $(wildcard *.c)
+static-syms.h: $(STATIC_SYM_SOURCES)
files="$^" ; \
for s in `grep -B 3 '\<dlsym' $$files | sed -n '/snprintf/{s:.*"\([^"]*\)".*:\1:;s:%s::;p}'` ; do \
sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -47,10 +47,16 @@ static void usage(void)
fprintf(stderr,
"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
" ip [ -force ] -batch filename\n"
+#ifndef IPROUTE2_TINY
"where OBJECT := { link | address | addrlabel | route | rule | neigh | ntable |\n"
" tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm |\n"
" netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila |\n"
" vrf | sr }\n"
+#else
+"where OBJECT := { link | address | route | rule | neigh | tunnel | maddress |\n"
+" mroute | mrule | monitor | netns | macsec | token | ila |\n"
+" vrf | sr }\n"
+#endif
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
" -f[amily] { inet | inet6 | mpls | bridge | link } |\n"
@@ -72,32 +78,44 @@ static const struct cmd {
int (*func)(int argc, char **argv);
} cmds[] = {
{ "address", do_ipaddr },
+#ifndef IPROUTE2_TINY
{ "addrlabel", do_ipaddrlabel },
+#endif
{ "maddress", do_multiaddr },
{ "route", do_iproute },
{ "rule", do_iprule },
{ "neighbor", do_ipneigh },
{ "neighbour", do_ipneigh },
+#ifndef IPROUTE2_TINY
{ "ntable", do_ipntable },
{ "ntbl", do_ipntable },
+#endif
{ "link", do_iplink },
+#ifndef IPROUTE2_TINY
{ "l2tp", do_ipl2tp },
{ "fou", do_ipfou },
+#endif
{ "ila", do_ipila },
{ "macsec", do_ipmacsec },
{ "tunnel", do_iptunnel },
{ "tunl", do_iptunnel },
+#ifndef IPROUTE2_TINY
{ "tuntap", do_iptuntap },
{ "tap", do_iptuntap },
{ "token", do_iptoken },
{ "tcpmetrics", do_tcp_metrics },
{ "tcp_metrics", do_tcp_metrics },
+#endif
{ "monitor", do_ipmonitor },
+#ifndef IPROUTE2_TINY
{ "xfrm", do_xfrm },
+#endif
{ "mroute", do_multiroute },
{ "mrule", do_multirule },
{ "netns", do_netns },
+#ifndef IPROUTE2_TINY
{ "netconf", do_ipnetconf },
+#endif
{ "vrf", do_ipvrf},
{ "sr", do_seg6 },
{ "help", do_help },
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -3,6 +3,10 @@ include ../config.mk
CFLAGS += $(FPIC)
+ifeq ($(IP_CONFIG_TINY),y)
+ CFLAGS += -DIPROUTE2_TINY
+endif
+
UTILOBJ = utils.o rt_names.o ll_map.o ll_types.o ll_proto.o ll_addr.o \
inet_proto.o namespace.o json_writer.o json_print.o \
names.o color.o bpf.o exec.o fs.o

View file

@ -1,6 +1,6 @@
--- a/tc/Makefile --- a/tc/Makefile
+++ b/tc/Makefile +++ b/tc/Makefile
@@ -114,7 +114,7 @@ LDLIBS += -L. -lm @@ -108,7 +108,7 @@ LDLIBS += -L. -lm
ifeq ($(SHARED_LIBS),y) ifeq ($(SHARED_LIBS),y)
LDLIBS += -ldl LDLIBS += -ldl
@ -9,7 +9,7 @@
endif endif
TCLIB := tc_core.o TCLIB := tc_core.o
@@ -144,7 +144,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc @@ -138,7 +138,7 @@ MODDESTDIR := $(DESTDIR)$(LIBDIR)/tc
all: tc $(TCSO) all: tc $(TCSO)
tc: $(TCOBJ) $(LIBNETLINK) libtc.a tc: $(TCOBJ) $(LIBNETLINK) libtc.a
@ -18,15 +18,15 @@
libtc.a: $(TCLIB) libtc.a: $(TCLIB)
$(QUIET_AR)$(AR) rcs $@ $^ $(QUIET_AR)$(AR) rcs $@ $^
@@ -166,6 +166,7 @@ install: all @@ -160,6 +160,7 @@ install: all
clean: clean:
rm -f $(TCOBJ) $(TCLIB) libtc.a tc *.so emp_ematch.tab.h; \ rm -f $(TCOBJ) $(TCLIB) libtc.a tc *.so emp_ematch.yacc.h; \
rm -f emp_ematch.tab.* rm -f emp_ematch.yacc.*
+ rm -f dynsyms.list + rm -f dynsyms.list
q_atm.so: q_atm.c q_atm.so: q_atm.c
$(QUIET_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -shared -fpic -o q_atm.so q_atm.c -latm $(QUIET_CC)$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -shared -fpic -o q_atm.so q_atm.c -latm
@@ -205,4 +206,16 @@ static-syms.h: $(wildcard *.c) @@ -199,4 +200,16 @@ static-syms.h: $(wildcard *.c)
sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \ sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \
done > $@ done > $@
@ -40,6 +40,6 @@
+ for s in `grep -B 3 '\<dlsym' $$files | sed -n '/snprintf/{s:.*"\([^"]*\)".*:\1:;s:%s::;p}'` ; do \ + for s in `grep -B 3 '\<dlsym' $$files | sed -n '/snprintf/{s:.*"\([^"]*\)".*:\1:;s:%s::;p}'` ; do \
+ sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:\1;:;p}' $$files ; \ + sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:\1;:;p}' $$files ; \
+ done >> $@ ; \ + done >> $@ ; \
+ echo "show_stats; print_nl; print_tm; parse_rtattr; parse_rtattr_flags; get_u32; matches; addattr_l; addattr_nest; addattr_nest_end; };" >> $@ + echo "show_stats; print_tm; parse_rtattr; get_u32; matches; addattr_l; addattr_nest; addattr_nest_end; };" >> $@
+ +
endif endif

View file

@ -11,7 +11,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY
--- a/ip/rtm_map.c --- a/ip/rtm_map.c
+++ b/ip/rtm_map.c +++ b/ip/rtm_map.c
@@ -54,6 +54,8 @@ char *rtnl_rtntype_n2a(int id, char *buf @@ -48,6 +48,8 @@ char *rtnl_rtntype_n2a(int id, char *buf
return "nat"; return "nat";
case RTN_XRESOLVE: case RTN_XRESOLVE:
return "xresolve"; return "xresolve";
@ -20,7 +20,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY
default: default:
snprintf(buf, len, "%d", id); snprintf(buf, len, "%d", id);
return buf; return buf;
@@ -89,6 +91,8 @@ int rtnl_rtntype_a2n(int *id, char *arg) @@ -83,6 +85,8 @@ int rtnl_rtntype_a2n(int *id, char *arg)
res = RTN_UNICAST; res = RTN_UNICAST;
else if (strcmp(arg, "throw") == 0) else if (strcmp(arg, "throw") == 0)
res = RTN_THROW; res = RTN_THROW;
@ -31,7 +31,7 @@ Subject: [PATCH] add support for dropping with FAILED_POLICY
if (!end || end == arg || *end || res > 255) if (!end || end == arg || *end || res > 255)
--- a/include/uapi/linux/rtnetlink.h --- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h +++ b/include/uapi/linux/rtnetlink.h
@@ -256,6 +256,7 @@ enum { @@ -228,6 +228,7 @@ enum {
RTN_THROW, /* Not in this table */ RTN_THROW, /* Not in this table */
RTN_NAT, /* Translate this address */ RTN_NAT, /* Translate this address */
RTN_XRESOLVE, /* Use external resolver */ RTN_XRESOLVE, /* Use external resolver */

View file

@ -1,20 +0,0 @@
--- a/configure
+++ b/configure
@@ -279,7 +279,7 @@ int main(int argc, char **argv) {
}
EOF
- $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1
+ $CC -o $TMPDIR/libbpf_test $TMPDIR/libbpf_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1
local ret=$?
rm -f $TMPDIR/libbpf_test.c $TMPDIR/libbpf_test
@@ -297,7 +297,7 @@ int main(int argc, char **argv) {
}
EOF
- $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS >/dev/null 2>&1
+ $CC -o $TMPDIR/libbpf_sec_test $TMPDIR/libbpf_sec_test.c $LIBBPF_CFLAGS $LIBBPF_LDLIBS $LDFLAGS >/dev/null 2>&1
local ret=$?
rm -f $TMPDIR/libbpf_sec_test.c $TMPDIR/libbpf_sec_test

View file

@ -1,6 +1,6 @@
--- a/configure --- a/configure
+++ b/configure +++ b/configure
@@ -431,14 +431,8 @@ EOF @@ -299,14 +299,8 @@ EOF
if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then if $CC -I$INCLUDE -o $TMPDIR/strtest $TMPDIR/strtest.c >/dev/null 2>&1; then
echo "no" echo "no"
else else

View file

@ -1,11 +0,0 @@
--- a/configure
+++ b/configure
@@ -374,7 +374,7 @@ check_libbpf()
check_selinux()
# SELinux is a compile time option in the ss utility
{
- if ${PKG_CONFIG} libselinux --exists; then
+ if [ "${HAVE_SELINUX}" = "y" ] && ${PKG_CONFIG} libselinux --exists; then
echo "HAVE_SELINUX:=y" >>$CONFIG
echo "yes"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,247 @@
--- /dev/null
+++ b/include/uapi/linux/tc_act/tc_nssmirred.h
@@ -0,0 +1,46 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#ifndef __LINUX_TC_NSS_MIR_H
+#define __LINUX_TC_NSS_MIR_H
+
+#include <linux/types.h>
+#include <linux/pkt_cls.h>
+
+/*
+ * tc_nss_mirred
+ * Structure for nssmirred action.
+ */
+struct tc_nss_mirred {
+ tc_gen;
+ __u32 from_ifindex; /* ifindex of the port to be redirected from */
+ __u32 to_ifindex; /* ifindex of the port to be redirected to */
+};
+
+/*
+ * Types of nssmirred action parameters.
+ */
+enum {
+ TCA_NSS_MIRRED_UNSPEC,
+ TCA_NSS_MIRRED_TM,
+ TCA_NSS_MIRRED_PARMS,
+ __TCA_NSS_MIRRED_MAX
+};
+#define TCA_NSS_MIRRED_MAX (__TCA_NSS_MIRRED_MAX - 1)
+
+#endif /* __LINUX_TC_NSS_MIR_H */
--- a/tc/Makefile
+++ b/tc/Makefile
@@ -39,6 +39,7 @@ TCMODULES += q_drr.o
TCMODULES += q_qfq.o
TCMODULES += m_gact.o
TCMODULES += m_mirred.o
+TCMODULES += m_nssmirred.o
TCMODULES += m_nat.o
TCMODULES += m_pedit.o
TCMODULES += m_ife.o
--- /dev/null
+++ b/tc/m_nssmirred.c
@@ -0,0 +1,185 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include "utils.h"
+#include "tc_util.h"
+#include "tc_common.h"
+#include <linux/tc_act/tc_nssmirred.h>
+
+/*
+ * explain()
+ * API to print the explaination of nssmirred action statement's
+ * elements.
+ */
+static void explain(void)
+{
+ fprintf(stderr, "Usage: nssmirred redirect <dev TO_DEVICENAME fromdev FROM_DEVICENAME> \n");
+ fprintf(stderr, "where: \n");
+ fprintf(stderr, "\tTO_DEVICENAME is the devicename to redirect to\n");
+ fprintf(stderr, "\tFROM_DEVICENAME is the devicename to redirect from\n");
+}
+
+/*
+ * usage()
+ * API to show the usage of the nssmirred action.
+ */
+static void usage(void)
+{
+ explain();
+ exit(-1);
+}
+
+/*
+ * parse_nss_mirred()
+ * Parse and validate the nssmirred action statement.
+ */
+static int parse_nss_mirred(struct action_util *a, int *argc_p, char ***argv_p,
+ int tca_id, struct nlmsghdr *n)
+{
+ int idx, argc = *argc_p;
+ char **argv = *argv_p;
+ struct tc_nss_mirred p;
+ struct rtattr *tail;
+
+ if (argc < 0) {
+ fprintf(stderr, "nssmirred bad argument count %d. Try option \"help\"\n", argc);
+ goto error;
+ }
+
+ if (matches(*argv, "nssmirred")) {
+ fprintf(stderr, "nssmirred bad argument %s. Try option \"help\"\n", *argv);
+ goto error;
+ }
+
+ NEXT_ARG();
+ if (!matches(*argv, "help")) {
+ usage();
+ }
+
+ if (matches(*argv, "redirect")) {
+ fprintf(stderr, "nssmirred bad argument %s. Try option \"help\"\n", *argv);
+ goto error;
+ }
+
+ NEXT_ARG();
+ if (matches(*argv, "dev")) {
+ fprintf(stderr, "nssmirred: bad value %s. Try option \"help\"\n", *argv);
+ goto error;
+ }
+
+ NEXT_ARG();
+ memset(&p, 0, sizeof(struct tc_nss_mirred));
+ if ((idx = ll_name_to_index(*argv)) == 0) {
+ fprintf(stderr, "Cannot find to device \"%s\"\n", *argv);
+ goto error;
+ }
+
+ p.to_ifindex = idx;
+ NEXT_ARG();
+ if (matches(*argv, "fromdev")) {
+ fprintf(stderr, "nssmirred: bad value %s. Try option \"help\"\n", *argv);
+ goto error;
+ }
+
+ NEXT_ARG();
+ if ((idx = ll_name_to_index(*argv)) == 0) {
+ fprintf(stderr, "Cannot find from device \"%s\"\n", *argv);
+ goto error;
+ }
+
+ p.from_ifindex = idx;
+ p.action = TC_ACT_STOLEN;
+ tail = NLMSG_TAIL(n);
+ addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+ addattr_l(n, MAX_MSG, TCA_NSS_MIRRED_PARMS, &p, sizeof (p));
+ tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
+ argc--;
+ argv++;
+ *argc_p = argc;
+ *argv_p = argv;
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * print_nss_mirred()
+ * Print information related to nssmirred action.
+ */
+static int print_nss_mirred(struct action_util *au, FILE * f, struct rtattr *arg)
+{
+ struct tc_nss_mirred *p;
+ struct rtattr *tb[TCA_NSS_MIRRED_MAX + 1];
+ const char *from_dev, *to_dev;
+
+ if (arg == NULL) {
+ return -1;
+ }
+
+ parse_rtattr_nested(tb, TCA_NSS_MIRRED_MAX, arg);
+
+ if (tb[TCA_NSS_MIRRED_PARMS] == NULL) {
+ fprintf(f, "[NULL nssmirred parameters]");
+ goto error;
+ }
+
+ p = RTA_DATA(tb[TCA_NSS_MIRRED_PARMS]);
+ if ((from_dev = ll_index_to_name(p->from_ifindex)) == 0) {
+ fprintf(stderr, "Invalid interface (index: %d)\n", p->from_ifindex);
+ goto error;
+ }
+
+ if ((to_dev = ll_index_to_name(p->to_ifindex)) == 0) {
+ fprintf(stderr, "Invalid interface (index: %d)\n", p->to_ifindex);
+ goto error;
+ }
+
+ fprintf(f, "nssmirred (%s to device %s) stolen\n", from_dev, to_dev);
+ fprintf(f, "\tindex %d ref %d bind %d\n",p->index,p->refcnt,p->bindcnt);
+
+ if (show_stats) {
+ if (tb[TCA_NSS_MIRRED_TM]) {
+ struct tcf_t *tm = RTA_DATA(tb[TCA_NSS_MIRRED_TM]);
+ print_tm(f,tm);
+ }
+ }
+ return 0;
+
+error:
+ return -1;
+}
+
+/*
+ * nssmirred_action_util
+ * nssmirred action utility structure.
+ */
+struct action_util nssmirred_action_util = {
+ .id = "nssmirred",
+ .parse_aopt = parse_nss_mirred,
+ .print_aopt = print_nss_mirred,
+};