Projects
openEuler:Mainline
iproute
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:iproute.spec
Changed
@@ -1,6 +1,8 @@ +#needsrootforbuild Name: iproute -Version: 5.15.0 -Release: 3 +Version: 6.1.0 +Epoch: 1 +Release: 6 Summary: Linux network configuration utilities License: GPLv2+ and Public Domain URL: https://kernel.org/pub/linux/utils/net/iproute2/ @@ -8,9 +10,13 @@ Patch1: bugfix-iproute2-3.10.0-fix-maddr-show.patch Patch2: bugfix-iproute2-change-proc-to-ipnetnsproc-which-is-private.patch +Patch3: backport-testsuite-fix-testsuite-build-failure-when-iproute-b.patch + +Patch9000: feature-iproute-add-support-for-ipvlan-l2e-mode.patch +Patch9001: bugfix-iproute2-cancel-some-test-cases.patch BuildRequires: gcc bison elfutils-libelf-devel flex iptables-devel -BuildRequires: libmnl-devel libselinux-devel pkgconfig libbpf-devel +BuildRequires: libmnl-devel libselinux-devel pkgconfig libbpf-devel sudo make Requires: libbpf psmisc Provides: /sbin/ip iproute-tc tc @@ -43,6 +49,13 @@ %configure %make_build +%check +make check +if test -n "$(find . -name *.err)"; then + echo "make check failed, please check" + exit 1 +fi + %install export CONFDIR='%{_sysconfdir}/iproute2' export SBINDIR='%{_sbindir}' @@ -76,6 +89,94 @@ %{_mandir}/* %changelog +* Sat Feb 25 2023 jiangheng <jiangheng14@huawei.com> - 1:6.1.0-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix ip netns attach failed + +* Sat Feb 18 2023 gaoxingwang <gaoxingwang1@huawei.com> - 1:6.1.0-5 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix testsuite build failure and delete libcap-devel dependency + +* Fri Feb 17 2023 gaoxingwang <gaoxingwang1@huawei.com> - 1:6.1.0-4 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add BuildRequire for make to fix build failure + +* Thu Feb 9 2023 gaoxingwang <gaoxingwang1@huawei.com> - 1:6.1.0-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add epoch version in changelog to fix check_spec_file ci failure + +* Wed Feb 1 2023 gaoxingwang <gaoxingwang1@huawei.com> - 6.1.0-2 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add epoch version + +* Tue Jan 31 2023 gaoxingwang <gaoxingwang1@huawei.com> - 6.1.0-1 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:update to 6.1.0 + +* Thu Dec 22 2022 gaoxingwang <gaoxingwang1@huawei.com> - 5.15.0-9 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:cancel some test cases that failed due to host configure + +* Wed Dec 21 2022 gaoxingwang <gaoxingwang1@huawei.com> - 5.15.0-8 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:cancle man page check + +* Mon Nov 21 2022 gaoxingwang <gaoxingwang1@huawei.com> - 5.15.0-7 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:enable make check + +* Wed Nov 09 2022 jiangheng <jiangheng14@huawei.com> - 5.15.0-6 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add ipvlan l2e mode support + +* Mon Oct 10 2022 jiangheng<jiangheng14@huawei.com> - 5.15.0-5 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:bridge: fix memory leak when doing fdb get + mptcp: fix memory leak when doing 'endpoint show' + mptcp: fix memory leak when getting limits + ip neigh: fix memory leak when doing 'get' + ip address: fix memory leak when specifying device + fix marco expansion in changelog + +* Fri Aug 26 2022 sunsuwan<sunsuwan3@huawei.com> - 5.15.0-4 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:lnstat: fix buffer overflow in header output + libnetlink: fix socket leak in rtnl_open_byptoyo + lnstat: fix strdup leak in w argument parsing + q_cake: allow fix buffer overflow on large labels + tc flower: fix buffer overflow on large labels + tc_tuil: fix parsing action control with space and sl + tipc: fix keylen check + fix devlink health dump command without arg + tc: em_u32: fix offset parsing + l2tp fix typo in AF_INET6 checksum JSON print + ip: Fix size_columns() for very large values + ip: Fix size_columns() invocation that passes a 32-bit quantity + * Tue Mar 01 2022 jiangheng<jiangheng12@huawei.com> - 5.15.0-3 - Type:bugfix - ID:NA @@ -92,7 +193,7 @@ - DESC: update to 5.15.0 * Mon Aug 02 2021 chenyanpanHW <chenyanpan@huawei.com> - 5.10.0-2 -- DESC: delete -S git from %autosetup, and delete BuildRequires git +- DESC: delete -S git from autosetup, and delete BuildRequires git * Tue Jan 26 2021 xihaochen<xihaochen@huawei.com> - 5.10.0-1 - Type:requirements
View file
_service:tar_scm:backport-testsuite-fix-testsuite-build-failure-when-iproute-b.patch
Added
@@ -0,0 +1,38 @@ +From c0a06885b944e1f14440f601a0b5266233814d54 Mon Sep 17 00:00:00 2001 +From: gaoxingwang <gaoxingwang1@huawei.com> +Date: Fri, 10 Feb 2023 16:45:31 +0800 +Subject: PATCH testsuite: fix testsuite build failure when iproute build + without libcap-devel + +iproute allows to build without libcap.The testsuite will fail to +compile when libcap dose not exists.It was required in 6d68d7f85d. + +Fixes: 6d68d7f85d ("testsuite: fix build failure") +Signed-off-by: gaoxingwang <gaoxingwang1@huawei.com> +Signed-off-by: Stephen Hemminger <stephen@networkplumber.org> +--- + testsuite/tools/Makefile | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/testsuite/tools/Makefile b/testsuite/tools/Makefile +index e0162ccc..0356ddae 100644 +--- a/testsuite/tools/Makefile ++++ b/testsuite/tools/Makefile +@@ -1,9 +1,13 @@ + # SPDX-License-Identifier: GPL-2.0 + CFLAGS= ++LDLIBS= + include ../../config.mk ++ifeq ($(HAVE_CAP),y) ++LDLIBS+= -lcap ++endif + + generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.a ../../lib/libutil.a +- $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -I../../include -I../../include/uapi -include../../include/uapi/linux/netlink.h -o $@ $^ -lmnl -lcap ++ $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -I../../include -I../../include/uapi -include../../include/uapi/linux/netlink.h -o $@ $^ -lmnl $(LDLIBS) + + clean: + rm -f generate_nlmsg +-- +2.27.0 +
View file
_service:tar_scm:bugfix-iproute2-cancel-some-test-cases.patch
Added
@@ -0,0 +1,408 @@ +From a24381ebd69218778c07c5d37c2a748109dd56c5 Mon Sep 17 00:00:00 2001 +From: gaoxingwang <gaoxingwang1@huawei.com> +Date: Tue, 31 Jan 2023 16:51:53 +0800 +Subject: PATCH cancel some test cases that failed due to host configure + +--- + Makefile | 6 -- + testsuite/tests/ip/link/add_type_bareudp.t | 86 ---------------------- + testsuite/tests/ip/link/add_type_xfrm.t | 17 ----- + testsuite/tests/tc/flower_mpls.t | 82 --------------------- + testsuite/tests/tc/mpls.t | 69 ----------------- + testsuite/tests/tc/vlan.t | 85 --------------------- + 6 files changed, 345 deletions(-) + delete mode 100755 testsuite/tests/ip/link/add_type_bareudp.t + delete mode 100755 testsuite/tests/ip/link/add_type_xfrm.t + delete mode 100755 testsuite/tests/tc/flower_mpls.t + delete mode 100755 testsuite/tests/tc/mpls.t + delete mode 100755 testsuite/tests/tc/vlan.t + +diff --git a/Makefile b/Makefile +index 8a17d61..29be241 100644 +--- a/Makefile ++++ b/Makefile +@@ -128,12 +128,6 @@ distclean: clobber + check: all + $(MAKE) -C testsuite + $(MAKE) -C testsuite alltests +- @if command -v man >/dev/null 2>&1; then \ +- echo "Checking manpages for syntax errors..."; \ +- $(MAKE) -C man check; \ +- else \ +- echo "man not installed, skipping checks for syntax errors."; \ +- fi + + cscope: + cscope -b -q -R -Iinclude -sip -slib -smisc -snetem -stc +diff --git a/testsuite/tests/ip/link/add_type_bareudp.t b/testsuite/tests/ip/link/add_type_bareudp.t +deleted file mode 100755 +index 8a2a1ed..0000000 +--- a/testsuite/tests/ip/link/add_type_bareudp.t ++++ /dev/null +@@ -1,86 +0,0 @@ +-#!/bin/sh +- +-. lib/generic.sh +- +-ts_log "Testing Add BareUDP interface (unicast MPLS)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (unicast MPLS)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype mpls_uc +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (unicast MPLS)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype mpls_uc" +-test_on "nomultiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (unicast MPLS)" link del dev $NEW_DEV +- +- +-ts_log "Testing Add BareUDP interface (multicast MPLS)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (multicast MPLS)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype mpls_mc +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (multicast MPLS)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype mpls_mc" +-test_on "nomultiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (multicast MPLS)" link del dev $NEW_DEV +- +- +-ts_log "Testing Add BareUDP interface (unicast and multicast MPLS)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (unicast and multicast MPLS)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype mpls_uc multiproto +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (unicast and multicast MPLS)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype mpls_uc" +-test_on "multiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (unicast and multicast MPLS)" link del dev $NEW_DEV +- +- +-ts_log "Testing Add BareUDP interface (IPv4)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (IPv4)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype ipv4 +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (IPv4)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype ip" +-test_on "nomultiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (IPv4)" link del dev $NEW_DEV +- +- +-ts_log "Testing Add BareUDP interface (IPv6)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (IPv6)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype ipv6 +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (IPv6)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype ipv6" +-test_on "nomultiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (IPv6)" link del dev $NEW_DEV +- +- +-ts_log "Testing Add BareUDP interface (IPv4 and IPv6)" +-NEW_DEV="$(rand_dev)" +- +-ts_ip "$0" "Add $NEW_DEV BareUDP interface (IPv4 and IPv6)" link add dev $NEW_DEV type bareudp dstport 6635 ethertype ipv4 multiproto +- +-ts_ip "$0" "Show $NEW_DEV BareUDP interface (IPv4 and IPv6)" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "dstport 6635" +-test_on "ethertype ip" +-test_on "multiproto" +- +-ts_ip "$0" "Del $NEW_DEV BareUDP interface (IPv4 and IPv6)" link del dev $NEW_DEV +diff --git a/testsuite/tests/ip/link/add_type_xfrm.t b/testsuite/tests/ip/link/add_type_xfrm.t +deleted file mode 100755 +index caba0e4..0000000 +--- a/testsuite/tests/ip/link/add_type_xfrm.t ++++ /dev/null +@@ -1,17 +0,0 @@ +-#!/bin/sh +- +-. lib/generic.sh +- +-ts_log "Testing Add XFRM Interface, With IF-ID" +- +-PHYS_DEV="lo" +-NEW_DEV="$(rand_dev)" +-IF_ID="0xf" +- +-ts_ip "$0" "Add $NEW_DEV xfrm interface" link add dev $NEW_DEV type xfrm dev $PHYS_DEV if_id $IF_ID +- +-ts_ip "$0" "Show $NEW_DEV xfrm interface" -d link show dev $NEW_DEV +-test_on "$NEW_DEV" +-test_on "if_id $IF_ID" +- +-ts_ip "$0" "Del $NEW_DEV xfrm interface" link del dev $NEW_DEV +diff --git a/testsuite/tests/tc/flower_mpls.t b/testsuite/tests/tc/flower_mpls.t +deleted file mode 100755 +index 430ed13..0000000 +--- a/testsuite/tests/tc/flower_mpls.t ++++ /dev/null +@@ -1,82 +0,0 @@ +-#!/bin/sh +- +-. lib/generic.sh +- +-DEV="$(rand_dev)" +-ts_ip "$0" "Add $DEV dummy interface" link add dev $DEV up type dummy +-ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +- +-reset_qdisc() +-{ +- ts_tc "$0" "Remove ingress qdisc" qdisc del dev $DEV ingress +- ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +-} +- +-ts_tc "$0" "Add MPLS filter matching first LSE with minimal values" \ +- filter add dev $DEV ingress protocol mpls_uc flower \ +- mpls_label 0 mpls_tc 0 mpls_bos 0 mpls_ttl 0 \ +- action drop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls_label 0" +-test_on "mpls_tc 0" +-test_on "mpls_bos 0" +-test_on "mpls_ttl 0" +- +-reset_qdisc +-ts_tc "$0" "Add MPLS filter matching first LSE with maximal values" \ +- filter add dev $DEV ingress protocol mpls_uc flower \ +- mpls_label 1048575 mpls_tc 7 mpls_bos 1 mpls_ttl 255 \ +- action drop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls_label 1048575" +-test_on "mpls_tc 7" +-test_on "mpls_bos 1" +-test_on "mpls_ttl 255" +- +-reset_qdisc +-ts_tc "$0" "Add MPLS filter matching second LSE with minimal values" \ +- filter add dev $DEV ingress protocol mpls_uc flower \ +- mpls lse depth 2 label 0 tc 0 bos 0 ttl 0 \ +- action drop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "lse" +-test_on "depth 2" +-test_on "label 0" +-test_on "tc 0" +-test_on "bos 0" +-test_on "ttl 0" +- +-reset_qdisc +-ts_tc "$0" "Add MPLS filter matching second LSE with maximal values" \ +- filter add dev $DEV ingress protocol mpls_uc flower \ +- mpls lse depth 2 label 1048575 tc 7 bos 1 ttl 255 \ +- action drop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "lse" +-test_on "depth 2" +-test_on "label 1048575" +-test_on "tc 7" +-test_on "bos 1" +-test_on "ttl 255" +- +-reset_qdisc +-ts_tc "$0" "Add MPLS filter matching two LSEs" \ +- filter add dev $DEV ingress protocol mpls_uc flower mpls \ +- lse depth 1 label 0 tc 0 bos 0 ttl 0 \ +- lse depth 2 label 1048575 tc 7 bos 1 ttl 255 \ +- action drop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "lse" +-test_on "depth 1" +-test_on "label 0" +-test_on "tc 0" +-test_on "bos 0" +-test_on "ttl 0" +-test_on "depth 2" +-test_on "label 1048575" +-test_on "tc 7" +-test_on "bos 1" +-test_on "ttl 255" +diff --git a/testsuite/tests/tc/mpls.t b/testsuite/tests/tc/mpls.t +deleted file mode 100755 +index cb25f36..0000000 +--- a/testsuite/tests/tc/mpls.t ++++ /dev/null +@@ -1,69 +0,0 @@ +-#!/bin/sh +- +-. lib/generic.sh +- +-DEV="$(rand_dev)" +-ts_ip "$0" "Add $DEV dummy interface" link add dev $DEV up type dummy +-ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +- +-reset_qdisc() +-{ +- ts_tc "$0" "Remove ingress qdisc" qdisc del dev $DEV ingress +- ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +-} +- +-ts_tc "$0" "Add mpls action pop" \ +- filter add dev $DEV ingress protocol mpls_uc matchall \ +- action mpls pop protocol ip +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "pop protocol ip pipe" +- +-reset_qdisc +-ts_tc "$0" "Add mpls action push" \ +- filter add dev $DEV ingress protocol ip matchall \ +- action mpls push protocol mpls_uc label 20 tc 3 bos 1 ttl 64 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "push" +-test_on "protocol mpls_uc" +-test_on "label 20" +-test_on "tc 3" +-test_on "bos 1" +-test_on "ttl 64" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add mpls action mac_push" \ +- filter add dev $DEV ingress matchall \ +- action mpls mac_push protocol mpls_uc label 20 tc 3 bos 1 ttl 64 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "mac_push" +-test_on "protocol mpls_uc" +-test_on "label 20" +-test_on "tc 3" +-test_on "bos 1" +-test_on "ttl 64" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add mpls action modify" \ +- filter add dev $DEV ingress protocol mpls_uc matchall \ +- action mpls modify label 20 tc 3 ttl 64 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "modify" +-test_on "label 20" +-test_on "tc 3" +-test_on "ttl 64" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add mpls action dec_ttl" \ +- filter add dev $DEV ingress protocol mpls_uc matchall \ +- action mpls dec_ttl +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "mpls" +-test_on "dec_ttl" +-test_on "pipe" +diff --git a/testsuite/tests/tc/vlan.t b/testsuite/tests/tc/vlan.t +deleted file mode 100755 +index 51529b2..0000000 +--- a/testsuite/tests/tc/vlan.t ++++ /dev/null +@@ -1,85 +0,0 @@ +-#!/bin/sh +- +-. lib/generic.sh +- +-DEV="$(rand_dev)" +-ts_ip "$0" "Add $DEV dummy interface" link add dev $DEV up type dummy +-ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +- +-reset_qdisc() +-{ +- ts_tc "$0" "Remove ingress qdisc" qdisc del dev $DEV ingress +- ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress +-} +- +-ts_tc "$0" "Add vlan action pop" \ +- filter add dev $DEV ingress matchall action vlan pop +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "pop" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action push (default parameters)" \ +- filter add dev $DEV ingress matchall action vlan push id 5 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "push" +-test_on "id 5" +-test_on "protocol 802.1Q" +-test_on "priority 0" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action push (explicit parameters)" \ +- filter add dev $DEV ingress matchall \ +- action vlan push id 5 protocol 802.1ad priority 2 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "push" +-test_on "id 5" +-test_on "protocol 802.1ad" +-test_on "priority 2" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action modify (default parameters)" \ +- filter add dev $DEV ingress matchall action vlan modify id 5 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "modify" +-test_on "id 5" +-test_on "protocol 802.1Q" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action modify (explicit parameters)" \ +- filter add dev $DEV ingress matchall \ +- action vlan modify id 5 protocol 802.1ad priority 2 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "modify" +-test_on "id 5" +-test_on "protocol 802.1ad" +-test_on "priority 2" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action pop_eth" \ +- filter add dev $DEV ingress matchall action vlan pop_eth +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "pop_eth" +-test_on "pipe" +- +-reset_qdisc +-ts_tc "$0" "Add vlan action push_eth" \ +- filter add dev $DEV ingress matchall \ +- action vlan push_eth dst_mac 02:00:00:00:00:02 \ +- src_mac 02:00:00:00:00:01 +-ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress +-test_on "vlan" +-test_on "push_eth" +-test_on "dst_mac 02:00:00:00:00:02" +-test_on "src_mac 02:00:00:00:00:01" +-test_on "pipe" +-- +2.27.0 +
View file
_service:tar_scm:bugfix-iproute2-change-proc-to-ipnetnsproc-which-is-private.patch
Changed
@@ -116,20 +116,18 @@ netns = open(net_path, O_RDONLY); if (netns < 0) { fprintf(stderr, "Cannot open network namespace: %s\n", -@@ -917,9 +972,11 @@ static int netns_add(int argc, char **argv, bool create) +@@ -911,9 +965,9 @@ static int netns_add(int argc, char **argv, bool create) + goto out_delete; + } + +- strcpy(proc_path, "/proc/self/ns/net"); ++ snprintf(proc_path, sizeof(proc_path), "/%s/self/ns/net", get_proc_string()); + } else { +- snprintf(proc_path, sizeof(proc_path), "/proc/%d/ns/net", pid); ++ snprintf(proc_path, sizeof(proc_path), "/%s/%d/ns/net", get_proc_string(), pid); } /* Bind the netns last so I can watch for it */ -- if (mount(proc_path, netns_path, "none", MS_BIND, NULL) < 0) { -+ char pid_net_pathMAXPATHLEN; -+ snprintf(pid_net_path, sizeof(pid_net_path), "%s/self/ns/net", get_proc_string()); -+ if (mount(pid_net_path, netns_path, "none", MS_BIND, NULL) < 0) { - fprintf(stderr, "Bind %s -> %s failed: %s\n", -- proc_path, netns_path, strerror(errno)); -+ pid_net_path, netns_path, strerror(errno)); - goto out_delete; - } - netns_restore(); -- 1.8.3.1
View file
_service:tar_scm:feature-iproute-add-support-for-ipvlan-l2e-mode.patch
Added
@@ -0,0 +1,56 @@ +From 3ea7f5ac296ee5c19459c2bf00fecf98f552a1c5 Mon Sep 17 00:00:00 2001 +From: Feilong Lin <linfeilong@huawei.com> +Date: Mon, 2 Mar 2020 20:52:06 +0800 + +--- + include/uapi/linux/if_link.h | 2 +- + ip/iplink_ipvlan.c | 10 +++++----- + 2 files changed, 6 insertions(+), 6 deletions(-) +diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h +index 1d4ed60..bddbdc7 100644 +--- a/include/uapi/linux/if_link.h ++++ b/include/uapi/linux/if_link.h +@@ -702,6 +702,7 @@ enum { + enum ipvlan_mode { + IPVLAN_MODE_L2 = 0, + IPVLAN_MODE_L3, ++ IPVLAN_MODE_L2E, + IPVLAN_MODE_L3S, + IPVLAN_MODE_MAX + }; +diff --git a/ip/iplink_ipvlan.c b/ip/iplink_ipvlan.c +index baae767..6de3138 100644 +--- a/ip/iplink_ipvlan.c ++++ b/ip/iplink_ipvlan.c +@@ -23,7 +23,7 @@ static void print_explain(struct link_util *lu, FILE *f) + fprintf(f, + "Usage: ... %s mode MODE FLAGS \n" + "\n" +- "MODE: l3 | l3s | l2\n" ++ "MODE: l3 | l2e | l3s | l2\n" + "FLAGS: bridge | private | vepa\n" + "(first values are the defaults if nothing is specified).\n", + lu->id); +@@ -47,8 +47,10 @@ static int ipvlan_parse_opt(struct link_util *lu, int argc, char **argv, + mode = IPVLAN_MODE_L3; + else if (strcmp(*argv, "l3s") == 0) + mode = IPVLAN_MODE_L3S; ++ else if (strcmp(*argv, "l2e") == 0) ++ mode = IPVLAN_MODE_L2E; + else { +- fprintf(stderr, "Error: argument of \"mode\" must be either \"l2\", \"l3\" or \"l3s\"\n"); ++ fprintf(stderr, "Error: argument of \"mode\" must be either \"l2\", \"l3\", \"l2e\", or \"l3s\"\n"); + return -1; + } + addattr16(n, 1024, IFLA_IPVLAN_MODE, mode); +@@ -88,6 +90,7 @@ static void ipvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) + __u16 mode = rta_getattr_u16(tbIFLA_IPVLAN_MODE); + const char *mode_str = mode == IPVLAN_MODE_L2 ? "l2" : + mode == IPVLAN_MODE_L3 ? "l3" : ++ mode == IPVLAN_MODE_L2E ? "l2e" : + mode == IPVLAN_MODE_L3S ? "l3s" : "unknown"; + + print_string(PRINT_ANY, "mode", " mode %s ", mode_str); +-- +2.19.1 +
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/iproute.git</param> - <param name="revision">a7dcf9f68c3f88932f1bc4d1254a2bdfdba79c29</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/vdpa.h
Deleted
@@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -/* - * vdpa device management interface - * Copyright (c) 2020 Mellanox Technologies Ltd. All rights reserved. - */ - -#ifndef _LINUX_VDPA_H_ -#define _LINUX_VDPA_H_ - -#define VDPA_GENL_NAME "vdpa" -#define VDPA_GENL_VERSION 0x1 - -enum vdpa_command { - VDPA_CMD_UNSPEC, - VDPA_CMD_MGMTDEV_NEW, - VDPA_CMD_MGMTDEV_GET, /* can dump */ - VDPA_CMD_DEV_NEW, - VDPA_CMD_DEV_DEL, - VDPA_CMD_DEV_GET, /* can dump */ -}; - -enum vdpa_attr { - VDPA_ATTR_UNSPEC, - - /* bus name (optional) + dev name together make the parent device handle */ - VDPA_ATTR_MGMTDEV_BUS_NAME, /* string */ - VDPA_ATTR_MGMTDEV_DEV_NAME, /* string */ - VDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES, /* u64 */ - - VDPA_ATTR_DEV_NAME, /* string */ - VDPA_ATTR_DEV_ID, /* u32 */ - VDPA_ATTR_DEV_VENDOR_ID, /* u32 */ - VDPA_ATTR_DEV_MAX_VQS, /* u32 */ - VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */ - - /* new attributes must be added above here */ - VDPA_ATTR_MAX, -}; - -#endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ifcfg
Deleted
@@ -1,150 +0,0 @@ -#! /bin/sh -# SPDX-License-Identifier: GPL-2.0 - -CheckForwarding () { - local sbase fwd - sbase=/proc/sys/net/ipv4/conf - fwd=0 - if -d $sbase ; then - for dir in $sbase/*/forwarding; do - fwd=$(( fwd + $(cat "$dir") )) - done - else - fwd=2 - fi - return $fwd -} - -RestartRDISC () { - killall -HUP rdisc || rdisc -fs -} - -ABCMaskLen () { - local class; - - class=${1%%.*} - if "$1" = "" -o $class -eq 0 -o $class -ge 224 ; then return 0 - elif $class -ge 224 ; then return 0 - elif $class -ge 192 ; then return 24 - elif $class -ge 128 ; then return 16 - else return 8; fi -} - -label="label $1" -ldev="$1" -dev=${1%:*} -if "$dev" = "" -o "$1" = "help" ; then - echo "Usage: ifcfg DEV add|del ADDR/LEN PEER | stop" 1>&2 - echo " add - add new address" 1>&2 - echo " del - delete address" 1>&2 - echo " stop - completely disable IP" 1>&2 - exit 1 -fi -shift - -CheckForwarding -fwd=$? -if $fwd -ne 0 ; then - echo "Forwarding is ON or its state is unknown ($fwd). OK, No RDISC." 1>&2 -fi - - -deleting=0 -case "$1" in -add) shift ;; -stop) - if "$ldev" != "$dev" ; then - echo "Cannot stop alias $ldev" 1>&2 - exit 1; - fi - ip -4 addr flush dev $dev $label || exit 1 - if $fwd -eq 0 ; then RestartRDISC; fi - exit 0 ;; -del*) - deleting=1; shift ;; -*) -esac - -ipaddr= -pfxlen= -if "$1" != "" ; then - ipaddr=${1%/*} - if "$1" != "$ipaddr" ; then - pfxlen=${1#*/} - fi - if "$ipaddr" = "" ; then - echo "$1 is bad IP address." 1>&2 - exit 1 - fi -fi -shift - -peer=$1 -if "$peer" != "" ; then - if "$pfxlen" != "" -a "$pfxlen" != "32" ; then - echo "Peer address with non-trivial netmask." 1>&2 - exit 1 - fi - pfx="$ipaddr peer $peer" -else - if "$ipaddr" = "" ; then - echo "Missing IP address argument." 1>&2 - exit 1 - fi - if "$pfxlen" = "" ; then - ABCMaskLen $ipaddr - pfxlen=$? - fi - pfx="$ipaddr/$pfxlen" -fi - -if "$ldev" = "$dev" -a "$ipaddr" != "" ; then - label= -fi - -if $deleting -ne 0 ; then - ip addr del $pfx dev $dev $label || exit 1 - if $fwd -eq 0 ; then RestartRDISC; fi - exit 0 -fi - - -if ! ip link set up dev $dev ; then - echo "Error: cannot enable interface $dev." 1>&2 - exit 1 -fi -if "$ipaddr" = "" ; then exit 0; fi - -if ! arping -q -c 2 -w 3 -D -I $dev $ipaddr ; then - echo "Error: some host already uses address $ipaddr on $dev." 1>&2 - exit 1 -fi - -if ! ip address add $pfx brd + dev $dev $label; then - echo "Error: failed to add $pfx on $dev." 1>&2 - exit 1 -fi - -arping -q -A -c 1 -I $dev $ipaddr -noarp=$? -( sleep 2 ; - arping -q -U -c 1 -I $dev $ipaddr ) >/dev/null 2>&1 </dev/null & - -ip route add unreachable 224.0.0.0/24 >/dev/null 2>&1 -ip route add unreachable 255.255.255.255 >/dev/null 2>&1 -if "`ip link ls $dev | grep -c MULTICAST`" -ge 1 ; then - ip route add 224.0.0.0/4 dev $dev scope global >/dev/null 2>&1 -fi - -if $fwd -eq 0 ; then - if $noarp -eq 0 ; then - ip ro append default dev $dev metric 30000 scope global - elif "$peer" != "" ; then - if ping -q -c 2 -w 4 $peer ; then - ip ro append default via $peer dev $dev metric 30001 - fi - fi - RestartRDISC -fi - -exit 0
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/routef
Deleted
@@ -1,10 +0,0 @@ -#! /bin/sh -# SPDX-License-Identifier: GPL-2.0 - -if -z "$*" ; then - exec ip -4 ro flush scope global type unicast -else - echo "Usage: routef" - echo - echo "This script will flush the IPv4 routing table" -fi
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/rtpr
Deleted
@@ -1,5 +0,0 @@ -#! /bin/sh -# SPDX-License-Identifier: GPL-2.0 - -exec tr "\\\\" " -"
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ifcfg.8
Deleted
@@ -1,48 +0,0 @@ -.TH IFCFG 8 "September 24 2009" "iproute2" "Linux" -.SH NAME -ifcfg \- simplistic script which replaces ifconfig IP management -.SH SYNOPSIS -.ad l -.in +8 -.ti -8 -.B ifcfg -.RI " " DEVICE " " command " " ADDRESS " " PEER " " -.sp - -.SH DESCRIPTION -This manual page documents briefly the -.B ifcfg -command. -.PP -This is a simplistic script replacing one option of -.B ifconfig -, namely, IP address management. It not only adds -addresses, but also carries out Duplicate Address Detection RFC-DHCP, -sends unsolicited ARP to update the caches of other hosts sharing -the interface, adds some control routes and restarts Router Discovery -when it is necessary. - -.SH IFCONFIG - COMMAND SYNTAX - -.SS -.TP -.B DEVICE -- it may have alias, suffix, separated by colon. - -.TP -.B command -- add, delete or stop. - -.TP -.B ADDRESS -- optionally followed by prefix length. - -.TP -.B peer -- optional peer address for pointpoint interfaces. - -.SH NOTES -This script is not suitable for use with IPv6. - -.SH SEE ALSO -.RB "IP Command reference " ip-cref.ps
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/routef.8
Deleted
@@ -1,1 +0,0 @@ -.so man8/routel.8
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/rtpr.8
Deleted
@@ -1,25 +0,0 @@ -.TH RTPR 8 "18 September, 2015" - -.SH NAME -rtpr \- replace backslashes with newlines. - -.SH DESCRIPTION -.B rtpr -is a trivial shell script which converts backslashes in standard input to newlines. It's sole purpose is to be fed with input from -.B ip -when executed with it's -.B --oneline -flag. - -.SH EXAMPLES -.TP -ip --oneline address show | rtpr -Undo oneline converted -.B ip-address -output. - -.SH SEE ALSO -.BR ip (8) - -.SH AUTHORS -Stephen Hemminger <shemming@brocade.com>
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/.gitignore
Added
@@ -0,0 +1,41 @@ +# locally generated +Config +static-syms.h +config.* +*.o +*.a +*.so +*~ +\#*# + +# cscope +cscope.* +ncscope.* +tags +TAGS + +# git files that we don't want to ignore even it they are dot-files +!.gitignore +!.mailmap + +# for patch generation +*.diff +*.patch +*.orig +*.rej + +# for quilt +.pc +patches +series + +# for gdb +.gdbinit +.gdb_history +*.gdb + +# tests +testsuite/results +testsuite/iproute2/iproute2-this +testsuite/tools/generate_nlmsg +testsuite/tests/ip/link/dev_wo_vf_rate.nl
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/.mailmap
Added
@@ -0,0 +1,22 @@ +# +# This list is used by git-shortlog to fix a few botched name translations +# in the git archive, either because the author's full name was messed up +# and/or not always written the same way, making contributions from the +# same person appearing not to be so or badly displayed. +# +# Format +# Full name <goodaddress> <badaddress> +Steve Wise <larrystevenwise@gmail.com> <swise@opengridcomputing.com> +Steve Wise <larrystevenwise@gmail.com> <swise@chelsio.com> + +Stephen Hemminger <stephen@networkplumber.org> <sthemmin@microsoft.com> +Stephen Hemminger <stephen@networkplumber.org> <shemming@brocade.com> +Stephen Hemminger <stephen@networkplumber.org> <stephen.hemminger@vyatta.com> +Stephen Hemminger <stephen@networkplumber.org> <shemminger@vyatta.com> +Stephen Hemminger <stephen@networkplumber.org> <shemminger> +Stephen Hemminger <stephen@networkplumber.org> <shemminger@linux-foundation.org> +Stephen Hemminger <stephen@networkplumber.org> <shemminger@osdl.org> +Stephen Hemminger <stephen@networkplumber.org> <osdl.org!shemminger> +Stephen Hemminger <stephen@networkplumber.org> <osdl.net!shemminger> + +David Ahern <dsahern@gmail.com> <dsa@cumulusnetworks.com>
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/Makefile
Changed
@@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 # Top level Makefile for iproute2 +-include config.mk + ifeq ("$(origin V)", "command line") VERBOSE = $(V) endif @@ -13,7 +15,6 @@ endif PREFIX?=/usr -LIBDIR?=$(PREFIX)/lib SBINDIR?=/sbin CONFDIR?=/etc/iproute2 NETNS_RUN_DIR?=/var/run/netns @@ -40,9 +41,18 @@ -DNETNS_RUN_DIR=\"$(NETNS_RUN_DIR)\" \ -DNETNS_ETC_DIR=\"$(NETNS_ETC_DIR)\" +#options for AX.25 +ADDLIB+=ax25_ntop.o + +#options for AX.25 +ADDLIB+=rose_ntop.o + #options for mpls ADDLIB+=mpls_ntop.o mpls_pton.o +#options for NETROM +ADDLIB+=netrom_ntop.o + CC := gcc HOSTCC ?= $(CC) DEFINES += -D_GNU_SOURCE @@ -55,12 +65,15 @@ CFLAGS := $(WFLAGS) $(CCOPTS) -I../include -I../include/uapi $(DEFINES) $(CFLAGS) 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 man +ifeq ($(HAVE_MNL),y) +SUBDIRS += tipc devlink rdma dcb vdpa +endif LIBNETLINK=../lib/libutil.a ../lib/libnetlink.a LDLIBS += $(LIBNETLINK) -all: config +all: config.mk @set -e; \ for i in $(SUBDIRS); \ do echo; echo $$i; $(MAKE) -C $$i; done @@ -80,7 +93,7 @@ @echo "Make Arguments:" @echo " V=0|1 - set build verbosity level" -config: +config.mk: @if ! -f config.mk -o configure -nt config.mk ; then \ sh configure $(KERNEL_INCLUDE); \ fi
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bash-completion/devlink -> _service:tar_scm:iproute2-6.1.0.tar.xz/bash-completion/devlink
Changed
@@ -33,6 +33,11 @@ dev) value=$(devlink dev show 2>/dev/null) ;; + selftests_id) + dev=${words4} + value=$(devlink -j dev selftests show 2>/dev/null \ + | jq ".selftests\"$dev\"") + ;; param_name) dev=${words4} value=$(devlink -j dev param show 2>/dev/null \ @@ -43,6 +48,19 @@ | jq '.port as $ports | $ports | keys as $key | ($ports$key.netdev // $key)') ;; + lc) + dev=${words3} + value=$(devlink -j lc show 2>/dev/null \ + | jq ".lc\"$dev\"" \ + | jq '. as $lcs | $lcs | keys as $key |($lcs$key.lc)' \ + 2>/dev/null) + ;; + lc_type) + dev=${words3} + lc=${words5} + value=$(devlink lc show $dev lc $lc -j 2>/dev/null \ + | jq '."supported_types"') + ;; region) value=$(devlink -j region show 2>/dev/null \ | jq '.regions' | jq 'keys') @@ -262,6 +280,29 @@ esac } +# Completion for devlink dev selftests +_devlink_dev_selftests() +{ + if $cword -gt 5 ; then + _devlink_direct_complete "selftests_id" + return + fi + case "$cword" in + 3) + COMPREPLY=( $( compgen -W "show run" -- "$cur" ) ) + return + ;; + 4) + _devlink_direct_complete "dev" + return + ;; + 5) + COMPREPLY=( $( compgen -W "id" -- "$cur" ) ) + return + ;; + esac +} + # Completion for devlink dev _devlink_dev() { @@ -274,7 +315,7 @@ fi return ;; - eswitch|param) + eswitch|param|selftests) _devlink_dev_$command return ;; @@ -395,6 +436,62 @@ esac } +# Completion for devlink lc set +_devlink_lc_set() +{ + case "$cword" in + 3) + _devlink_direct_complete "dev" + return + ;; + 4) + COMPREPLY=( $( compgen -W "lc" -- "$cur" ) ) + ;; + 5) + _devlink_direct_complete "lc" + ;; + 6) + COMPREPLY=( $( compgen -W "type notype" -- "$cur" ) ) + return + ;; + 7) + if "$prev" == "type" ; then + _devlink_direct_complete "lc_type" + fi + esac +} + +# Completion for devlink lc show +_devlink_lc_show() +{ + case $cword in + 3) + _devlink_direct_complete "dev" + ;; + 4) + COMPREPLY=( $( compgen -W "lc" -- "$cur" ) ) + ;; + 5) + _devlink_direct_complete "lc" + ;; + esac +} + +# Completion for devlink lc +_devlink_lc() +{ + case $command in + set) + _devlink_lc_set + return + ;; + show) + _devlink_lc_show + return + ;; + esac +} + # Completion for devlink dpipe _devlink_dpipe() { @@ -988,6 +1085,7 @@ local object=${words1} local command=${words2} local pprev=${wordscword - 2} + local prev=${wordscword - 1} if $objects =~ $object ; then if $cword -eq 2 ; then
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bash-completion/tc -> _service:tar_scm:iproute2-6.1.0.tar.xz/bash-completion/tc
Changed
@@ -127,10 +127,10 @@ protocol) # list comes from lib/ll_proto.c COMPREPLY+=( $( compgen -W ' 802.1Q 802.1ad 802_2 802_3 LLDP aarp \ all aoe arp atalk atmfate atmmpoa ax25 bpq can control cust \ - ddcmp dec diag dna_dl dna_rc dna_rt econet ieeepup ieeepupat \ - ip ipv4 ipv6 ipx irda lat localtalk loop mobitex ppp_disc \ - ppp_mp ppp_ses ppptalk pup pupat rarp sca snap tipc tr_802_2 \ - wan_ppp x25' -- "$cur" ) ) + ddcmp dec diag dna_dl dna_rc dna_rt econet ethercat ieeepup \ + ieeepupat ip ipv4 ipv6 ipx irda lat localtalk loop mobitex \ + ppp_disc ppp_mp ppp_ses ppptalk profinet pup pupat rarp sca \ + snap tipc tr_802_2 wan_ppp x25' -- "$cur" ) ) return 0 ;; prio)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/Makefile
Changed
@@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o +BROBJ = bridge.o fdb.o monitor.o link.o mdb.o vlan.o vni.o include ../config.mk
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/br_common.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/br_common.h
Changed
@@ -12,13 +12,18 @@ int print_fdb(struct nlmsghdr *n, void *arg); void print_stp_state(__u8 state); int parse_stp_state(const char *arg); -int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor); +int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, + bool global_only); +int print_vnifilter_rtm(struct nlmsghdr *n, void *arg, bool monitor); +void br_print_router_port_stats(struct rtattr *pattr); +void print_headers(FILE *fp, const char *label); int do_fdb(int argc, char **argv); int do_mdb(int argc, char **argv); int do_monitor(int argc, char **argv); int do_vlan(int argc, char **argv); int do_link(int argc, char **argv); +int do_vni(int argc, char **argv); extern int preferred_family; extern int show_stats;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/bridge.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/bridge.c
Changed
@@ -58,6 +58,7 @@ { "fdb", do_fdb }, { "mdb", do_mdb }, { "vlan", do_vlan }, + { "vni", do_vni }, { "monitor", do_monitor }, { "help", do_help }, { 0 }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/fdb.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/fdb.c
Changed
@@ -44,7 +44,11 @@ " bridge fdb show br BRDEV brport DEV vlan VID \n" " state STATE dynamic \n" " bridge fdb get to LLADDR br BRDEV { brport | dev } DEV\n" - " vlan VID vni VNI self master dynamic \n"); + " vlan VID vni VNI self master dynamic \n" + " bridge fdb flush dev DEV brport DEV vlan VID \n" + " self master nopermanent | nostatic | nodynamic \n" + " noadded_by_user noextern_learn nosticky \n" + " nooffloaded \n"); exit(-1); } @@ -175,6 +179,8 @@ if (filter_dynamic && (r->ndm_state & NUD_PERMANENT)) return 0; + print_headers(fp, "NEIGH"); + open_json_object(NULL); if (n->nlmsg_type == RTM_DELNEIGH) print_bool(PRINT_ANY, "deleted", "Deleted ", true); @@ -571,6 +577,7 @@ char *addr = NULL; short vlan = -1; char *endptr; + int ret; while (argc > 0) { if ((strcmp(*argv, "brport") == 0) || strcmp(*argv, "dev") == 0) { @@ -657,11 +664,147 @@ * if -json was specified. */ new_json_obj(json); + ret = 0; if (print_fdb(answer, stdout) < 0) { fprintf(stderr, "An error :-)\n"); - return -1; + ret = -1; } delete_json_obj(); + free(answer); + + return ret; +} + +static int fdb_flush(int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct ndmsg ndm; + char buf256; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg)), + .n.nlmsg_flags = NLM_F_REQUEST | NLM_F_BULK, + .n.nlmsg_type = RTM_DELNEIGH, + .ndm.ndm_family = PF_BRIDGE, + }; + unsigned short ndm_state_mask = 0; + unsigned short ndm_flags_mask = 0; + short vid = -1, port_ifidx = -1; + unsigned short ndm_flags = 0; + unsigned short ndm_state = 0; + char *d = NULL, *port = NULL; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + d = *argv; + } else if (strcmp(*argv, "master") == 0) { + ndm_flags |= NTF_MASTER; + } else if (strcmp(*argv, "self") == 0) { + ndm_flags |= NTF_SELF; + } else if (strcmp(*argv, "permanent") == 0) { + ndm_state |= NUD_PERMANENT; + ndm_state_mask |= NUD_PERMANENT; + } else if (strcmp(*argv, "nopermanent") == 0) { + ndm_state &= ~NUD_PERMANENT; + ndm_state_mask |= NUD_PERMANENT; + } else if (strcmp(*argv, "static") == 0) { + ndm_state |= NUD_NOARP; + ndm_state_mask |= NUD_NOARP | NUD_PERMANENT; + } else if (strcmp(*argv, "nostatic") == 0) { + ndm_state &= ~NUD_NOARP; + ndm_state_mask |= NUD_NOARP; + } else if (strcmp(*argv, "dynamic") == 0) { + ndm_state &= ~NUD_NOARP | NUD_PERMANENT; + ndm_state_mask |= NUD_NOARP | NUD_PERMANENT; + } else if (strcmp(*argv, "nodynamic") == 0) { + ndm_state |= NUD_NOARP; + ndm_state_mask |= NUD_NOARP; + } else if (strcmp(*argv, "added_by_user") == 0) { + ndm_flags |= NTF_USE; + ndm_flags_mask |= NTF_USE; + } else if (strcmp(*argv, "noadded_by_user") == 0) { + ndm_flags &= ~NTF_USE; + ndm_flags_mask |= NTF_USE; + } else if (strcmp(*argv, "extern_learn") == 0) { + ndm_flags |= NTF_EXT_LEARNED; + ndm_flags_mask |= NTF_EXT_LEARNED; + } else if (strcmp(*argv, "noextern_learn") == 0) { + ndm_flags &= ~NTF_EXT_LEARNED; + ndm_flags_mask |= NTF_EXT_LEARNED; + } else if (strcmp(*argv, "sticky") == 0) { + ndm_flags |= NTF_STICKY; + ndm_flags_mask |= NTF_STICKY; + } else if (strcmp(*argv, "nosticky") == 0) { + ndm_flags &= ~NTF_STICKY; + ndm_flags_mask |= NTF_STICKY; + } else if (strcmp(*argv, "offloaded") == 0) { + ndm_flags |= NTF_OFFLOADED; + ndm_flags_mask |= NTF_OFFLOADED; + } else if (strcmp(*argv, "nooffloaded") == 0) { + ndm_flags &= ~NTF_OFFLOADED; + ndm_flags_mask |= NTF_OFFLOADED; + } else if (strcmp(*argv, "brport") == 0) { + if (port) + duparg2("brport", *argv); + NEXT_ARG(); + port = *argv; + } else if (strcmp(*argv, "vlan") == 0) { + if (vid >= 0) + duparg2("vlan", *argv); + NEXT_ARG(); + vid = atoi(*argv); + } else { + if (strcmp(*argv, "help") == 0) + NEXT_ARG(); + } + argc--; argv++; + } + + if (d == NULL) { + fprintf(stderr, "Device is a required argument.\n"); + return -1; + } + + req.ndm.ndm_ifindex = ll_name_to_index(d); + if (req.ndm.ndm_ifindex == 0) { + fprintf(stderr, "Cannot find bridge device \"%s\"\n", d); + return -1; + } + + if (port) { + port_ifidx = ll_name_to_index(port); + if (port_ifidx == 0) { + fprintf(stderr, "Cannot find bridge port device \"%s\"\n", + port); + return -1; + } + } + + if (vid >= 4096) { + fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid); + return -1; + } + + /* if self and master were not specified assume self */ + if (!(ndm_flags & (NTF_SELF | NTF_MASTER))) + ndm_flags |= NTF_SELF; + + req.ndm.ndm_flags = ndm_flags; + req.ndm.ndm_state = ndm_state; + if (port_ifidx > -1) + addattr32(&req.n, sizeof(req), NDA_IFINDEX, port_ifidx); + if (vid > -1) + addattr16(&req.n, sizeof(req), NDA_VLAN, vid); + if (ndm_flags_mask) + addattr8(&req.n, sizeof(req), NDA_NDM_FLAGS_MASK, + ndm_flags_mask); + if (ndm_state_mask) + addattr16(&req.n, sizeof(req), NDA_NDM_STATE_MASK, + ndm_state_mask); + + if (rtnl_talk(&rth, &req.n, NULL) < 0) + return -1; return 0; } @@ -669,6 +812,7 @@ int do_fdb(int argc, char **argv) { ll_init_map(&rth); + timestamp = 0; if (argc > 0) { if (matches(*argv, "add") == 0) @@ -685,6 +829,8 @@ matches(*argv, "lst") == 0 || matches(*argv, "list") == 0) return fdb_show(argc-1, argv+1); + if (strcmp(*argv, "flush") == 0) + return fdb_flush(argc-1, argv+1); if (matches(*argv, "help") == 0) usage(); } else
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/link.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/link.c
Changed
@@ -153,6 +153,12 @@ if (prtbIFLA_BRPORT_MCAST_FLOOD) print_on_off(PRINT_ANY, "mcast_flood", "mcast_flood %s ", rta_getattr_u8(prtbIFLA_BRPORT_MCAST_FLOOD)); + if (prtbIFLA_BRPORT_BCAST_FLOOD) + print_on_off(PRINT_ANY, "bcast_flood", "bcast_flood %s ", + rta_getattr_u8(prtbIFLA_BRPORT_BCAST_FLOOD)); + if (prtbIFLA_BRPORT_MULTICAST_ROUTER) + print_uint(PRINT_ANY, "mcast_router", "mcast_router %u ", + rta_getattr_u8(prtbIFLA_BRPORT_MULTICAST_ROUTER)); if (prtbIFLA_BRPORT_MCAST_TO_UCAST) print_on_off(PRINT_ANY, "mcast_to_unicast", "mcast_to_unicast %s ", rta_getattr_u8(prtbIFLA_BRPORT_MCAST_TO_UCAST)); @@ -175,6 +181,9 @@ if (prtbIFLA_BRPORT_ISOLATED) print_on_off(PRINT_ANY, "isolated", "isolated %s ", rta_getattr_u8(prtbIFLA_BRPORT_ISOLATED)); + if (prtbIFLA_BRPORT_LOCKED) + print_on_off(PRINT_ANY, "locked", "locked %s ", + rta_getattr_u8(prtbIFLA_BRPORT_LOCKED)); } else print_stp_state(rta_getattr_u8(attr)); } @@ -192,12 +201,6 @@ if (aftbIFLA_BRIDGE_MODE) print_hwmode(rta_getattr_u16(aftbIFLA_BRIDGE_MODE)); - - if (!show_details) - return; - - if (aftbIFLA_BRIDGE_VLAN_INFO) - print_vlan_info(aftbIFLA_BRIDGE_VLAN_INFO, ifindex); } int print_linkinfo(struct nlmsghdr *n, void *arg) @@ -227,6 +230,8 @@ if (!name) return -1; + print_headers(fp, "LINK"); + open_json_object(NULL); if (n->nlmsg_type == RTM_DELLINK) print_bool(PRINT_ANY, "deleted", "Deleted ", true); @@ -270,11 +275,14 @@ " learning {on | off} \n" " learning_sync {on | off} \n" " flood {on | off} \n" + " mcast_router MULTICAST_ROUTER \n" " mcast_flood {on | off} \n" + " bcast_flood {on | off} \n" " mcast_to_unicast {on | off} \n" " neigh_suppress {on | off} \n" " vlan_tunnel {on | off} \n" " isolated {on | off} \n" + " locked {on | off} \n" " hwmode {vepa | veb} \n" " backup_port DEVICE nobackup_port \n" " self master \n" @@ -301,8 +309,11 @@ __s8 learning_sync = -1; __s8 flood = -1; __s8 vlan_tunnel = -1; + __s8 mcast_router = -1; __s8 mcast_flood = -1; + __s8 bcast_flood = -1; __s8 mcast_to_unicast = -1; + __s8 locked = -1; __s8 isolated = -1; __s8 hairpin = -1; __s8 bpdu_guard = -1; @@ -355,11 +366,19 @@ flood = parse_on_off("flood", *argv, &ret); if (ret) return ret; + } else if (strcmp(*argv, "mcast_router") == 0) { + NEXT_ARG(); + mcast_router = atoi(*argv); } else if (strcmp(*argv, "mcast_flood") == 0) { NEXT_ARG(); mcast_flood = parse_on_off("mcast_flood", *argv, &ret); if (ret) return ret; + } else if (strcmp(*argv, "bcast_flood") == 0) { + NEXT_ARG(); + bcast_flood = parse_on_off("bcast_flood", *argv, &ret); + if (ret) + return ret; } else if (strcmp(*argv, "mcast_to_unicast") == 0) { NEXT_ARG(); mcast_to_unicast = parse_on_off("mcast_to_unicast", *argv, &ret); @@ -415,6 +434,11 @@ isolated = parse_on_off("isolated", *argv, &ret); if (ret) return ret; + } else if (strcmp(*argv, "locked") == 0) { + NEXT_ARG(); + locked = parse_on_off("locked", *argv, &ret); + if (ret) + return ret; } else if (strcmp(*argv, "backup_port") == 0) { NEXT_ARG(); backup_port_idx = ll_name_to_index(*argv); @@ -459,9 +483,15 @@ addattr8(&req.n, sizeof(req), IFLA_BRPORT_PROTECT, root_block); if (flood >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_UNICAST_FLOOD, flood); + if (mcast_router >= 0) + addattr8(&req.n, sizeof(req), IFLA_BRPORT_MULTICAST_ROUTER, + mcast_router); if (mcast_flood >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_MCAST_FLOOD, mcast_flood); + if (bcast_flood >= 0) + addattr8(&req.n, sizeof(req), IFLA_BRPORT_BCAST_FLOOD, + bcast_flood); if (mcast_to_unicast >= 0) addattr8(&req.n, sizeof(req), IFLA_BRPORT_MCAST_TO_UCAST, mcast_to_unicast); @@ -489,6 +519,9 @@ if (isolated != -1) addattr8(&req.n, sizeof(req), IFLA_BRPORT_ISOLATED, isolated); + if (locked >= 0) + addattr8(&req.n, sizeof(req), IFLA_BRPORT_LOCKED, locked); + if (backup_port_idx != -1) addattr32(&req.n, sizeof(req), IFLA_BRPORT_BACKUP_PORT, backup_port_idx); @@ -538,19 +571,9 @@ return nodev(filter_dev); } - if (show_details) { - if (rtnl_linkdump_req_filter(&rth, PF_BRIDGE, - (compress_vlans ? - RTEXT_FILTER_BRVLAN_COMPRESSED : - RTEXT_FILTER_BRVLAN)) < 0) { - perror("Cannon send dump request"); - exit(1); - } - } else { - if (rtnl_linkdump_req(&rth, PF_BRIDGE) < 0) { - perror("Cannon send dump request"); - exit(1); - } + if (rtnl_linkdump_req(&rth, PF_BRIDGE) < 0) { + perror("Cannot send dump request"); + exit(1); } new_json_obj(json); @@ -567,6 +590,8 @@ int do_link(int argc, char **argv) { ll_init_map(&rth); + timestamp = 0; + if (argc > 0) { if (matches(*argv, "set") == 0 || matches(*argv, "change") == 0)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/mdb.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/mdb.c
Changed
@@ -59,7 +59,7 @@ return tbuf; } -static void __print_router_port_stats(FILE *f, struct rtattr *pattr) +void br_print_router_port_stats(struct rtattr *pattr) { struct rtattr *tbMDBA_ROUTER_PATTR_MAX + 1; @@ -101,13 +101,13 @@ print_string(PRINT_JSON, "port", NULL, port_ifname); if (show_stats) - __print_router_port_stats(f, i); + br_print_router_port_stats(i); close_json_object(); } else if (show_stats) { fprintf(f, "router ports on %s: %s", brifname, port_ifname); - __print_router_port_stats(f, i); + br_print_router_port_stats(i); fprintf(f, "\n"); } else { fprintf(f, "%s ", port_ifname); @@ -380,6 +380,8 @@ if (ret != 1) return ret; + print_headers(fp, "MDB"); + if (n->nlmsg_type == RTM_DELMDB) print_bool(PRINT_ANY, "deleted", "Deleted ", true); @@ -564,6 +566,7 @@ int do_mdb(int argc, char **argv) { ll_init_map(&rth); + timestamp = 0; if (argc > 0) { if (matches(*argv, "add") == 0)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/monitor.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/monitor.c
Changed
@@ -31,7 +31,7 @@ static void usage(void) { - fprintf(stderr, "Usage: bridge monitor file | link | fdb | mdb | vlan | all\n"); + fprintf(stderr, "Usage: bridge monitor file | link | fdb | mdb | vlan | vni | all\n"); exit(-1); } @@ -40,27 +40,17 @@ { FILE *fp = arg; - if (timestamp) - print_timestamp(fp); - switch (n->nlmsg_type) { case RTM_NEWLINK: case RTM_DELLINK: - if (prefix_banner) - fprintf(fp, "LINK"); - return print_linkinfo(n, arg); case RTM_NEWNEIGH: case RTM_DELNEIGH: - if (prefix_banner) - fprintf(fp, "NEIGH"); return print_fdb(n, arg); case RTM_NEWMDB: case RTM_DELMDB: - if (prefix_banner) - fprintf(fp, "MDB"); return print_mdb_mon(n, arg); case NLMSG_TSTAMP: @@ -69,15 +59,26 @@ case RTM_NEWVLAN: case RTM_DELVLAN: - if (prefix_banner) - fprintf(fp, "VLAN"); - return print_vlan_rtm(n, arg, true); + return print_vlan_rtm(n, arg, true, false); + + case RTM_NEWTUNNEL: + case RTM_DELTUNNEL: + return print_vnifilter_rtm(n, arg, true); default: return 0; } } +void print_headers(FILE *fp, const char *label) +{ + if (timestamp) + print_timestamp(fp); + + if (prefix_banner) + fprintf(fp, "%s", label); +} + int do_monitor(int argc, char **argv) { char *file = NULL; @@ -86,6 +87,7 @@ int lneigh = 0; int lmdb = 0; int lvlan = 0; + int lvni = 0; rtnl_close(&rth); @@ -105,9 +107,13 @@ } else if (matches(*argv, "vlan") == 0) { lvlan = 1; groups = 0; + } else if (strcmp(*argv, "vni") == 0) { + lvni = 1; + groups = 0; } else if (strcmp(*argv, "all") == 0) { groups = ~RTMGRP_TC; lvlan = 1; + lvni = 1; prefix_banner = 1; } else if (matches(*argv, "help") == 0) { usage(); @@ -151,6 +157,11 @@ exit(1); } + if (lvni && rtnl_add_nl_group(&rth, RTNLGRP_TUNNEL) < 0) { + fprintf(stderr, "Failed to add bridge vni group to list\n"); + exit(1); + } + ll_init_map(&rth); if (rtnl_listen(&rth, accept_msg, stdout) < 0)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/bridge/vlan.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/bridge/vlan.c
Changed
@@ -9,6 +9,7 @@ #include <linux/if_bridge.h> #include <linux/if_ether.h> #include <string.h> +#include <errno.h> #include "json_print.h" #include "libnetlink.h" @@ -35,8 +36,23 @@ " pvid untagged \n" " self master \n" " bridge vlan { set } vid VLAN_ID dev DEV state STP_STATE \n" + " mcast_router MULTICAST_ROUTER \n" " bridge vlan { show } dev DEV vid VLAN_ID \n" - " bridge vlan { tunnelshow } dev DEV vid VLAN_ID \n"); + " bridge vlan { tunnelshow } dev DEV vid VLAN_ID \n" + " bridge vlan global { set } vid VLAN_ID dev DEV\n" + " mcast_snooping MULTICAST_SNOOPING \n" + " mcast_querier MULTICAST_QUERIER \n" + " mcast_igmp_version IGMP_VERSION \n" + " mcast_mld_version MLD_VERSION \n" + " mcast_last_member_count LAST_MEMBER_COUNT \n" + " mcast_last_member_interval LAST_MEMBER_INTERVAL \n" + " mcast_startup_query_count STARTUP_QUERY_COUNT \n" + " mcast_startup_query_interval STARTUP_QUERY_INTERVAL \n" + " mcast_membership_interval MEMBERSHIP_INTERVAL \n" + " mcast_querier_interval QUERIER_INTERVAL \n" + " mcast_query_interval QUERY_INTERVAL \n" + " mcast_query_response_interval QUERY_RESPONSE_INTERVAL \n" + " bridge vlan global { show } dev DEV vid VLAN_ID \n"); exit(-1); } @@ -257,16 +273,24 @@ }; struct bridge_vlan_info vinfo = {}; struct rtattr *afspec; - short vid_end = -1; char *d = NULL; short vid = -1; - int state = -1; + afspec = addattr_nest(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY); + afspec->rta_type |= NLA_F_NESTED; while (argc > 0) { if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); d = *argv; + req.bvm.ifindex = ll_name_to_index(d); + if (req.bvm.ifindex == 0) { + fprintf(stderr, + "Cannot find network device \"%s\"\n", + d); + return -1; + } } else if (strcmp(*argv, "vid") == 0) { + short vid_end = -1; char *p; NEXT_ARG(); @@ -284,8 +308,22 @@ } else { vid = atoi(*argv); } + if (vid >= 4096) { + fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", + vid); + return -1; + } + + vinfo.flags = BRIDGE_VLAN_INFO_ONLY_OPTS; + vinfo.vid = vid; + addattr_l(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_INFO, + &vinfo, sizeof(vinfo)); + if (vid_end != -1) + addattr16(&req.n, sizeof(req), + BRIDGE_VLANDB_ENTRY_RANGE, vid_end); } else if (strcmp(*argv, "state") == 0) { char *endptr; + int state; NEXT_ARG(); state = strtol(*argv, &endptr, 10); @@ -295,42 +333,197 @@ fprintf(stderr, "Error: invalid STP state\n"); return -1; } + addattr8(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_STATE, + state); + } else if (strcmp(*argv, "mcast_router") == 0) { + __u8 mcast_router; + + NEXT_ARG(); + if (get_u8(&mcast_router, *argv, 0)) + invarg("invalid mcast_router", *argv); + addattr8(&req.n, sizeof(req), + BRIDGE_VLANDB_ENTRY_MCAST_ROUTER, + mcast_router); } else { if (matches(*argv, "help") == 0) NEXT_ARG(); } argc--; argv++; } + addattr_nest_end(&req.n, afspec); if (d == NULL || vid == -1) { fprintf(stderr, "Device and VLAN ID are required arguments.\n"); return -1; } - req.bvm.ifindex = ll_name_to_index(d); - if (req.bvm.ifindex == 0) { - fprintf(stderr, "Cannot find network device \"%s\"\n", d); + if (rtnl_talk(&rth, &req.n, NULL) < 0) return -1; - } - if (vid >= 4096) { - fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", vid); - return -1; - } - afspec = addattr_nest(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY); + return 0; +} + +static int vlan_global_option_set(int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct br_vlan_msg bvm; + char buf1024; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct br_vlan_msg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_NEWVLAN, + .bvm.family = PF_BRIDGE, + }; + struct rtattr *afspec; + short vid_end = -1; + char *d = NULL; + short vid = -1; + __u64 val64; + __u32 val32; + __u8 val8; + + afspec = addattr_nest(&req.n, sizeof(req), + BRIDGE_VLANDB_GLOBAL_OPTIONS); afspec->rta_type |= NLA_F_NESTED; + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + d = *argv; + req.bvm.ifindex = ll_name_to_index(d); + if (req.bvm.ifindex == 0) { + fprintf(stderr, "Cannot find network device \"%s\"\n", + d); + return -1; + } + } else if (strcmp(*argv, "vid") == 0) { + char *p; - vinfo.flags = BRIDGE_VLAN_INFO_ONLY_OPTS; - vinfo.vid = vid; - addattr_l(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_INFO, &vinfo, - sizeof(vinfo)); - if (vid_end != -1) - addattr16(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_RANGE, - vid_end); - if (state >= 0) - addattr8(&req.n, sizeof(req), BRIDGE_VLANDB_ENTRY_STATE, state); + NEXT_ARG(); + p = strchr(*argv, '-'); + if (p) { + *p = '\0'; + p++; + vid = atoi(*argv); + vid_end = atoi(p); + if (vid >= vid_end || vid_end >= 4096) { + fprintf(stderr, "Invalid VLAN range \"%hu-%hu\"\n", + vid, vid_end); + return -1; + } + } else { + vid = atoi(*argv); + } + if (vid >= 4096) { + fprintf(stderr, "Invalid VLAN ID \"%hu\"\n", + vid); + return -1; + } + addattr16(&req.n, sizeof(req), BRIDGE_VLANDB_GOPTS_ID, + vid); + if (vid_end != -1) + addattr16(&req.n, sizeof(req), + BRIDGE_VLANDB_GOPTS_RANGE, vid_end); + } else if (strcmp(*argv, "mcast_snooping") == 0) { + NEXT_ARG(); + if (get_u8(&val8, *argv, 0)) + invarg("invalid mcast_snooping", *argv); + addattr8(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING, val8); + } else if (strcmp(*argv, "mcast_querier") == 0) { + NEXT_ARG(); + if (get_u8(&val8, *argv, 0)) + invarg("invalid mcast_querier", *argv); + addattr8(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, val8); + } else if (strcmp(*argv, "mcast_igmp_version") == 0) { + NEXT_ARG(); + if (get_u8(&val8, *argv, 0)) + invarg("invalid mcast_igmp_version", *argv); + addattr8(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION, val8); + } else if (strcmp(*argv, "mcast_mld_version") == 0) { + NEXT_ARG(); + if (get_u8(&val8, *argv, 0)) + invarg("invalid mcast_mld_version", *argv); + addattr8(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION, val8); + } else if (strcmp(*argv, "mcast_last_member_count") == 0) { + NEXT_ARG(); + if (get_u32(&val32, *argv, 0)) + invarg("invalid mcast_last_member_count", *argv); + addattr32(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT, + val32); + } else if (strcmp(*argv, "mcast_startup_query_count") == 0) { + NEXT_ARG(); + if (get_u32(&val32, *argv, 0)) + invarg("invalid mcast_startup_query_count", + *argv); + addattr32(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT, + val32); + } else if (strcmp(*argv, "mcast_last_member_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_last_member_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL, + val64); + } else if (strcmp(*argv, "mcast_membership_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_membership_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL, + val64); + } else if (strcmp(*argv, "mcast_querier_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_querier_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL, + val64); + } else if (strcmp(*argv, "mcast_query_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_query_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL, + val64); + } else if (strcmp(*argv, "mcast_query_response_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_query_response_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL, + val64); + } else if (strcmp(*argv, "mcast_startup_query_interval") == 0) { + NEXT_ARG(); + if (get_u64(&val64, *argv, 0)) + invarg("invalid mcast_startup_query_interval", + *argv); + addattr64(&req.n, 1024, + BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL, + val64); + } else { + if (strcmp(*argv, "help") == 0) + NEXT_ARG(); + } + argc--; argv++; + } addattr_nest_end(&req.n, afspec); + if (d == NULL || vid == -1) { + fprintf(stderr, "Device and VLAN ID are required arguments.\n"); + return -1; + } + if (rtnl_talk(&rth, &req.n, NULL) < 0) return -1; @@ -621,11 +814,225 @@ return 0; } -int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor) +static void print_vlan_router_ports(struct rtattr *rattr) +{ + int rem = RTA_PAYLOAD(rattr); + struct rtattr *i; + + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + open_json_array(PRINT_ANY, is_json_context() ? "router_ports" : + "router ports: "); + for (i = RTA_DATA(rattr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) { + uint32_t *port_ifindex = RTA_DATA(i); + const char *port_ifname = ll_index_to_name(*port_ifindex); + + open_json_object(NULL); + if (show_stats && i != RTA_DATA(rattr)) { + print_nl(); + /* start: IFNAMSIZ + 4 + strlen("router ports: ") */ + print_string(PRINT_FP, NULL, + "%-" __stringify(IFNAMSIZ) "s " + " ", + ""); + } + print_string(PRINT_ANY, "port", "%s ", port_ifname); + if (show_stats) + br_print_router_port_stats(i); + close_json_object(); + } + close_json_array(PRINT_JSON, NULL); + print_nl(); +} + +static void print_vlan_global_opts(struct rtattr *a, int ifindex) +{ + struct rtattr *vtbBRIDGE_VLANDB_GOPTS_MAX + 1, *vattr; + __u16 vid, vrange = 0; + + if ((a->rta_type & NLA_TYPE_MASK) != BRIDGE_VLANDB_GLOBAL_OPTIONS) + return; + + parse_rtattr_flags(vtb, BRIDGE_VLANDB_GOPTS_MAX, RTA_DATA(a), + RTA_PAYLOAD(a), NLA_F_NESTED); + vid = rta_getattr_u16(vtbBRIDGE_VLANDB_GOPTS_ID); + if (vtbBRIDGE_VLANDB_GOPTS_RANGE) + vrange = rta_getattr_u16(vtbBRIDGE_VLANDB_GOPTS_RANGE); + else + vrange = vid; + + if (filter_vlan && (filter_vlan < vid || filter_vlan > vrange)) + return; + + if (vlan_rtm_cur_ifidx != ifindex) { + open_vlan_port(ifindex, VLAN_SHOW_VLAN); + open_json_object(NULL); + vlan_rtm_cur_ifidx = ifindex; + } else { + open_json_object(NULL); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + } + print_range("vlan", vid, vrange); + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_SNOOPING) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_SNOOPING; + print_uint(PRINT_ANY, "mcast_snooping", "mcast_snooping %u ", + rta_getattr_u8(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERIER) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERIER; + print_uint(PRINT_ANY, "mcast_querier", "mcast_querier %u ", + rta_getattr_u8(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION; + print_uint(PRINT_ANY, "mcast_igmp_version", + "mcast_igmp_version %u ", rta_getattr_u8(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION; + print_uint(PRINT_ANY, "mcast_mld_version", + "mcast_mld_version %u ", rta_getattr_u8(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT; + print_uint(PRINT_ANY, "mcast_last_member_count", + "mcast_last_member_count %u ", + rta_getattr_u32(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL; + print_lluint(PRINT_ANY, "mcast_last_member_interval", + "mcast_last_member_interval %llu ", + rta_getattr_u64(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT; + print_uint(PRINT_ANY, "mcast_startup_query_count", + "mcast_startup_query_count %u ", + rta_getattr_u32(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL; + print_lluint(PRINT_ANY, "mcast_startup_query_interval", + "mcast_startup_query_interval %llu ", + rta_getattr_u64(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL; + print_lluint(PRINT_ANY, "mcast_membership_interval", + "mcast_membership_interval %llu ", + rta_getattr_u64(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL; + print_lluint(PRINT_ANY, "mcast_querier_interval", + "mcast_querier_interval %llu ", + rta_getattr_u64(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL; + print_lluint(PRINT_ANY, "mcast_query_interval", + "mcast_query_interval %llu ", + rta_getattr_u64(vattr)); + } + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL) { + vattr = vtbBRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL; + print_lluint(PRINT_ANY, "mcast_query_response_interval", + "mcast_query_response_interval %llu ", + rta_getattr_u64(vattr)); + } + print_nl(); + if (vtbBRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS) { + vattr = RTA_DATA(vtbBRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS); + print_vlan_router_ports(vattr); + } + close_json_object(); +} + +static void print_vlan_opts(struct rtattr *a, int ifindex) +{ + struct rtattr *vtbBRIDGE_VLANDB_ENTRY_MAX + 1, *vattr; + struct bridge_vlan_xstats vstats; + struct bridge_vlan_info *vinfo; + __u16 vrange = 0; + __u8 state = 0; + + if ((a->rta_type & NLA_TYPE_MASK) != BRIDGE_VLANDB_ENTRY) + return; + + parse_rtattr_flags(vtb, BRIDGE_VLANDB_ENTRY_MAX, RTA_DATA(a), + RTA_PAYLOAD(a), NLA_F_NESTED); + vinfo = RTA_DATA(vtbBRIDGE_VLANDB_ENTRY_INFO); + + memset(&vstats, 0, sizeof(vstats)); + if (vtbBRIDGE_VLANDB_ENTRY_RANGE) + vrange = rta_getattr_u16(vtbBRIDGE_VLANDB_ENTRY_RANGE); + else + vrange = vinfo->vid; + + if (filter_vlan && (filter_vlan < vinfo->vid || filter_vlan > vrange)) + return; + + if (vtbBRIDGE_VLANDB_ENTRY_STATE) + state = rta_getattr_u8(vtbBRIDGE_VLANDB_ENTRY_STATE); + + if (vtbBRIDGE_VLANDB_ENTRY_STATS) { + struct rtattr *stbBRIDGE_VLANDB_STATS_MAX+1; + struct rtattr *attr; + + attr = vtbBRIDGE_VLANDB_ENTRY_STATS; + parse_rtattr(stb, BRIDGE_VLANDB_STATS_MAX, RTA_DATA(attr), + RTA_PAYLOAD(attr)); + + if (stbBRIDGE_VLANDB_STATS_RX_BYTES) { + attr = stbBRIDGE_VLANDB_STATS_RX_BYTES; + vstats.rx_bytes = rta_getattr_u64(attr); + } + if (stbBRIDGE_VLANDB_STATS_RX_PACKETS) { + attr = stbBRIDGE_VLANDB_STATS_RX_PACKETS; + vstats.rx_packets = rta_getattr_u64(attr); + } + if (stbBRIDGE_VLANDB_STATS_TX_PACKETS) { + attr = stbBRIDGE_VLANDB_STATS_TX_PACKETS; + vstats.tx_packets = rta_getattr_u64(attr); + } + if (stbBRIDGE_VLANDB_STATS_TX_BYTES) { + attr = stbBRIDGE_VLANDB_STATS_TX_BYTES; + vstats.tx_bytes = rta_getattr_u64(attr); + } + } + + if (vlan_rtm_cur_ifidx != ifindex) { + open_vlan_port(ifindex, VLAN_SHOW_VLAN); + open_json_object(NULL); + vlan_rtm_cur_ifidx = ifindex; + } else { + open_json_object(NULL); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + } + print_range("vlan", vinfo->vid, vrange); + print_vlan_flags(vinfo->flags); + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + print_stp_state(state); + if (vtbBRIDGE_VLANDB_ENTRY_MCAST_ROUTER) { + vattr = vtbBRIDGE_VLANDB_ENTRY_MCAST_ROUTER; + print_uint(PRINT_ANY, "mcast_router", "mcast_router %u ", + rta_getattr_u8(vattr)); + } + print_nl(); + if (show_stats) + __print_one_vlan_stats(&vstats); + close_json_object(); +} + +int print_vlan_rtm(struct nlmsghdr *n, void *arg, bool monitor, bool global_only) { - struct rtattr *vtbBRIDGE_VLANDB_ENTRY_MAX + 1, *a; struct br_vlan_msg *bvm = NLMSG_DATA(n); int len = n->nlmsg_len; + struct rtattr *a; + FILE *fp = arg; int rem; if (n->nlmsg_type != RTM_NEWVLAN && n->nlmsg_type != RTM_DELVLAN && @@ -647,6 +1054,8 @@ if (filter_index && filter_index != bvm->ifindex) return 0; + print_headers(fp, "VLAN"); + if (n->nlmsg_type == RTM_DELVLAN) print_bool(PRINT_ANY, "deleted", "Deleted ", true); @@ -660,66 +1069,21 @@ rem = len; for (a = BRVLAN_RTA(bvm); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) { - struct bridge_vlan_xstats vstats; - struct bridge_vlan_info *vinfo; - __u32 vrange = 0; - __u8 state = 0; - - parse_rtattr_flags(vtb, BRIDGE_VLANDB_ENTRY_MAX, RTA_DATA(a), - RTA_PAYLOAD(a), NLA_F_NESTED); - vinfo = RTA_DATA(vtbBRIDGE_VLANDB_ENTRY_INFO); - - memset(&vstats, 0, sizeof(vstats)); - if (vtbBRIDGE_VLANDB_ENTRY_RANGE) - vrange = rta_getattr_u16(vtbBRIDGE_VLANDB_ENTRY_RANGE); - else - vrange = vinfo->vid; + unsigned short rta_type = a->rta_type & NLA_TYPE_MASK; - if (vtbBRIDGE_VLANDB_ENTRY_STATE) - state = rta_getattr_u8(vtbBRIDGE_VLANDB_ENTRY_STATE); - - if (vtbBRIDGE_VLANDB_ENTRY_STATS) { - struct rtattr *stbBRIDGE_VLANDB_STATS_MAX+1; - struct rtattr *attr; - - attr = vtbBRIDGE_VLANDB_ENTRY_STATS; - parse_rtattr(stb, BRIDGE_VLANDB_STATS_MAX, RTA_DATA(attr), - RTA_PAYLOAD(attr)); + /* skip unknown attributes */ + if (rta_type > BRIDGE_VLANDB_MAX || + (global_only && rta_type != BRIDGE_VLANDB_GLOBAL_OPTIONS)) + continue; - if (stbBRIDGE_VLANDB_STATS_RX_BYTES) { - attr = stbBRIDGE_VLANDB_STATS_RX_BYTES; - vstats.rx_bytes = rta_getattr_u64(attr); - } - if (stbBRIDGE_VLANDB_STATS_RX_PACKETS) { - attr = stbBRIDGE_VLANDB_STATS_RX_PACKETS; - vstats.rx_packets = rta_getattr_u64(attr); - } - if (stbBRIDGE_VLANDB_STATS_TX_PACKETS) { - attr = stbBRIDGE_VLANDB_STATS_TX_PACKETS; - vstats.tx_packets = rta_getattr_u64(attr); - } - if (stbBRIDGE_VLANDB_STATS_TX_BYTES) { - attr = stbBRIDGE_VLANDB_STATS_TX_BYTES; - vstats.tx_bytes = rta_getattr_u64(attr); - } - } - if (vlan_rtm_cur_ifidx != bvm->ifindex) { - open_vlan_port(bvm->ifindex, VLAN_SHOW_VLAN); - open_json_object(NULL); - vlan_rtm_cur_ifidx = bvm->ifindex; - } else { - open_json_object(NULL); - print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + switch (rta_type) { + case BRIDGE_VLANDB_ENTRY: + print_vlan_opts(a, bvm->ifindex); + break; + case BRIDGE_VLANDB_GLOBAL_OPTIONS: + print_vlan_global_opts(a, bvm->ifindex); + break; } - print_range("vlan", vinfo->vid, vrange); - print_vlan_flags(vinfo->flags); - print_nl(); - print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); - print_stp_state(state); - print_nl(); - if (show_stats) - __print_one_vlan_stats(&vstats); - close_json_object(); } return 0; @@ -727,7 +1091,12 @@ static int print_vlan_rtm_filter(struct nlmsghdr *n, void *arg) { - return print_vlan_rtm(n, arg, false); + return print_vlan_rtm(n, arg, false, false); +} + +static int print_vlan_rtm_global_filter(struct nlmsghdr *n, void *arg) +{ + return print_vlan_rtm(n, arg, false, true); } static int vlan_show(int argc, char **argv, int subject) @@ -813,7 +1182,8 @@ __u32 filt_mask; filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS); - if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) { + if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask, + NULL, NULL) < 0) { perror("Cannot send dump request"); exit(1); } @@ -828,7 +1198,8 @@ } filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS_SLAVE); - if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) { + if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask, + NULL, NULL) < 0) { perror("Cannot send slave dump request"); exit(1); } @@ -845,6 +1216,61 @@ return 0; } +static int vlan_global_show(int argc, char **argv) +{ + __u32 dump_flags = BRIDGE_VLANDB_DUMPF_GLOBAL; + int ret = 0, subject = VLAN_SHOW_VLAN; + char *filter_dev = NULL; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (filter_dev) + duparg("dev", *argv); + filter_dev = *argv; + } else if (strcmp(*argv, "vid") == 0) { + NEXT_ARG(); + if (filter_vlan) + duparg("vid", *argv); + filter_vlan = atoi(*argv); + } + argc--; argv++; + } + + if (filter_dev) { + filter_index = ll_name_to_index(filter_dev); + if (!filter_index) + return nodev(filter_dev); + } + + new_json_obj(json); + + if (rtnl_brvlandump_req(&rth, PF_BRIDGE, dump_flags) < 0) { + perror("Cannot send dump request"); + exit(1); + } + + if (!is_json_context()) { + printf("%-" __stringify(IFNAMSIZ) "s %-" + __stringify(VLAN_ID_LEN) "s", "port", + "vlan-id"); + printf("\n"); + } + + ret = rtnl_dump_filter(&rth, print_vlan_rtm_global_filter, &subject); + if (ret < 0) { + fprintf(stderr, "Dump terminated\n"); + exit(1); + } + + if (vlan_rtm_cur_ifidx != -1) + close_vlan_port(); + + delete_json_obj(); + fflush(stdout); + return 0; +} + void print_vlan_info(struct rtattr *tb, int ifindex) { struct rtattr *i, *list = tb; @@ -889,9 +1315,28 @@ close_vlan_port(); } +static int vlan_global(int argc, char **argv) +{ + if (argc > 0) { + if (strcmp(*argv, "show") == 0 || + strcmp(*argv, "lst") == 0 || + strcmp(*argv, "list") == 0) + return vlan_global_show(argc-1, argv+1); + else if (strcmp(*argv, "set") == 0) + return vlan_global_option_set(argc-1, argv+1); + else + usage(); + } else { + return vlan_global_show(0, NULL); + } + + return 0; +} + int do_vlan(int argc, char **argv) { ll_init_map(&rth); + timestamp = 0; if (argc > 0) { if (matches(*argv, "add") == 0) @@ -907,6 +1352,8 @@ } if (matches(*argv, "set") == 0) return vlan_option_set(argc-1, argv+1); + if (strcmp(*argv, "global") == 0) + return vlan_global(argc-1, argv+1); if (matches(*argv, "help") == 0) usage(); } else {
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/bridge/vni.c
Added
@@ -0,0 +1,443 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Command to manage vnifiltering on a vxlan device + * + * Authors: Roopa Prabhu <roopa@nvidia.com> + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <linux/if_link.h> +#include <linux/if_bridge.h> +#include <linux/if_ether.h> + +#include "json_print.h" +#include "libnetlink.h" +#include "br_common.h" +#include "utils.h" + +static unsigned int filter_index; + +#define VXLAN_ID_LEN 15 + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +static void usage(void) +{ + fprintf(stderr, + "Usage: bridge vni { add | del } vni VNI\n" + " { group | remote } IP_ADDRESS \n" + " dev DEV \n" + " bridge vni { show }\n" + "\n" + "Where: VNI := 0-16777215\n" + ); + exit(-1); +} + +static int parse_vni_filter(const char *argv, struct nlmsghdr *n, int reqsize, + inet_prefix *group) +{ + char *vnilist = strdupa(argv); + char *vni = strtok(vnilist, ","); + int group_type = AF_UNSPEC; + struct rtattr *nlvlist_e; + char *v; + int i; + + if (group && is_addrtype_inet(group)) + group_type = (group->family == AF_INET) ? VXLAN_VNIFILTER_ENTRY_GROUP : + VXLAN_VNIFILTER_ENTRY_GROUP6; + + for (i = 0; vni; i++) { + __u32 vni_start = 0, vni_end = 0; + + v = strchr(vni, '-'); + if (v) { + *v = '\0'; + v++; + vni_start = atoi(vni); + vni_end = atoi(v); + } else { + vni_start = atoi(vni); + } + nlvlist_e = addattr_nest(n, reqsize, VXLAN_VNIFILTER_ENTRY | + NLA_F_NESTED); + addattr32(n, 1024, VXLAN_VNIFILTER_ENTRY_START, vni_start); + if (vni_end) + addattr32(n, 1024, VXLAN_VNIFILTER_ENTRY_END, vni_end); + if (group) + addattr_l(n, 1024, group_type, group->data, group->bytelen); + addattr_nest_end(n, nlvlist_e); + vni = strtok(NULL, ","); + } + + return 0; +} + +static int vni_modify(int cmd, int argc, char **argv) +{ + struct { + struct nlmsghdr n; + struct tunnel_msg tmsg; + char buf1024; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tunnel_msg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = cmd, + .tmsg.family = PF_BRIDGE, + }; + bool group_present = false; + inet_prefix daddr; + char *vni = NULL; + char *d = NULL; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + d = *argv; + } else if (strcmp(*argv, "vni") == 0) { + NEXT_ARG(); + if (vni) + invarg("duplicate vni", *argv); + vni = *argv; + } else if (strcmp(*argv, "group") == 0) { + if (group_present) + invarg("duplicate group", *argv); + if (is_addrtype_inet_not_multi(&daddr)) { + fprintf(stderr, "vxlan: both group and remote"); + fprintf(stderr, " cannot be specified\n"); + return -1; + } + NEXT_ARG(); + get_addr(&daddr, *argv, AF_UNSPEC); + if (!is_addrtype_inet_multi(&daddr)) + invarg("invalid group address", *argv); + group_present = true; + } else if (strcmp(*argv, "remote") == 0) { + if (group_present) + invarg("duplicate group", *argv); + NEXT_ARG(); + get_addr(&daddr, *argv, AF_UNSPEC); + group_present = true; + } else { + if (strcmp(*argv, "help") == 0) + usage(); + } + argc--; argv++; + } + + if (d == NULL || vni == NULL) { + fprintf(stderr, "Device and VNI ID are required arguments.\n"); + return -1; + } + + if (!vni && group_present) { + fprintf(stderr, "Group can only be specified with a vni\n"); + return -1; + } + + if (vni) + parse_vni_filter(vni, &req.n, sizeof(req), + (group_present ? &daddr : NULL)); + + req.tmsg.ifindex = ll_name_to_index(d); + if (req.tmsg.ifindex == 0) { + fprintf(stderr, "Cannot find vxlan device \"%s\"\n", d); + return -1; + } + + if (rtnl_talk(&rth, &req.n, NULL) < 0) + return -1; + + return 0; +} + +static void open_vni_port(int ifi_index, const char *fmt) +{ + open_json_object(NULL); + print_color_string(PRINT_ANY, COLOR_IFNAME, "ifname", + "%-" __stringify(IFNAMSIZ) "s ", + ll_index_to_name(ifi_index)); + open_json_array(PRINT_JSON, "vnis"); +} + +static void close_vni_port(void) +{ + close_json_array(PRINT_JSON, NULL); + close_json_object(); +} + +static void print_range(const char *name, __u32 start, __u32 id) +{ + char end64; + + snprintf(end, sizeof(end), "%sEnd", name); + + print_uint(PRINT_ANY, name, " %u", start); + if (start != id) + print_uint(PRINT_ANY, end, "-%-14u ", id); + +} + +static void print_vnifilter_entry_stats(struct rtattr *stats_attr) +{ + struct rtattr *stbVNIFILTER_ENTRY_STATS_MAX+1; + __u64 stat; + + open_json_object("stats"); + parse_rtattr_flags(stb, VNIFILTER_ENTRY_STATS_MAX, RTA_DATA(stats_attr), + RTA_PAYLOAD(stats_attr), NLA_F_NESTED); + + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + print_string(PRINT_FP, NULL, "RX: ", ""); + + if (stbVNIFILTER_ENTRY_STATS_RX_BYTES) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_RX_BYTES); + print_lluint(PRINT_ANY, "rx_bytes", "bytes %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_RX_PKTS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_RX_PKTS); + print_lluint(PRINT_ANY, "rx_pkts", "pkts %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_RX_DROPS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_RX_DROPS); + print_lluint(PRINT_ANY, "rx_drops", "drops %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_RX_ERRORS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_RX_ERRORS); + print_lluint(PRINT_ANY, "rx_errors", "errors %llu ", stat); + } + + print_nl(); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + print_string(PRINT_FP, NULL, "TX: ", ""); + + if (stbVNIFILTER_ENTRY_STATS_TX_BYTES) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_TX_BYTES); + print_lluint(PRINT_ANY, "tx_bytes", "bytes %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_TX_PKTS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_TX_PKTS); + print_lluint(PRINT_ANY, "tx_pkts", "pkts %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_TX_DROPS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_TX_DROPS); + print_lluint(PRINT_ANY, "tx_drops", "drops %llu ", stat); + } + if (stbVNIFILTER_ENTRY_STATS_TX_ERRORS) { + stat = rta_getattr_u64(stbVNIFILTER_ENTRY_STATS_TX_ERRORS); + print_lluint(PRINT_ANY, "tx_errors", "errors %llu ", stat); + } + close_json_object(); +} + +static void print_vni(struct rtattr *t, int ifindex) +{ + struct rtattr *ttbVXLAN_VNIFILTER_ENTRY_MAX+1; + __u32 vni_start = 0; + __u32 vni_end = 0; + + parse_rtattr_flags(ttb, VXLAN_VNIFILTER_ENTRY_MAX, RTA_DATA(t), + RTA_PAYLOAD(t), NLA_F_NESTED); + + if (ttbVXLAN_VNIFILTER_ENTRY_START) + vni_start = rta_getattr_u32(ttbVXLAN_VNIFILTER_ENTRY_START); + + if (ttbVXLAN_VNIFILTER_ENTRY_END) + vni_end = rta_getattr_u32(ttbVXLAN_VNIFILTER_ENTRY_END); + + if (vni_end) + print_range("vni", vni_start, vni_end); + else + print_uint(PRINT_ANY, "vni", " %-14u", vni_start); + + if (ttbVXLAN_VNIFILTER_ENTRY_GROUP) { + __be32 addr = rta_getattr_u32(ttbVXLAN_VNIFILTER_ENTRY_GROUP); + + if (addr) { + if (IN_MULTICAST(ntohl(addr))) + print_string(PRINT_ANY, + "group", + " %s", + format_host(AF_INET, 4, &addr)); + else + print_string(PRINT_ANY, + "remote", + " %s", + format_host(AF_INET, 4, &addr)); + } + } else if (ttbVXLAN_VNIFILTER_ENTRY_GROUP6) { + struct in6_addr addr; + + memcpy(&addr, RTA_DATA(ttbVXLAN_VNIFILTER_ENTRY_GROUP6), sizeof(struct in6_addr)); + if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) { + if (IN6_IS_ADDR_MULTICAST(&addr)) + print_string(PRINT_ANY, + "group", + " %s", + format_host(AF_INET6, + sizeof(struct in6_addr), + &addr)); + else + print_string(PRINT_ANY, + "remote", + " %s", + format_host(AF_INET6, + sizeof(struct in6_addr), + &addr)); + } + } + + if (ttbVXLAN_VNIFILTER_ENTRY_STATS) + print_vnifilter_entry_stats(ttbVXLAN_VNIFILTER_ENTRY_STATS); + + close_json_object(); + print_string(PRINT_FP, NULL, "%s", _SL_); +} + +int print_vnifilter_rtm(struct nlmsghdr *n, void *arg, bool monitor) +{ + struct tunnel_msg *tmsg = NLMSG_DATA(n); + int len = n->nlmsg_len; + bool first = true; + struct rtattr *t; + FILE *fp = arg; + int rem; + + if (n->nlmsg_type != RTM_NEWTUNNEL && + n->nlmsg_type != RTM_DELTUNNEL && + n->nlmsg_type != RTM_GETTUNNEL) { + fprintf(stderr, "Unknown vni tunnel rtm msg: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + return 0; + } + + len -= NLMSG_LENGTH(sizeof(*tmsg)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + if (tmsg->family != AF_BRIDGE) + return 0; + + if (filter_index && filter_index != tmsg->ifindex) + return 0; + + print_headers(fp, "TUNNEL"); + + if (n->nlmsg_type == RTM_DELTUNNEL) + print_bool(PRINT_ANY, "deleted", "Deleted ", true); + + rem = len; + for (t = TUNNEL_RTA(tmsg); RTA_OK(t, rem); t = RTA_NEXT(t, rem)) { + unsigned short rta_type = t->rta_type & NLA_TYPE_MASK; + + if (rta_type != VXLAN_VNIFILTER_ENTRY) + continue; + if (first) { + open_vni_port(tmsg->ifindex, "%s"); + open_json_object(NULL); + first = false; + } else { + open_json_object(NULL); + print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", ""); + } + + print_vni(t, tmsg->ifindex); + } + close_vni_port(); + + print_string(PRINT_FP, NULL, "%s", _SL_); + + fflush(stdout); + return 0; +} + +static int print_vnifilter_rtm_filter(struct nlmsghdr *n, void *arg) +{ + return print_vnifilter_rtm(n, arg, false); +} + +static int vni_show(int argc, char **argv) +{ + char *filter_dev = NULL; + __u8 flags = 0; + int ret = 0; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (filter_dev) + duparg("dev", *argv); + filter_dev = *argv; + } + argc--; argv++; + } + + if (filter_dev) { + filter_index = ll_name_to_index(filter_dev); + if (!filter_index) + return nodev(filter_dev); + } + + new_json_obj(json); + + if (show_stats) + flags = TUNNEL_MSG_FLAG_STATS; + + if (rtnl_tunneldump_req(&rth, PF_BRIDGE, filter_index, flags) < 0) { + perror("Cannot send dump request"); + exit(1); + } + + if (!is_json_context()) { + printf("%-" __stringify(IFNAMSIZ) "s %-" + __stringify(VXLAN_ID_LEN) "s %-" + __stringify(15) "s", + "dev", "vni", "group/remote"); + printf("\n"); + } + + ret = rtnl_dump_filter(&rth, print_vnifilter_rtm_filter, NULL); + if (ret < 0) { + fprintf(stderr, "Dump ternminated\n"); + exit(1); + } + + delete_json_obj(); + fflush(stdout); + return 0; +} + +int do_vni(int argc, char **argv) +{ + ll_init_map(&rth); + timestamp = 0; + + if (argc > 0) { + if (strcmp(*argv, "add") == 0) + return vni_modify(RTM_NEWTUNNEL, argc-1, argv+1); + if (strcmp(*argv, "delete") == 0) + return vni_modify(RTM_DELTUNNEL, argc-1, argv+1); + if (strcmp(*argv, "show") == 0 || + strcmp(*argv, "lst") == 0 || + strcmp(*argv, "list") == 0) + return vni_show(argc-1, argv+1); + if (strcmp(*argv, "help") == 0) + usage(); + } else { + return vni_show(0, NULL); + } + + fprintf(stderr, "Command \"%s\" is unknown, try \"bridge vni help\".\n", *argv); + exit(-1); +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/configure -> _service:tar_scm:iproute2-6.1.0.tar.xz/configure
Changed
@@ -3,6 +3,8 @@ # This is not an autoconf generated configure INCLUDE="$PWD/include" +PREFIX="/usr" +LIBDIR="\${prefix}/lib" # Output file which is input to Makefile CONFIG=config.mk @@ -148,6 +150,15 @@ rm -f $TMPDIR/ipttest.c $TMPDIR/ipttest } +check_lib_dir() +{ + LIBDIR=$(echo $LIBDIR | sed "s|\${prefix}|$PREFIX|") + + echo -n "lib directory: " + echo "$LIBDIR" + echo "LIBDIR:=$LIBDIR" >> $CONFIG +} + check_ipt() { if ! grep TC_CONFIG_XT $CONFIG > /dev/null; then @@ -180,6 +191,7 @@ check_setns() { cat >$TMPDIR/setnstest.c <<EOF +#define _GNU_SOURCE #include <sched.h> int main(int argc, char **argv) { @@ -384,6 +396,19 @@ fi } +check_tirpc() +{ + if ${PKG_CONFIG} libtirpc --exists; then + echo "HAVE_RPC:=y" >>$CONFIG + echo "yes" + + echo 'LDLIBS +=' `${PKG_CONFIG} --libs libtirpc` >>$CONFIG + echo 'CFLAGS += -DHAVE_RPC' `${PKG_CONFIG} --cflags libtirpc` >>$CONFIG + else + echo "no" + fi +} + check_mnl() { if ${PKG_CONFIG} libmnl --exists; then @@ -485,12 +510,14 @@ { cat <<EOF Usage: $0 OPTIONS - --include_dir Path to iproute2 include dir - --libbpf_dir Path to libbpf DESTDIR - --libbpf_force Enable/disable libbpf by force. Available options: - on: require link against libbpf, quit config if no libbpf support - off: disable libbpf probing - -h | --help Show this usage info + --include_dir <dir> Path to iproute2 include dir + --libdir <dir> Path to iproute2 lib dir + --libbpf_dir <dir> Path to libbpf DESTDIR + --libbpf_force <on|off> Enable/disable libbpf by force. Available options: + on: require link against libbpf, quit config if no libbpf support + off: disable libbpf probing + --prefix <dir> Path prefix of the lib files to install + -h | --help Show this usage info EOF exit $1 } @@ -499,30 +526,56 @@ if $# -eq 1 && "$(echo $1 | cut -c 1)" != '-' ; then INCLUDE="$1" else - while true; do + while "$#" -gt 0 ; do case "$1" in --include_dir) - INCLUDE=$2 - shift 2 ;; + shift + INCLUDE="$1" ;; + --include_dir=*) + INCLUDE="${1#*=}" ;; + --libdir) + shift + LIBDIR="$1" ;; + --libdir=*) + LIBDIR="${1#*=}" ;; --libbpf_dir) - LIBBPF_DIR="$2" - shift 2 ;; + shift + LIBBPF_DIR="$1" ;; + --libbpf_dir=*) + LIBBPF_DIR="${1#*=}" ;; --libbpf_force) - if "$2" != 'on' && "$2" != 'off' ; then - usage 1 - fi - LIBBPF_FORCE=$2 - shift 2 ;; + shift + LIBBPF_FORCE="$1" ;; + --libbpf_force=*) + LIBBPF_FORCE="${1#*=}" ;; + --prefix) + shift + PREFIX="$1" ;; + --prefix=*) + PREFIX="${1#*=}" ;; -h | --help) usage 0 ;; - "") - break ;; + --*) + ;; *) - shift 1 ;; + usage 1 ;; esac + "$#" -gt 0 && shift done fi + -d "$INCLUDE" || usage 1 +if "${LIBBPF_DIR-unused}" != "unused" ; then + -d "$LIBBPF_DIR" || usage 1 +fi +if "${LIBBPF_FORCE-unused}" != "unused" ; then + if "$LIBBPF_FORCE" != 'on' && "$LIBBPF_FORCE" != 'off' ; then + usage 1 + fi +fi + -z "$PREFIX" && usage 1 + -z "$LIBDIR" && usage 1 + echo "# Generated config based on" $INCLUDE >$CONFIG quiet_config >> $CONFIG @@ -546,6 +599,7 @@ fi echo +check_lib_dir if ! grep -q TC_CONFIG_NO_XT $CONFIG; then echo -n "iptables modules directory: " check_ipt_lib_dir @@ -560,6 +614,9 @@ echo -n "SELinux support: " check_selinux +echo -n "libtirpc support: " +check_tirpc + echo -n "libbpf support: " check_libbpf
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/dcb/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/dcb/Makefile
Changed
@@ -1,10 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk -TARGETS := - -ifeq ($(HAVE_MNL),y) - DCBOBJ = dcb.o \ dcb_app.o \ dcb_buffer.o \ @@ -15,8 +11,6 @@ TARGETS += dcb LDLIBS += -lm -endif - all: $(TARGETS) $(LIBS) dcb: $(DCBOBJ) $(LIBNETLINK)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/dcb/dcb.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/dcb/dcb.c
Changed
@@ -106,7 +106,7 @@ { struct dcb_set_attribute_response *resp = data; uint16_t len; - uint8_t err; + int8_t err; if (mnl_attr_get_type(attr) != resp->response_attr) return MNL_CB_OK; @@ -117,10 +117,12 @@ return MNL_CB_ERROR; } + /* The attribute is formally u8, but actually an i8 containing a + * negative errno value. + */ err = mnl_attr_get_u8(attr); if (err) { - fprintf(stderr, "Error when attempting to set attribute: %s\n", - strerror(err)); + errno = -err; return MNL_CB_ERROR; } @@ -154,7 +156,8 @@ }; struct nlmsghdr *nlh; - nlh = mnlu_msg_prepare(dcb->buf, nlmsg_type, NLM_F_REQUEST, &dcbm, sizeof(dcbm)); + nlh = mnlu_msg_prepare(dcb->buf, nlmsg_type, NLM_F_REQUEST | NLM_F_ACK, + &dcbm, sizeof(dcbm)); mnl_attr_put_strz(nlh, DCB_ATTR_IFNAME, dev); return nlh; } @@ -242,9 +245,11 @@ if (ret) return ret; + errno = 0; ret = dcb_talk(dcb, nlh, dcb_set_attribute_cb, &resp); if (ret) { - perror("Attribute write"); + if (errno) + perror("Attribute write"); return ret; } return 0; @@ -326,51 +331,51 @@ void dcb_print_array_u8(const __u8 *array, size_t size) { - SPRINT_BUF(b); size_t i; for (i = 0; i < size; i++) { - snprintf(b, sizeof(b), "%zd:%%d ", i); - print_uint(PRINT_ANY, NULL, b, arrayi); + print_uint(PRINT_JSON, NULL, NULL, arrayi); + print_uint(PRINT_FP, NULL, "%zd:", i); + print_uint(PRINT_FP, NULL, "%d ", arrayi); } } void dcb_print_array_u64(const __u64 *array, size_t size) { - SPRINT_BUF(b); size_t i; for (i = 0; i < size; i++) { - snprintf(b, sizeof(b), "%zd:%%" PRIu64 " ", i); - print_u64(PRINT_ANY, NULL, b, arrayi); + print_u64(PRINT_JSON, NULL, NULL, arrayi); + print_uint(PRINT_FP, NULL, "%zd:", i); + print_u64(PRINT_FP, NULL, "%" PRIu64 " ", arrayi); } } void dcb_print_array_on_off(const __u8 *array, size_t size) { - SPRINT_BUF(b); size_t i; for (i = 0; i < size; i++) { - snprintf(b, sizeof(b), "%zd:%%s ", i); - print_on_off(PRINT_ANY, NULL, b, arrayi); + print_on_off(PRINT_JSON, NULL, NULL, arrayi); + print_uint(PRINT_FP, NULL, "%zd:", i); + print_on_off(PRINT_FP, NULL, "%s ", arrayi); } } void dcb_print_array_kw(const __u8 *array, size_t array_size, const char *const kw, size_t kw_size) { - SPRINT_BUF(b); size_t i; for (i = 0; i < array_size; i++) { + const char *str = "???"; __u8 emt = arrayi; - snprintf(b, sizeof(b), "%zd:%%s ", i); if (emt < kw_size && kwemt) - print_string(PRINT_ANY, NULL, b, kwemt); - else - print_string(PRINT_ANY, NULL, b, "???"); + str = kwemt; + print_string(PRINT_JSON, NULL, NULL, str); + print_uint(PRINT_FP, NULL, "%zd:", i); + print_string(PRINT_FP, NULL, "%s ", str); } }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/dcb/dcb_app.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/dcb/dcb_app.c
Changed
@@ -654,6 +654,8 @@ dcb_app_print_dgram_port_prio(&tab); } else if (matches(*argv, "port-prio") == 0) { dcb_app_print_port_prio(&tab); + } else if (matches(*argv, "default-prio") == 0) { + dcb_app_print_default_prio(&tab); } else { fprintf(stderr, "What is \"%s\"?\n", *argv); dcb_app_help_show_flush();
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/devlink/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/devlink/Makefile
Changed
@@ -1,16 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk -TARGETS := - -ifeq ($(HAVE_MNL),y) - DEVLINKOBJ = devlink.o mnlg.o TARGETS += devlink LDLIBS += -lm -endif - all: $(TARGETS) $(LIBS) devlink: $(DEVLINKOBJ) $(LIBNETLINK)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/devlink/devlink.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/devlink/devlink.c
Changed
@@ -71,8 +71,6 @@ #define INDENT_STR_MAXLEN 32 static char g_indent_strINDENT_STR_MAXLEN + 1 = ""; -static bool use_iec = false; - static void __attribute__((format(printf, 1, 2))) pr_err(const char *fmt, ...) { @@ -294,6 +292,9 @@ #define DL_OPT_PORT_FN_RATE_TX_MAX BIT(49) #define DL_OPT_PORT_FN_RATE_NODE_NAME BIT(50) #define DL_OPT_PORT_FN_RATE_PARENT BIT(51) +#define DL_OPT_LINECARD BIT(52) +#define DL_OPT_LINECARD_TYPE BIT(53) +#define DL_OPT_SELFTESTS BIT(54) struct dl_opts { uint64_t present; /* flags of present items */ @@ -315,7 +316,7 @@ bool dpipe_counters_enabled; enum devlink_eswitch_encap_mode eswitch_encap_mode; const char *resource_path; - uint64_t resource_size; + __u64 resource_size; uint32_t resource_id; bool resource_id_valid; const char *param_name; @@ -323,12 +324,12 @@ enum devlink_param_cmode cmode; char *region_name; uint32_t region_snapshot_id; - uint64_t region_address; - uint64_t region_length; + __u64 region_address; + __u64 region_length; const char *flash_file_name; const char *flash_component; const char *reporter_name; - uint64_t reporter_graceful_period; + __u64 reporter_graceful_period; bool reporter_auto_recover; bool reporter_auto_dump; const char *trap_name; @@ -337,8 +338,8 @@ bool netns_is_pid; uint32_t netns; uint32_t trap_policer_id; - uint64_t trap_policer_rate; - uint64_t trap_policer_burst; + __u64 trap_policer_rate; + __u64 trap_policer_burst; char port_function_hw_addrMAX_ADDR_LEN; uint32_t port_function_hw_addr_len; uint32_t overwrite_mask; @@ -354,6 +355,9 @@ uint64_t rate_tx_max; char *rate_node_name; const char *rate_parent_node; + uint32_t linecard_index; + const char *linecard_type; + bool selftests_optDEVLINK_ATTR_SELFTEST_ID_MAX + 1; }; struct dl { @@ -367,6 +371,9 @@ bool pretty_output; bool verbose; bool stats; + bool hex; + bool use_iec; + bool map_loaded; struct { bool present; char *bus_name; @@ -692,6 +699,12 @@ DEVLINK_ATTR_TRAP_POLICER_ID = MNL_TYPE_U32, DEVLINK_ATTR_TRAP_POLICER_RATE = MNL_TYPE_U64, DEVLINK_ATTR_TRAP_POLICER_BURST = MNL_TYPE_U64, + DEVLINK_ATTR_LINECARD_INDEX = MNL_TYPE_U32, + DEVLINK_ATTR_LINECARD_STATE = MNL_TYPE_U8, + DEVLINK_ATTR_LINECARD_TYPE = MNL_TYPE_STRING, + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES = MNL_TYPE_NESTED, + DEVLINK_ATTR_NESTED_DEVLINK = MNL_TYPE_NESTED, + DEVLINK_ATTR_SELFTESTS = MNL_TYPE_NESTED, }; static const enum mnl_attr_data_type @@ -769,7 +782,7 @@ struct ifname_map *ifname_map; const char *bus_name; const char *dev_name; - uint32_t port_ifindex; + uint32_t port_index; const char *port_ifname; mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); @@ -782,10 +795,10 @@ bus_name = mnl_attr_get_str(tbDEVLINK_ATTR_BUS_NAME); dev_name = mnl_attr_get_str(tbDEVLINK_ATTR_DEV_NAME); - port_ifindex = mnl_attr_get_u32(tbDEVLINK_ATTR_PORT_INDEX); + port_index = mnl_attr_get_u32(tbDEVLINK_ATTR_PORT_INDEX); port_ifname = mnl_attr_get_str(tbDEVLINK_ATTR_PORT_NETDEV_NAME); ifname_map = ifname_map_alloc(bus_name, dev_name, - port_ifindex, port_ifname); + port_index, port_ifname); if (!ifname_map) return MNL_CB_ERROR; list_add(&ifname_map->list, &dl->ifname_map_list); @@ -804,13 +817,15 @@ } } -static int ifname_map_init(struct dl *dl) +static void ifname_map_init(struct dl *dl) { - struct nlmsghdr *nlh; - int err; - INIT_LIST_HEAD(&dl->ifname_map_list); +} +static int ifname_map_load(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_GET, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); @@ -823,11 +838,33 @@ return 0; } +static int ifname_map_check_load(struct dl *dl) +{ + int err; + + if (dl->map_loaded) + return 0; + + err = ifname_map_load(dl); + if (err) { + pr_err("Failed to create index map\n"); + return err; + } + dl->map_loaded = true; + return 0; +} + + static int ifname_map_lookup(struct dl *dl, const char *ifname, char **p_bus_name, char **p_dev_name, uint32_t *p_port_index) { struct ifname_map *ifname_map; + int err; + + err = ifname_map_check_load(dl); + if (err) + return err; list_for_each_entry(ifname_map, &dl->ifname_map_list, list) { if (strcmp(ifname, ifname_map->ifname) == 0) { @@ -846,6 +883,12 @@ { struct ifname_map *ifname_map; + int err; + + err = ifname_map_check_load(dl); + if (err) + return err; + list_for_each_entry(ifname_map, &dl->ifname_map_list, list) { if (strcmp(bus_name, ifname_map->bus_name) == 0 && strcmp(dev_name, ifname_map->dev_name) == 0 && @@ -857,62 +900,6 @@ return -ENOENT; } -static int strtouint64_t(const char *str, uint64_t *p_val) -{ - char *endptr; - unsigned long long int val; - - val = strtoull(str, &endptr, 10); - if (endptr == str || *endptr != '\0') - return -EINVAL; - if (val > ULONG_MAX) - return -ERANGE; - *p_val = val; - return 0; -} - -static int strtouint32_t(const char *str, uint32_t *p_val) -{ - char *endptr; - unsigned long int val; - - val = strtoul(str, &endptr, 10); - if (endptr == str || *endptr != '\0') - return -EINVAL; - if (val > UINT_MAX) - return -ERANGE; - *p_val = val; - return 0; -} - -static int strtouint16_t(const char *str, uint16_t *p_val) -{ - char *endptr; - unsigned long int val; - - val = strtoul(str, &endptr, 10); - if (endptr == str || *endptr != '\0') - return -EINVAL; - if (val > USHRT_MAX) - return -ERANGE; - *p_val = val; - return 0; -} - -static int strtouint8_t(const char *str, uint8_t *p_val) -{ - char *endptr; - unsigned long int val; - - val = strtoul(str, &endptr, 10); - if (endptr == str || *endptr != '\0') - return -EINVAL; - if (val > UCHAR_MAX) - return -ERANGE; - *p_val = val; - return 0; -} - static int strtobool(const char *str, bool *p_val) { bool val; @@ -980,7 +967,7 @@ pr_err("Port identification \"%s\" is invalid\n", str); return err; } - err = strtouint32_t(portstr, p_port_index); + err = get_u32(p_port_index, portstr, 10); if (err) { pr_err("Port index \"%s\" is not a number or not within range\n", portstr); @@ -1159,7 +1146,7 @@ } if (strspn(identifier, "0123456789") == strlen(identifier)) { - err = strtouint32_t(identifier, p_port_index); + err = get_u32(p_port_index, identifier, 10); if (err) { pr_err("Port index \"%s\" is not a number" " or not within range\n", identifier); @@ -1173,7 +1160,7 @@ return 0; } -static int dl_argv_uint64_t(struct dl *dl, uint64_t *p_val) +static int dl_argv_uint64_t(struct dl *dl, __u64 *p_val) { char *str = dl_argv_next(dl); int err; @@ -1183,7 +1170,7 @@ return -EINVAL; } - err = strtouint64_t(str, p_val); + err = get_u64(p_val, str, 10); if (err) { pr_err("\"%s\" is not a number or not within range\n", str); return err; @@ -1201,7 +1188,7 @@ return -EINVAL; } - err = strtouint32_t(str, p_val); + err = get_u32(p_val, str, 10); if (err) { pr_err("\"%s\" is not a number or not within range\n", str); return err; @@ -1219,7 +1206,7 @@ return -EINVAL; } - err = strtouint16_t(str, p_val); + err = get_u16(p_val, str, 10); if (err) { pr_err("\"%s\" is not a number or not within range\n", str); return err; @@ -1456,6 +1443,17 @@ { .str = NULL, } }; +static int selftests_get(const char *selftest_name, bool *selftests_opt) +{ + if (strcmp(selftest_name, "flash") == 0) { + selftests_opt0 = true; + } else { + pr_err("Unknown selftest \"%s\"\n", selftest_name); + return -EINVAL; + } + return 0; +} + static int port_flavour_parse(const char *flavour, uint16_t *value) { int num; @@ -1545,6 +1543,9 @@ {DL_OPT_PORT_FUNCTION_HW_ADDR, "Port function's hardware address is expected."}, {DL_OPT_PORT_FLAVOUR, "Port flavour is expected."}, {DL_OPT_PORT_PFNUMBER, "Port PCI PF number is expected."}, + {DL_OPT_LINECARD, "Linecard index expected."}, + {DL_OPT_LINECARD_TYPE, "Linecard type expected."}, + {DL_OPT_SELFTESTS, "Test name is expected"}, }; static int dl_args_finding_required_validate(uint64_t o_required, @@ -1848,6 +1849,21 @@ return err; o_found |= DL_OPT_FLASH_OVERWRITE; + } else if (dl_argv_match(dl, "id") && + (o_all & DL_OPT_SELFTESTS)) { + dl_arg_inc(dl); + while (dl_argc(dl)) { + const char *selftest_name; + err = dl_argv_str(dl, &selftest_name); + if (err) + return err; + err = selftests_get(selftest_name, + opts->selftests_opt); + if (err) + return err; + } + o_found |= DL_OPT_SELFTESTS; + } else if (dl_argv_match(dl, "reporter") && (o_all & DL_OPT_HEALTH_REPORTER_NAME)) { dl_arg_inc(dl); @@ -2063,6 +2079,25 @@ dl_arg_inc(dl); opts->rate_parent_node = ""; o_found |= DL_OPT_PORT_FN_RATE_PARENT; + } else if (dl_argv_match(dl, "lc") && + (o_all & DL_OPT_LINECARD)) { + dl_arg_inc(dl); + err = dl_argv_uint32_t(dl, &opts->linecard_index); + if (err) + return err; + o_found |= DL_OPT_LINECARD; + } else if (dl_argv_match(dl, "type") && + (o_all & DL_OPT_LINECARD_TYPE)) { + dl_arg_inc(dl); + err = dl_argv_str(dl, &opts->linecard_type); + if (err) + return err; + o_found |= DL_OPT_LINECARD_TYPE; + } else if (dl_argv_match(dl, "notype") && + (o_all & DL_OPT_LINECARD_TYPE)) { + dl_arg_inc(dl); + opts->linecard_type = ""; + o_found |= DL_OPT_LINECARD_TYPE; } else { pr_err("Unknown option \"%s\"\n", dl_argv(dl)); return -EINVAL; @@ -2118,6 +2153,34 @@ mnl_attr_put(nlh, DEVLINK_ATTR_RELOAD_LIMITS, sizeof(limits), &limits); } +static void +dl_selftests_put(struct nlmsghdr *nlh, const struct dl_opts *opts) +{ + bool test_sel = false; + struct nlattr *nest; + int id; + + nest = mnl_attr_nest_start(nlh, DEVLINK_ATTR_SELFTESTS); + + for (id = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1; + id <= DEVLINK_ATTR_SELFTEST_ID_MAX && + opts->selftests_optid; id++) { + if (opts->selftests_optid) { + test_sel = true; + mnl_attr_put(nlh, id, 0, NULL); + } + } + + /* No test selected from user, select all */ + if (!test_sel) { + for (id = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1; + id <= DEVLINK_ATTR_SELFTEST_ID_MAX; id++) + mnl_attr_put(nlh, id, 0, NULL); + } + + mnl_attr_nest_end(nlh, nest); +} + static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) { struct dl_opts *opts = &dl->opts; @@ -2212,6 +2275,8 @@ opts->flash_component); if (opts->present & DL_OPT_FLASH_OVERWRITE) dl_flash_update_overwrite_put(nlh, opts); + if (opts->present & DL_OPT_SELFTESTS) + dl_selftests_put(nlh, opts); if (opts->present & DL_OPT_HEALTH_REPORTER_NAME) mnl_attr_put_strz(nlh, DEVLINK_ATTR_HEALTH_REPORTER_NAME, opts->reporter_name); @@ -2276,18 +2341,12 @@ if (opts->present & DL_OPT_PORT_FN_RATE_PARENT) mnl_attr_put_strz(nlh, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, opts->rate_parent_node); -} - -static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, - uint64_t o_required, uint64_t o_optional) -{ - int err; - - err = dl_argv_parse(dl, o_required, o_optional); - if (err) - return err; - dl_opts_put(nlh, dl); - return 0; + if (opts->present & DL_OPT_LINECARD) + mnl_attr_put_u32(nlh, DEVLINK_ATTR_LINECARD_INDEX, + opts->linecard_index); + if (opts->present & DL_OPT_LINECARD_TYPE) + mnl_attr_put_strz(nlh, DEVLINK_ATTR_LINECARD_TYPE, + opts->linecard_type); } static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) @@ -2297,6 +2356,7 @@ struct nlattr *attr_dev_name = tbDEVLINK_ATTR_DEV_NAME; struct nlattr *attr_port_index = tbDEVLINK_ATTR_PORT_INDEX; struct nlattr *attr_sb_index = tbDEVLINK_ATTR_SB_INDEX; + struct nlattr *attr_linecard_index = tbDEVLINK_ATTR_LINECARD_INDEX; if (opts->present & DL_OPT_HANDLE && attr_bus_name && attr_dev_name) { @@ -2324,6 +2384,12 @@ if (sb_index != opts->sb_index) return false; } + if (opts->present & DL_OPT_LINECARD && attr_linecard_index) { + uint32_t linecard_index = mnl_attr_get_u32(attr_linecard_index); + + if (linecard_index != opts->linecard_index) + return false; + } return true; } @@ -2340,6 +2406,8 @@ pr_err(" action { driver_reinit | fw_activate } limit no_reset \n"); pr_err(" devlink dev info DEV \n"); pr_err(" devlink dev flash DEV file PATH component NAME overwrite SECTION \n"); + pr_err(" devlink dev selftests show DEV\n"); + pr_err(" devlink dev selftests run DEV id TESTNAME \n"); } static bool cmp_arr_last_handle(struct dl *dl, const char *bus_name, @@ -2374,6 +2442,25 @@ !cmp_arr_last_handle(dl, bus_name, dev_name); } +static void pr_out_nested_handle(struct nlattr *nla_nested_dl) +{ + struct nlattr *tbDEVLINK_ATTR_MAX + 1 = {}; + char buf64; + int err; + + err = mnl_attr_parse_nested(nla_nested_dl, attr_cb, tb); + if (err != MNL_CB_OK) + return; + + if (!tbDEVLINK_ATTR_BUS_NAME || + !tbDEVLINK_ATTR_DEV_NAME) + return; + + sprintf(buf, "%s/%s", mnl_attr_get_str(tbDEVLINK_ATTR_BUS_NAME), + mnl_attr_get_str(tbDEVLINK_ATTR_DEV_NAME)); + print_string(PRINT_ANY, "nested_devlink", " nested_devlink %s", buf); +} + static void __pr_out_handle_start(struct dl *dl, struct nlattr **tb, bool content, bool array) { @@ -2434,6 +2521,41 @@ pr_out_handle_end(dl); } +static void pr_out_selftests_handle_start(struct dl *dl, struct nlattr **tb) +{ + const char *bus_name = mnl_attr_get_str(tbDEVLINK_ATTR_BUS_NAME); + const char *dev_name = mnl_attr_get_str(tbDEVLINK_ATTR_DEV_NAME); + char buf64; + + sprintf(buf, "%s/%s", bus_name, dev_name); + + if (dl->json_output) { + if (should_arr_last_handle_end(dl, bus_name, dev_name)) + close_json_array(PRINT_JSON, NULL); + if (should_arr_last_handle_start(dl, bus_name, + dev_name)) { + open_json_array(PRINT_JSON, buf); + arr_last_handle_set(dl, bus_name, dev_name); + } + } else { + if (should_arr_last_handle_end(dl, bus_name, dev_name)) + __pr_out_indent_dec(); + if (should_arr_last_handle_start(dl, bus_name, + dev_name)) { + pr_out("%s%s", buf, ":"); + __pr_out_newline(); + __pr_out_indent_inc(); + arr_last_handle_set(dl, bus_name, dev_name); + } + } +} + +static void pr_out_selftests_handle_end(struct dl *dl) +{ + if (!dl->json_output) + __pr_out_newline(); +} + static bool cmp_arr_last_port_handle(struct dl *dl, const char *bus_name, const char *dev_name, uint32_t port_index) { @@ -2734,12 +2856,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_ESWITCH_GET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0); - if (err) - return err; + dl_opts_put(nlh, dl); pr_out_section_start(dl, "dev"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_eswitch_show_cb, dl); @@ -2752,16 +2876,17 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE, + DL_OPT_ESWITCH_MODE | + DL_OPT_ESWITCH_INLINE_MODE | + DL_OPT_ESWITCH_ENCAP_MODE); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_ESWITCH_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, - DL_OPT_ESWITCH_MODE | - DL_OPT_ESWITCH_INLINE_MODE | - DL_OPT_ESWITCH_ENCAP_MODE); - - if (err) - return err; + dl_opts_put(nlh, dl); if (dl->opts.present == 1) { pr_err("Need to set at least one option\n"); @@ -3036,6 +3161,7 @@ struct param_ctx { struct dl *dl; int nla_type; + bool cmode_found; union { uint8_t vu8; uint16_t vu16; @@ -3088,6 +3214,7 @@ cmode = mnl_attr_get_u8(nla_valueDEVLINK_ATTR_PARAM_VALUE_CMODE); if (cmode == dl->opts.cmode) { + ctx->cmode_found = true; val_attr = nla_valueDEVLINK_ATTR_PARAM_VALUE_DATA; switch (nla_type) { case MNL_TYPE_U8: @@ -3140,6 +3267,10 @@ err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_param_set_cb, &ctx); if (err) return err; + if (!ctx.cmode_found) { + pr_err("Configuration mode not supported\n"); + return -ENOTSUP; + } nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PARAM_SET, NLM_F_REQUEST | NLM_F_ACK); @@ -3159,7 +3290,7 @@ &val_u32); val_u8 = val_u32; } else { - err = strtouint8_t(dl->opts.param_value, &val_u8); + err = get_u8(&val_u8, dl->opts.param_value, 10); } if (err) goto err_param_value_parse; @@ -3176,7 +3307,7 @@ &val_u32); val_u16 = val_u32; } else { - err = strtouint16_t(dl->opts.param_value, &val_u16); + err = get_u16(&val_u16, dl->opts.param_value, 10); } if (err) goto err_param_value_parse; @@ -3192,7 +3323,7 @@ dl->opts.param_value, &val_u32); else - err = strtouint32_t(dl->opts.param_value, &val_u32); + err = get_u32(&val_u32, dl->opts.param_value, 10); if (err) goto err_param_value_parse; if (val_u32 == ctx.value.vu32) @@ -3248,18 +3379,18 @@ struct nlmsghdr *nlh; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PARAM_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | - DL_OPT_PARAM_NAME, 0); + } else { + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_PARAM_NAME, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PARAM_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "param"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_param_show_cb, dl); pr_out_section_end(dl); @@ -3404,17 +3535,19 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "dev"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_show_cb, dl); pr_out_section_end(dl); @@ -3482,14 +3615,16 @@ return 0; } + err = dl_argv_parse(dl, DL_OPT_HANDLE, + DL_OPT_NETNS | DL_OPT_RELOAD_ACTION | + DL_OPT_RELOAD_LIMIT); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RELOAD, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, - DL_OPT_NETNS | DL_OPT_RELOAD_ACTION | - DL_OPT_RELOAD_LIMIT); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_reload_cb, dl); } @@ -3624,17 +3759,19 @@ return 0; } - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_INFO_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_INFO_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "info"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_versions_show_cb, dl); pr_out_section_end(dl); @@ -3693,12 +3830,12 @@ mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); if (!tbDEVLINK_ATTR_BUS_NAME || !tbDEVLINK_ATTR_DEV_NAME) - return MNL_CB_ERROR; + return MNL_CB_STOP; bus_name = mnl_attr_get_str(tbDEVLINK_ATTR_BUS_NAME); dev_name = mnl_attr_get_str(tbDEVLINK_ATTR_DEV_NAME); if (strcmp(bus_name, opts->bus_name) || strcmp(dev_name, opts->dev_name)) - return MNL_CB_ERROR; + return MNL_CB_STOP; if (genl->cmd == DEVLINK_CMD_FLASH_UPDATE_END) { pr_out("\n"); @@ -3889,13 +4026,15 @@ return 0; } + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_FLASH_FILE_NAME, + DL_OPT_FLASH_COMPONENT | DL_OPT_FLASH_OVERWRITE); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_FLASH_UPDATE, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_FLASH_FILE_NAME, - DL_OPT_FLASH_COMPONENT | DL_OPT_FLASH_OVERWRITE); - if (err) - return err; + dl_opts_put(nlh, dl); err = mnlu_gen_socket_open(&nlg_ntf, DEVLINK_GENL_NAME, DEVLINK_GENL_VERSION); @@ -3953,6 +4092,237 @@ return err; } +static const char *devlink_get_selftest_name(int id) +{ + switch (id) { + case DEVLINK_ATTR_SELFTEST_ID_FLASH: + return "flash"; + default: + return "unknown"; + } +} + +static const enum mnl_attr_data_type +devlink_selftest_id_policyDEVLINK_ATTR_SELFTEST_ID_MAX + 1 = { + DEVLINK_ATTR_SELFTEST_ID_FLASH = MNL_TYPE_FLAG, +}; + +static int selftests_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type; + + if (mnl_attr_type_valid(attr, DEVLINK_ATTR_SELFTEST_ID_MAX) < 0) + return MNL_CB_OK; + + type = mnl_attr_get_type(attr); + if (mnl_attr_validate(attr, devlink_selftest_id_policytype) < 0) + return MNL_CB_ERROR; + + tbtype = attr; + return MNL_CB_OK; +} + +static int cmd_dev_selftests_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *selftestsDEVLINK_ATTR_SELFTEST_ID_MAX + 1 = {}; + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tbDEVLINK_ATTR_MAX + 1 = {}; + struct dl *dl = data; + int avail = 0; + int err; + int i; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + + if (!tbDEVLINK_ATTR_BUS_NAME || !tbDEVLINK_ATTR_DEV_NAME || + !tbDEVLINK_ATTR_SELFTESTS) + return MNL_CB_ERROR; + + err = mnl_attr_parse_nested(tbDEVLINK_ATTR_SELFTESTS, + selftests_attr_cb, selftests); + if (err != MNL_CB_OK) + return MNL_CB_ERROR; + + for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1; + i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) { + if (!(selftestsi)) + continue; + + if (!avail) { + pr_out_selftests_handle_start(dl, tb); + avail = 1; + } + + check_indent_newline(dl); + print_string(PRINT_ANY, NULL, "%s", devlink_get_selftest_name(i)); + } + + if (avail) { + pr_out_selftests_handle_end(dl); + } + + return MNL_CB_OK; +} + +static const char *devlink_selftest_status_to_str(uint8_t status) +{ + switch (status) { + case DEVLINK_SELFTEST_STATUS_SKIP: + return "skipped"; + case DEVLINK_SELFTEST_STATUS_PASS: + return "passed"; + case DEVLINK_SELFTEST_STATUS_FAIL: + return "failed"; + default: + return "unknown"; + } +} + +static const enum mnl_attr_data_type +devlink_selftests_result_policyDEVLINK_ATTR_SELFTEST_RESULT_MAX + 1 = { + DEVLINK_ATTR_SELFTEST_RESULT = MNL_TYPE_NESTED, + DEVLINK_ATTR_SELFTEST_RESULT_ID = MNL_TYPE_U32, + DEVLINK_ATTR_SELFTEST_RESULT_STATUS = MNL_TYPE_U8, +}; + +static int selftests_result_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type; + + if (mnl_attr_type_valid(attr, DEVLINK_ATTR_SELFTEST_RESULT_MAX) < 0) + return MNL_CB_OK; + + type = mnl_attr_get_type(attr); + if (mnl_attr_validate(attr, devlink_selftests_result_policytype) < 0) + return MNL_CB_ERROR; + + tbtype = attr; + return MNL_CB_OK; +} + +static int cmd_dev_selftests_run_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tbDEVLINK_ATTR_MAX + 1 = {}; + struct nlattr *selftest; + struct dl *dl = data; + int avail = 0; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + + if (!tbDEVLINK_ATTR_BUS_NAME || !tbDEVLINK_ATTR_DEV_NAME || + !tbDEVLINK_ATTR_SELFTESTS) + return MNL_CB_ERROR; + + mnl_attr_for_each_nested(selftest, tbDEVLINK_ATTR_SELFTESTS) { + struct nlattr *resultDEVLINK_ATTR_SELFTEST_RESULT_MAX + 1 = {}; + uint8_t status; + int err; + int id; + + err = mnl_attr_parse_nested(selftest, + selftests_result_attr_cb, result); + if (err != MNL_CB_OK) + return MNL_CB_ERROR; + + if (!resultDEVLINK_ATTR_SELFTEST_RESULT_ID || + !resultDEVLINK_ATTR_SELFTEST_RESULT_STATUS) + return MNL_CB_ERROR; + + if (!avail) { + pr_out_section_start(dl, "selftests"); + __pr_out_handle_start(dl, tb, true, false); + __pr_out_indent_inc(); + avail = 1; + if (!dl->json_output) + __pr_out_newline(); + } + + id = mnl_attr_get_u32(resultDEVLINK_ATTR_SELFTEST_RESULT_ID); + status = mnl_attr_get_u8(resultDEVLINK_ATTR_SELFTEST_RESULT_STATUS); + + pr_out_object_start(dl, devlink_get_selftest_name(id)); + check_indent_newline(dl); + print_string_name_value("status", + devlink_selftest_status_to_str(status)); + pr_out_object_end(dl); + if (!dl->json_output) + __pr_out_newline(); + } + + if (avail) { + __pr_out_indent_dec(); + pr_out_handle_end(dl); + pr_out_section_end(dl); + } + + return MNL_CB_OK; +} + +static int cmd_dev_selftests_run(struct dl *dl) +{ + struct nlmsghdr *nlh; + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + int err; + + err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_SELFTESTS); + if (err) + return err; + + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SELFTESTS_RUN, flags); + + dl_opts_put(nlh, dl); + + if (!(dl->opts.present & DL_OPT_SELFTESTS)) + dl_selftests_put(nlh, &dl->opts); + + err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_selftests_run_cb, dl); + return err; +} + +static int cmd_dev_selftests_show(struct dl *dl) +{ + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlmsghdr *nlh; + int err; + + if (dl_argc(dl) == 0) { + flags |= NLM_F_DUMP; + } else { + err = dl_argv_parse(dl, DL_OPT_HANDLE, 0); + if (err) + return err; + } + + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SELFTESTS_GET, flags); + + dl_opts_put(nlh, dl); + + pr_out_section_start(dl, "selftests"); + err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_dev_selftests_show_cb, dl); + pr_out_section_end(dl); + return err; +} + +static int cmd_dev_selftests(struct dl *dl) +{ + if (dl_argv_match(dl, "help")) { + cmd_dev_help(); + return 0; + } else if (dl_argv_match(dl, "show") || + dl_argv_match(dl, "list") || dl_no_arg(dl)) { + dl_arg_inc(dl); + return cmd_dev_selftests_show(dl); + } else if (dl_argv_match(dl, "run")) { + dl_arg_inc(dl); + return cmd_dev_selftests_run(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +} + static int cmd_dev(struct dl *dl) { if (dl_argv_match(dl, "help")) { @@ -3977,6 +4347,9 @@ } else if (dl_argv_match(dl, "flash")) { dl_arg_inc(dl); return cmd_dev_flash(dl); + } else if (dl_argv_match(dl, "selftests")) { + dl_arg_inc(dl); + return cmd_dev_selftests(dl); } pr_err("Command \"%s\" not found\n", dl_argv(dl)); return -ENOENT; @@ -4153,6 +4526,9 @@ break; } } + if (tbDEVLINK_ATTR_LINECARD_INDEX) + print_uint(PRINT_ANY, "lc", " lc %u", + mnl_attr_get_u32(tbDEVLINK_ATTR_LINECARD_INDEX)); if (tbDEVLINK_ATTR_PORT_NUMBER) { uint32_t port_number; @@ -4193,17 +4569,19 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLEP, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "port"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_port_show_cb, dl); pr_out_section_end(dl); @@ -4215,12 +4593,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_PORT_TYPE, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_TYPE, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4230,12 +4610,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_PORT_COUNT, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_SPLIT, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_COUNT, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4245,12 +4627,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLEP, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_UNSPLIT, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4261,18 +4645,19 @@ struct nlmsghdr *nlh; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_PARAM_NAME, 0); + if (err) + return err; + } nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_PARAM_GET, flags); - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | - DL_OPT_PARAM_NAME, 0); - if (err) - return err; - } + dl_opts_put(nlh, dl); pr_out_section_start(dl, "param"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_port_param_show_cb, dl); @@ -4296,13 +4681,15 @@ cmd_port_function_help(); return 0; } + err = dl_argv_parse(dl, DL_OPT_HANDLEP, + DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, - DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4421,7 +4808,7 @@ &val_u32); val_u8 = val_u32; } else { - err = strtouint8_t(dl->opts.param_value, &val_u8); + err = get_u8(&val_u8, dl->opts.param_value, 10); } if (err) goto err_param_value_parse; @@ -4438,7 +4825,7 @@ &val_u32); val_u16 = val_u32; } else { - err = strtouint16_t(dl->opts.param_value, &val_u16); + err = get_u16(&val_u16, dl->opts.param_value, 10); } if (err) goto err_param_value_parse; @@ -4454,7 +4841,7 @@ dl->opts.param_value, &val_u32); else - err = strtouint32_t(dl->opts.param_value, &val_u32); + err = get_u32(&val_u32, dl->opts.param_value, 10); if (err) goto err_param_value_parse; if (val_u32 == ctx.value.vu32) @@ -4557,7 +4944,7 @@ mnl_attr_get_u64(tbDEVLINK_ATTR_RATE_TX_SHARE); if (rate) - print_rate(use_iec, PRINT_ANY, "tx_share", + print_rate(dl->use_iec, PRINT_ANY, "tx_share", " tx_share %s", rate); } if (tbDEVLINK_ATTR_RATE_TX_MAX) { @@ -4565,7 +4952,7 @@ mnl_attr_get_u64(tbDEVLINK_ATTR_RATE_TX_MAX); if (rate) - print_rate(use_iec, PRINT_ANY, "tx_max", + print_rate(dl->use_iec, PRINT_ANY, "tx_max", " tx_max %s", rate); } if (tbDEVLINK_ATTR_RATE_PARENT_NODE_NAME) { @@ -4615,18 +5002,21 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | - DL_OPT_PORT_FN_RATE_NODE_NAME, 0); + } + else { + err = dl_argv_parse(dl, + DL_OPT_HANDLEP | DL_OPT_PORT_FN_RATE_NODE_NAME, + 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "rate"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_port_fn_rate_show_cb, dl); pr_out_section_end(dl); @@ -4658,14 +5048,16 @@ struct nlmsghdr *nlh; int err; - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_NEW, - NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_PORT_FN_RATE_NODE_NAME, - DL_OPT_PORT_FN_RATE_TX_SHARE | - DL_OPT_PORT_FN_RATE_TX_MAX); + err = dl_argv_parse(dl, DL_OPT_PORT_FN_RATE_NODE_NAME, + DL_OPT_PORT_FN_RATE_TX_SHARE | DL_OPT_PORT_FN_RATE_TX_MAX | + DL_OPT_PORT_FN_RATE_PARENT); if (err) return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_NEW, + NLM_F_REQUEST | NLM_F_ACK); + dl_opts_put(nlh, dl); + if ((dl->opts.present & DL_OPT_PORT_FN_RATE_TX_SHARE) && (dl->opts.present & DL_OPT_PORT_FN_RATE_TX_MAX)) { err = port_fn_check_tx_rates(dl->opts.rate_tx_share, @@ -4682,12 +5074,14 @@ struct nlmsghdr *nlh; int err; - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_DEL, - NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_PORT_FN_RATE_NODE_NAME, 0); + err = dl_argv_parse(dl, DL_OPT_PORT_FN_RATE_NODE_NAME, 0); if (err) return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_DEL, + NLM_F_REQUEST | NLM_F_ACK); + dl_opts_put(nlh, dl); + return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4815,14 +5209,16 @@ return 0; } + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_HANDLEP | + DL_OPT_PORT_FLAVOUR | DL_OPT_PORT_PFNUMBER, + DL_OPT_PORT_SFNUMBER | DL_OPT_PORT_CONTROLLER); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_NEW, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_HANDLEP | - DL_OPT_PORT_FLAVOUR | DL_OPT_PORT_PFNUMBER, - DL_OPT_PORT_SFNUMBER | DL_OPT_PORT_CONTROLLER); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_port_show_cb, dl); } @@ -4842,12 +5238,14 @@ return 0; } + err = dl_argv_parse(dl, DL_OPT_HANDLEP, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_DEL, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -4897,6 +5295,146 @@ return -ENOENT; } +static void cmd_linecard_help(void) +{ + pr_err("Usage: devlink lc show DEV lc LC_INDEX \n"); + pr_err(" devlink lc set DEV lc LC_INDEX { type LC_TYPE | notype } \n"); +} + +static const char *linecard_state_name(uint16_t flavour) +{ + switch (flavour) { + case DEVLINK_LINECARD_STATE_UNPROVISIONED: + return "unprovisioned"; + case DEVLINK_LINECARD_STATE_UNPROVISIONING: + return "unprovisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONING: + return "provisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONING_FAILED: + return "provisioning_failed"; + case DEVLINK_LINECARD_STATE_PROVISIONED: + return "provisioned"; + case DEVLINK_LINECARD_STATE_ACTIVE: + return "active"; + default: + return "<unknown state>"; + } +} + +static void pr_out_linecard_supported_types(struct dl *dl, struct nlattr **tb) +{ + struct nlattr *nla_types = tbDEVLINK_ATTR_LINECARD_SUPPORTED_TYPES; + struct nlattr *nla_type; + + if (!nla_types) + return; + + pr_out_array_start(dl, "supported_types"); + check_indent_newline(dl); + mnl_attr_for_each_nested(nla_type, nla_types) { + print_string(PRINT_ANY, NULL, " %s", + mnl_attr_get_str(nla_type)); + } + pr_out_array_end(dl); +} + +static void pr_out_linecard(struct dl *dl, struct nlattr **tb) +{ + uint8_t state; + + pr_out_handle_start_arr(dl, tb); + check_indent_newline(dl); + print_uint(PRINT_ANY, "lc", "lc %u", + mnl_attr_get_u32(tbDEVLINK_ATTR_LINECARD_INDEX)); + state = mnl_attr_get_u8(tbDEVLINK_ATTR_LINECARD_STATE); + print_string(PRINT_ANY, "state", " state %s", + linecard_state_name(state)); + if (tbDEVLINK_ATTR_LINECARD_TYPE) + print_string(PRINT_ANY, "type", " type %s", + mnl_attr_get_str(tbDEVLINK_ATTR_LINECARD_TYPE)); + if (tbDEVLINK_ATTR_NESTED_DEVLINK) + pr_out_nested_handle(tbDEVLINK_ATTR_NESTED_DEVLINK); + + pr_out_linecard_supported_types(dl, tb); + pr_out_handle_end(dl); +} + +static int cmd_linecard_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct dl *dl = data; + struct nlattr *tbDEVLINK_ATTR_MAX + 1 = {}; + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tbDEVLINK_ATTR_BUS_NAME || !tbDEVLINK_ATTR_DEV_NAME || + !tbDEVLINK_ATTR_LINECARD_INDEX || + !tbDEVLINK_ATTR_LINECARD_STATE) + return MNL_CB_ERROR; + pr_out_linecard(dl, tb); + return MNL_CB_OK; +} + +static int cmd_linecard_show(struct dl *dl) +{ + struct nlmsghdr *nlh; + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + int err; + + if (dl_no_arg(dl)) { + flags |= NLM_F_DUMP; + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_LINECARD); + if (err) + return err; + } + + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_LINECARD_GET, + flags); + + dl_opts_put(nlh, dl); + + pr_out_section_start(dl, "lc"); + err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_linecard_show_cb, dl); + pr_out_section_end(dl); + return err; +} + +static int cmd_linecard_set(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_LINECARD | + DL_OPT_LINECARD_TYPE, 0); + if (err) + return err; + + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_LINECARD_SET, + NLM_F_REQUEST | NLM_F_ACK); + + dl_opts_put(nlh, dl); + + return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); +} + +static int cmd_linecard(struct dl *dl) +{ + if (dl_argv_match(dl, "help")) { + cmd_linecard_help(); + return 0; + } else if (dl_argv_match(dl, "show") || + dl_argv_match(dl, "list") || dl_no_arg(dl)) { + dl_arg_inc(dl); + return cmd_linecard_show(dl); + } else if (dl_argv_match(dl, "set")) { + dl_arg_inc(dl); + return cmd_linecard_set(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +} + static void cmd_sb_help(void) { pr_err("Usage: devlink sb show DEV sb SB_INDEX \n"); @@ -4960,17 +5498,19 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_SB); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "sb"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_sb_show_cb, dl); pr_out_section_end(dl); @@ -5037,18 +5577,20 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_POOL_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_SB_POOL, - DL_OPT_SB); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_SB_POOL, + DL_OPT_SB); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_POOL_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "pool"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_sb_pool_show_cb, dl); pr_out_section_end(dl); @@ -5060,13 +5602,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_SB_POOL | + DL_OPT_SB_SIZE | DL_OPT_SB_THTYPE, DL_OPT_SB); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_POOL_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_SB_POOL | - DL_OPT_SB_SIZE | DL_OPT_SB_THTYPE, DL_OPT_SB); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -5122,19 +5666,20 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_PORT_POOL_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLEP | DL_OPT_SB_POOL, - DL_OPT_SB); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB_POOL, + DL_OPT_SB); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_PORT_POOL_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "port_pool"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_sb_port_pool_show_cb, dl); pr_out_section_end(dl); @@ -5146,13 +5691,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB_POOL | DL_OPT_SB_TH, + DL_OPT_SB); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_PORT_POOL_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_POOL | - DL_OPT_SB_TH, DL_OPT_SB); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -5226,18 +5773,20 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | - DL_OPT_SB_TYPE, DL_OPT_SB); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | + DL_OPT_SB_TYPE, DL_OPT_SB); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "tc_bind"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_sb_tc_bind_show_cb, dl); pr_out_section_end(dl); @@ -5249,14 +5798,16 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | + DL_OPT_SB_TYPE | DL_OPT_SB_POOL | DL_OPT_SB_TH, + DL_OPT_SB); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_SB_TC | - DL_OPT_SB_TYPE | DL_OPT_SB_POOL | DL_OPT_SB_TH, - DL_OPT_SB); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -5603,12 +6154,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_SB); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_OCC_SNAPSHOT, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -5618,12 +6171,14 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_SB); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_OCC_MAX_CLEAR, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, DL_OPT_SB); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -5714,6 +6269,10 @@ case DEVLINK_CMD_TRAP_POLICER_SET: return "set"; case DEVLINK_CMD_TRAP_POLICER_NEW: return "new"; case DEVLINK_CMD_TRAP_POLICER_DEL: return "del"; + case DEVLINK_CMD_LINECARD_GET: return "get"; + case DEVLINK_CMD_LINECARD_SET: return "set"; + case DEVLINK_CMD_LINECARD_NEW: return "new"; + case DEVLINK_CMD_LINECARD_DEL: return "del"; default: return "<unknown cmd>"; } } @@ -5767,6 +6326,11 @@ case DEVLINK_CMD_TRAP_POLICER_NEW: case DEVLINK_CMD_TRAP_POLICER_DEL: return "trap-policer"; + case DEVLINK_CMD_LINECARD_GET: + case DEVLINK_CMD_LINECARD_SET: + case DEVLINK_CMD_LINECARD_NEW: + case DEVLINK_CMD_LINECARD_DEL: + return "lc"; default: return "<unknown obj>"; } } @@ -5959,6 +6523,18 @@ pr_out_mon_header(genl->cmd); pr_out_trap_policer(dl, tb, false); break; + case DEVLINK_CMD_LINECARD_GET: /* fall through */ + case DEVLINK_CMD_LINECARD_SET: /* fall through */ + case DEVLINK_CMD_LINECARD_NEW: /* fall through */ + case DEVLINK_CMD_LINECARD_DEL: + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tbDEVLINK_ATTR_BUS_NAME || !tbDEVLINK_ATTR_DEV_NAME || + !tbDEVLINK_ATTR_LINECARD_INDEX) + return MNL_CB_ERROR; + pr_out_mon_header(genl->cmd); + pr_out_linecard(dl, tb); + pr_out_mon_footer(); + break; } fflush(stdout); return MNL_CB_OK; @@ -5977,7 +6553,8 @@ strcmp(cur_obj, "health") != 0 && strcmp(cur_obj, "trap") != 0 && strcmp(cur_obj, "trap-group") != 0 && - strcmp(cur_obj, "trap-policer") != 0) { + strcmp(cur_obj, "trap-policer") != 0 && + strcmp(cur_obj, "lc") != 0) { pr_err("Unknown object \"%s\"\n", cur_obj); return -EINVAL; } @@ -5998,7 +6575,7 @@ static void cmd_mon_help(void) { pr_err("Usage: devlink monitor all | OBJECT-LIST \n" - "where OBJECT-LIST := { dev | port | health | trap | trap-group | trap-policer }\n"); + "where OBJECT-LIST := { dev | port | lc | health | trap | trap-group | trap-policer }\n"); } static int cmd_mon(struct dl *dl) @@ -6503,12 +7080,14 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_DPIPE_HEADERS_GET, flags); - - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0); + err = dl_argv_parse(dl, DL_OPT_HANDLE, 0); if (err) return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_DPIPE_HEADERS_GET, flags); + + dl_opts_put(nlh, dl); + err = dpipe_ctx_init(&ctx, dl); if (err) return err; @@ -6956,14 +7535,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_DPIPE_TABLE_NAME | + DL_OPT_DPIPE_TABLE_COUNTERS, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_DPIPE_TABLE_NAME | - DL_OPT_DPIPE_TABLE_COUNTERS, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -7845,6 +8425,10 @@ if (tbDEVLINK_ATTR_REGION_SNAPSHOT_ID) pr_out_snapshot(dl, tb); + if (tbDEVLINK_ATTR_REGION_MAX_SNAPSHOTS) + pr_out_u64(dl, "max", + mnl_attr_get_u32(tbDEVLINK_ATTR_REGION_MAX_SNAPSHOTS)); + pr_out_region_handle_end(dl); } @@ -7870,17 +8454,19 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION, 0); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE_REGION, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "regions"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_region_show_cb, dl); pr_out_section_end(dl); @@ -7892,13 +8478,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE_REGION | + DL_OPT_REGION_SNAPSHOT_ID, 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_DEL, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION | - DL_OPT_REGION_SNAPSHOT_ID, 0); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -7942,13 +8530,16 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, + DL_OPT_HANDLE_REGION | DL_OPT_REGION_SNAPSHOT_ID, + 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_READ, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION | - DL_OPT_REGION_SNAPSHOT_ID, 0); - if (err) - return err; + dl_opts_put(nlh, dl); pr_out_section_start(dl, "dump"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_region_read_cb, dl); @@ -7963,14 +8554,16 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE_REGION | DL_OPT_REGION_ADDRESS | + DL_OPT_REGION_LENGTH | DL_OPT_REGION_SNAPSHOT_ID, + 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_READ, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION | - DL_OPT_REGION_ADDRESS | DL_OPT_REGION_LENGTH | - DL_OPT_REGION_SNAPSHOT_ID, 0); - if (err) - return err; + dl_opts_put(nlh, dl); pr_out_section_start(dl, "read"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_region_read_cb, dl); @@ -8002,13 +8595,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE_REGION, + DL_OPT_REGION_SNAPSHOT_ID); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_NEW, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE_REGION, - DL_OPT_REGION_SNAPSHOT_ID); - if (err) - return err; + dl_opts_put(nlh, dl); pr_out_section_start(dl, "regions"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_region_snapshot_new_cb, dl); @@ -8020,7 +8615,7 @@ { pr_err("Usage: devlink region show DEV/REGION \n"); pr_err(" devlink region del DEV/REGION snapshot SNAPSHOT_ID\n"); - pr_err(" devlink region new DEV/REGION snapshot SNAPSHOT_ID\n"); + pr_err(" devlink region new DEV/REGION snapshot SNAPSHOT_ID \n"); pr_err(" devlink region dump DEV/REGION snapshot SNAPSHOT_ID \n"); pr_err(" devlink region read DEV/REGION snapshot SNAPSHOT_ID address ADDRESS length LENGTH\n"); } @@ -8075,14 +8670,16 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_HANDLEP | + DL_OPT_HEALTH_REPORTER_NAME, + 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_HANDLEP | - DL_OPT_HEALTH_REPORTER_NAME, 0); - if (err) - return err; + dl_opts_put(nlh, dl); dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); @@ -8090,6 +8687,8 @@ static int fmsg_value_show(struct dl *dl, int type, struct nlattr *nl_data) { + const char *num_fmt = dl->hex ? "%#x" : "%u"; + const char *num64_fmt = dl->hex ? "%#"PRIx64 : "%"PRIu64; uint8_t *data; uint32_t len; @@ -8099,16 +8698,16 @@ print_bool(PRINT_ANY, NULL, "%s", mnl_attr_get_u8(nl_data)); break; case MNL_TYPE_U8: - print_uint(PRINT_ANY, NULL, "%u", mnl_attr_get_u8(nl_data)); + print_uint(PRINT_ANY, NULL, num_fmt, mnl_attr_get_u8(nl_data)); break; case MNL_TYPE_U16: - print_uint(PRINT_ANY, NULL, "%u", mnl_attr_get_u16(nl_data)); + print_uint(PRINT_ANY, NULL, num_fmt, mnl_attr_get_u16(nl_data)); break; case MNL_TYPE_U32: - print_uint(PRINT_ANY, NULL, "%u", mnl_attr_get_u32(nl_data)); + print_uint(PRINT_ANY, NULL, num_fmt, mnl_attr_get_u32(nl_data)); break; case MNL_TYPE_U64: - print_u64(PRINT_ANY, NULL, "%"PRIu64, mnl_attr_get_u64(nl_data)); + print_u64(PRINT_ANY, NULL, num64_fmt, mnl_attr_get_u64(nl_data)); break; case MNL_TYPE_NUL_STRING: print_string(PRINT_ANY, NULL, "%s", mnl_attr_get_str(nl_data)); @@ -8324,14 +8923,16 @@ struct nlmsghdr *nlh; int err; - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, cmd, flags | NLM_F_REQUEST | NLM_F_ACK); - - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_HANDLEP | - DL_OPT_HEALTH_REPORTER_NAME, 0); + err = dl_argv_parse(dl, + DL_OPT_HANDLE | DL_OPT_HANDLEP | DL_OPT_HEALTH_REPORTER_NAME, + 0); if (err) return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, cmd, flags | NLM_F_REQUEST | NLM_F_ACK); + + dl_opts_put(nlh, dl); + cmd_fmsg_init(dl, &data); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_fmsg_object_cb, &data); free(data.name); @@ -8364,14 +8965,16 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_HANDLEP | + DL_OPT_HEALTH_REPORTER_NAME, + 0); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_HEALTH_REPORTER_RECOVER, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_HANDLEP | - DL_OPT_HEALTH_REPORTER_NAME, 0); - if (err) - return err; + dl_opts_put(nlh, dl); dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); @@ -8538,19 +9141,21 @@ uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_HEALTH_REPORTER_GET, - flags); - - if (dl_argc(dl) > 0) { + } else { ctx.show_port = true; - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_HANDLEP | - DL_OPT_HEALTH_REPORTER_NAME, 0); + err = dl_argv_parse(dl, + DL_OPT_HANDLE | DL_OPT_HANDLEP | + DL_OPT_HEALTH_REPORTER_NAME, 0); if (err) return err; } + + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_HEALTH_REPORTER_GET, + flags); + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "health"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_health_show_cb, &ctx); @@ -8572,6 +9177,23 @@ pr_err(" auto_dump { true | false } \n"); } +static int cmd_health_dump(struct dl *dl) +{ + if (dl_argv_match(dl, "help")) { + cmd_health_help(); + return 0; + } else if (dl_argv_match(dl, "show") || + dl_argv_match(dl, "list") || dl_no_arg(dl)) { + dl_arg_inc(dl); + return cmd_health_dump_show(dl); + } else if (dl_argv_match(dl, "clear")) { + dl_arg_inc(dl); + return cmd_health_dump_clear(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +} + static int cmd_health(struct dl *dl) { if (dl_argv_match(dl, "help")) { @@ -8592,13 +9214,7 @@ return cmd_health_test(dl); } else if (dl_argv_match(dl, "dump")) { dl_arg_inc(dl); - if (dl_argv_match(dl, "show")) { - dl_arg_inc(dl); - return cmd_health_dump_show(dl); - } else if (dl_argv_match(dl, "clear")) { - dl_arg_inc(dl); - return cmd_health_dump_clear(dl); - } + return cmd_health_dump(dl); } else if (dl_argv_match(dl, "set")) { dl_arg_inc(dl); return cmd_health_set_params(dl); @@ -8719,18 +9335,19 @@ struct nlmsghdr *nlh; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_TRAP_NAME, 0); + } + else { + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_TRAP_NAME, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "trap"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_trap_show_cb, dl); pr_out_section_end(dl); @@ -8743,13 +9360,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_TRAP_NAME, + DL_OPT_TRAP_ACTION); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_TRAP_NAME, - DL_OPT_TRAP_ACTION); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -8794,19 +9413,20 @@ struct nlmsghdr *nlh; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GROUP_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, - 0); + } + else { + err = dl_argv_parse(dl, + DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GROUP_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "trap_group"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_trap_group_show_cb, dl); pr_out_section_end(dl); @@ -8819,14 +9439,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, + DL_OPT_TRAP_ACTION | DL_OPT_TRAP_POLICER_ID); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GROUP_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, - DL_OPT_TRAP_ACTION | DL_OPT_TRAP_POLICER_ID); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -8891,19 +9512,20 @@ struct nlmsghdr *nlh; int err; - if (dl_argc(dl) == 0) + if (dl_no_arg(dl)) { flags |= NLM_F_DUMP; - - nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_POLICER_GET, flags); - - if (dl_argc(dl) > 0) { - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, - 0); + } + else { + err = dl_argv_parse(dl, + DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, 0); if (err) return err; } + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_POLICER_GET, flags); + + dl_opts_put(nlh, dl); + pr_out_section_start(dl, "trap_policer"); err = mnlu_gen_socket_sndrcv(&dl->nlg, nlh, cmd_trap_policer_show_cb, dl); pr_out_section_end(dl); @@ -8916,15 +9538,15 @@ struct nlmsghdr *nlh; int err; + err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, + DL_OPT_TRAP_POLICER_RATE | DL_OPT_TRAP_POLICER_BURST); + if (err) + return err; + nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_POLICER_SET, NLM_F_REQUEST | NLM_F_ACK); - err = dl_argv_parse_put(nlh, dl, - DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, - DL_OPT_TRAP_POLICER_RATE | - DL_OPT_TRAP_POLICER_BURST); - if (err) - return err; + dl_opts_put(nlh, dl); return mnlu_gen_socket_sndrcv(&dl->nlg, nlh, NULL, NULL); } @@ -8973,8 +9595,8 @@ { pr_err("Usage: devlink OPTIONS OBJECT { COMMAND | help }\n" " devlink -force -batch filename -Netns netnsname\n" - "where OBJECT := { dev | port | sb | monitor | dpipe | resource | region | health | trap }\n" - " OPTIONS := { -Version | -no-nice-names | -json | -pretty | -verbose -statistics }\n"); + "where OBJECT := { dev | port | lc | sb | monitor | dpipe | resource | region | health | trap }\n" + " OPTIONS := { -Version | -no-nice-names | -json | -pretty | -verbose -statistics -hex }\n"); } static int dl_cmd(struct dl *dl, int argc, char **argv) @@ -9012,6 +9634,9 @@ } else if (dl_argv_match(dl, "trap")) { dl_arg_inc(dl); return cmd_trap(dl); + } else if (dl_argv_match(dl, "lc")) { + dl_arg_inc(dl); + return cmd_linecard(dl); } pr_err("Object \"%s\" not found\n", dl_argv(dl)); return -ENOENT; @@ -9028,17 +9653,10 @@ return -errno; } - err = ifname_map_init(dl); - if (err) { - pr_err("Failed to create index map\n"); - goto err_ifname_map_create; - } + ifname_map_init(dl); + new_json_obj_plain(dl->json_output); return 0; - -err_ifname_map_create: - mnlu_gen_socket_close(&dl->nlg); - return err; } static void dl_fini(struct dl *dl) @@ -9088,6 +9706,7 @@ { "statistics", no_argument, NULL, 's' }, { "Netns", required_argument, NULL, 'N' }, { "iec", no_argument, NULL, 'i' }, + { "hex", no_argument, NULL, 'x' }, { NULL, 0, NULL, 0 } }; const char *batch_file = NULL; @@ -9103,7 +9722,7 @@ return EXIT_FAILURE; } - while ((opt = getopt_long(argc, argv, "Vfb:njpvsN:i", + while ((opt = getopt_long(argc, argv, "Vfb:njpvsN:ix", long_options, NULL)) >= 0) { switch (opt) { @@ -9139,7 +9758,10 @@ } break; case 'i': - use_iec = true; + dl->use_iec = true; + break; + case 'x': + dl->hex = true; break; default: pr_err("Unknown option.\n");
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/devlink/mnlg.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/devlink/mnlg.c
Changed
@@ -22,14 +22,6 @@ #include "utils.h" #include "mnlg.h" -struct mnlg_socket { - struct mnl_socket *nl; - char *buf; - uint32_t id; - uint8_t version; - unsigned int seq; -}; - int mnlg_socket_send(struct mnlu_gen_socket *nlg, const struct nlmsghdr *nlh) { return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/doc/actions/actions-general -> _service:tar_scm:iproute2-6.1.0.tar.xz/doc/actions/actions-general
Changed
@@ -72,7 +72,7 @@ 2)In order to take advantage of some of the targets written by the iptables people, a classifier can have a packet being massaged by an iptable target. I have only tested with mangler targets up to now. -(infact anything that is not in the mangling table is disabled right now) +(in fact anything that is not in the mangling table is disabled right now) In terms of hooks: *ingress is mapped to pre-routing hook
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/doc/actions/gact-usage -> _service:tar_scm:iproute2-6.1.0.tar.xz/doc/actions/gact-usage
Changed
@@ -10,7 +10,7 @@ ACTION semantics - pass and ok are equivalent to accept -- continue allows to restart classification lookup +- continue allows one to restart classification lookup - drop drops packets - reclassify implies continue classification where we left off
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/genl/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/genl/Makefile
Changed
@@ -11,8 +11,6 @@ GENLOBJ += $(GENLMODULES) -GENLLIB := - ifeq ($(SHARED_LIBS),y) LDFLAGS += -Wl,-export-dynamic LDLIBS += -lm -ldl @@ -20,14 +18,14 @@ all: genl -genl: $(GENLOBJ) $(LIBNETLINK) $(LIBUTIL) $(GENLLIB) +genl: $(GENLOBJ) $(LIBNETLINK) $(QUIET_LINK)$(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@ install: all install -m 0755 genl $(DESTDIR)$(SBINDIR) clean: - rm -f $(GENLOBJ) $(GENLLIB) genl + rm -f $(GENLOBJ) genl ifneq ($(SHARED_LIBS),y)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/genl/genl_utils.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/genl/genl_utils.h
Changed
@@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _TC_UTIL_H_ -#define _TC_UTIL_H_ 1 +#ifndef _GENL_UTILS_H_ +#define _GENL_UTILS_H_ 1 #include <linux/genetlink.h> #include "utils.h"
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/bpf_util.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/bpf_util.h
Changed
@@ -68,6 +68,7 @@ struct bpf_cfg_in { const char *object; const char *section; + const char *prog_name; const char *uds; enum bpf_prog_type type; enum bpf_mode mode; @@ -287,6 +288,8 @@ int bpf_dump_prog_info(FILE *f, uint32_t id); +int bpf(int cmd, union bpf_attr *attr, unsigned int size); + #ifdef HAVE_ELF int bpf_send_map_fds(const char *path, const char *obj); int bpf_recv_map_fds(const char *path, int *fds, struct bpf_map_aux *aux,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/libnetlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/libnetlink.h
Changed
@@ -37,6 +37,12 @@ struct nlmsg_list *tail; }; +struct ipstats_req { + struct nlmsghdr nlh; + struct if_stats_msg ifsm; + char buf128; +}; + extern int rcvbuf; int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions) @@ -88,7 +94,10 @@ int rtnl_nsiddump_req_filter_fn(struct rtnl_handle *rth, int family, req_filter_fn_t filter_fn) __attribute__((warn_unused_result)); -int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask) +int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask, + int (*filter_fn)(struct ipstats_req *req, + void *data), + void *filter_data) __attribute__((warn_unused_result)); int rtnl_dump_request(struct rtnl_handle *rth, int type, void *req, int len) @@ -103,6 +112,10 @@ req_filter_fn_t filter_fn) __attribute__((warn_unused_result)); +int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex, + __u8 flags) + __attribute__((warn_unused_result)); + struct rtnl_ctrl_data { int nsid; }; @@ -158,6 +171,9 @@ #define rtnl_dump_filter_errhndlr(rth, filter, farg, errhndlr, earg) \ rtnl_dump_filter_errhndlr_nc(rth, filter, farg, errhndlr, earg, 0) +int rtnl_echo_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, int json, + int (*print_info)(struct nlmsghdr *n, void *arg)) + __attribute__((warn_unused_result)); int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer) __attribute__((warn_unused_result)); @@ -172,7 +188,7 @@ int rtnl_send_check(struct rtnl_handle *rth, const void *buf, int) __attribute__((warn_unused_result)); int nl_dump_ext_ack(const struct nlmsghdr *nlh, nl_ext_ack_fn_t errfn); -int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error); +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, unsigned int offset, int error); int addattr(struct nlmsghdr *n, int maxlen, int type); int addattr8(struct nlmsghdr *n, int maxlen, int type, __u8 data); @@ -322,6 +338,11 @@ ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct br_vlan_msg)))) #endif +#ifndef TUNNEL_RTA +#define TUNNEL_RTA(r) \ + ((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct tunnel_msg)))) +#endif + /* User defined nlmsg_type which is used mostly for logging netlink * messages from dump file */ #define NLMSG_TSTAMP 15
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/mnl_utils.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/mnl_utils.h
Changed
@@ -6,6 +6,7 @@ struct mnl_socket *nl; char *buf; uint32_t family; + uint32_t maxattr; unsigned int seq; uint8_t version; };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/rt_names.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/rt_names.h
Changed
@@ -31,6 +31,9 @@ const char * ll_proto_n2a(unsigned short id, char *buf, int len); int ll_proto_a2n(unsigned short *id, const char *buf); +const char *ppp_proto_n2a(unsigned short id, char *buf, int len); +int ppp_proto_a2n(unsigned short *id, const char *buf); + const char *nl_proto_n2a(int id, char *buf, int len); int nl_proto_a2n(__u32 *id, const char *arg);
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/asm-generic/posix_types.h
Added
@@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __ASM_GENERIC_POSIX_TYPES_H +#define __ASM_GENERIC_POSIX_TYPES_H + +#include <asm/bitsperlong.h> +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. + * + * First the types that are often defined in different ways across + * architectures, so that you can override them. + */ + +#ifndef __kernel_long_t +typedef long __kernel_long_t; +typedef unsigned long __kernel_ulong_t; +#endif + +#ifndef __kernel_ino_t +typedef __kernel_ulong_t __kernel_ino_t; +#endif + +#ifndef __kernel_mode_t +typedef unsigned int __kernel_mode_t; +#endif + +#ifndef __kernel_pid_t +typedef int __kernel_pid_t; +#endif + +#ifndef __kernel_ipc_pid_t +typedef int __kernel_ipc_pid_t; +#endif + +#ifndef __kernel_uid_t +typedef unsigned int __kernel_uid_t; +typedef unsigned int __kernel_gid_t; +#endif + +#ifndef __kernel_suseconds_t +typedef __kernel_long_t __kernel_suseconds_t; +#endif + +#ifndef __kernel_daddr_t +typedef int __kernel_daddr_t; +#endif + +#ifndef __kernel_uid32_t +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; +#endif + +#ifndef __kernel_old_uid_t +typedef __kernel_uid_t __kernel_old_uid_t; +typedef __kernel_gid_t __kernel_old_gid_t; +#endif + +#ifndef __kernel_old_dev_t +typedef unsigned int __kernel_old_dev_t; +#endif + +/* + * Most 32 bit architectures use "unsigned int" size_t, + * and all 64 bit architectures use "unsigned long" size_t. + */ +#ifndef __kernel_size_t +#if __BITS_PER_LONG != 64 +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +#else +typedef __kernel_ulong_t __kernel_size_t; +typedef __kernel_long_t __kernel_ssize_t; +typedef __kernel_long_t __kernel_ptrdiff_t; +#endif +#endif + +#ifndef __kernel_fsid_t +typedef struct { + int val2; +} __kernel_fsid_t; +#endif + +/* + * anything below here should be completely generic + */ +typedef __kernel_long_t __kernel_off_t; +typedef long long __kernel_loff_t; +typedef __kernel_long_t __kernel_old_time_t; +typedef __kernel_long_t __kernel_time_t; +typedef long long __kernel_time64_t; +typedef __kernel_long_t __kernel_clock_t; +typedef int __kernel_timer_t; +typedef int __kernel_clockid_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; + +#endif /* __ASM_GENERIC_POSIX_TYPES_H */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/amt.h
Added
@@ -0,0 +1,62 @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (c) 2021 Taehee Yoo <ap420073@gmail.com> + */ +#ifndef _AMT_H_ +#define _AMT_H_ + +enum ifla_amt_mode { + /* AMT interface works as Gateway mode. + * The Gateway mode encapsulates IGMP/MLD traffic and decapsulates + * multicast traffic. + */ + AMT_MODE_GATEWAY = 0, + /* AMT interface works as Relay mode. + * The Relay mode encapsulates multicast traffic and decapsulates + * IGMP/MLD traffic. + */ + AMT_MODE_RELAY, + __AMT_MODE_MAX, +}; + +#define AMT_MODE_MAX (__AMT_MODE_MAX - 1) + +enum { + IFLA_AMT_UNSPEC, + /* This attribute specify mode etier Gateway or Relay. */ + IFLA_AMT_MODE, + /* This attribute specify Relay port. + * AMT interface is created as Gateway mode, this attribute is used + * to specify relay(remote) port. + * AMT interface is created as Relay mode, this attribute is used + * as local port. + */ + IFLA_AMT_RELAY_PORT, + /* This attribute specify Gateway port. + * AMT interface is created as Gateway mode, this attribute is used + * as local port. + * AMT interface is created as Relay mode, this attribute is not used. + */ + IFLA_AMT_GATEWAY_PORT, + /* This attribute specify physical device */ + IFLA_AMT_LINK, + /* This attribute specify local ip address */ + IFLA_AMT_LOCAL_IP, + /* This attribute specify Relay ip address. + * So, this is not used by Relay. + */ + IFLA_AMT_REMOTE_IP, + /* This attribute specify Discovery ip address. + * When Gateway get started, it send discovery message to find the + * Relay's ip address. + * So, this is not used by Relay. + */ + IFLA_AMT_DISCOVERY_IP, + /* This attribute specify number of maximum tunnel. */ + IFLA_AMT_MAX_TUNNELS, + __IFLA_AMT_MAX, +}; + +#define IFLA_AMT_MAX (__IFLA_AMT_MAX - 1) + +#endif /* _AMT_H_ */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/ax25.h
Added
@@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * These are the public elements of the Linux kernel AX.25 code. A similar + * file netrom.h exists for the NET/ROM protocol. + */ + +#ifndef AX25_KERNEL_H +#define AX25_KERNEL_H + +#include <linux/socket.h> + +#define AX25_MTU 256 +#define AX25_MAX_DIGIS 8 + +#define AX25_WINDOW 1 +#define AX25_T1 2 +#define AX25_N2 3 +#define AX25_T3 4 +#define AX25_T2 5 +#define AX25_BACKOFF 6 +#define AX25_EXTSEQ 7 +#define AX25_PIDINCL 8 +#define AX25_IDLE 9 +#define AX25_PACLEN 10 +#define AX25_IAMDIGI 12 + +#define AX25_KILL 99 + +#define SIOCAX25GETUID (SIOCPROTOPRIVATE+0) +#define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1) +#define SIOCAX25DELUID (SIOCPROTOPRIVATE+2) +#define SIOCAX25NOUID (SIOCPROTOPRIVATE+3) +#define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) +#define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) +#define SIOCAX25GETINFOOLD (SIOCPROTOPRIVATE+9) +#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) +#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) +#define SIOCAX25DEVCTL (SIOCPROTOPRIVATE+12) +#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+13) + +#define AX25_SET_RT_IPMODE 2 + +#define AX25_NOUID_DEFAULT 0 +#define AX25_NOUID_BLOCK 1 + +typedef struct { + char ax25_call7; /* 6 call + SSID (shifted ascii!) */ +} ax25_address; + +struct sockaddr_ax25 { + __kernel_sa_family_t sax25_family; + ax25_address sax25_call; + int sax25_ndigis; + /* Digipeater ax25_address sets follow */ +}; + +#define sax25_uid sax25_ndigis + +struct full_sockaddr_ax25 { + struct sockaddr_ax25 fsa_ax25; + ax25_address fsa_digipeaterAX25_MAX_DIGIS; +}; + +struct ax25_routes_struct { + ax25_address port_addr; + ax25_address dest_addr; + unsigned char digi_count; + ax25_address digi_addrAX25_MAX_DIGIS; +}; + +struct ax25_route_opt_struct { + ax25_address port_addr; + ax25_address dest_addr; + int cmd; + int arg; +}; + +struct ax25_ctl_struct { + ax25_address port_addr; + ax25_address source_addr; + ax25_address dest_addr; + unsigned int cmd; + unsigned long arg; + unsigned char digi_count; + ax25_address digi_addrAX25_MAX_DIGIS; +}; + +/* this will go away. Please do not export to user land */ +struct ax25_info_struct_deprecated { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; +}; + +struct ax25_info_struct { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; + unsigned int vs, vr, va, vs_max; + unsigned int paclen; + unsigned int window; +}; + +struct ax25_fwd_struct { + ax25_address port_from; + ax25_address port_to; +}; + +#endif
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/batman_adv.h
Added
@@ -0,0 +1,704 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) B.A.T.M.A.N. contributors: + * + * Matthias Schiffer + */ + +#ifndef _LINUX_BATMAN_ADV_H_ +#define _LINUX_BATMAN_ADV_H_ + +#define BATADV_NL_NAME "batadv" + +#define BATADV_NL_MCAST_GROUP_CONFIG "config" +#define BATADV_NL_MCAST_GROUP_TPMETER "tpmeter" + +/** + * enum batadv_tt_client_flags - TT client specific flags + * + * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire. + * Bits from 8 to 15 are called _local flags_ because they are used for local + * computations only. + * + * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with + * the other nodes in the network. To achieve this goal these flags are included + * in the TT CRC computation. + */ +enum batadv_tt_client_flags { + /** + * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table + */ + BATADV_TT_CLIENT_DEL = (1 << 0), + + /** + * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and + * the new update telling its new real location has not been + * received/sent yet + */ + BATADV_TT_CLIENT_ROAM = (1 << 1), + + /** + * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi + * interface. This information is used by the "AP Isolation" feature + */ + BATADV_TT_CLIENT_WIFI = (1 << 4), + + /** + * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This + * information is used by the Extended Isolation feature + */ + BATADV_TT_CLIENT_ISOLA = (1 << 5), + + /** + * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from + * the table + */ + BATADV_TT_CLIENT_NOPURGE = (1 << 8), + + /** + * @BATADV_TT_CLIENT_NEW: this client has been added to the local table + * but has not been announced yet + */ + BATADV_TT_CLIENT_NEW = (1 << 9), + + /** + * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it + * is kept in the table for one more originator interval for consistency + * purposes + */ + BATADV_TT_CLIENT_PENDING = (1 << 10), + + /** + * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be + * part of the network but no node has already announced it + */ + BATADV_TT_CLIENT_TEMP = (1 << 11), +}; + +/** + * enum batadv_mcast_flags_priv - Private, own multicast flags + * + * These are internal, multicast related flags. Currently they describe certain + * multicast related attributes of the segment this originator bridges into the + * mesh. + * + * Those attributes are used to determine the public multicast flags this + * originator is going to announce via TT. + * + * For netlink, if BATADV_MCAST_FLAGS_BRIDGED is unset then all querier + * related flags are undefined. + */ +enum batadv_mcast_flags_priv { + /** + * @BATADV_MCAST_FLAGS_BRIDGED: There is a bridge on top of the mesh + * interface. + */ + BATADV_MCAST_FLAGS_BRIDGED = (1 << 0), + + /** + * @BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS: Whether an IGMP querier + * exists in the mesh + */ + BATADV_MCAST_FLAGS_QUERIER_IPV4_EXISTS = (1 << 1), + + /** + * @BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS: Whether an MLD querier + * exists in the mesh + */ + BATADV_MCAST_FLAGS_QUERIER_IPV6_EXISTS = (1 << 2), + + /** + * @BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING: If an IGMP querier + * exists, whether it is potentially shadowing multicast listeners + * (i.e. querier is behind our own bridge segment) + */ + BATADV_MCAST_FLAGS_QUERIER_IPV4_SHADOWING = (1 << 3), + + /** + * @BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING: If an MLD querier + * exists, whether it is potentially shadowing multicast listeners + * (i.e. querier is behind our own bridge segment) + */ + BATADV_MCAST_FLAGS_QUERIER_IPV6_SHADOWING = (1 << 4), +}; + +/** + * enum batadv_gw_modes - gateway mode of node + */ +enum batadv_gw_modes { + /** @BATADV_GW_MODE_OFF: gw mode disabled */ + BATADV_GW_MODE_OFF, + + /** @BATADV_GW_MODE_CLIENT: send DHCP requests to gw servers */ + BATADV_GW_MODE_CLIENT, + + /** @BATADV_GW_MODE_SERVER: announce itself as gateway server */ + BATADV_GW_MODE_SERVER, +}; + +/** + * enum batadv_nl_attrs - batman-adv netlink attributes + */ +enum batadv_nl_attrs { + /** + * @BATADV_ATTR_UNSPEC: unspecified attribute to catch errors + */ + BATADV_ATTR_UNSPEC, + + /** + * @BATADV_ATTR_VERSION: batman-adv version string + */ + BATADV_ATTR_VERSION, + + /** + * @BATADV_ATTR_ALGO_NAME: name of routing algorithm + */ + BATADV_ATTR_ALGO_NAME, + + /** + * @BATADV_ATTR_MESH_IFINDEX: index of the batman-adv interface + */ + BATADV_ATTR_MESH_IFINDEX, + + /** + * @BATADV_ATTR_MESH_IFNAME: name of the batman-adv interface + */ + BATADV_ATTR_MESH_IFNAME, + + /** + * @BATADV_ATTR_MESH_ADDRESS: mac address of the batman-adv interface + */ + BATADV_ATTR_MESH_ADDRESS, + + /** + * @BATADV_ATTR_HARD_IFINDEX: index of the non-batman-adv interface + */ + BATADV_ATTR_HARD_IFINDEX, + + /** + * @BATADV_ATTR_HARD_IFNAME: name of the non-batman-adv interface + */ + BATADV_ATTR_HARD_IFNAME, + + /** + * @BATADV_ATTR_HARD_ADDRESS: mac address of the non-batman-adv + * interface + */ + BATADV_ATTR_HARD_ADDRESS, + + /** + * @BATADV_ATTR_ORIG_ADDRESS: originator mac address + */ + BATADV_ATTR_ORIG_ADDRESS, + + /** + * @BATADV_ATTR_TPMETER_RESULT: result of run (see + * batadv_tp_meter_status) + */ + BATADV_ATTR_TPMETER_RESULT, + + /** + * @BATADV_ATTR_TPMETER_TEST_TIME: time (msec) the run took + */ + BATADV_ATTR_TPMETER_TEST_TIME, + + /** + * @BATADV_ATTR_TPMETER_BYTES: amount of acked bytes during run + */ + BATADV_ATTR_TPMETER_BYTES, + + /** + * @BATADV_ATTR_TPMETER_COOKIE: session cookie to match tp_meter session + */ + BATADV_ATTR_TPMETER_COOKIE, + + /** + * @BATADV_ATTR_PAD: attribute used for padding for 64-bit alignment + */ + BATADV_ATTR_PAD, + + /** + * @BATADV_ATTR_ACTIVE: Flag indicating if the hard interface is active + */ + BATADV_ATTR_ACTIVE, + + /** + * @BATADV_ATTR_TT_ADDRESS: Client MAC address + */ + BATADV_ATTR_TT_ADDRESS, + + /** + * @BATADV_ATTR_TT_TTVN: Translation table version + */ + BATADV_ATTR_TT_TTVN, + + /** + * @BATADV_ATTR_TT_LAST_TTVN: Previous translation table version + */ + BATADV_ATTR_TT_LAST_TTVN, + + /** + * @BATADV_ATTR_TT_CRC32: CRC32 over translation table + */ + BATADV_ATTR_TT_CRC32, + + /** + * @BATADV_ATTR_TT_VID: VLAN ID + */ + BATADV_ATTR_TT_VID, + + /** + * @BATADV_ATTR_TT_FLAGS: Translation table client flags + */ + BATADV_ATTR_TT_FLAGS, + + /** + * @BATADV_ATTR_FLAG_BEST: Flags indicating entry is the best + */ + BATADV_ATTR_FLAG_BEST, + + /** + * @BATADV_ATTR_LAST_SEEN_MSECS: Time in milliseconds since last seen + */ + BATADV_ATTR_LAST_SEEN_MSECS, + + /** + * @BATADV_ATTR_NEIGH_ADDRESS: Neighbour MAC address + */ + BATADV_ATTR_NEIGH_ADDRESS, + + /** + * @BATADV_ATTR_TQ: TQ to neighbour + */ + BATADV_ATTR_TQ, + + /** + * @BATADV_ATTR_THROUGHPUT: Estimated throughput to Neighbour + */ + BATADV_ATTR_THROUGHPUT, + + /** + * @BATADV_ATTR_BANDWIDTH_UP: Reported uplink bandwidth + */ + BATADV_ATTR_BANDWIDTH_UP, + + /** + * @BATADV_ATTR_BANDWIDTH_DOWN: Reported downlink bandwidth + */ + BATADV_ATTR_BANDWIDTH_DOWN, + + /** + * @BATADV_ATTR_ROUTER: Gateway router MAC address + */ + BATADV_ATTR_ROUTER, + + /** + * @BATADV_ATTR_BLA_OWN: Flag indicating own originator + */ + BATADV_ATTR_BLA_OWN, + + /** + * @BATADV_ATTR_BLA_ADDRESS: Bridge loop avoidance claim MAC address + */ + BATADV_ATTR_BLA_ADDRESS, + + /** + * @BATADV_ATTR_BLA_VID: BLA VLAN ID + */ + BATADV_ATTR_BLA_VID, + + /** + * @BATADV_ATTR_BLA_BACKBONE: BLA gateway originator MAC address + */ + BATADV_ATTR_BLA_BACKBONE, + + /** + * @BATADV_ATTR_BLA_CRC: BLA CRC + */ + BATADV_ATTR_BLA_CRC, + + /** + * @BATADV_ATTR_DAT_CACHE_IP4ADDRESS: Client IPv4 address + */ + BATADV_ATTR_DAT_CACHE_IP4ADDRESS, + + /** + * @BATADV_ATTR_DAT_CACHE_HWADDRESS: Client MAC address + */ + BATADV_ATTR_DAT_CACHE_HWADDRESS, + + /** + * @BATADV_ATTR_DAT_CACHE_VID: VLAN ID + */ + BATADV_ATTR_DAT_CACHE_VID, + + /** + * @BATADV_ATTR_MCAST_FLAGS: Per originator multicast flags + */ + BATADV_ATTR_MCAST_FLAGS, + + /** + * @BATADV_ATTR_MCAST_FLAGS_PRIV: Private, own multicast flags + */ + BATADV_ATTR_MCAST_FLAGS_PRIV, + + /** + * @BATADV_ATTR_VLANID: VLAN id on top of soft interface + */ + BATADV_ATTR_VLANID, + + /** + * @BATADV_ATTR_AGGREGATED_OGMS_ENABLED: whether the batman protocol + * messages of the mesh interface shall be aggregated or not. + */ + BATADV_ATTR_AGGREGATED_OGMS_ENABLED, + + /** + * @BATADV_ATTR_AP_ISOLATION_ENABLED: whether the data traffic going + * from a wireless client to another wireless client will be silently + * dropped. + */ + BATADV_ATTR_AP_ISOLATION_ENABLED, + + /** + * @BATADV_ATTR_ISOLATION_MARK: the isolation mark which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MARK, + + /** + * @BATADV_ATTR_ISOLATION_MASK: the isolation (bit)mask which is used to + * classify clients as "isolated" by the Extended Isolation feature. + */ + BATADV_ATTR_ISOLATION_MASK, + + /** + * @BATADV_ATTR_BONDING_ENABLED: whether the data traffic going through + * the mesh will be sent using multiple interfaces at the same time. + */ + BATADV_ATTR_BONDING_ENABLED, + + /** + * @BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED: whether the bridge loop + * avoidance feature is enabled. This feature detects and avoids loops + * between the mesh and devices bridged with the soft interface + */ + BATADV_ATTR_BRIDGE_LOOP_AVOIDANCE_ENABLED, + + /** + * @BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED: whether the distributed + * arp table feature is enabled. This feature uses a distributed hash + * table to answer ARP requests without flooding the request through + * the whole mesh. + */ + BATADV_ATTR_DISTRIBUTED_ARP_TABLE_ENABLED, + + /** + * @BATADV_ATTR_FRAGMENTATION_ENABLED: whether the data traffic going + * through the mesh will be fragmented or silently discarded if the + * packet size exceeds the outgoing interface MTU. + */ + BATADV_ATTR_FRAGMENTATION_ENABLED, + + /** + * @BATADV_ATTR_GW_BANDWIDTH_DOWN: defines the download bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_DOWN, + + /** + * @BATADV_ATTR_GW_BANDWIDTH_UP: defines the upload bandwidth which + * is propagated by this node if %BATADV_ATTR_GW_BANDWIDTH_MODE was set + * to 'server'. + */ + BATADV_ATTR_GW_BANDWIDTH_UP, + + /** + * @BATADV_ATTR_GW_MODE: defines the state of the gateway features. + * Possible values are specified in enum batadv_gw_modes + */ + BATADV_ATTR_GW_MODE, + + /** + * @BATADV_ATTR_GW_SEL_CLASS: defines the selection criteria this node + * will use to choose a gateway if gw_mode was set to 'client'. + */ + BATADV_ATTR_GW_SEL_CLASS, + + /** + * @BATADV_ATTR_HOP_PENALTY: defines the penalty which will be applied + * to an originator message's tq-field on every hop and/or per + * hard interface + */ + BATADV_ATTR_HOP_PENALTY, + + /** + * @BATADV_ATTR_LOG_LEVEL: bitmask with to define which debug messages + * should be send to the debug log/trace ring buffer + */ + BATADV_ATTR_LOG_LEVEL, + + /** + * @BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED: whether multicast + * optimizations should be replaced by simple broadcast-like flooding + * of multicast packets. If set to non-zero then all nodes in the mesh + * are going to use classic flooding for any multicast packet with no + * optimizations. + */ + BATADV_ATTR_MULTICAST_FORCEFLOOD_ENABLED, + + /** + * @BATADV_ATTR_NETWORK_CODING_ENABLED: whether Network Coding (using + * some magic to send fewer wifi packets but still the same content) is + * enabled or not. + */ + BATADV_ATTR_NETWORK_CODING_ENABLED, + + /** + * @BATADV_ATTR_ORIG_INTERVAL: defines the interval in milliseconds in + * which batman sends its protocol messages. + */ + BATADV_ATTR_ORIG_INTERVAL, + + /** + * @BATADV_ATTR_ELP_INTERVAL: defines the interval in milliseconds in + * which batman emits probing packets for neighbor sensing (ELP). + */ + BATADV_ATTR_ELP_INTERVAL, + + /** + * @BATADV_ATTR_THROUGHPUT_OVERRIDE: defines the throughput value to be + * used by B.A.T.M.A.N. V when estimating the link throughput using + * this interface. If the value is set to 0 then batman-adv will try to + * estimate the throughput by itself. + */ + BATADV_ATTR_THROUGHPUT_OVERRIDE, + + /** + * @BATADV_ATTR_MULTICAST_FANOUT: defines the maximum number of packet + * copies that may be generated for a multicast-to-unicast conversion. + * Once this limit is exceeded distribution will fall back to broadcast. + */ + BATADV_ATTR_MULTICAST_FANOUT, + + /* add attributes above here, update the policy in netlink.c */ + + /** + * @__BATADV_ATTR_AFTER_LAST: internal use + */ + __BATADV_ATTR_AFTER_LAST, + + /** + * @NUM_BATADV_ATTR: total number of batadv_nl_attrs available + */ + NUM_BATADV_ATTR = __BATADV_ATTR_AFTER_LAST, + + /** + * @BATADV_ATTR_MAX: highest attribute number currently defined + */ + BATADV_ATTR_MAX = __BATADV_ATTR_AFTER_LAST - 1 +}; + +/** + * enum batadv_nl_commands - supported batman-adv netlink commands + */ +enum batadv_nl_commands { + /** + * @BATADV_CMD_UNSPEC: unspecified command to catch errors + */ + BATADV_CMD_UNSPEC, + + /** + * @BATADV_CMD_GET_MESH: Get attributes from softif/mesh + */ + BATADV_CMD_GET_MESH, + + /** + * @BATADV_CMD_GET_MESH_INFO: Alias for @BATADV_CMD_GET_MESH + */ + BATADV_CMD_GET_MESH_INFO = BATADV_CMD_GET_MESH, + + /** + * @BATADV_CMD_TP_METER: Start a tp meter session + */ + BATADV_CMD_TP_METER, + + /** + * @BATADV_CMD_TP_METER_CANCEL: Cancel a tp meter session + */ + BATADV_CMD_TP_METER_CANCEL, + + /** + * @BATADV_CMD_GET_ROUTING_ALGOS: Query the list of routing algorithms. + */ + BATADV_CMD_GET_ROUTING_ALGOS, + + /** + * @BATADV_CMD_GET_HARDIF: Get attributes from a hardif of the + * current softif + */ + BATADV_CMD_GET_HARDIF, + + /** + * @BATADV_CMD_GET_HARDIFS: Alias for @BATADV_CMD_GET_HARDIF + */ + BATADV_CMD_GET_HARDIFS = BATADV_CMD_GET_HARDIF, + + /** + * @BATADV_CMD_GET_TRANSTABLE_LOCAL: Query list of local translations + */ + BATADV_CMD_GET_TRANSTABLE_LOCAL, + + /** + * @BATADV_CMD_GET_TRANSTABLE_GLOBAL: Query list of global translations + */ + BATADV_CMD_GET_TRANSTABLE_GLOBAL, + + /** + * @BATADV_CMD_GET_ORIGINATORS: Query list of originators + */ + BATADV_CMD_GET_ORIGINATORS, + + /** + * @BATADV_CMD_GET_NEIGHBORS: Query list of neighbours + */ + BATADV_CMD_GET_NEIGHBORS, + + /** + * @BATADV_CMD_GET_GATEWAYS: Query list of gateways + */ + BATADV_CMD_GET_GATEWAYS, + + /** + * @BATADV_CMD_GET_BLA_CLAIM: Query list of bridge loop avoidance claims + */ + BATADV_CMD_GET_BLA_CLAIM, + + /** + * @BATADV_CMD_GET_BLA_BACKBONE: Query list of bridge loop avoidance + * backbones + */ + BATADV_CMD_GET_BLA_BACKBONE, + + /** + * @BATADV_CMD_GET_DAT_CACHE: Query list of DAT cache entries + */ + BATADV_CMD_GET_DAT_CACHE, + + /** + * @BATADV_CMD_GET_MCAST_FLAGS: Query list of multicast flags + */ + BATADV_CMD_GET_MCAST_FLAGS, + + /** + * @BATADV_CMD_SET_MESH: Set attributes for softif/mesh + */ + BATADV_CMD_SET_MESH, + + /** + * @BATADV_CMD_SET_HARDIF: Set attributes for hardif of the + * current softif + */ + BATADV_CMD_SET_HARDIF, + + /** + * @BATADV_CMD_GET_VLAN: Get attributes from a VLAN of the + * current softif + */ + BATADV_CMD_GET_VLAN, + + /** + * @BATADV_CMD_SET_VLAN: Set attributes for VLAN of the + * current softif + */ + BATADV_CMD_SET_VLAN, + + /* add new commands above here */ + + /** + * @__BATADV_CMD_AFTER_LAST: internal use + */ + __BATADV_CMD_AFTER_LAST, + + /** + * @BATADV_CMD_MAX: highest used command number + */ + BATADV_CMD_MAX = __BATADV_CMD_AFTER_LAST - 1 +}; + +/** + * enum batadv_tp_meter_reason - reason of a tp meter test run stop + */ +enum batadv_tp_meter_reason { + /** + * @BATADV_TP_REASON_COMPLETE: sender finished tp run + */ + BATADV_TP_REASON_COMPLETE = 3, + + /** + * @BATADV_TP_REASON_CANCEL: sender was stopped during run + */ + BATADV_TP_REASON_CANCEL = 4, + + /* error status >= 128 */ + + /** + * @BATADV_TP_REASON_DST_UNREACHABLE: receiver could not be reached or + * didn't answer + */ + BATADV_TP_REASON_DST_UNREACHABLE = 128, + + /** + * @BATADV_TP_REASON_RESEND_LIMIT: (unused) sender retry reached limit + */ + BATADV_TP_REASON_RESEND_LIMIT = 129, + + /** + * @BATADV_TP_REASON_ALREADY_ONGOING: test to or from the same node + * already ongoing + */ + BATADV_TP_REASON_ALREADY_ONGOING = 130, + + /** + * @BATADV_TP_REASON_MEMORY_ERROR: test was stopped due to low memory + */ + BATADV_TP_REASON_MEMORY_ERROR = 131, + + /** + * @BATADV_TP_REASON_CANT_SEND: failed to send via outgoing interface + */ + BATADV_TP_REASON_CANT_SEND = 132, + + /** + * @BATADV_TP_REASON_TOO_MANY: too many ongoing sessions + */ + BATADV_TP_REASON_TOO_MANY = 133, +}; + +/** + * enum batadv_ifla_attrs - batman-adv ifla nested attributes + */ +enum batadv_ifla_attrs { + /** + * @IFLA_BATADV_UNSPEC: unspecified attribute which is not parsed by + * rtnetlink + */ + IFLA_BATADV_UNSPEC, + + /** + * @IFLA_BATADV_ALGO_NAME: routing algorithm (name) which should be + * used by the newly registered batadv net_device. + */ + IFLA_BATADV_ALGO_NAME, + + /* add attributes above here, update the policy in soft-interface.c */ + + /** + * @__IFLA_BATADV_MAX: internal use + */ + __IFLA_BATADV_MAX, +}; + +#define IFLA_BATADV_MAX (__IFLA_BATADV_MAX - 1) + +#endif /* _LINUX_BATMAN_ADV_H_ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/bpf.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/bpf.h
Changed
@@ -87,10 +87,35 @@ __u32 attach_type; /* program attach type (enum bpf_attach_type) */ }; +enum bpf_cgroup_iter_order { + BPF_CGROUP_ITER_ORDER_UNSPEC = 0, + BPF_CGROUP_ITER_SELF_ONLY, /* process only a single object. */ + BPF_CGROUP_ITER_DESCENDANTS_PRE, /* walk descendants in pre-order. */ + BPF_CGROUP_ITER_DESCENDANTS_POST, /* walk descendants in post-order. */ + BPF_CGROUP_ITER_ANCESTORS_UP, /* walk ancestors upward. */ +}; + union bpf_iter_link_info { struct { __u32 map_fd; } map; + struct { + enum bpf_cgroup_iter_order order; + + /* At most one of cgroup_fd and cgroup_id can be non-zero. If + * both are zero, the walk starts from the default cgroup v2 + * root. For walking v1 hierarchy, one should always explicitly + * specify cgroup_fd. + */ + __u32 cgroup_fd; + __u64 cgroup_id; + } cgroup; + /* Parameters of task iterators. */ + struct { + __u32 tid; + __u32 pid; + __u32 pid_fd; + } task; }; /* BPF syscall commands, see bpf(2) man-page for more details. */ @@ -330,6 +355,8 @@ * *ctx_out*, *data_in* and *data_out* must be NULL. * *repeat* must be zero. * + * BPF_PROG_RUN is an alias for BPF_PROG_TEST_RUN. + * * Return * Returns zero on success. On error, -1 is returned and *errno* * is set appropriately. @@ -906,6 +933,8 @@ BPF_MAP_TYPE_RINGBUF, BPF_MAP_TYPE_INODE_STORAGE, BPF_MAP_TYPE_TASK_STORAGE, + BPF_MAP_TYPE_BLOOM_FILTER, + BPF_MAP_TYPE_USER_RINGBUF, }; /* Note that tracing related programs such as @@ -994,6 +1023,8 @@ BPF_SK_REUSEPORT_SELECT, BPF_SK_REUSEPORT_SELECT_OR_MIGRATE, BPF_PERF_EVENT, + BPF_TRACE_KPROBE_MULTI, + BPF_LSM_CGROUP, __MAX_BPF_ATTACH_TYPE }; @@ -1008,6 +1039,8 @@ BPF_LINK_TYPE_NETNS = 5, BPF_LINK_TYPE_XDP = 6, BPF_LINK_TYPE_PERF_EVENT = 7, + BPF_LINK_TYPE_KPROBE_MULTI = 8, + BPF_LINK_TYPE_STRUCT_OPS = 9, MAX_BPF_LINK_TYPE, }; @@ -1110,6 +1143,16 @@ */ #define BPF_F_SLEEPABLE (1U << 4) +/* If BPF_F_XDP_HAS_FRAGS is used in BPF_PROG_LOAD command, the loaded program + * fully support xdp frags. + */ +#define BPF_F_XDP_HAS_FRAGS (1U << 5) + +/* link_create.kprobe_multi.flags used in LINK_CREATE command for + * BPF_TRACE_KPROBE_MULTI attach type to create return probe. + */ +#define BPF_F_KPROBE_MULTI_RETURN (1U << 0) + /* When BPF ldimm64's insn0.src_reg != 0 then this can have * the following extensions: * @@ -1216,7 +1259,7 @@ /* Query effective (directly attached + inherited from ancestor cgroups) * programs that will be executed for events within a cgroup. - * attach_flags with this flag are returned only for directly attached programs. + * attach_flags with this flag are always returned 0. */ #define BPF_F_QUERY_EFFECTIVE (1U << 0) @@ -1224,6 +1267,8 @@ /* If set, run the test on the cpu specified by bpf_attr.test.cpu */ #define BPF_F_TEST_RUN_ON_CPU (1U << 0) +/* If set, XDP frames will be transmitted after processing */ +#define BPF_F_TEST_XDP_LIVE_FRAMES (1U << 1) /* type for BPF_ENABLE_STATS */ enum bpf_stats_type { @@ -1274,6 +1319,13 @@ * struct stored as the * map value */ + /* Any per-map-type extra fields + * + * BPF_MAP_TYPE_BLOOM_FILTER - the lowest 4 bits indicate the + * number of hash functions (if 0, the bloom filter will default + * to using 5 hash functions). + */ + __u64 map_extra; }; struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */ @@ -1334,8 +1386,10 @@ /* or valid module BTF object fd or 0 to attach to vmlinux */ __u32 attach_btf_obj_fd; }; - __u32 :32; /* pad */ + __u32 core_relo_cnt; /* number of bpf_core_relo */ __aligned_u64 fd_array; /* array of FDs */ + __aligned_u64 core_relos; + __u32 core_relo_rec_size; /* sizeof(struct bpf_core_relo) */ }; struct { /* anonymous struct used by BPF_OBJ_* commands */ @@ -1376,6 +1430,7 @@ __aligned_u64 ctx_out; __u32 flags; __u32 cpu; + __u32 batch_size; } test; struct { /* anonymous struct used by BPF_*_GET_*_ID */ @@ -1403,6 +1458,10 @@ __u32 attach_flags; __aligned_u64 prog_ids; __u32 prog_cnt; + /* output: per-program attach_flags. + * not allowed to be set during effective query. + */ + __aligned_u64 prog_attach_flags; } query; struct { /* anonymous struct used by BPF_RAW_TRACEPOINT_OPEN command */ @@ -1455,6 +1514,22 @@ */ __u64 bpf_cookie; } perf_event; + struct { + __u32 flags; + __u32 cnt; + __aligned_u64 syms; + __aligned_u64 addrs; + __aligned_u64 cookies; + } kprobe_multi; + struct { + /* this is overlaid with the target_btf_id above. */ + __u32 target_btf_id; + /* black box user-provided value passed through + * to BPF program at the execution time and + * accessible through bpf_get_attach_cookie() BPF helper + */ + __u64 cookie; + } tracing; }; } link_create; @@ -1629,7 +1704,7 @@ * u32 bpf_get_smp_processor_id(void) * Description * Get the SMP (symmetric multiprocessing) processor id. Note that - * all programs run with preemption disabled, which means that the + * all programs run with migration disabled, which means that the * SMP processor id is stable during all the execution of the * program. * Return @@ -1736,7 +1811,7 @@ * if the maximum number of tail calls has been reached for this * chain of programs. This limit is defined in the kernel by the * macro **MAX_TAIL_CALL_CNT** (not accessible to user space), - * which is currently set to 32. + * which is currently set to 33. * Return * 0 on success, or a negative error in case of failure. * @@ -1765,6 +1840,8 @@ * 0 on success, or a negative error in case of failure. * * u64 bpf_get_current_pid_tgid(void) + * Description + * Get the current pid and tgid. * Return * A 64-bit integer containing the current tgid and pid, and * created as such: @@ -1772,6 +1849,8 @@ * *current_task*\ **->pid**. * * u64 bpf_get_current_uid_gid(void) + * Description + * Get the current uid and gid. * Return * A 64-bit integer containing the current GID and UID, and * created as such: *current_gid* **<< 32 \|** *current_uid*. @@ -2246,6 +2325,8 @@ * The 32-bit hash. * * u64 bpf_get_current_task(void) + * Description + * Get the current task. * Return * A pointer to the current task struct. * @@ -2276,8 +2357,8 @@ * Return * The return value depends on the result of the test, and can be: * - * * 0, if current task belongs to the cgroup2. - * * 1, if current task does not belong to the cgroup2. + * * 1, if current task belongs to the cgroup2. + * * 0, if current task does not belong to the cgroup2. * * A negative error code, if an error occurred. * * long bpf_skb_change_tail(struct sk_buff *skb, u32 len, u64 flags) @@ -2309,7 +2390,8 @@ * Pull in non-linear data in case the *skb* is non-linear and not * all of *len* are part of the linear section. Make *len* bytes * from *skb* readable and writable. If a zero value is passed for - * *len*, then the whole length of the *skb* is pulled. + * *len*, then all bytes in the linear part of *skb* will be made + * readable and writable. * * This helper is only needed for reading and writing with direct * packet access. @@ -2359,6 +2441,8 @@ * indicate that the hash is outdated and to trigger a * recalculation the next time the kernel tries to access this * hash or when the **bpf_get_hash_recalc**\ () helper is called. + * Return + * void. * * long bpf_get_numa_node_id(void) * Description @@ -2456,6 +2540,8 @@ * A 8-byte long unique number or 0 if *sk* is NULL. * * u32 bpf_get_socket_uid(struct sk_buff *skb) + * Description + * Get the owner UID of the socked associated to *skb*. * Return * The owner UID of the socket associated to *skb*. If the socket * is **NULL**, or if it is not a full socket (i.e. if it is a @@ -2516,10 +2602,12 @@ * There are two supported modes at this time: * * * **BPF_ADJ_ROOM_MAC**: Adjust room at the mac layer - * (room space is added or removed below the layer 2 header). + * (room space is added or removed between the layer 2 and + * layer 3 headers). * * * **BPF_ADJ_ROOM_NET**: Adjust room at the network layer - * (room space is added or removed below the layer 3 header). + * (room space is added or removed between the layer 3 and + * layer 4 headers). * * The following flags are supported at this time: * @@ -2951,8 +3039,18 @@ * **BPF_F_USER_STACK** * Collect a user space stack instead of a kernel stack. * **BPF_F_USER_BUILD_ID** - * Collect buildid+offset instead of ips for user stack, - * only valid if **BPF_F_USER_STACK** is also specified. + * Collect (build_id, file_offset) instead of ips for user + * stack, only valid if **BPF_F_USER_STACK** is also + * specified. + * + * *file_offset* is an offset relative to the beginning + * of the executable or shared object file backing the vma + * which the *ip* falls in. It is *not* an offset relative + * to that object's base address. Accordingly, it must be + * adjusted by adding (sh_addr - sh_offset), where + * sh_{addr,offset} correspond to the executable section + * containing *file_offset* in the object, for comparisons + * to symbols' st_value to be valid. * * **bpf_get_stack**\ () can collect up to * **PERF_MAX_STACK_DEPTH** both kernel and user frames, subject @@ -2965,8 +3063,8 @@ * * # sysctl kernel.perf_event_max_stack=<new value> * Return - * A non-negative value equal to or less than *size* on success, - * or a negative error in case of failure. + * The non-negative copied *buf* length equal to or less than + * *size* on success, or a negative error in case of failure. * * long bpf_skb_load_bytes_relative(const void *skb, u32 offset, void *to, u32 len, u32 start_header) * Description @@ -3230,6 +3328,9 @@ * The id is returned or 0 in case the id could not be retrieved. * * u64 bpf_get_current_cgroup_id(void) + * Description + * Get the current cgroup id based on the cgroup within which + * the current task is running. * Return * A 64-bit integer containing the current cgroup id based * on the cgroup within which the current task is running. @@ -3540,10 +3641,11 @@ * * *iph* points to the start of the IPv4 or IPv6 header, while * *iph_len* contains **sizeof**\ (**struct iphdr**) or - * **sizeof**\ (**struct ip6hdr**). + * **sizeof**\ (**struct ipv6hdr**). * * *th* points to the start of the TCP header, while *th_len* - * contains **sizeof**\ (**struct tcphdr**). + * contains the length of the TCP header (at least + * **sizeof**\ (**struct tcphdr**)). * Return * 0 if *iph* and *th* are a valid SYN cookie ACK, or a negative * error otherwise. @@ -3726,10 +3828,11 @@ * * *iph* points to the start of the IPv4 or IPv6 header, while * *iph_len* contains **sizeof**\ (**struct iphdr**) or - * **sizeof**\ (**struct ip6hdr**). + * **sizeof**\ (**struct ipv6hdr**). * * *th* points to the start of the TCP header, while *th_len* - * contains the length of the TCP header. + * contains the length of the TCP header with options (at least + * **sizeof**\ (**struct tcphdr**)). * Return * On success, lower 32 bits hold the generated SYN cookie in * followed by 16 bits which hold the MSS value for that cookie, @@ -4046,7 +4149,7 @@ * arguments. The *data* are a **u64** array and corresponding format string * values are stored in the array. For strings and pointers where pointees * are accessed, only the pointer values are stored in the *data* array. - * The *data_len* is the size of *data* in bytes. + * The *data_len* is the size of *data* in bytes - must be a multiple of 8. * * Formats **%s**, **%p{i,I}{4,6}** requires to read kernel memory. * Reading kernel memory may fail due to either invalid address or @@ -4269,8 +4372,8 @@ * * # sysctl kernel.perf_event_max_stack=<new value> * Return - * A non-negative value equal to or less than *size* on success, - * or a negative error in case of failure. + * The non-negative copied *buf* length equal to or less than + * *size* on success, or a negative error in case of failure. * * long bpf_load_hdr_opt(struct bpf_sock_ops *skops, void *searchby_res, u32 len, u64 flags) * Description @@ -4363,7 +4466,7 @@ * * **-EEXIST** if the option already exists. * - * **-EFAULT** on failrue to parse the existing header options. + * **-EFAULT** on failure to parse the existing header options. * * **-EPERM** if the helper cannot be used under the current * *skops*\ **->op**. @@ -4572,7 +4675,7 @@ * a *map* with *task* as the **key**. From this * perspective, the usage is not much different from * **bpf_map_lookup_elem**\ (*map*, **&**\ *task*) except this - * helper enforces the key must be an task_struct and the map must also + * helper enforces the key must be a task_struct and the map must also * be a **BPF_MAP_TYPE_TASK_STORAGE**. * * Underneath, the value is stored locally at *task* instead of @@ -4630,7 +4733,7 @@ * * long bpf_ima_inode_hash(struct inode *inode, void *dst, u32 size) * Description - * Returns the stored IMA hash of the *inode* (if it's avaialable). + * Returns the stored IMA hash of the *inode* (if it's available). * If the hash is larger than *size*, then only *size* * bytes will be copied to *dst* * Return @@ -4654,12 +4757,12 @@ * * The argument *len_diff* can be used for querying with a planned * size change. This allows to check MTU prior to changing packet - * ctx. Providing an *len_diff* adjustment that is larger than the + * ctx. Providing a *len_diff* adjustment that is larger than the * actual packet size (resulting in negative packet size) will in - * principle not exceed the MTU, why it is not considered a - * failure. Other BPF-helpers are needed for performing the - * planned size change, why the responsability for catch a negative - * packet size belong in those helpers. + * principle not exceed the MTU, which is why it is not considered + * a failure. Other BPF helpers are needed for performing the + * planned size change; therefore the responsibility for catching + * a negative packet size belongs in those helpers. * * Specifying *ifindex* zero means the MTU check is performed * against the current net device. This is practical if this isn't @@ -4751,7 +4854,8 @@ * Each format specifier in **fmt** corresponds to one u64 element * in the **data** array. For strings and pointers where pointees * are accessed, only the pointer values are stored in the *data* - * array. The *data_len* is the size of *data* in bytes. + * array. The *data_len* is the size of *data* in bytes - must be + * a multiple of 8. * * Formats **%s** and **%p{i,I}{4,6}** require to read kernel * memory. Reading kernel memory may fail due to either invalid @@ -4856,6 +4960,7 @@ * Get address of the traced function (for tracing and kprobe programs). * Return * Address of the traced function. + * 0 for kprobes placed within the function (not at the entry). * * u64 bpf_get_attach_cookie(void *ctx) * Description @@ -4877,6 +4982,459 @@ * Get the struct pt_regs associated with **task**. * Return * A pointer to struct pt_regs. + * + * long bpf_get_branch_snapshot(void *entries, u32 size, u64 flags) + * Description + * Get branch trace from hardware engines like Intel LBR. The + * hardware engine is stopped shortly after the helper is + * called. Therefore, the user need to filter branch entries + * based on the actual use case. To capture branch trace + * before the trigger point of the BPF program, the helper + * should be called at the beginning of the BPF program. + * + * The data is stored as struct perf_branch_entry into output + * buffer *entries*. *size* is the size of *entries* in bytes. + * *flags* is reserved for now and must be zero. + * + * Return + * On success, number of bytes written to *buf*. On error, a + * negative value. + * + * **-EINVAL** if *flags* is not zero. + * + * **-ENOENT** if architecture does not support branch records. + * + * long bpf_trace_vprintk(const char *fmt, u32 fmt_size, const void *data, u32 data_len) + * Description + * Behaves like **bpf_trace_printk**\ () helper, but takes an array of u64 + * to format and can handle more format args as a result. + * + * Arguments are to be used as in **bpf_seq_printf**\ () helper. + * Return + * The number of bytes written to the buffer, or a negative error + * in case of failure. + * + * struct unix_sock *bpf_skc_to_unix_sock(void *sk) + * Description + * Dynamically cast a *sk* pointer to a *unix_sock* pointer. + * Return + * *sk* if casting is valid, or **NULL** otherwise. + * + * long bpf_kallsyms_lookup_name(const char *name, int name_sz, int flags, u64 *res) + * Description + * Get the address of a kernel symbol, returned in *res*. *res* is + * set to 0 if the symbol is not found. + * Return + * On success, zero. On error, a negative value. + * + * **-EINVAL** if *flags* is not zero. + * + * **-EINVAL** if string *name* is not the same size as *name_sz*. + * + * **-ENOENT** if symbol is not found. + * + * **-EPERM** if caller does not have permission to obtain kernel address. + * + * long bpf_find_vma(struct task_struct *task, u64 addr, void *callback_fn, void *callback_ctx, u64 flags) + * Description + * Find vma of *task* that contains *addr*, call *callback_fn* + * function with *task*, *vma*, and *callback_ctx*. + * The *callback_fn* should be a static function and + * the *callback_ctx* should be a pointer to the stack. + * The *flags* is used to control certain aspects of the helper. + * Currently, the *flags* must be 0. + * + * The expected callback signature is + * + * long (\*callback_fn)(struct task_struct \*task, struct vm_area_struct \*vma, void \*callback_ctx); + * + * Return + * 0 on success. + * **-ENOENT** if *task->mm* is NULL, or no vma contains *addr*. + * **-EBUSY** if failed to try lock mmap_lock. + * **-EINVAL** for invalid **flags**. + * + * long bpf_loop(u32 nr_loops, void *callback_fn, void *callback_ctx, u64 flags) + * Description + * For **nr_loops**, call **callback_fn** function + * with **callback_ctx** as the context parameter. + * The **callback_fn** should be a static function and + * the **callback_ctx** should be a pointer to the stack. + * The **flags** is used to control certain aspects of the helper. + * Currently, the **flags** must be 0. Currently, nr_loops is + * limited to 1 << 23 (~8 million) loops. + * + * long (\*callback_fn)(u32 index, void \*ctx); + * + * where **index** is the current index in the loop. The index + * is zero-indexed. + * + * If **callback_fn** returns 0, the helper will continue to the next + * loop. If return value is 1, the helper will skip the rest of + * the loops and return. Other return values are not used now, + * and will be rejected by the verifier. + * + * Return + * The number of loops performed, **-EINVAL** for invalid **flags**, + * **-E2BIG** if **nr_loops** exceeds the maximum number of loops. + * + * long bpf_strncmp(const char *s1, u32 s1_sz, const char *s2) + * Description + * Do strncmp() between **s1** and **s2**. **s1** doesn't need + * to be null-terminated and **s1_sz** is the maximum storage + * size of **s1**. **s2** must be a read-only string. + * Return + * An integer less than, equal to, or greater than zero + * if the first **s1_sz** bytes of **s1** is found to be + * less than, to match, or be greater than **s2**. + * + * long bpf_get_func_arg(void *ctx, u32 n, u64 *value) + * Description + * Get **n**-th argument register (zero based) of the traced function (for tracing programs) + * returned in **value**. + * + * Return + * 0 on success. + * **-EINVAL** if n >= argument register count of traced function. + * + * long bpf_get_func_ret(void *ctx, u64 *value) + * Description + * Get return value of the traced function (for tracing programs) + * in **value**. + * + * Return + * 0 on success. + * **-EOPNOTSUPP** for tracing programs other than BPF_TRACE_FEXIT or BPF_MODIFY_RETURN. + * + * long bpf_get_func_arg_cnt(void *ctx) + * Description + * Get number of registers of the traced function (for tracing programs) where + * function arguments are stored in these registers. + * + * Return + * The number of argument registers of the traced function. + * + * int bpf_get_retval(void) + * Description + * Get the BPF program's return value that will be returned to the upper layers. + * + * This helper is currently supported by cgroup programs and only by the hooks + * where BPF program's return value is returned to the userspace via errno. + * Return + * The BPF program's return value. + * + * int bpf_set_retval(int retval) + * Description + * Set the BPF program's return value that will be returned to the upper layers. + * + * This helper is currently supported by cgroup programs and only by the hooks + * where BPF program's return value is returned to the userspace via errno. + * + * Note that there is the following corner case where the program exports an error + * via bpf_set_retval but signals success via 'return 1': + * + * bpf_set_retval(-EPERM); + * return 1; + * + * In this case, the BPF program's return value will use helper's -EPERM. This + * still holds true for cgroup/bind{4,6} which supports extra 'return 3' success case. + * + * Return + * 0 on success, or a negative error in case of failure. + * + * u64 bpf_xdp_get_buff_len(struct xdp_buff *xdp_md) + * Description + * Get the total size of a given xdp buff (linear and paged area) + * Return + * The total size of a given xdp buffer. + * + * long bpf_xdp_load_bytes(struct xdp_buff *xdp_md, u32 offset, void *buf, u32 len) + * Description + * This helper is provided as an easy way to load data from a + * xdp buffer. It can be used to load *len* bytes from *offset* from + * the frame associated to *xdp_md*, into the buffer pointed by + * *buf*. + * Return + * 0 on success, or a negative error in case of failure. + * + * long bpf_xdp_store_bytes(struct xdp_buff *xdp_md, u32 offset, void *buf, u32 len) + * Description + * Store *len* bytes from buffer *buf* into the frame + * associated to *xdp_md*, at *offset*. + * Return + * 0 on success, or a negative error in case of failure. + * + * long bpf_copy_from_user_task(void *dst, u32 size, const void *user_ptr, struct task_struct *tsk, u64 flags) + * Description + * Read *size* bytes from user space address *user_ptr* in *tsk*'s + * address space, and stores the data in *dst*. *flags* is not + * used yet and is provided for future extensibility. This helper + * can only be used by sleepable programs. + * Return + * 0 on success, or a negative error in case of failure. On error + * *dst* buffer is zeroed out. + * + * long bpf_skb_set_tstamp(struct sk_buff *skb, u64 tstamp, u32 tstamp_type) + * Description + * Change the __sk_buff->tstamp_type to *tstamp_type* + * and set *tstamp* to the __sk_buff->tstamp together. + * + * If there is no need to change the __sk_buff->tstamp_type, + * the tstamp value can be directly written to __sk_buff->tstamp + * instead. + * + * BPF_SKB_TSTAMP_DELIVERY_MONO is the only tstamp that + * will be kept during bpf_redirect_*(). A non zero + * *tstamp* must be used with the BPF_SKB_TSTAMP_DELIVERY_MONO + * *tstamp_type*. + * + * A BPF_SKB_TSTAMP_UNSPEC *tstamp_type* can only be used + * with a zero *tstamp*. + * + * Only IPv4 and IPv6 skb->protocol are supported. + * + * This function is most useful when it needs to set a + * mono delivery time to __sk_buff->tstamp and then + * bpf_redirect_*() to the egress of an iface. For example, + * changing the (rcv) timestamp in __sk_buff->tstamp at + * ingress to a mono delivery time and then bpf_redirect_*() + * to sch_fq@phy-dev. + * Return + * 0 on success. + * **-EINVAL** for invalid input + * **-EOPNOTSUPP** for unsupported protocol + * + * long bpf_ima_file_hash(struct file *file, void *dst, u32 size) + * Description + * Returns a calculated IMA hash of the *file*. + * If the hash is larger than *size*, then only *size* + * bytes will be copied to *dst* + * Return + * The **hash_algo** is returned on success, + * **-EOPNOTSUP** if the hash calculation failed or **-EINVAL** if + * invalid arguments are passed. + * + * void *bpf_kptr_xchg(void *map_value, void *ptr) + * Description + * Exchange kptr at pointer *map_value* with *ptr*, and return the + * old value. *ptr* can be NULL, otherwise it must be a referenced + * pointer which will be released when this helper is called. + * Return + * The old value of kptr (which can be NULL). The returned pointer + * if not NULL, is a reference which must be released using its + * corresponding release function, or moved into a BPF map before + * program exit. + * + * void *bpf_map_lookup_percpu_elem(struct bpf_map *map, const void *key, u32 cpu) + * Description + * Perform a lookup in *percpu map* for an entry associated to + * *key* on *cpu*. + * Return + * Map value associated to *key* on *cpu*, or **NULL** if no entry + * was found or *cpu* is invalid. + * + * struct mptcp_sock *bpf_skc_to_mptcp_sock(void *sk) + * Description + * Dynamically cast a *sk* pointer to a *mptcp_sock* pointer. + * Return + * *sk* if casting is valid, or **NULL** otherwise. + * + * long bpf_dynptr_from_mem(void *data, u32 size, u64 flags, struct bpf_dynptr *ptr) + * Description + * Get a dynptr to local memory *data*. + * + * *data* must be a ptr to a map value. + * The maximum *size* supported is DYNPTR_MAX_SIZE. + * *flags* is currently unused. + * Return + * 0 on success, -E2BIG if the size exceeds DYNPTR_MAX_SIZE, + * -EINVAL if flags is not 0. + * + * long bpf_ringbuf_reserve_dynptr(void *ringbuf, u32 size, u64 flags, struct bpf_dynptr *ptr) + * Description + * Reserve *size* bytes of payload in a ring buffer *ringbuf* + * through the dynptr interface. *flags* must be 0. + * + * Please note that a corresponding bpf_ringbuf_submit_dynptr or + * bpf_ringbuf_discard_dynptr must be called on *ptr*, even if the + * reservation fails. This is enforced by the verifier. + * Return + * 0 on success, or a negative error in case of failure. + * + * void bpf_ringbuf_submit_dynptr(struct bpf_dynptr *ptr, u64 flags) + * Description + * Submit reserved ring buffer sample, pointed to by *data*, + * through the dynptr interface. This is a no-op if the dynptr is + * invalid/null. + * + * For more information on *flags*, please see + * 'bpf_ringbuf_submit'. + * Return + * Nothing. Always succeeds. + * + * void bpf_ringbuf_discard_dynptr(struct bpf_dynptr *ptr, u64 flags) + * Description + * Discard reserved ring buffer sample through the dynptr + * interface. This is a no-op if the dynptr is invalid/null. + * + * For more information on *flags*, please see + * 'bpf_ringbuf_discard'. + * Return + * Nothing. Always succeeds. + * + * long bpf_dynptr_read(void *dst, u32 len, struct bpf_dynptr *src, u32 offset, u64 flags) + * Description + * Read *len* bytes from *src* into *dst*, starting from *offset* + * into *src*. + * *flags* is currently unused. + * Return + * 0 on success, -E2BIG if *offset* + *len* exceeds the length + * of *src*'s data, -EINVAL if *src* is an invalid dynptr or if + * *flags* is not 0. + * + * long bpf_dynptr_write(struct bpf_dynptr *dst, u32 offset, void *src, u32 len, u64 flags) + * Description + * Write *len* bytes from *src* into *dst*, starting from *offset* + * into *dst*. + * *flags* is currently unused. + * Return + * 0 on success, -E2BIG if *offset* + *len* exceeds the length + * of *dst*'s data, -EINVAL if *dst* is an invalid dynptr or if *dst* + * is a read-only dynptr or if *flags* is not 0. + * + * void *bpf_dynptr_data(struct bpf_dynptr *ptr, u32 offset, u32 len) + * Description + * Get a pointer to the underlying dynptr data. + * + * *len* must be a statically known value. The returned data slice + * is invalidated whenever the dynptr is invalidated. + * Return + * Pointer to the underlying dynptr data, NULL if the dynptr is + * read-only, if the dynptr is invalid, or if the offset and length + * is out of bounds. + * + * s64 bpf_tcp_raw_gen_syncookie_ipv4(struct iphdr *iph, struct tcphdr *th, u32 th_len) + * Description + * Try to issue a SYN cookie for the packet with corresponding + * IPv4/TCP headers, *iph* and *th*, without depending on a + * listening socket. + * + * *iph* points to the IPv4 header. + * + * *th* points to the start of the TCP header, while *th_len* + * contains the length of the TCP header (at least + * **sizeof**\ (**struct tcphdr**)). + * Return + * On success, lower 32 bits hold the generated SYN cookie in + * followed by 16 bits which hold the MSS value for that cookie, + * and the top 16 bits are unused. + * + * On failure, the returned value is one of the following: + * + * **-EINVAL** if *th_len* is invalid. + * + * s64 bpf_tcp_raw_gen_syncookie_ipv6(struct ipv6hdr *iph, struct tcphdr *th, u32 th_len) + * Description + * Try to issue a SYN cookie for the packet with corresponding + * IPv6/TCP headers, *iph* and *th*, without depending on a + * listening socket. + * + * *iph* points to the IPv6 header. + * + * *th* points to the start of the TCP header, while *th_len* + * contains the length of the TCP header (at least + * **sizeof**\ (**struct tcphdr**)). + * Return + * On success, lower 32 bits hold the generated SYN cookie in + * followed by 16 bits which hold the MSS value for that cookie, + * and the top 16 bits are unused. + * + * On failure, the returned value is one of the following: + * + * **-EINVAL** if *th_len* is invalid. + * + * **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin. + * + * long bpf_tcp_raw_check_syncookie_ipv4(struct iphdr *iph, struct tcphdr *th) + * Description + * Check whether *iph* and *th* contain a valid SYN cookie ACK + * without depending on a listening socket. + * + * *iph* points to the IPv4 header. + * + * *th* points to the TCP header. + * Return + * 0 if *iph* and *th* are a valid SYN cookie ACK. + * + * On failure, the returned value is one of the following: + * + * **-EACCES** if the SYN cookie is not valid. + * + * long bpf_tcp_raw_check_syncookie_ipv6(struct ipv6hdr *iph, struct tcphdr *th) + * Description + * Check whether *iph* and *th* contain a valid SYN cookie ACK + * without depending on a listening socket. + * + * *iph* points to the IPv6 header. + * + * *th* points to the TCP header. + * Return + * 0 if *iph* and *th* are a valid SYN cookie ACK. + * + * On failure, the returned value is one of the following: + * + * **-EACCES** if the SYN cookie is not valid. + * + * **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin. + * + * u64 bpf_ktime_get_tai_ns(void) + * Description + * A nonsettable system-wide clock derived from wall-clock time but + * ignoring leap seconds. This clock does not experience + * discontinuities and backwards jumps caused by NTP inserting leap + * seconds as CLOCK_REALTIME does. + * + * See: **clock_gettime**\ (**CLOCK_TAI**) + * Return + * Current *ktime*. + * + * long bpf_user_ringbuf_drain(struct bpf_map *map, void *callback_fn, void *ctx, u64 flags) + * Description + * Drain samples from the specified user ring buffer, and invoke + * the provided callback for each such sample: + * + * long (\*callback_fn)(struct bpf_dynptr \*dynptr, void \*ctx); + * + * If **callback_fn** returns 0, the helper will continue to try + * and drain the next sample, up to a maximum of + * BPF_MAX_USER_RINGBUF_SAMPLES samples. If the return value is 1, + * the helper will skip the rest of the samples and return. Other + * return values are not used now, and will be rejected by the + * verifier. + * Return + * The number of drained samples if no error was encountered while + * draining samples, or 0 if no samples were present in the ring + * buffer. If a user-space producer was epoll-waiting on this map, + * and at least one sample was drained, they will receive an event + * notification notifying them of available space in the ring + * buffer. If the BPF_RB_NO_WAKEUP flag is passed to this + * function, no wakeup notification will be sent. If the + * BPF_RB_FORCE_WAKEUP flag is passed, a wakeup notification will + * be sent even if no sample was drained. + * + * On failure, the returned value is one of the following: + * + * **-EBUSY** if the ring buffer is contended, and another calling + * context was concurrently draining the ring buffer. + * + * **-EINVAL** if user-space is not properly tracking the ring + * buffer due to the producer position not being aligned to 8 + * bytes, a sample not being aligned to 8 bytes, or the producer + * position not matching the advertised length of a sample. + * + * **-E2BIG** if user-space has tried to publish a sample which is + * larger than the size of the ring buffer, or which cannot fit + * within a struct bpf_dynptr. */ #define __BPF_FUNC_MAPPER(FN) \ FN(unspec), \ @@ -5055,6 +5613,40 @@ FN(get_func_ip), \ FN(get_attach_cookie), \ FN(task_pt_regs), \ + FN(get_branch_snapshot), \ + FN(trace_vprintk), \ + FN(skc_to_unix_sock), \ + FN(kallsyms_lookup_name), \ + FN(find_vma), \ + FN(loop), \ + FN(strncmp), \ + FN(get_func_arg), \ + FN(get_func_ret), \ + FN(get_func_arg_cnt), \ + FN(get_retval), \ + FN(set_retval), \ + FN(xdp_get_buff_len), \ + FN(xdp_load_bytes), \ + FN(xdp_store_bytes), \ + FN(copy_from_user_task), \ + FN(skb_set_tstamp), \ + FN(ima_file_hash), \ + FN(kptr_xchg), \ + FN(map_lookup_percpu_elem), \ + FN(skc_to_mptcp_sock), \ + FN(dynptr_from_mem), \ + FN(ringbuf_reserve_dynptr), \ + FN(ringbuf_submit_dynptr), \ + FN(ringbuf_discard_dynptr), \ + FN(dynptr_read), \ + FN(dynptr_write), \ + FN(dynptr_data), \ + FN(tcp_raw_gen_syncookie_ipv4), \ + FN(tcp_raw_gen_syncookie_ipv6), \ + FN(tcp_raw_check_syncookie_ipv4), \ + FN(tcp_raw_check_syncookie_ipv6), \ + FN(ktime_get_tai_ns), \ + FN(user_ringbuf_drain), \ /* */ /* integer value in 'imm' field of BPF_CALL instruction selects which helper @@ -5117,6 +5709,11 @@ BPF_F_SEQ_NUMBER = (1ULL << 3), }; +/* BPF_FUNC_skb_get_tunnel_key flags. */ +enum { + BPF_F_TUNINFO_FLAGS = (1ULL << 4), +}; + /* BPF_FUNC_perf_event_output, BPF_FUNC_perf_event_read and * BPF_FUNC_perf_event_read_value flags. */ @@ -5244,6 +5841,15 @@ __u64 :64; \ } __attribute__((aligned(8))) +enum { + BPF_SKB_TSTAMP_UNSPEC, + BPF_SKB_TSTAMP_DELIVERY_MONO, /* tstamp has mono delivery time */ + /* For any BPF_SKB_TSTAMP_* that the bpf prog cannot handle, + * the bpf prog should handle it like BPF_SKB_TSTAMP_UNSPEC + * and try to deduce it by ingress, egress or skb->sk->sk_clockid. + */ +}; + /* user accessible mirror of in-kernel sk_buff. * new fields can only be added to the end of this structure */ @@ -5284,6 +5890,9 @@ __u32 gso_segs; __bpf_md_ptr(struct bpf_sock *, sk); __u32 gso_size; + __u8 tstamp_type; + __u32 :24; /* Padding, future use. */ + __u64 hwtstamp; }; struct bpf_tunnel_key { @@ -5294,8 +5903,15 @@ }; __u8 tunnel_tos; __u8 tunnel_ttl; - __u16 tunnel_ext; /* Padding, future use. */ + union { + __u16 tunnel_ext; /* compat */ + __be16 tunnel_flags; + }; __u32 tunnel_label; + union { + __u32 local_ipv4; + __u32 local_ipv64; + }; }; /* user accessible mirror of in-kernel xfrm_state. @@ -5334,6 +5950,11 @@ * represented by BPF_REDIRECT above). */ BPF_LWT_REROUTE = 128, + /* BPF_FLOW_DISSECTOR_CONTINUE: used by BPF_PROG_TYPE_FLOW_DISSECTOR + * to indicate that no custom dissection was performed, and + * fallback to standard dissector is requested. + */ + BPF_FLOW_DISSECTOR_CONTINUE = 129, }; struct bpf_sock { @@ -5347,7 +5968,8 @@ __u32 src_ip4; __u32 src_ip64; __u32 src_port; /* host byte order */ - __u32 dst_port; /* network byte order */ + __be16 dst_port; /* network byte order */ + __u16 :16; /* zero padding */ __u32 dst_ip4; __u32 dst_ip64; __u32 state; @@ -5577,6 +6199,9 @@ __u64 run_time_ns; __u64 run_cnt; __u64 recursion_misses; + __u32 verified_insns; + __u32 attach_btf_obj_id; + __u32 attach_btf_id; } __attribute__((aligned(8))); struct bpf_map_info { @@ -5594,6 +6219,8 @@ __u32 btf_id; __u32 btf_key_type_id; __u32 btf_value_type_id; + __u32 :32; /* alignment pad */ + __u64 map_extra; } __attribute__((aligned(8))); struct bpf_btf_info { @@ -5626,11 +6253,26 @@ struct { __aligned_u64 target_name; /* in/out: target_name buffer ptr */ __u32 target_name_len; /* in/out: target_name buffer len */ + + /* If the iter specific field is 32 bits, it can be put + * in the first or second union. Otherwise it should be + * put in the second union. + */ union { struct { __u32 map_id; } map; }; + union { + struct { + __u64 cgroup_id; + __u32 order; + } cgroup; + struct { + __u32 tid; + __u32 pid; + } task; + }; } iter; struct { __u32 netns_ino; @@ -6186,6 +6828,11 @@ __u64 :64; } __attribute__((aligned(8))); +struct bpf_dynptr { + __u64 :64; + __u64 :64; +} __attribute__((aligned(8))); + struct bpf_sysctl { __u32 write; /* Sysctl is being read (= 0) or written (= 1). * Allows 1,2,4-byte read, but no write. @@ -6222,10 +6869,12 @@ __u32 protocol; /* IP protocol (IPPROTO_TCP, IPPROTO_UDP) */ __u32 remote_ip4; /* Network byte order */ __u32 remote_ip64; /* Network byte order */ - __u32 remote_port; /* Network byte order */ + __be16 remote_port; /* Network byte order */ + __u16 :16; /* Zero padding */ __u32 local_ip4; /* Network byte order */ __u32 local_ip64; /* Network byte order */ __u32 local_port; /* Host byte order */ + __u32 ingress_ifindex; /* The arriving interface. Determined by inet_iif. */ }; /* @@ -6258,4 +6907,79 @@ BTF_F_ZERO = (1ULL << 3), }; +/* bpf_core_relo_kind encodes which aspect of captured field/type/enum value + * has to be adjusted by relocations. It is emitted by llvm and passed to + * libbpf and later to the kernel. + */ +enum bpf_core_relo_kind { + BPF_CORE_FIELD_BYTE_OFFSET = 0, /* field byte offset */ + BPF_CORE_FIELD_BYTE_SIZE = 1, /* field size in bytes */ + BPF_CORE_FIELD_EXISTS = 2, /* field existence in target kernel */ + BPF_CORE_FIELD_SIGNED = 3, /* field signedness (0 - unsigned, 1 - signed) */ + BPF_CORE_FIELD_LSHIFT_U64 = 4, /* bitfield-specific left bitshift */ + BPF_CORE_FIELD_RSHIFT_U64 = 5, /* bitfield-specific right bitshift */ + BPF_CORE_TYPE_ID_LOCAL = 6, /* type ID in local BPF object */ + BPF_CORE_TYPE_ID_TARGET = 7, /* type ID in target kernel */ + BPF_CORE_TYPE_EXISTS = 8, /* type existence in target kernel */ + BPF_CORE_TYPE_SIZE = 9, /* type size in bytes */ + BPF_CORE_ENUMVAL_EXISTS = 10, /* enum value existence in target kernel */ + BPF_CORE_ENUMVAL_VALUE = 11, /* enum value integer value */ + BPF_CORE_TYPE_MATCHES = 12, /* type match in target kernel */ +}; + +/* + * "struct bpf_core_relo" is used to pass relocation data form LLVM to libbpf + * and from libbpf to the kernel. + * + * CO-RE relocation captures the following data: + * - insn_off - instruction offset (in bytes) within a BPF program that needs + * its insn->imm field to be relocated with actual field info; + * - type_id - BTF type ID of the "root" (containing) entity of a relocatable + * type or field; + * - access_str_off - offset into corresponding .BTF string section. String + * interpretation depends on specific relocation kind: + * - for field-based relocations, string encodes an accessed field using + * a sequence of field and array indices, separated by colon (:). It's + * conceptually very close to LLVM's getelementptr (0) instruction's + * arguments for identifying offset to a field. + * - for type-based relocations, strings is expected to be just "0"; + * - for enum value-based relocations, string contains an index of enum + * value within its enum type; + * - kind - one of enum bpf_core_relo_kind; + * + * Example: + * struct sample { + * int a; + * struct { + * int b10; + * }; + * }; + * + * struct sample *s = ...; + * int *x = &s->a; // encoded as "0:0" (a is field #0) + * int *y = &s->b5; // encoded as "0:1:0:5" (anon struct is field #1, + * // b is field #0 inside anon struct, accessing elem #5) + * int *z = &s10->b; // encoded as "10:1" (ptr is used as an array) + * + * type_id for all relocs in this example will capture BTF type id of + * `struct sample`. + * + * Such relocation is emitted when using __builtin_preserve_access_index() + * Clang built-in, passing expression that captures field address, e.g.: + * + * bpf_probe_read(&dst, sizeof(dst), + * __builtin_preserve_access_index(&src->a.b.c)); + * + * In this case Clang will emit field relocation recording necessary data to + * be able to find offset of embedded `a.b.c` field within `src` struct. + * + * 0 https://llvm.org/docs/LangRef.html#getelementptr-instruction + */ +struct bpf_core_relo { + __u32 insn_off; + __u32 type_id; + __u32 access_str_off; + enum bpf_core_relo_kind kind; +}; + #endif /* __LINUX_BPF_H__ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/btf.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/btf.h
Changed
@@ -33,17 +33,17 @@ /* "info" bits arrangement * bits 0-15: vlen (e.g. # of struct's members) * bits 16-23: unused - * bits 24-27: kind (e.g. int, ptr, array...etc) - * bits 28-30: unused + * bits 24-28: kind (e.g. int, ptr, array...etc) + * bits 29-30: unused * bit 31: kind_flag, currently used by - * struct, union and fwd + * struct, union, enum, fwd and enum64 */ __u32 info; - /* "size" is used by INT, ENUM, STRUCT, UNION and DATASEC. + /* "size" is used by INT, ENUM, STRUCT, UNION, DATASEC and ENUM64. * "size" tells the size of the type it is describing. * * "type" is used by PTR, TYPEDEF, VOLATILE, CONST, RESTRICT, - * FUNC, FUNC_PROTO and VAR. + * FUNC, FUNC_PROTO, VAR, DECL_TAG and TYPE_TAG. * "type" is a type_id referring to another type. */ union { @@ -56,25 +56,31 @@ #define BTF_INFO_VLEN(info) ((info) & 0xffff) #define BTF_INFO_KFLAG(info) ((info) >> 31) -#define BTF_KIND_UNKN 0 /* Unknown */ -#define BTF_KIND_INT 1 /* Integer */ -#define BTF_KIND_PTR 2 /* Pointer */ -#define BTF_KIND_ARRAY 3 /* Array */ -#define BTF_KIND_STRUCT 4 /* Struct */ -#define BTF_KIND_UNION 5 /* Union */ -#define BTF_KIND_ENUM 6 /* Enumeration */ -#define BTF_KIND_FWD 7 /* Forward */ -#define BTF_KIND_TYPEDEF 8 /* Typedef */ -#define BTF_KIND_VOLATILE 9 /* Volatile */ -#define BTF_KIND_CONST 10 /* Const */ -#define BTF_KIND_RESTRICT 11 /* Restrict */ -#define BTF_KIND_FUNC 12 /* Function */ -#define BTF_KIND_FUNC_PROTO 13 /* Function Proto */ -#define BTF_KIND_VAR 14 /* Variable */ -#define BTF_KIND_DATASEC 15 /* Section */ -#define BTF_KIND_FLOAT 16 /* Floating point */ -#define BTF_KIND_MAX BTF_KIND_FLOAT -#define NR_BTF_KINDS (BTF_KIND_MAX + 1) +enum { + BTF_KIND_UNKN = 0, /* Unknown */ + BTF_KIND_INT = 1, /* Integer */ + BTF_KIND_PTR = 2, /* Pointer */ + BTF_KIND_ARRAY = 3, /* Array */ + BTF_KIND_STRUCT = 4, /* Struct */ + BTF_KIND_UNION = 5, /* Union */ + BTF_KIND_ENUM = 6, /* Enumeration up to 32-bit values */ + BTF_KIND_FWD = 7, /* Forward */ + BTF_KIND_TYPEDEF = 8, /* Typedef */ + BTF_KIND_VOLATILE = 9, /* Volatile */ + BTF_KIND_CONST = 10, /* Const */ + BTF_KIND_RESTRICT = 11, /* Restrict */ + BTF_KIND_FUNC = 12, /* Function */ + BTF_KIND_FUNC_PROTO = 13, /* Function Proto */ + BTF_KIND_VAR = 14, /* Variable */ + BTF_KIND_DATASEC = 15, /* Section */ + BTF_KIND_FLOAT = 16, /* Floating point */ + BTF_KIND_DECL_TAG = 17, /* Decl Tag */ + BTF_KIND_TYPE_TAG = 18, /* Type Tag */ + BTF_KIND_ENUM64 = 19, /* Enumeration up to 64-bit values */ + + NR_BTF_KINDS, + BTF_KIND_MAX = NR_BTF_KINDS - 1, +}; /* For some specific BTF_KIND, "struct btf_type" is immediately * followed by extra data. @@ -170,4 +176,25 @@ __u32 size; }; +/* BTF_KIND_DECL_TAG is followed by a single "struct btf_decl_tag" to describe + * additional information related to the tag applied location. + * If component_idx == -1, the tag is applied to a struct, union, + * variable or function. Otherwise, it is applied to a struct/union + * member or a func argument, and component_idx indicates which member + * or argument (0 ... vlen-1). + */ +struct btf_decl_tag { + __s32 component_idx; +}; + +/* BTF_KIND_ENUM64 is followed by multiple "struct btf_enum64". + * The exact number of btf_enum64 is stored in the vlen (of the + * info in "struct btf_type"). + */ +struct btf_enum64 { + __u32 name_off; + __u32 val_lo32; + __u32 val_hi32; +}; + #endif /* __LINUX_BTF_H__ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/can.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/can.h
Changed
@@ -48,6 +48,7 @@ #include <linux/types.h> #include <linux/socket.h> +#include <linux/stddef.h> /* for offsetof */ /* controller area network (CAN) kernel definitions */ @@ -60,6 +61,7 @@ #define CAN_SFF_MASK 0x000007FFU /* standard frame format (SFF) */ #define CAN_EFF_MASK 0x1FFFFFFFU /* extended frame format (EFF) */ #define CAN_ERR_MASK 0x1FFFFFFFU /* omit EFF, RTR, ERR flags */ +#define CANXL_PRIO_MASK CAN_SFF_MASK /* 11 bit priority mask */ /* * Controller Area Network Identifier structure @@ -73,6 +75,7 @@ #define CAN_SFF_ID_BITS 11 #define CAN_EFF_ID_BITS 29 +#define CANXL_PRIO_BITS CAN_SFF_ID_BITS /* * Controller Area Network Error Message Frame Mask structure @@ -91,6 +94,16 @@ #define CANFD_MAX_DLC 15 #define CANFD_MAX_DLEN 64 +/* + * CAN XL payload length and DLC definitions according to ISO 11898-1 + * CAN XL DLC ranges from 0 .. 2047 => data length from 1 .. 2048 byte + */ +#define CANXL_MIN_DLC 0 +#define CANXL_MAX_DLC 2047 +#define CANXL_MAX_DLC_MASK 0x07FF +#define CANXL_MIN_DLEN 1 +#define CANXL_MAX_DLEN 2048 + /** * struct can_frame - Classical CAN frame structure (aka CAN 2.0B) * @can_id: CAN ID of the frame and CAN_*_FLAG flags, see canid_t definition @@ -141,8 +154,8 @@ * When this is done the former differentiation via CAN_MTU / CANFD_MTU gets * lost. CANFD_FDF allows programmers to mark CAN FD frames in the case of * using struct canfd_frame for mixed CAN / CAN FD content (dual use). - * N.B. the Kernel APIs do NOT provide mixed CAN / CAN FD content inside of - * struct canfd_frame therefore the CANFD_FDF flag is disregarded by Linux. + * Since the introduction of CAN XL the CANFD_FDF flag is set in all CAN FD + * frame structures provided by the CAN subsystem of the Linux kernel. */ #define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ #define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ @@ -166,8 +179,46 @@ __u8 dataCANFD_MAX_DLEN __attribute__((aligned(8))); }; +/* + * defined bits for canxl_frame.flags + * + * The canxl_frame.flags element contains two bits CANXL_XLF and CANXL_SEC + * and shares the relative position of the struct canfd_frame.len element. + * The CANXL_XLF bit ALWAYS needs to be set to indicate a valid CAN XL frame. + * As a side effect setting this bit intentionally breaks the length checks + * for Classical CAN and CAN FD frames. + * + * Undefined bits in canxl_frame.flags are reserved and shall be set to zero. + */ +#define CANXL_XLF 0x80 /* mandatory CAN XL frame flag (must always be set!) */ +#define CANXL_SEC 0x01 /* Simple Extended Content (security/segmentation) */ + +/** + * struct canxl_frame - CAN with e'X'tended frame 'L'ength frame structure + * @prio: 11 bit arbitration priority with zero'ed CAN_*_FLAG flags + * @flags: additional flags for CAN XL + * @sdt: SDU (service data unit) type + * @len: frame payload length in byte (CANXL_MIN_DLEN .. CANXL_MAX_DLEN) + * @af: acceptance field + * @data: CAN XL frame payload (CANXL_MIN_DLEN .. CANXL_MAX_DLEN byte) + * + * @prio shares the same position as @can_id from struct canfd_frame. + */ +struct canxl_frame { + canid_t prio; /* 11 bit priority for arbitration (canid_t) */ + __u8 flags; /* additional flags for CAN XL */ + __u8 sdt; /* SDU (service data unit) type */ + __u16 len; /* frame payload length in byte */ + __u32 af; /* acceptance field */ + __u8 dataCANXL_MAX_DLEN; +}; + #define CAN_MTU (sizeof(struct can_frame)) #define CANFD_MTU (sizeof(struct canfd_frame)) +#define CANXL_MTU (sizeof(struct canxl_frame)) +#define CANXL_HDR_SIZE (offsetof(struct canxl_frame, data)) +#define CANXL_MIN_MTU (CANXL_HDR_SIZE + 64) +#define CANXL_MAX_MTU CANXL_MTU /* particular protocols of the protocol family PF_CAN */ #define CAN_RAW 1 /* RAW sockets */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/can/netlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/can/netlink.h
Changed
@@ -101,6 +101,8 @@ #define CAN_CTRLMODE_PRESUME_ACK 0x40 /* Ignore missing CAN ACKs */ #define CAN_CTRLMODE_FD_NON_ISO 0x80 /* CAN FD in non-ISO mode */ #define CAN_CTRLMODE_CC_LEN8_DLC 0x100 /* Classic CAN DLC option */ +#define CAN_CTRLMODE_TDC_AUTO 0x200 /* CAN transiver automatically calculates TDCV */ +#define CAN_CTRLMODE_TDC_MANUAL 0x400 /* TDCV is manually set up by user */ /* * CAN device statistics @@ -134,10 +136,48 @@ IFLA_CAN_BITRATE_CONST, IFLA_CAN_DATA_BITRATE_CONST, IFLA_CAN_BITRATE_MAX, - __IFLA_CAN_MAX + IFLA_CAN_TDC, + IFLA_CAN_CTRLMODE_EXT, + + /* add new constants above here */ + __IFLA_CAN_MAX, + IFLA_CAN_MAX = __IFLA_CAN_MAX - 1 }; -#define IFLA_CAN_MAX (__IFLA_CAN_MAX - 1) +/* + * CAN FD Transmitter Delay Compensation (TDC) + * + * Please refer to struct can_tdc_const and can_tdc in + * include/linux/can/bittiming.h for further details. + */ +enum { + IFLA_CAN_TDC_UNSPEC, + IFLA_CAN_TDC_TDCV_MIN, /* u32 */ + IFLA_CAN_TDC_TDCV_MAX, /* u32 */ + IFLA_CAN_TDC_TDCO_MIN, /* u32 */ + IFLA_CAN_TDC_TDCO_MAX, /* u32 */ + IFLA_CAN_TDC_TDCF_MIN, /* u32 */ + IFLA_CAN_TDC_TDCF_MAX, /* u32 */ + IFLA_CAN_TDC_TDCV, /* u32 */ + IFLA_CAN_TDC_TDCO, /* u32 */ + IFLA_CAN_TDC_TDCF, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_TDC, + IFLA_CAN_TDC_MAX = __IFLA_CAN_TDC - 1 +}; + +/* + * IFLA_CAN_CTRLMODE_EXT nest: controller mode extended parameters + */ +enum { + IFLA_CAN_CTRLMODE_UNSPEC, + IFLA_CAN_CTRLMODE_SUPPORTED, /* u32 */ + + /* add new constants above here */ + __IFLA_CAN_CTRLMODE, + IFLA_CAN_CTRLMODE_MAX = __IFLA_CAN_CTRLMODE - 1 +}; /* u16 termination range: 1..65535 Ohms */ #define CAN_TERMINATION_DISABLED 0
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/devlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/devlink.h
Changed
@@ -131,6 +131,14 @@ DEVLINK_CMD_RATE_NEW, DEVLINK_CMD_RATE_DEL, + DEVLINK_CMD_LINECARD_GET, /* can dump */ + DEVLINK_CMD_LINECARD_SET, + DEVLINK_CMD_LINECARD_NEW, + DEVLINK_CMD_LINECARD_DEL, + + DEVLINK_CMD_SELFTESTS_GET, /* can dump */ + DEVLINK_CMD_SELFTESTS_RUN, + /* add new commands above here */ __DEVLINK_CMD_MAX, DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 @@ -271,6 +279,30 @@ #define DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS \ (_BITUL(__DEVLINK_FLASH_OVERWRITE_MAX_BIT) - 1) +enum devlink_attr_selftest_id { + DEVLINK_ATTR_SELFTEST_ID_UNSPEC, + DEVLINK_ATTR_SELFTEST_ID_FLASH, /* flag */ + + __DEVLINK_ATTR_SELFTEST_ID_MAX, + DEVLINK_ATTR_SELFTEST_ID_MAX = __DEVLINK_ATTR_SELFTEST_ID_MAX - 1 +}; + +enum devlink_selftest_status { + DEVLINK_SELFTEST_STATUS_SKIP, + DEVLINK_SELFTEST_STATUS_PASS, + DEVLINK_SELFTEST_STATUS_FAIL +}; + +enum devlink_attr_selftest_result { + DEVLINK_ATTR_SELFTEST_RESULT_UNSPEC, + DEVLINK_ATTR_SELFTEST_RESULT, /* nested */ + DEVLINK_ATTR_SELFTEST_RESULT_ID, /* u32, enum devlink_attr_selftest_id */ + DEVLINK_ATTR_SELFTEST_RESULT_STATUS, /* u8, enum devlink_selftest_status */ + + __DEVLINK_ATTR_SELFTEST_RESULT_MAX, + DEVLINK_ATTR_SELFTEST_RESULT_MAX = __DEVLINK_ATTR_SELFTEST_RESULT_MAX - 1 +}; + /** * enum devlink_trap_action - Packet trap action. * @DEVLINK_TRAP_ACTION_DROP: Packet is dropped by the device and a copy is not @@ -338,6 +370,19 @@ #define DEVLINK_RELOAD_LIMITS_VALID_MASK (_BITUL(__DEVLINK_RELOAD_LIMIT_MAX) - 1) +enum devlink_linecard_state { + DEVLINK_LINECARD_STATE_UNSPEC, + DEVLINK_LINECARD_STATE_UNPROVISIONED, + DEVLINK_LINECARD_STATE_UNPROVISIONING, + DEVLINK_LINECARD_STATE_PROVISIONING, + DEVLINK_LINECARD_STATE_PROVISIONING_FAILED, + DEVLINK_LINECARD_STATE_PROVISIONED, + DEVLINK_LINECARD_STATE_ACTIVE, + + __DEVLINK_LINECARD_STATE_MAX, + DEVLINK_LINECARD_STATE_MAX = __DEVLINK_LINECARD_STATE_MAX - 1 +}; + enum devlink_attr { /* don't change the order or add anything between, this is ABI! */ DEVLINK_ATTR_UNSPEC, @@ -551,6 +596,17 @@ DEVLINK_ATTR_RATE_NODE_NAME, /* string */ DEVLINK_ATTR_RATE_PARENT_NODE_NAME, /* string */ + DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, /* u32 */ + + DEVLINK_ATTR_LINECARD_INDEX, /* u32 */ + DEVLINK_ATTR_LINECARD_STATE, /* u8 */ + DEVLINK_ATTR_LINECARD_TYPE, /* string */ + DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES, /* nested */ + + DEVLINK_ATTR_NESTED_DEVLINK, /* nested */ + + DEVLINK_ATTR_SELFTESTS, /* nested */ + /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/elf-em.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/elf-em.h
Changed
@@ -51,6 +51,7 @@ #define EM_RISCV 243 /* RISC-V */ #define EM_BPF 247 /* Linux BPF - in-kernel virtual machine */ #define EM_CSKY 252 /* C-SKY */ +#define EM_LOONGARCH 258 /* LoongArch */ #define EM_FRV 0x5441 /* Fujitsu FR-V */ /*
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/genetlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/genetlink.h
Changed
@@ -87,6 +87,8 @@ __CTRL_ATTR_MCAST_GRP_MAX, }; +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) + enum { CTRL_ATTR_POLICY_UNSPEC, CTRL_ATTR_POLICY_DO, @@ -96,7 +98,6 @@ CTRL_ATTR_POLICY_DUMP_MAX = __CTRL_ATTR_POLICY_DUMP_MAX - 1 }; -#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) - +#define CTRL_ATTR_POLICY_MAX (__CTRL_ATTR_POLICY_DUMP_MAX - 1) #endif /* __LINUX_GENERIC_NETLINK_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_addr.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_addr.h
Changed
@@ -33,8 +33,9 @@ IFA_CACHEINFO, IFA_MULTICAST, IFA_FLAGS, - IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ + IFA_RT_PRIORITY, /* u32, priority/metric for prefix route */ IFA_TARGET_NETNSID, + IFA_PROTO, /* u8, address protocol */ __IFA_MAX, }; @@ -67,4 +68,10 @@ #define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg)))) #define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg)) +/* ifa_proto */ +#define IFAPROT_UNSPEC 0 +#define IFAPROT_KERNEL_LO 1 /* loopback */ +#define IFAPROT_KERNEL_RA 2 /* set by kernel from router announcement */ +#define IFAPROT_KERNEL_LL 3 /* link-local set by kernel */ + #endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_alg.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_alg.h
Changed
@@ -42,7 +42,7 @@ struct af_alg_iv { __u32 ivlen; - __u8 iv0; + __u8 iv; }; /* Socket options */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_bridge.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_bridge.h
Changed
@@ -122,6 +122,7 @@ IFLA_BRIDGE_VLAN_TUNNEL_INFO, IFLA_BRIDGE_MRP, IFLA_BRIDGE_CFM, + IFLA_BRIDGE_MST, __IFLA_BRIDGE_MAX, }; #define IFLA_BRIDGE_MAX (__IFLA_BRIDGE_MAX - 1) @@ -453,6 +454,21 @@ #define IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX (__IFLA_BRIDGE_CFM_CC_PEER_STATUS_MAX - 1) +enum { + IFLA_BRIDGE_MST_UNSPEC, + IFLA_BRIDGE_MST_ENTRY, + __IFLA_BRIDGE_MST_MAX, +}; +#define IFLA_BRIDGE_MST_MAX (__IFLA_BRIDGE_MST_MAX - 1) + +enum { + IFLA_BRIDGE_MST_ENTRY_UNSPEC, + IFLA_BRIDGE_MST_ENTRY_MSTI, + IFLA_BRIDGE_MST_ENTRY_STATE, + __IFLA_BRIDGE_MST_ENTRY_MAX, +}; +#define IFLA_BRIDGE_MST_ENTRY_MAX (__IFLA_BRIDGE_MST_ENTRY_MAX - 1) + struct bridge_stp_xstats { __u64 transition_blk; __u64 transition_fwd; @@ -564,6 +580,7 @@ BRIDGE_VLANDB_GOPTS_MCAST_QUERIER, BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS, BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE, + BRIDGE_VLANDB_GOPTS_MSTI, __BRIDGE_VLANDB_GOPTS_MAX }; #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1) @@ -759,6 +776,7 @@ enum br_boolopt_id { BR_BOOLOPT_NO_LL_LEARN, BR_BOOLOPT_MCAST_VLAN_SNOOPING, + BR_BOOLOPT_MST_ENABLE, BR_BOOLOPT_MAX };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_ether.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_ether.h
Changed
@@ -86,7 +86,10 @@ * over Ethernet */ #define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#define ETH_P_PROFINET 0x8892 /* PROFINET */ +#define ETH_P_REALTEK 0x8899 /* Multiple proprietary protocols */ #define ETH_P_AOE 0x88A2 /* ATA over Ethernet */ +#define ETH_P_ETHERCAT 0x88A4 /* EtherCAT */ #define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */ #define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */ #define ETH_P_PREAUTH 0x88C7 /* 802.11 Preauthentication */ @@ -113,10 +116,11 @@ #define ETH_P_QINQ3 0x9300 /* deprecated QinQ VLAN NOT AN OFFICIALLY REGISTERED ID */ #define ETH_P_EDSA 0xDADA /* Ethertype DSA NOT AN OFFICIALLY REGISTERED ID */ #define ETH_P_DSA_8021Q 0xDADB /* Fake VLAN Header for DSA NOT AN OFFICIALLY REGISTERED ID */ +#define ETH_P_DSA_A5PSW 0xE001 /* A5PSW Tag Value NOT AN OFFICIALLY REGISTERED ID */ #define ETH_P_IFE 0xED3E /* ForCES inter-FE LFB type */ #define ETH_P_AF_IUCV 0xFBFB /* IBM af_iucv NOT AN OFFICIALLY REGISTERED ID */ -#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is less than this value +#define ETH_P_802_3_MIN 0x0600 /* If the value in the ethernet type is more than this value * then the frame is Ethernet II. Else it is 802.3 */ /* @@ -134,6 +138,7 @@ #define ETH_P_LOCALTALK 0x0009 /* Localtalk pseudo type */ #define ETH_P_CAN 0x000C /* CAN: Controller Area Network */ #define ETH_P_CANFD 0x000D /* CANFD: CAN flexible data rate*/ +#define ETH_P_CANXL 0x000E /* CANXL: eXtended frame Length */ #define ETH_P_PPPTALK 0x0010 /* Dummy type for Atalk over PPP*/ #define ETH_P_TR_802_2 0x0011 /* 802.2 frames */ #define ETH_P_MOBITEX 0x0015 /* Mobitex (kaz@cafe.net) */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_link.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_link.h
Changed
@@ -211,6 +211,9 @@ * @rx_nohandler: Number of packets received on the interface * but dropped by the networking stack because the device is * not designated to receive packets (e.g. backup link in a bond). + * + * @rx_otherhost_dropped: Number of packets dropped due to mismatch + * in destination MAC address. */ struct rtnl_link_stats64 { __u64 rx_packets; @@ -243,6 +246,23 @@ __u64 rx_compressed; __u64 tx_compressed; __u64 rx_nohandler; + + __u64 rx_otherhost_dropped; +}; + +/* Subset of link stats useful for in-HW collection. Meaning of the fields is as + * for struct rtnl_link_stats64. + */ +struct rtnl_hw_stats64 { + __u64 rx_packets; + __u64 tx_packets; + __u64 rx_bytes; + __u64 tx_bytes; + __u64 rx_errors; + __u64 tx_errors; + __u64 rx_dropped; + __u64 tx_dropped; + __u64 multicast; }; /* The struct should be in sync with struct ifmap */ @@ -347,6 +367,10 @@ */ IFLA_PARENT_DEV_NAME, IFLA_PARENT_DEV_BUS_NAME, + IFLA_GRO_MAX_SIZE, + IFLA_TSO_MAX_SIZE, + IFLA_TSO_MAX_SEGS, + IFLA_ALLMULTI, /* Allmulti count: > 0 means acts ALLMULTI */ __IFLA_MAX }; @@ -534,6 +558,7 @@ IFLA_BRPORT_MRP_IN_OPEN, IFLA_BRPORT_MCAST_EHT_HOSTS_LIMIT, IFLA_BRPORT_MCAST_EHT_HOSTS_CNT, + IFLA_BRPORT_LOCKED, __IFLA_BRPORT_MAX }; #define IFLA_BRPORT_MAX (__IFLA_BRPORT_MAX - 1) @@ -668,6 +693,7 @@ IFLA_XFRM_UNSPEC, IFLA_XFRM_LINK, IFLA_XFRM_IF_ID, + IFLA_XFRM_COLLECT_METADATA, __IFLA_XFRM_MAX }; @@ -709,7 +735,55 @@ #define IPVLAN_F_PRIVATE 0x01 #define IPVLAN_F_VEPA 0x02 +/* Tunnel RTM header */ +struct tunnel_msg { + __u8 family; + __u8 flags; + __u16 reserved2; + __u32 ifindex; +}; + /* VXLAN section */ + +/* include statistics in the dump */ +#define TUNNEL_MSG_FLAG_STATS 0x01 + +#define TUNNEL_MSG_VALID_USER_FLAGS TUNNEL_MSG_FLAG_STATS + +/* Embedded inside VXLAN_VNIFILTER_ENTRY_STATS */ +enum { + VNIFILTER_ENTRY_STATS_UNSPEC, + VNIFILTER_ENTRY_STATS_RX_BYTES, + VNIFILTER_ENTRY_STATS_RX_PKTS, + VNIFILTER_ENTRY_STATS_RX_DROPS, + VNIFILTER_ENTRY_STATS_RX_ERRORS, + VNIFILTER_ENTRY_STATS_TX_BYTES, + VNIFILTER_ENTRY_STATS_TX_PKTS, + VNIFILTER_ENTRY_STATS_TX_DROPS, + VNIFILTER_ENTRY_STATS_TX_ERRORS, + VNIFILTER_ENTRY_STATS_PAD, + __VNIFILTER_ENTRY_STATS_MAX +}; +#define VNIFILTER_ENTRY_STATS_MAX (__VNIFILTER_ENTRY_STATS_MAX - 1) + +enum { + VXLAN_VNIFILTER_ENTRY_UNSPEC, + VXLAN_VNIFILTER_ENTRY_START, + VXLAN_VNIFILTER_ENTRY_END, + VXLAN_VNIFILTER_ENTRY_GROUP, + VXLAN_VNIFILTER_ENTRY_GROUP6, + VXLAN_VNIFILTER_ENTRY_STATS, + __VXLAN_VNIFILTER_ENTRY_MAX +}; +#define VXLAN_VNIFILTER_ENTRY_MAX (__VXLAN_VNIFILTER_ENTRY_MAX - 1) + +enum { + VXLAN_VNIFILTER_UNSPEC, + VXLAN_VNIFILTER_ENTRY, + __VXLAN_VNIFILTER_MAX +}; +#define VXLAN_VNIFILTER_MAX (__VXLAN_VNIFILTER_MAX - 1) + enum { IFLA_VXLAN_UNSPEC, IFLA_VXLAN_ID, @@ -741,6 +815,7 @@ IFLA_VXLAN_GPE, IFLA_VXLAN_TTL_INHERIT, IFLA_VXLAN_DF, + IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */ __IFLA_VXLAN_MAX }; #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1) @@ -774,6 +849,7 @@ IFLA_GENEVE_LABEL, IFLA_GENEVE_TTL_INHERIT, IFLA_GENEVE_DF, + IFLA_GENEVE_INNER_PROTO_INHERIT, __IFLA_GENEVE_MAX }; #define IFLA_GENEVE_MAX (__IFLA_GENEVE_MAX - 1) @@ -819,6 +895,8 @@ IFLA_GTP_FD1, IFLA_GTP_PDP_HASHSIZE, IFLA_GTP_ROLE, + IFLA_GTP_CREATE_SOCKETS, + IFLA_GTP_RESTART_COUNT, __IFLA_GTP_MAX, }; #define IFLA_GTP_MAX (__IFLA_GTP_MAX - 1) @@ -856,6 +934,8 @@ IFLA_BOND_TLB_DYNAMIC_LB, IFLA_BOND_PEER_NOTIF_DELAY, IFLA_BOND_AD_LACP_ACTIVE, + IFLA_BOND_MISSED_MAX, + IFLA_BOND_NS_IP6_TARGET, __IFLA_BOND_MAX, }; @@ -883,6 +963,7 @@ IFLA_BOND_SLAVE_AD_AGGREGATOR_ID, IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE, IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE, + IFLA_BOND_SLAVE_PRIO, __IFLA_BOND_SLAVE_MAX, }; @@ -1152,6 +1233,17 @@ #define IFLA_STATS_FILTER_BIT(ATTR) (1 << (ATTR - 1)) +enum { + IFLA_STATS_GETSET_UNSPEC, + IFLA_STATS_GET_FILTERS, /* Nest of IFLA_STATS_LINK_xxx, each a u32 with + * a filter mask for the corresponding group. + */ + IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS, /* 0 or 1 as u8 */ + __IFLA_STATS_GETSET_MAX, +}; + +#define IFLA_STATS_GETSET_MAX (__IFLA_STATS_GETSET_MAX - 1) + /* These are embedded into IFLA_STATS_LINK_XSTATS: * IFLA_STATS_LINK_XSTATS * -> LINK_XSTATS_TYPE_xxx @@ -1169,10 +1261,21 @@ enum { IFLA_OFFLOAD_XSTATS_UNSPEC, IFLA_OFFLOAD_XSTATS_CPU_HIT, /* struct rtnl_link_stats64 */ + IFLA_OFFLOAD_XSTATS_HW_S_INFO, /* HW stats info. A nest */ + IFLA_OFFLOAD_XSTATS_L3_STATS, /* struct rtnl_hw_stats64 */ __IFLA_OFFLOAD_XSTATS_MAX }; #define IFLA_OFFLOAD_XSTATS_MAX (__IFLA_OFFLOAD_XSTATS_MAX - 1) +enum { + IFLA_OFFLOAD_XSTATS_HW_S_INFO_UNSPEC, + IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST, /* u8 */ + IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED, /* u8 */ + __IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX, +}; +#define IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX \ + (__IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX - 1) + /* XDP section */ #define XDP_FLAGS_UPDATE_IF_NOEXIST (1U << 0) @@ -1271,4 +1374,14 @@ #define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1) +/* DSA section */ + +enum { + IFLA_DSA_UNSPEC, + IFLA_DSA_MASTER, + __IFLA_DSA_MAX, +}; + +#define IFLA_DSA_MAX (__IFLA_DSA_MAX - 1) + #endif /* _LINUX_IF_LINK_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_macsec.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_macsec.h
Changed
@@ -22,6 +22,8 @@ #define MACSEC_KEYID_LEN 16 +#define MACSEC_SALT_LEN 12 + /* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */ #define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL #define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_tun.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_tun.h
Changed
@@ -67,6 +67,8 @@ #define IFF_TAP 0x0002 #define IFF_NAPI 0x0010 #define IFF_NAPI_FRAGS 0x0020 +/* Used in TUNSETIFF to bring up tun/tap without carrier */ +#define IFF_NO_CARRIER 0x0040 #define IFF_NO_PI 0x1000 /* This flag has no real effect */ #define IFF_ONE_QUEUE 0x2000 @@ -108,7 +110,7 @@ struct tun_filter { __u16 flags; /* TUN_FLT_ flags see above */ __u16 count; /* Number of addresses */ - __u8 addr0ETH_ALEN; + __u8 addrETH_ALEN; }; #endif /* __IF_TUN_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/if_tunnel.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/if_tunnel.h
Changed
@@ -176,8 +176,10 @@ #define TUNNEL_VXLAN_OPT __cpu_to_be16(0x1000) #define TUNNEL_NOCACHE __cpu_to_be16(0x2000) #define TUNNEL_ERSPAN_OPT __cpu_to_be16(0x4000) +#define TUNNEL_GTP_OPT __cpu_to_be16(0x8000) #define TUNNEL_OPTIONS_PRESENT \ - (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT) + (TUNNEL_GENEVE_OPT | TUNNEL_VXLAN_OPT | TUNNEL_ERSPAN_OPT | \ + TUNNEL_GTP_OPT) #endif /* _IF_TUNNEL_H_ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/in.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/in.h
Changed
@@ -20,6 +20,7 @@ #define _LINUX_IN_H #include <linux/types.h> +#include <linux/stddef.h> #include <linux/libc-compat.h> #include <linux/socket.h> @@ -68,6 +69,8 @@ #define IPPROTO_PIM IPPROTO_PIM IPPROTO_COMP = 108, /* Compression Header Protocol */ #define IPPROTO_COMP IPPROTO_COMP + IPPROTO_L2TP = 115, /* Layer 2 Tunnelling Protocol */ +#define IPPROTO_L2TP IPPROTO_L2TP IPPROTO_SCTP = 132, /* Stream Control Transport Protocol */ #define IPPROTO_SCTP IPPROTO_SCTP IPPROTO_UDPLITE = 136, /* UDP-Lite (RFC 3828) */ @@ -188,21 +191,13 @@ }; struct ip_msfilter { + __be32 imsf_multiaddr; + __be32 imsf_interface; + __u32 imsf_fmode; + __u32 imsf_numsrc; union { - struct { - __be32 imsf_multiaddr_aux; - __be32 imsf_interface_aux; - __u32 imsf_fmode_aux; - __u32 imsf_numsrc_aux; - __be32 imsf_slist1; - }; - struct { - __be32 imsf_multiaddr; - __be32 imsf_interface; - __u32 imsf_fmode; - __u32 imsf_numsrc; - __be32 imsf_slist_flex; - }; + __be32 imsf_slist1; + __DECLARE_FLEX_ARRAY(__be32, imsf_slist_flex); }; };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/inet_diag.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/inet_diag.h
Changed
@@ -104,7 +104,7 @@ __u8 family; __u8 prefix_len; int port; - __be32 addr0; + __be32 addr; }; struct inet_diag_markcond {
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/ioam6_iptunnel.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/ioam6_iptunnel.h
Changed
@@ -9,9 +9,47 @@ #ifndef _LINUX_IOAM6_IPTUNNEL_H #define _LINUX_IOAM6_IPTUNNEL_H +/* Encap modes: + * - inline: direct insertion + * - encap: ip6ip6 encapsulation + * - auto: __inline__ for local packets, encap for in-transit packets + */ +enum { + __IOAM6_IPTUNNEL_MODE_MIN, + + IOAM6_IPTUNNEL_MODE_INLINE, + IOAM6_IPTUNNEL_MODE_ENCAP, + IOAM6_IPTUNNEL_MODE_AUTO, + + __IOAM6_IPTUNNEL_MODE_MAX, +}; + +#define IOAM6_IPTUNNEL_MODE_MIN (__IOAM6_IPTUNNEL_MODE_MIN + 1) +#define IOAM6_IPTUNNEL_MODE_MAX (__IOAM6_IPTUNNEL_MODE_MAX - 1) + enum { IOAM6_IPTUNNEL_UNSPEC, + + /* Encap mode */ + IOAM6_IPTUNNEL_MODE, /* u8 */ + + /* Tunnel dst address. + * For encap,auto modes. + */ + IOAM6_IPTUNNEL_DST, /* struct in6_addr */ + + /* IOAM Trace Header */ IOAM6_IPTUNNEL_TRACE, /* struct ioam6_trace_hdr */ + + /* Insertion frequency: + * "k over n" packets (0 < k <= n) + * 0.0001% ... 100% + */ +#define IOAM6_IPTUNNEL_FREQ_MIN 1 +#define IOAM6_IPTUNNEL_FREQ_MAX 1000000 + IOAM6_IPTUNNEL_FREQ_K, /* u32 */ + IOAM6_IPTUNNEL_FREQ_N, /* u32 */ + __IOAM6_IPTUNNEL_MAX, };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/ip.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/ip.h
Changed
@@ -100,8 +100,10 @@ __u8 ttl; __u8 protocol; __sum16 check; - __be32 saddr; - __be32 daddr; + __struct_group(/* no tag */, addrs, /* no attrs */, + __be32 saddr; + __be32 daddr; + ); /*The options start here. */ }; @@ -112,13 +114,13 @@ __be16 reserved; __be32 spi; __be32 seq_no; /* Sequence number */ - __u8 auth_data0; /* Variable len but >=4. Mind the 64 bit alignment! */ + __u8 auth_data; /* Variable len but >=4. Mind the 64 bit alignment! */ }; struct ip_esp_hdr { __be32 spi; __be32 seq_no; /* Sequence number */ - __u8 enc_data0; /* Variable len but >=8. Mind the 64 bit alignment! */ + __u8 enc_data; /* Variable len but >=8. Mind the 64 bit alignment! */ }; struct ip_comp_hdr { @@ -169,6 +171,7 @@ IPV4_DEVCONF_DROP_UNICAST_IN_L2_MULTICAST, IPV4_DEVCONF_DROP_GRATUITOUS_ARP, IPV4_DEVCONF_BC_FORWARDING, + IPV4_DEVCONF_ARP_EVICT_NOCARRIER, __IPV4_DEVCONF_MAX };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/l2tp.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/l2tp.h
Changed
@@ -13,8 +13,6 @@ #include <linux/in.h> #include <linux/in6.h> -#define IPPROTO_L2TP 115 - /** * struct sockaddr_l2tpip - the sockaddr structure for L2TP-over-IP sockets * @l2tp_family: address family number AF_L2TPIP.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/lwtunnel.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/lwtunnel.h
Changed
@@ -15,6 +15,7 @@ LWTUNNEL_ENCAP_SEG6_LOCAL, LWTUNNEL_ENCAP_RPL, LWTUNNEL_ENCAP_IOAM6, + LWTUNNEL_ENCAP_XFRM, __LWTUNNEL_ENCAP_MAX, }; @@ -111,4 +112,13 @@ #define LWT_BPF_MAX_HEADROOM 256 +enum { + LWT_XFRM_UNSPEC, + LWT_XFRM_IF_ID, + LWT_XFRM_LINK, + __LWT_XFRM_MAX, +}; + +#define LWT_XFRM_MAX (__LWT_XFRM_MAX - 1) + #endif /* _LWTUNNEL_H_ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/magic.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/magic.h
Changed
@@ -6,6 +6,7 @@ #define AFFS_SUPER_MAGIC 0xadff #define AFS_SUPER_MAGIC 0x5346414F #define AUTOFS_SUPER_MAGIC 0x0187 +#define CEPH_SUPER_MAGIC 0x00c36400 #define CODA_SUPER_MAGIC 0x73757245 #define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ #define CRAMFS_MAGIC_WEND 0x453dcd28 /* magic number with the wrong endianess */ @@ -35,6 +36,7 @@ #define EFIVARFS_MAGIC 0xde5e81e4 #define HOSTFS_SUPER_MAGIC 0x00c0ffee #define OVERLAYFS_SUPER_MAGIC 0x794c7630 +#define FUSE_SUPER_MAGIC 0x65735546 #define MINIX_SUPER_MAGIC 0x137F /* minix v1 fs, 14 char names */ #define MINIX_SUPER_MAGIC2 0x138F /* minix v1 fs, 30 char names */ @@ -43,6 +45,7 @@ #define MINIX3_SUPER_MAGIC 0x4d5a /* minix v3 fs, 60 char names */ #define MSDOS_SUPER_MAGIC 0x4d44 /* MD */ +#define EXFAT_SUPER_MAGIC 0x2011BAB0 #define NCP_SUPER_MAGIC 0x564c /* Guess, what 0x564c is :-) */ #define NFS_SUPER_MAGIC 0x6969 #define OCFS2_SUPER_MAGIC 0x7461636f @@ -51,6 +54,7 @@ #define QNX6_SUPER_MAGIC 0x68191122 /* qnx6 fs detection */ #define AFS_FS_MAGIC 0x6B414653 + #define REISERFS_SUPER_MAGIC 0x52654973 /* used by gcc */ /* used by file system utilities that look at the superblock, etc. */ @@ -59,6 +63,9 @@ #define REISER2FS_JR_SUPER_MAGIC_STRING "ReIsEr3Fs" #define SMB_SUPER_MAGIC 0x517B +#define CIFS_SUPER_MAGIC 0xFF534D42 /* the first four bytes of SMB PDUs */ +#define SMB2_SUPER_MAGIC 0xFE534D42 + #define CGROUP_SUPER_MAGIC 0x27e0eb #define CGROUP2_SUPER_MAGIC 0x63677270 @@ -91,12 +98,8 @@ /* Since UDF 2.01 is ISO 13346 based... */ #define UDF_SUPER_MAGIC 0x15013346 -#define BALLOON_KVM_MAGIC 0x13661366 -#define ZSMALLOC_MAGIC 0x58295829 #define DMA_BUF_MAGIC 0x444d4142 /* "DMAB" */ #define DEVMEM_MAGIC 0x454d444d /* "DMEM" */ -#define Z3FOLD_MAGIC 0x33 -#define PPC_CMM_MAGIC 0xc7571590 #define SECRETMEM_MAGIC 0x5345434d /* "SECM" */ #endif /* __LINUX_MAGIC_H__ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/mptcp.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/mptcp.h
Changed
@@ -2,8 +2,14 @@ #ifndef _MPTCP_H #define _MPTCP_H +#include <netinet/in.h> /* for sockaddr_in and sockaddr_in6 */ +#include <sys/socket.h> /* for struct sockaddr */ + #include <linux/const.h> #include <linux/types.h> +#include <linux/in.h> /* for sockaddr_in */ +#include <linux/in6.h> /* for sockaddr_in6 */ +#include <linux/socket.h> /* for sockaddr_storage and sa_family */ #define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0) #define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1) @@ -48,6 +54,9 @@ MPTCP_PM_ATTR_ADDR, /* nested address */ MPTCP_PM_ATTR_RCV_ADD_ADDRS, /* u32 */ MPTCP_PM_ATTR_SUBFLOWS, /* u32 */ + MPTCP_PM_ATTR_TOKEN, /* u32 */ + MPTCP_PM_ATTR_LOC_ID, /* u8 */ + MPTCP_PM_ATTR_ADDR_REMOTE, /* nested address */ __MPTCP_PM_ATTR_MAX }; @@ -74,6 +83,7 @@ #define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1) #define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2) #define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3) +#define MPTCP_PM_ADDR_FLAG_IMPLICIT (1 << 4) enum { MPTCP_PM_CMD_UNSPEC, @@ -85,6 +95,10 @@ MPTCP_PM_CMD_SET_LIMITS, MPTCP_PM_CMD_GET_LIMITS, MPTCP_PM_CMD_SET_FLAGS, + MPTCP_PM_CMD_ANNOUNCE, + MPTCP_PM_CMD_REMOVE, + MPTCP_PM_CMD_SUBFLOW_CREATE, + MPTCP_PM_CMD_SUBFLOW_DESTROY, __MPTCP_PM_CMD_AFTER_LAST }; @@ -129,19 +143,21 @@ * MPTCP_EVENT_REMOVED: token, rem_id * An address has been lost by the peer. * - * MPTCP_EVENT_SUB_ESTABLISHED: token, family, saddr4 | saddr6, - * daddr4 | daddr6, sport, dport, backup, - * if_idx , error + * MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, + * saddr4 | saddr6, daddr4 | daddr6, sport, + * dport, backup, if_idx , error * A new subflow has been established. 'error' should not be set. * - * MPTCP_EVENT_SUB_CLOSED: token, family, saddr4 | saddr6, daddr4 | daddr6, - * sport, dport, backup, if_idx , error + * MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6, + * daddr4 | daddr6, sport, dport, backup, if_idx + * , error * A subflow has been closed. An error (copy of sk_err) could be set if an * error has been detected for this subflow. * - * MPTCP_EVENT_SUB_PRIORITY: token, family, saddr4 | saddr6, daddr4 | daddr6, - * sport, dport, backup, if_idx , error - * The priority of a subflow has changed. 'error' should not be set. + * MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6, + * daddr4 | daddr6, sport, dport, backup, if_idx + * , error + * The priority of a subflow has changed. 'error' should not be set. */ enum mptcp_event_type { MPTCP_EVENT_UNSPEC = 0, @@ -178,6 +194,7 @@ MPTCP_ATTR_IF_IDX, /* s32 */ MPTCP_ATTR_RESET_REASON,/* u32 */ MPTCP_ATTR_RESET_FLAGS, /* u32 */ + MPTCP_ATTR_SERVER_SIDE, /* u8 */ __MPTCP_ATTR_AFTER_LAST }; @@ -193,4 +210,32 @@ #define MPTCP_RST_EBADPERF 5 #define MPTCP_RST_EMIDDLEBOX 6 +struct mptcp_subflow_data { + __u32 size_subflow_data; /* size of this structure in userspace */ + __u32 num_subflows; /* must be 0, set by kernel */ + __u32 size_kernel; /* must be 0, set by kernel */ + __u32 size_user; /* size of one element in data */ +} __attribute__((aligned(8))); + +struct mptcp_subflow_addrs { + union { + __kernel_sa_family_t sa_family; + struct sockaddr sa_local; + struct sockaddr_in sin_local; + struct sockaddr_in6 sin6_local; + struct __kernel_sockaddr_storage ss_local; + }; + union { + struct sockaddr sa_remote; + struct sockaddr_in sin_remote; + struct sockaddr_in6 sin6_remote; + struct __kernel_sockaddr_storage ss_remote; + }; +}; + +/* MPTCP socket options */ +#define MPTCP_INFO 1 +#define MPTCP_TCPINFO 2 +#define MPTCP_SUBFLOW_ADDRS 3 + #endif /* _MPTCP_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/neighbour.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/neighbour.h
Changed
@@ -31,6 +31,9 @@ NDA_PROTOCOL, /* Originator of entry */ NDA_NH_ID, NDA_FDB_EXT_ATTRS, + NDA_FLAGS_EXT, + NDA_NDM_STATE_MASK, + NDA_NDM_FLAGS_MASK, __NDA_MAX }; @@ -40,14 +43,16 @@ * Neighbor Cache Entry Flags */ -#define NTF_USE 0x01 -#define NTF_SELF 0x02 -#define NTF_MASTER 0x04 -#define NTF_PROXY 0x08 /* == ATF_PUBL */ -#define NTF_EXT_LEARNED 0x10 -#define NTF_OFFLOADED 0x20 -#define NTF_STICKY 0x40 -#define NTF_ROUTER 0x80 +#define NTF_USE (1 << 0) +#define NTF_SELF (1 << 1) +#define NTF_MASTER (1 << 2) +#define NTF_PROXY (1 << 3) /* == ATF_PUBL */ +#define NTF_EXT_LEARNED (1 << 4) +#define NTF_OFFLOADED (1 << 5) +#define NTF_STICKY (1 << 6) +#define NTF_ROUTER (1 << 7) +/* Extended flags under NDA_FLAGS_EXT: */ +#define NTF_EXT_MANAGED (1 << 0) /* * Neighbor Cache Entry States. @@ -65,12 +70,22 @@ #define NUD_PERMANENT 0x80 #define NUD_NONE 0x00 -/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change - * and make no address resolution or NUD. - * NUD_PERMANENT also cannot be deleted by garbage collectors. +/* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change and make no + * address resolution or NUD. + * + * NUD_PERMANENT also cannot be deleted by garbage collectors. This holds true + * for dynamic entries with NTF_EXT_LEARNED flag as well. However, upon carrier + * down event, NUD_PERMANENT entries are not flushed whereas NTF_EXT_LEARNED + * flagged entries explicitly are (which is also consistent with the routing + * subsystem). + * * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry * states don't make sense and thus are ignored. Such entries don't age and * can roam. + * + * NTF_EXT_MANAGED flagged neigbor entries are managed by the kernel on behalf + * of a user space control plane, and automatically refreshed so that (if + * possible) they remain in NUD_REACHABLE state. */ struct nda_cacheinfo { @@ -139,6 +154,7 @@ NDTPA_QUEUE_LENBYTES, /* u32 */ NDTPA_MCAST_REPROBES, /* u32 */ NDTPA_PAD, + NDTPA_INTERVAL_PROBE_TIME_MS, /* u64, msecs */ __NDTPA_MAX }; #define NDTPA_MAX (__NDTPA_MAX - 1)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netfilter.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netfilter.h
Changed
@@ -49,6 +49,7 @@ enum nf_dev_hooks { NF_NETDEV_INGRESS, + NF_NETDEV_EGRESS, NF_NETDEV_NUMHOOKS };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netfilter/ipset/ip_set.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netfilter/ipset/ip_set.h
Changed
@@ -3,10 +3,6 @@ * Patrick Schaaf <bof@bof.de> * Martin Josefsson <gandalf@wlug.westbo.se> * Copyright (C) 2003-2011 Jozsef Kadlecsik <kadlec@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #ifndef _IP_SET_H #define _IP_SET_H
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netfilter/x_tables.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netfilter/x_tables.h
Changed
@@ -28,7 +28,7 @@ __u16 match_size; } u; - unsigned char data0; + unsigned char data; }; struct xt_entry_target { @@ -119,7 +119,7 @@ unsigned int num_counters; /* The counters (actually `number' of these). */ - struct xt_counters counters0; + struct xt_counters counters; }; #define XT_INV_PROTO 0x40 /* Invert the sense of PROTO. */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netfilter_ipv4/ip_tables.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netfilter_ipv4/ip_tables.h
Changed
@@ -119,7 +119,7 @@ struct xt_counters counters; /* The matches (if any), then the target. */ - unsigned char elems0; + unsigned char elems; }; /* @@ -201,7 +201,7 @@ struct xt_counters *counters; /* The entries (hang off end: not really an array). */ - struct ipt_entry entries0; + struct ipt_entry entries; }; /* The argument to IPT_SO_GET_ENTRIES. */ @@ -213,7 +213,7 @@ unsigned int size; /* The entries. */ - struct ipt_entry entrytable0; + struct ipt_entry entrytable; }; /* Helper functions */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netfilter_ipv6/ip6_tables.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netfilter_ipv6/ip6_tables.h
Changed
@@ -241,7 +241,7 @@ struct xt_counters *counters; /* The entries (hang off end: not really an array). */ - struct ip6t_entry entries0; + struct ip6t_entry entries; }; /* The argument to IP6T_SO_GET_ENTRIES. */ @@ -253,7 +253,7 @@ unsigned int size; /* The entries. */ - struct ip6t_entry entrytable0; + struct ip6t_entry entrytable; }; /* Helper functions */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/netlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/netlink.h
Changed
@@ -20,7 +20,7 @@ #define NETLINK_CONNECTOR 11 #define NETLINK_NETFILTER 12 /* netfilter subsystem */ #define NETLINK_IP6_FW 13 -#define NETLINK_DNRTMSG 14 /* DECnet routing messages */ +#define NETLINK_DNRTMSG 14 /* DECnet routing messages (obsolete) */ #define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */ #define NETLINK_GENERIC 16 /* leave room for NETLINK_DM (DM Events) */ @@ -41,12 +41,20 @@ __u32 nl_groups; /* multicast groups mask */ }; +/** + * struct nlmsghdr - fixed format metadata header of Netlink messages + * @nlmsg_len: Length of message including header + * @nlmsg_type: Message content type + * @nlmsg_flags: Additional flags + * @nlmsg_seq: Sequence number + * @nlmsg_pid: Sending process port ID + */ struct nlmsghdr { - __u32 nlmsg_len; /* Length of message including header */ - __u16 nlmsg_type; /* Message content */ - __u16 nlmsg_flags; /* Additional flags */ - __u32 nlmsg_seq; /* Sequence number */ - __u32 nlmsg_pid; /* Sending process port ID */ + __u32 nlmsg_len; + __u16 nlmsg_type; + __u16 nlmsg_flags; + __u32 nlmsg_seq; + __u32 nlmsg_pid; }; /* Flags values */ @@ -54,7 +62,7 @@ #define NLM_F_REQUEST 0x01 /* It is request message. */ #define NLM_F_MULTI 0x02 /* Multipart message, terminated by NLMSG_DONE */ #define NLM_F_ACK 0x04 /* Reply with ack, with zero or error code */ -#define NLM_F_ECHO 0x08 /* Echo this request */ +#define NLM_F_ECHO 0x08 /* Receive resulting notifications */ #define NLM_F_DUMP_INTR 0x10 /* Dump was inconsistent due to sequence change */ #define NLM_F_DUMP_FILTERED 0x20 /* Dump was filtered as requested */ @@ -72,6 +80,7 @@ /* Modifiers to DELETE request */ #define NLM_F_NONREC 0x100 /* Do not delete recursively */ +#define NLM_F_BULK 0x200 /* Delete multiple objects */ /* Flags for ACK message */ #define NLM_F_CAPPED 0x100 /* request was capped */ @@ -131,6 +140,10 @@ * be used - in the success case - to identify a created * object or operation or similar (binary) * @NLMSGERR_ATTR_POLICY: policy for a rejected attribute + * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute, + * %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was + * missing at the message level + * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing * @__NLMSGERR_ATTR_MAX: number of attributes * @NLMSGERR_ATTR_MAX: highest attribute number */ @@ -140,6 +153,8 @@ NLMSGERR_ATTR_OFFS, NLMSGERR_ATTR_COOKIE, NLMSGERR_ATTR_POLICY, + NLMSGERR_ATTR_MISS_TYPE, + NLMSGERR_ATTR_MISS_NEST, __NLMSGERR_ATTR_MAX, NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 @@ -332,6 +347,9 @@ * bitfield32 type (U32) * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64) * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment + * + * @__NL_POLICY_TYPE_ATTR_MAX: number of attributes + * @NL_POLICY_TYPE_ATTR_MAX: highest attribute number */ enum netlink_policy_type_attr { NL_POLICY_TYPE_ATTR_UNSPEC,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/pfkeyv2.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/pfkeyv2.h
Changed
@@ -309,6 +309,7 @@ #define SADB_X_AALG_SHA2_512HMAC 7 #define SADB_X_AALG_RIPEMD160HMAC 8 #define SADB_X_AALG_AES_XCBC_MAC 9 +#define SADB_X_AALG_SM3_256HMAC 10 #define SADB_X_AALG_NULL 251 /* kame */ #define SADB_AALG_MAX 251 @@ -329,6 +330,7 @@ #define SADB_X_EALG_AES_GCM_ICV16 20 #define SADB_X_EALG_CAMELLIACBC 22 #define SADB_X_EALG_NULL_AES_GMAC 23 +#define SADB_X_EALG_SM4CBC 24 #define SADB_EALG_MAX 253 /* last EALG */ /* private allocations should use 249-255 (RFC2407) */ #define SADB_X_EALG_SERPENTCBC 252 /* draft-ietf-ipsec-ciph-aes-cbc-00 */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/pkt_cls.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/pkt_cls.h
Changed
@@ -19,13 +19,16 @@ TCA_ACT_FLAGS, TCA_ACT_HW_STATS, TCA_ACT_USED_HW_STATS, + TCA_ACT_IN_HW_COUNT, __TCA_ACT_MAX }; /* See other TCA_ACT_FLAGS_ * flags in include/net/act_api.h. */ -#define TCA_ACT_FLAGS_NO_PERCPU_STATS 1 /* Don't use percpu allocator for - * actions stats. - */ +#define TCA_ACT_FLAGS_NO_PERCPU_STATS (1 << 0) /* Don't use percpu allocator for + * actions stats. + */ +#define TCA_ACT_FLAGS_SKIP_HW (1 << 1) /* don't offload action to HW */ +#define TCA_ACT_FLAGS_SKIP_SW (1 << 2) /* don't use action in SW */ /* tca HW stats type * When user does not pass the attribute, he does not care. @@ -253,7 +256,7 @@ short hoff; __be32 hmask; - struct tc_u32_key keys0; + struct tc_u32_key keys; }; struct tc_u32_mark { @@ -265,7 +268,7 @@ struct tc_u32_pcnt { __u64 rcnt; __u64 rhit; - __u64 kcnts0; + __u64 kcnts; }; /* Flags */ @@ -584,6 +587,13 @@ TCA_FLOWER_KEY_HASH, /* u32 */ TCA_FLOWER_KEY_HASH_MASK, /* u32 */ + TCA_FLOWER_KEY_NUM_OF_VLANS, /* u8 */ + + TCA_FLOWER_KEY_PPPOE_SID, /* be16 */ + TCA_FLOWER_KEY_PPP_PROTO, /* be16 */ + + TCA_FLOWER_KEY_L2TPV3_SID, /* be32 */ + __TCA_FLOWER_MAX, }; @@ -613,6 +623,10 @@ * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_ * attributes */ + TCA_FLOWER_KEY_ENC_OPTS_GTP, /* Nested + * TCA_FLOWER_KEY_ENC_OPT_GTP_ + * attributes + */ __TCA_FLOWER_KEY_ENC_OPTS_MAX, }; @@ -652,6 +666,17 @@ (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1) enum { + TCA_FLOWER_KEY_ENC_OPT_GTP_UNSPEC, + TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE, /* u8 */ + TCA_FLOWER_KEY_ENC_OPT_GTP_QFI, /* u8 */ + + __TCA_FLOWER_KEY_ENC_OPT_GTP_MAX, +}; + +#define TCA_FLOWER_KEY_ENC_OPT_GTP_MAX \ + (__TCA_FLOWER_KEY_ENC_OPT_GTP_MAX - 1) + +enum { TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC, TCA_FLOWER_KEY_MPLS_OPTS_LSE, __TCA_FLOWER_KEY_MPLS_OPTS_MAX,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/pkt_sched.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/pkt_sched.h
Changed
@@ -840,6 +840,8 @@ TCA_FQ_CODEL_CE_THRESHOLD, TCA_FQ_CODEL_DROP_BATCH_SIZE, TCA_FQ_CODEL_MEMORY_LIMIT, + TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR, + TCA_FQ_CODEL_CE_THRESHOLD_MASK, __TCA_FQ_CODEL_MAX }; @@ -1231,6 +1233,16 @@ #define TCA_TAPRIO_ATTR_FLAG_FULL_OFFLOAD _BITUL(1) enum { + TCA_TAPRIO_TC_ENTRY_UNSPEC, + TCA_TAPRIO_TC_ENTRY_INDEX, /* u32 */ + TCA_TAPRIO_TC_ENTRY_MAX_SDU, /* u32 */ + + /* add new constants above here */ + __TCA_TAPRIO_TC_ENTRY_CNT, + TCA_TAPRIO_TC_ENTRY_MAX = (__TCA_TAPRIO_TC_ENTRY_CNT - 1) +}; + +enum { TCA_TAPRIO_ATTR_UNSPEC, TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */ TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */ @@ -1243,6 +1255,7 @@ TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION, /* s64 */ TCA_TAPRIO_ATTR_FLAGS, /* u32 */ TCA_TAPRIO_ATTR_TXTIME_DELAY, /* u32 */ + TCA_TAPRIO_ATTR_TC_ENTRY, /* nest */ __TCA_TAPRIO_ATTR_MAX, };
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/ppp_defs.h
Added
@@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * ppp_defs.h - PPP definitions. + * + * Copyright 1994-2000 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 as published by the Free Software Foundation. + */ +#include <linux/types.h> + +#ifndef _PPP_DEFS_H_ +#define _PPP_DEFS_H_ + +/* + * The basic PPP frame. + */ +#define PPP_HDRLEN 4 /* octets for standard ppp header */ +#define PPP_FCSLEN 2 /* octets for FCS */ +#define PPP_MRU 1500 /* default MRU = max length of info field */ + +#define PPP_ADDRESS(p) (((__u8 *)(p))0) +#define PPP_CONTROL(p) (((__u8 *)(p))1) +#define PPP_PROTOCOL(p) ((((__u8 *)(p))2 << 8) + ((__u8 *)(p))3) + +/* + * Significant octet values. + */ +#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */ +#define PPP_UI 0x03 /* Unnumbered Information */ +#define PPP_FLAG 0x7e /* Flag Sequence */ +#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */ +#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */ + +/* + * Protocol field values. + */ +#define PPP_IP 0x21 /* Internet Protocol */ +#define PPP_AT 0x29 /* AppleTalk Protocol */ +#define PPP_IPX 0x2b /* IPX protocol */ +#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */ +#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */ +#define PPP_MP 0x3d /* Multilink protocol */ +#define PPP_IPV6 0x57 /* Internet Protocol Version 6 */ +#define PPP_COMPFRAG 0xfb /* fragment compressed below bundle */ +#define PPP_COMP 0xfd /* compressed packet */ +#define PPP_MPLS_UC 0x0281 /* Multi Protocol Label Switching - Unicast */ +#define PPP_MPLS_MC 0x0283 /* Multi Protocol Label Switching - Multicast */ +#define PPP_IPCP 0x8021 /* IP Control Protocol */ +#define PPP_ATCP 0x8029 /* AppleTalk Control Protocol */ +#define PPP_IPXCP 0x802b /* IPX Control Protocol */ +#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */ +#define PPP_CCPFRAG 0x80fb /* CCP at link level (below MP bundle) */ +#define PPP_CCP 0x80fd /* Compression Control Protocol */ +#define PPP_MPLSCP 0x80fd /* MPLS Control Protocol */ +#define PPP_LCP 0xc021 /* Link Control Protocol */ +#define PPP_PAP 0xc023 /* Password Authentication Protocol */ +#define PPP_LQR 0xc025 /* Link Quality Report protocol */ +#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */ +#define PPP_CBCP 0xc029 /* Callback Control Protocol */ + +/* + * Values for FCS calculations. + */ + +#define PPP_INITFCS 0xffff /* Initial FCS value */ +#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */ + + +/* + * Extended asyncmap - allows any character to be escaped. + */ + +typedef __u32 ext_accm8; + +/* + * What to do with network protocol (NP) packets. + */ +enum NPmode { + NPMODE_PASS, /* pass the packet through */ + NPMODE_DROP, /* silently drop the packet */ + NPMODE_ERROR, /* return an error */ + NPMODE_QUEUE /* save it up for later. */ +}; + +/* + * Statistics for LQRP and pppstats + */ +struct pppstat { + __u32 ppp_discards; /* # frames discarded */ + + __u32 ppp_ibytes; /* bytes received */ + __u32 ppp_ioctects; /* bytes received not in error */ + __u32 ppp_ipackets; /* packets received */ + __u32 ppp_ierrors; /* receive errors */ + __u32 ppp_ilqrs; /* # LQR frames received */ + + __u32 ppp_obytes; /* raw bytes sent */ + __u32 ppp_ooctects; /* frame bytes sent */ + __u32 ppp_opackets; /* packets sent */ + __u32 ppp_oerrors; /* transmit errors */ + __u32 ppp_olqrs; /* # LQR frames sent */ +}; + +struct vjstat { + __u32 vjs_packets; /* outbound packets */ + __u32 vjs_compressed; /* outbound compressed packets */ + __u32 vjs_searches; /* searches for connection state */ + __u32 vjs_misses; /* times couldn't find conn. state */ + __u32 vjs_uncompressedin; /* inbound uncompressed packets */ + __u32 vjs_compressedin; /* inbound compressed packets */ + __u32 vjs_errorin; /* inbound unknown type packets */ + __u32 vjs_tossed; /* inbound packets tossed because of error */ +}; + +struct compstat { + __u32 unc_bytes; /* total uncompressed bytes */ + __u32 unc_packets; /* total uncompressed packets */ + __u32 comp_bytes; /* compressed bytes */ + __u32 comp_packets; /* compressed packets */ + __u32 inc_bytes; /* incompressible bytes */ + __u32 inc_packets; /* incompressible packets */ + + /* the compression ratio is defined as in_count / bytes_out */ + __u32 in_count; /* Bytes received */ + __u32 bytes_out; /* Bytes transmitted */ + + double ratio; /* not computed in kernel. */ +}; + +struct ppp_stats { + struct pppstat p; /* basic PPP statistics */ + struct vjstat vj; /* VJ header compression statistics */ +}; + +struct ppp_comp_stats { + struct compstat c; /* packet compression statistics */ + struct compstat d; /* packet decompression statistics */ +}; + +/* + * The following structure records the time in seconds since + * the last NP packet was sent or received. + * + * Linux implements both 32-bit and 64-bit time_t versions + * for compatibility with user space that defines ppp_idle + * based on the libc time_t. + */ +struct ppp_idle { + __kernel_old_time_t xmit_idle; /* time since last NP packet sent */ + __kernel_old_time_t recv_idle; /* time since last NP packet received */ +}; + +struct ppp_idle32 { + __s32 xmit_idle; /* time since last NP packet sent */ + __s32 recv_idle; /* time since last NP packet received */ +}; + +struct ppp_idle64 { + __s64 xmit_idle; /* time since last NP packet sent */ + __s64 recv_idle; /* time since last NP packet received */ +}; + +#endif /* _PPP_DEFS_H_ */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/rose.h
Added
@@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * These are the public elements of the Linux kernel Rose implementation. + * For kernel AX.25 see the file ax25.h. This file requires ax25.h for the + * definition of the ax25_address structure. + */ + +#ifndef ROSE_KERNEL_H +#define ROSE_KERNEL_H + +#include <linux/socket.h> +#include <linux/ax25.h> + +#define ROSE_MTU 251 + +#define ROSE_MAX_DIGIS 6 + +#define ROSE_DEFER 1 +#define ROSE_T1 2 +#define ROSE_T2 3 +#define ROSE_T3 4 +#define ROSE_IDLE 5 +#define ROSE_QBITINCL 6 +#define ROSE_HOLDBACK 7 + +#define SIOCRSGCAUSE (SIOCPROTOPRIVATE+0) +#define SIOCRSSCAUSE (SIOCPROTOPRIVATE+1) +#define SIOCRSL2CALL (SIOCPROTOPRIVATE+2) +#define SIOCRSSL2CALL (SIOCPROTOPRIVATE+2) +#define SIOCRSACCEPT (SIOCPROTOPRIVATE+3) +#define SIOCRSCLRRT (SIOCPROTOPRIVATE+4) +#define SIOCRSGL2CALL (SIOCPROTOPRIVATE+5) +#define SIOCRSGFACILITIES (SIOCPROTOPRIVATE+6) + +#define ROSE_DTE_ORIGINATED 0x00 +#define ROSE_NUMBER_BUSY 0x01 +#define ROSE_INVALID_FACILITY 0x03 +#define ROSE_NETWORK_CONGESTION 0x05 +#define ROSE_OUT_OF_ORDER 0x09 +#define ROSE_ACCESS_BARRED 0x0B +#define ROSE_NOT_OBTAINABLE 0x0D +#define ROSE_REMOTE_PROCEDURE 0x11 +#define ROSE_LOCAL_PROCEDURE 0x13 +#define ROSE_SHIP_ABSENT 0x39 + +typedef struct { + char rose_addr5; +} rose_address; + +struct sockaddr_rose { + __kernel_sa_family_t srose_family; + rose_address srose_addr; + ax25_address srose_call; + int srose_ndigis; + ax25_address srose_digi; +}; + +struct full_sockaddr_rose { + __kernel_sa_family_t srose_family; + rose_address srose_addr; + ax25_address srose_call; + unsigned int srose_ndigis; + ax25_address srose_digisROSE_MAX_DIGIS; +}; + +struct rose_route_struct { + rose_address address; + unsigned short mask; + ax25_address neighbour; + char device16; + unsigned char ndigis; + ax25_address digipeatersAX25_MAX_DIGIS; +}; + +struct rose_cause_struct { + unsigned char cause; + unsigned char diagnostic; +}; + +struct rose_facilities_struct { + rose_address source_addr, dest_addr; + ax25_address source_call, dest_call; + unsigned char source_ndigis, dest_ndigis; + ax25_address source_digisROSE_MAX_DIGIS; + ax25_address dest_digisROSE_MAX_DIGIS; + unsigned int rand; + rose_address fail_addr; + ax25_address fail_call; +}; + +#endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/rtnetlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/rtnetlink.h
Changed
@@ -146,6 +146,8 @@ #define RTM_NEWSTATS RTM_NEWSTATS RTM_GETSTATS = 94, #define RTM_GETSTATS RTM_GETSTATS + RTM_SETSTATS, +#define RTM_SETSTATS RTM_SETSTATS RTM_NEWCACHEREPORT = 96, #define RTM_NEWCACHEREPORT RTM_NEWCACHEREPORT @@ -185,6 +187,13 @@ RTM_GETNEXTHOPBUCKET, #define RTM_GETNEXTHOPBUCKET RTM_GETNEXTHOPBUCKET + RTM_NEWTUNNEL = 120, +#define RTM_NEWTUNNEL RTM_NEWTUNNEL + RTM_DELTUNNEL, +#define RTM_DELTUNNEL RTM_DELTUNNEL + RTM_GETTUNNEL, +#define RTM_GETTUNNEL RTM_GETTUNNEL + __RTM_MAX, #define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1) }; @@ -431,7 +440,7 @@ /* RTA_VIA */ struct rtvia { __kernel_sa_family_t rtvia_family; - __u8 rtvia_addr0; + __u8 rtvia_addr; }; /* RTM_CACHEINFO */ @@ -752,6 +761,12 @@ #define RTNLGRP_NEXTHOP RTNLGRP_NEXTHOP RTNLGRP_BRVLAN, #define RTNLGRP_BRVLAN RTNLGRP_BRVLAN + RTNLGRP_MCTP_IFADDR, +#define RTNLGRP_MCTP_IFADDR RTNLGRP_MCTP_IFADDR + RTNLGRP_TUNNEL, +#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL + RTNLGRP_STATS, +#define RTNLGRP_STATS RTNLGRP_STATS __RTNLGRP_MAX }; #define RTNLGRP_MAX (__RTNLGRP_MAX - 1) @@ -800,6 +815,7 @@ #define RTEXT_FILTER_MRP (1 << 4) #define RTEXT_FILTER_CFM_CONFIG (1 << 5) #define RTEXT_FILTER_CFM_STATUS (1 << 6) +#define RTEXT_FILTER_MST (1 << 7) /* End of information exported to user level */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/sctp.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/sctp.h
Changed
@@ -365,7 +365,7 @@ __u16 sac_outbound_streams; __u16 sac_inbound_streams; sctp_assoc_t sac_assoc_id; - __u8 sac_info0; + __u8 sac_info; }; /* @@ -436,7 +436,7 @@ __u32 sre_length; __be16 sre_error; sctp_assoc_t sre_assoc_id; - __u8 sre_data0; + __u8 sre_data; }; @@ -453,7 +453,7 @@ __u32 ssf_error; struct sctp_sndrcvinfo ssf_info; sctp_assoc_t ssf_assoc_id; - __u8 ssf_data0; + __u8 ssf_data; }; struct sctp_send_failed_event { @@ -463,7 +463,7 @@ __u32 ssf_error; struct sctp_sndinfo ssfe_info; sctp_assoc_t ssf_assoc_id; - __u8 ssf_data0; + __u8 ssf_data; }; /* @@ -1023,7 +1023,7 @@ struct sctp_getaddrs { sctp_assoc_t assoc_id; /*input*/ __u32 addr_num; /*output*/ - __u8 addrs0; /*output, variable size*/ + __u8 addrs; /*output, variable size*/ }; /* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/seg6.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/seg6.h
Changed
@@ -30,7 +30,7 @@ __u8 flags; __u16 tag; - struct in6_addr segments0; + struct in6_addr segments; }; #define SR6_FLAG1_PROTECTED (1 << 6)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/seg6_iptunnel.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/seg6_iptunnel.h
Changed
@@ -26,7 +26,7 @@ struct seg6_iptunnel_encap { int mode; - struct ipv6_sr_hdr srh0; + struct ipv6_sr_hdr srh; }; #define SEG6_IPTUN_ENCAP_SIZE(x) ((sizeof(*x)) + (((x)->srh->hdrlen + 1) << 3)) @@ -35,6 +35,8 @@ SEG6_IPTUN_MODE_INLINE, SEG6_IPTUN_MODE_ENCAP, SEG6_IPTUN_MODE_L2ENCAP, + SEG6_IPTUN_MODE_ENCAP_RED, + SEG6_IPTUN_MODE_L2ENCAP_RED, }; #endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/seg6_local.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/seg6_local.h
Changed
@@ -28,6 +28,7 @@ SEG6_LOCAL_BPF, SEG6_LOCAL_VRFTABLE, SEG6_LOCAL_COUNTERS, + SEG6_LOCAL_FLAVORS, __SEG6_LOCAL_MAX, }; #define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1) @@ -110,4 +111,27 @@ #define SEG6_LOCAL_CNT_MAX (__SEG6_LOCAL_CNT_MAX - 1) +/* SRv6 End* Flavor attributes */ +enum { + SEG6_LOCAL_FLV_UNSPEC, + SEG6_LOCAL_FLV_OPERATION, + SEG6_LOCAL_FLV_LCBLOCK_BITS, + SEG6_LOCAL_FLV_LCNODE_FN_BITS, + __SEG6_LOCAL_FLV_MAX, +}; + +#define SEG6_LOCAL_FLV_MAX (__SEG6_LOCAL_FLV_MAX - 1) + +/* Designed flavor operations for SRv6 End* Behavior */ +enum { + SEG6_LOCAL_FLV_OP_UNSPEC, + SEG6_LOCAL_FLV_OP_PSP, + SEG6_LOCAL_FLV_OP_USP, + SEG6_LOCAL_FLV_OP_USD, + SEG6_LOCAL_FLV_OP_NEXT_CSID, + __SEG6_LOCAL_FLV_OP_MAX +}; + +#define SEG6_LOCAL_FLV_OP_MAX (__SEG6_LOCAL_FLV_OP_MAX - 1) + #endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/snmp.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/snmp.h
Changed
@@ -344,6 +344,8 @@ LINUX_MIB_TLSRXDEVICE, /* TlsRxDevice */ LINUX_MIB_TLSDECRYPTERROR, /* TlsDecryptError */ LINUX_MIB_TLSRXDEVICERESYNC, /* TlsRxDeviceResync */ + LINUX_MIB_TLSDECRYPTRETRY, /* TlsDecryptRetry */ + LINUX_MIB_TLSRXNOPADVIOL, /* TlsRxNoPadViolation */ __LINUX_MIB_TLSMAX };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/socket.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/socket.h
Changed
@@ -31,4 +31,8 @@ #define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK) +#define SOCK_TXREHASH_DEFAULT 255 +#define SOCK_TXREHASH_DISABLED 0 +#define SOCK_TXREHASH_ENABLED 1 + #endif /* _LINUX_SOCKET_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/stddef.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/stddef.h
Changed
@@ -1,6 +1,47 @@ /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _LINUX_STDDEF_H +#define _LINUX_STDDEF_H + #ifndef __always_inline #define __always_inline __inline__ #endif + +/** + * __struct_group() - Create a mirrored named and anonyomous struct + * + * @TAG: The tag name for the named sub-struct (usually empty) + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes (usually empty) + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical layout + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. + * The named struct can also be explicitly tagged for layer reuse, as well + * as both having struct attributes appended. + */ +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } + +/** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME; \ + } +#endif
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tc_act/tc_bpf.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tc_act/tc_bpf.h
Changed
@@ -1,11 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __LINUX_TC_BPF_H
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tc_act/tc_skbedit.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tc_act/tc_skbedit.h
Changed
@@ -2,19 +2,6 @@ /* * Copyright (c) 2008, Intel Corporation. * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 Temple - * Place - Suite 330, Boston, MA 02111-1307 USA. - * * Author: Alexander Duyck <alexander.h.duyck@intel.com> */ @@ -29,6 +16,7 @@ #define SKBEDIT_F_PTYPE 0x8 #define SKBEDIT_F_MASK 0x10 #define SKBEDIT_F_INHERITDSFIELD 0x20 +#define SKBEDIT_F_TXQ_SKBHASH 0x40 struct tc_skbedit { tc_gen; @@ -45,6 +33,7 @@ TCA_SKBEDIT_PTYPE, TCA_SKBEDIT_MASK, TCA_SKBEDIT_FLAGS, + TCA_SKBEDIT_QUEUE_MAPPING_MAX, __TCA_SKBEDIT_MAX }; #define TCA_SKBEDIT_MAX (__TCA_SKBEDIT_MAX - 1)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tc_act/tc_skbmod.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tc_act/tc_skbmod.h
Changed
@@ -1,12 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * Copyright (c) 2016, Jamal Hadi Salim - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. -*/ + */ #ifndef __LINUX_TC_SKBMOD_H #define __LINUX_TC_SKBMOD_H
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tc_act/tc_tunnel_key.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tc_act/tc_tunnel_key.h
Changed
@@ -2,11 +2,6 @@ /* * Copyright (c) 2016, Amir Vadai <amir@vadai.me> * Copyright (c) 2016, Mellanox Technologies. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __LINUX_TC_TUNNEL_KEY_H
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tc_act/tc_vlan.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tc_act/tc_vlan.h
Changed
@@ -1,11 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. */ #ifndef __LINUX_TC_VLAN_H
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/tls.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/tls.h
Changed
@@ -39,6 +39,8 @@ /* TLS socket options */ #define TLS_TX 1 /* Set transmit parameters */ #define TLS_RX 2 /* Set receive parameters */ +#define TLS_TX_ZEROCOPY_RO 3 /* TX zerocopy (only sendfile now) */ +#define TLS_RX_EXPECT_NO_PAD 4 /* Attempt opportunistic zero-copy */ /* Supported versions */ #define TLS_VERSION_MINOR(ver) ((ver) & 0xFF) @@ -84,6 +86,34 @@ #define TLS_CIPHER_CHACHA20_POLY1305_TAG_SIZE 16 #define TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE 8 +#define TLS_CIPHER_SM4_GCM 55 +#define TLS_CIPHER_SM4_GCM_IV_SIZE 8 +#define TLS_CIPHER_SM4_GCM_KEY_SIZE 16 +#define TLS_CIPHER_SM4_GCM_SALT_SIZE 4 +#define TLS_CIPHER_SM4_GCM_TAG_SIZE 16 +#define TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE 8 + +#define TLS_CIPHER_SM4_CCM 56 +#define TLS_CIPHER_SM4_CCM_IV_SIZE 8 +#define TLS_CIPHER_SM4_CCM_KEY_SIZE 16 +#define TLS_CIPHER_SM4_CCM_SALT_SIZE 4 +#define TLS_CIPHER_SM4_CCM_TAG_SIZE 16 +#define TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE 8 + +#define TLS_CIPHER_ARIA_GCM_128 57 +#define TLS_CIPHER_ARIA_GCM_128_IV_SIZE 8 +#define TLS_CIPHER_ARIA_GCM_128_KEY_SIZE 16 +#define TLS_CIPHER_ARIA_GCM_128_SALT_SIZE 4 +#define TLS_CIPHER_ARIA_GCM_128_TAG_SIZE 16 +#define TLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE 8 + +#define TLS_CIPHER_ARIA_GCM_256 58 +#define TLS_CIPHER_ARIA_GCM_256_IV_SIZE 8 +#define TLS_CIPHER_ARIA_GCM_256_KEY_SIZE 32 +#define TLS_CIPHER_ARIA_GCM_256_SALT_SIZE 4 +#define TLS_CIPHER_ARIA_GCM_256_TAG_SIZE 16 +#define TLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE 8 + #define TLS_SET_RECORD_TYPE 1 #define TLS_GET_RECORD_TYPE 2 @@ -124,12 +154,46 @@ unsigned char rec_seqTLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE; }; +struct tls12_crypto_info_sm4_gcm { + struct tls_crypto_info info; + unsigned char ivTLS_CIPHER_SM4_GCM_IV_SIZE; + unsigned char keyTLS_CIPHER_SM4_GCM_KEY_SIZE; + unsigned char saltTLS_CIPHER_SM4_GCM_SALT_SIZE; + unsigned char rec_seqTLS_CIPHER_SM4_GCM_REC_SEQ_SIZE; +}; + +struct tls12_crypto_info_sm4_ccm { + struct tls_crypto_info info; + unsigned char ivTLS_CIPHER_SM4_CCM_IV_SIZE; + unsigned char keyTLS_CIPHER_SM4_CCM_KEY_SIZE; + unsigned char saltTLS_CIPHER_SM4_CCM_SALT_SIZE; + unsigned char rec_seqTLS_CIPHER_SM4_CCM_REC_SEQ_SIZE; +}; + +struct tls12_crypto_info_aria_gcm_128 { + struct tls_crypto_info info; + unsigned char ivTLS_CIPHER_ARIA_GCM_128_IV_SIZE; + unsigned char keyTLS_CIPHER_ARIA_GCM_128_KEY_SIZE; + unsigned char saltTLS_CIPHER_ARIA_GCM_128_SALT_SIZE; + unsigned char rec_seqTLS_CIPHER_ARIA_GCM_128_REC_SEQ_SIZE; +}; + +struct tls12_crypto_info_aria_gcm_256 { + struct tls_crypto_info info; + unsigned char ivTLS_CIPHER_ARIA_GCM_256_IV_SIZE; + unsigned char keyTLS_CIPHER_ARIA_GCM_256_KEY_SIZE; + unsigned char saltTLS_CIPHER_ARIA_GCM_256_SALT_SIZE; + unsigned char rec_seqTLS_CIPHER_ARIA_GCM_256_REC_SEQ_SIZE; +}; + enum { TLS_INFO_UNSPEC, TLS_INFO_VERSION, TLS_INFO_CIPHER, TLS_INFO_TXCONF, TLS_INFO_RXCONF, + TLS_INFO_ZC_RO_TX, + TLS_INFO_RX_NO_PAD, __TLS_INFO_MAX, }; #define TLS_INFO_MAX (__TLS_INFO_MAX - 1)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/types.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/types.h
Changed
@@ -14,12 +14,15 @@ * any application/library that wants linux/types.h. */ +/* sparse defines __CHECKER__; see Documentation/dev-tools/sparse.rst */ #ifdef __CHECKER__ -#define __bitwise__ __attribute__((bitwise)) +#define __bitwise __attribute__((bitwise)) #else -#define __bitwise__ +#define __bitwise #endif -#define __bitwise __bitwise__ + +/* The kernel doesn't use this legacy form, but user space does */ +#define __bitwise__ __bitwise typedef __u16 __bitwise __le16; typedef __u16 __bitwise __be16;
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/virtio_config.h
Added
@@ -0,0 +1,104 @@ +#ifndef _LINUX_VIRTIO_CONFIG_H +#define _LINUX_VIRTIO_CONFIG_H +/* This header, excluding the #ifdef __KERNEL__ part, is BSD licensed so + * anyone can use the definitions to implement compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ + +/* Virtio devices use a standardized configuration space to define their + * features and pass configuration information, but each implementation can + * store and access that space differently. */ +#include <linux/types.h> + +/* Status byte for guest to report progress, and synchronize features. */ +/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */ +#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1 +/* We have found a driver for the device. */ +#define VIRTIO_CONFIG_S_DRIVER 2 +/* Driver has used its parts of the config, and is happy */ +#define VIRTIO_CONFIG_S_DRIVER_OK 4 +/* Driver has finished configuring features */ +#define VIRTIO_CONFIG_S_FEATURES_OK 8 +/* Device entered invalid state, driver must reset it */ +#define VIRTIO_CONFIG_S_NEEDS_RESET 0x40 +/* We've given up on this device. */ +#define VIRTIO_CONFIG_S_FAILED 0x80 + +/* + * Virtio feature bits VIRTIO_TRANSPORT_F_START through + * VIRTIO_TRANSPORT_F_END are reserved for the transport + * being used (e.g. virtio_ring, virtio_pci etc.), the + * rest are per-device feature bits. + */ +#define VIRTIO_TRANSPORT_F_START 28 +#define VIRTIO_TRANSPORT_F_END 41 + +#ifndef VIRTIO_CONFIG_NO_LEGACY +/* Do we get callbacks when the ring is completely used, even if we've + * suppressed them? */ +#define VIRTIO_F_NOTIFY_ON_EMPTY 24 + +/* Can the device handle any descriptor layout? */ +#define VIRTIO_F_ANY_LAYOUT 27 +#endif /* VIRTIO_CONFIG_NO_LEGACY */ + +/* v1.0 compliant. */ +#define VIRTIO_F_VERSION_1 32 + +/* + * If clear - device has the platform DMA (e.g. IOMMU) bypass quirk feature. + * If set - use platform DMA tools to access the memory. + * + * Note the reverse polarity (compared to most other features), + * this is for compatibility with legacy systems. + */ +#define VIRTIO_F_ACCESS_PLATFORM 33 +/* Legacy name for VIRTIO_F_ACCESS_PLATFORM (for compatibility with old userspace) */ +#define VIRTIO_F_IOMMU_PLATFORM VIRTIO_F_ACCESS_PLATFORM + +/* This feature indicates support for the packed virtqueue layout. */ +#define VIRTIO_F_RING_PACKED 34 + +/* + * Inorder feature indicates that all buffers are used by the device + * in the same order in which they have been made available. + */ +#define VIRTIO_F_IN_ORDER 35 + +/* + * This feature indicates that memory accesses by the driver and the + * device are ordered in a way described by the platform. + */ +#define VIRTIO_F_ORDER_PLATFORM 36 + +/* + * Does the device support Single Root I/O Virtualization? + */ +#define VIRTIO_F_SR_IOV 37 + +/* + * This feature indicates that the driver can reset a queue individually. + */ +#define VIRTIO_F_RING_RESET 40 +#endif /* _LINUX_VIRTIO_CONFIG_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/virtio_ids.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/virtio_ids.h
Changed
@@ -73,12 +73,12 @@ * Virtio Transitional IDs */ -#define VIRTIO_TRANS_ID_NET 1000 /* transitional virtio net */ -#define VIRTIO_TRANS_ID_BLOCK 1001 /* transitional virtio block */ -#define VIRTIO_TRANS_ID_BALLOON 1002 /* transitional virtio balloon */ -#define VIRTIO_TRANS_ID_CONSOLE 1003 /* transitional virtio console */ -#define VIRTIO_TRANS_ID_SCSI 1004 /* transitional virtio SCSI */ -#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */ -#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */ +#define VIRTIO_TRANS_ID_NET 0x1000 /* transitional virtio net */ +#define VIRTIO_TRANS_ID_BLOCK 0x1001 /* transitional virtio block */ +#define VIRTIO_TRANS_ID_BALLOON 0x1002 /* transitional virtio balloon */ +#define VIRTIO_TRANS_ID_CONSOLE 0x1003 /* transitional virtio console */ +#define VIRTIO_TRANS_ID_SCSI 0x1004 /* transitional virtio SCSI */ +#define VIRTIO_TRANS_ID_RNG 0x1005 /* transitional virtio rng */ +#define VIRTIO_TRANS_ID_9P 0x1009 /* transitional virtio 9p console */ #endif /* _LINUX_VIRTIO_IDS_H */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/virtio_net.h
Added
@@ -0,0 +1,390 @@ +#ifndef _LINUX_VIRTIO_NET_H +#define _LINUX_VIRTIO_NET_H +/* This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ +#include <linux/types.h> +#include <linux/virtio_ids.h> +#include <linux/virtio_config.h> +#include <linux/virtio_types.h> +#include <linux/if_ether.h> + +/* The feature bitmap for virtio net */ +#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */ +#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */ +#define VIRTIO_NET_F_CTRL_GUEST_OFFLOADS 2 /* Dynamic offload configuration. */ +#define VIRTIO_NET_F_MTU 3 /* Initial MTU advice */ +#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */ +#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */ +#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */ +#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO6 w/ ECN in. */ +#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */ +#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */ +#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */ +#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO6 w/ ECN in. */ +#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */ +#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */ +#define VIRTIO_NET_F_STATUS 16 /* virtio_net_config.status available */ +#define VIRTIO_NET_F_CTRL_VQ 17 /* Control channel available */ +#define VIRTIO_NET_F_CTRL_RX 18 /* Control channel RX mode support */ +#define VIRTIO_NET_F_CTRL_VLAN 19 /* Control channel VLAN filtering */ +#define VIRTIO_NET_F_CTRL_RX_EXTRA 20 /* Extra RX mode control support */ +#define VIRTIO_NET_F_GUEST_ANNOUNCE 21 /* Guest can announce device on the + * network */ +#define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow + * Steering */ +#define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ +#define VIRTIO_NET_F_NOTF_COAL 53 /* Device supports notifications coalescing */ +#define VIRTIO_NET_F_HASH_REPORT 57 /* Supports hash report */ +#define VIRTIO_NET_F_RSS 60 /* Supports RSS RX steering */ +#define VIRTIO_NET_F_RSC_EXT 61 /* extended coalescing info */ +#define VIRTIO_NET_F_STANDBY 62 /* Act as standby for another device + * with the same MAC. + */ +#define VIRTIO_NET_F_SPEED_DUPLEX 63 /* Device set linkspeed and duplex */ + +#ifndef VIRTIO_NET_NO_LEGACY +#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */ +#endif /* VIRTIO_NET_NO_LEGACY */ + +#define VIRTIO_NET_S_LINK_UP 1 /* Link is up */ +#define VIRTIO_NET_S_ANNOUNCE 2 /* Announcement is needed */ + +/* supported/enabled hash types */ +#define VIRTIO_NET_RSS_HASH_TYPE_IPv4 (1 << 0) +#define VIRTIO_NET_RSS_HASH_TYPE_TCPv4 (1 << 1) +#define VIRTIO_NET_RSS_HASH_TYPE_UDPv4 (1 << 2) +#define VIRTIO_NET_RSS_HASH_TYPE_IPv6 (1 << 3) +#define VIRTIO_NET_RSS_HASH_TYPE_TCPv6 (1 << 4) +#define VIRTIO_NET_RSS_HASH_TYPE_UDPv6 (1 << 5) +#define VIRTIO_NET_RSS_HASH_TYPE_IP_EX (1 << 6) +#define VIRTIO_NET_RSS_HASH_TYPE_TCP_EX (1 << 7) +#define VIRTIO_NET_RSS_HASH_TYPE_UDP_EX (1 << 8) + +struct virtio_net_config { + /* The config defining mac address (if VIRTIO_NET_F_MAC) */ + __u8 macETH_ALEN; + /* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */ + __virtio16 status; + /* Maximum number of each of transmit and receive queues; + * see VIRTIO_NET_F_MQ and VIRTIO_NET_CTRL_MQ. + * Legal values are between 1 and 0x8000 + */ + __virtio16 max_virtqueue_pairs; + /* Default maximum transmit unit advice */ + __virtio16 mtu; + /* + * speed, in units of 1Mb. All values 0 to INT_MAX are legal. + * Any other value stands for unknown. + */ + __le32 speed; + /* + * 0x00 - half duplex + * 0x01 - full duplex + * Any other value stands for unknown. + */ + __u8 duplex; + /* maximum size of RSS key */ + __u8 rss_max_key_size; + /* maximum number of indirection table entries */ + __le16 rss_max_indirection_table_length; + /* bitmask of supported VIRTIO_NET_RSS_HASH_ types */ + __le32 supported_hash_types; +} __attribute__((packed)); + +/* + * This header comes first in the scatter-gather list. If you don't + * specify GSO or CSUM features, you can simply ignore the header. + * + * This is bitwise-equivalent to the legacy struct virtio_net_hdr_mrg_rxbuf, + * only flattened. + */ +struct virtio_net_hdr_v1 { +#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 /* Use csum_start, csum_offset */ +#define VIRTIO_NET_HDR_F_DATA_VALID 2 /* Csum is valid */ +#define VIRTIO_NET_HDR_F_RSC_INFO 4 /* rsc info in csum_ fields */ + __u8 flags; +#define VIRTIO_NET_HDR_GSO_NONE 0 /* Not a GSO frame */ +#define VIRTIO_NET_HDR_GSO_TCPV4 1 /* GSO frame, IPv4 TCP (TSO) */ +#define VIRTIO_NET_HDR_GSO_UDP 3 /* GSO frame, IPv4 UDP (UFO) */ +#define VIRTIO_NET_HDR_GSO_TCPV6 4 /* GSO frame, IPv6 TCP */ +#define VIRTIO_NET_HDR_GSO_ECN 0x80 /* TCP has ECN set */ + __u8 gso_type; + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ + union { + struct { + __virtio16 csum_start; + __virtio16 csum_offset; + }; + /* Checksum calculation */ + struct { + /* Position to start checksumming from */ + __virtio16 start; + /* Offset after that to place checksum */ + __virtio16 offset; + } csum; + /* Receive Segment Coalescing */ + struct { + /* Number of coalesced segments */ + __le16 segments; + /* Number of duplicated acks */ + __le16 dup_acks; + } rsc; + }; + __virtio16 num_buffers; /* Number of merged rx buffers */ +}; + +struct virtio_net_hdr_v1_hash { + struct virtio_net_hdr_v1 hdr; + __le32 hash_value; +#define VIRTIO_NET_HASH_REPORT_NONE 0 +#define VIRTIO_NET_HASH_REPORT_IPv4 1 +#define VIRTIO_NET_HASH_REPORT_TCPv4 2 +#define VIRTIO_NET_HASH_REPORT_UDPv4 3 +#define VIRTIO_NET_HASH_REPORT_IPv6 4 +#define VIRTIO_NET_HASH_REPORT_TCPv6 5 +#define VIRTIO_NET_HASH_REPORT_UDPv6 6 +#define VIRTIO_NET_HASH_REPORT_IPv6_EX 7 +#define VIRTIO_NET_HASH_REPORT_TCPv6_EX 8 +#define VIRTIO_NET_HASH_REPORT_UDPv6_EX 9 + __le16 hash_report; + __le16 padding; +}; + +#ifndef VIRTIO_NET_NO_LEGACY +/* This header comes first in the scatter-gather list. + * For legacy virtio, if VIRTIO_F_ANY_LAYOUT is not negotiated, it must + * be the first element of the scatter-gather list. If you don't + * specify GSO or CSUM features, you can simply ignore the header. */ +struct virtio_net_hdr { + /* See VIRTIO_NET_HDR_F_* */ + __u8 flags; + /* See VIRTIO_NET_HDR_GSO_* */ + __u8 gso_type; + __virtio16 hdr_len; /* Ethernet + IP + tcp/udp hdrs */ + __virtio16 gso_size; /* Bytes to append to hdr_len per frame */ + __virtio16 csum_start; /* Position to start checksumming from */ + __virtio16 csum_offset; /* Offset after that to place checksum */ +}; + +/* This is the version of the header to use when the MRG_RXBUF + * feature has been negotiated. */ +struct virtio_net_hdr_mrg_rxbuf { + struct virtio_net_hdr hdr; + __virtio16 num_buffers; /* Number of merged rx buffers */ +}; +#endif /* ...VIRTIO_NET_NO_LEGACY */ + +/* + * Control virtqueue data structures + * + * The control virtqueue expects a header in the first sg entry + * and an ack/status response in the last entry. Data for the + * command goes in between. + */ +struct virtio_net_ctrl_hdr { + __u8 class; + __u8 cmd; +} __attribute__((packed)); + +typedef __u8 virtio_net_ctrl_ack; + +#define VIRTIO_NET_OK 0 +#define VIRTIO_NET_ERR 1 + +/* + * Control the RX mode, ie. promisucous, allmulti, etc... + * All commands require an "out" sg entry containing a 1 byte + * state value, zero = disable, non-zero = enable. Commands + * 0 and 1 are supported with the VIRTIO_NET_F_CTRL_RX feature. + * Commands 2-5 are added with VIRTIO_NET_F_CTRL_RX_EXTRA. + */ +#define VIRTIO_NET_CTRL_RX 0 + #define VIRTIO_NET_CTRL_RX_PROMISC 0 + #define VIRTIO_NET_CTRL_RX_ALLMULTI 1 + #define VIRTIO_NET_CTRL_RX_ALLUNI 2 + #define VIRTIO_NET_CTRL_RX_NOMULTI 3 + #define VIRTIO_NET_CTRL_RX_NOUNI 4 + #define VIRTIO_NET_CTRL_RX_NOBCAST 5 + +/* + * Control the MAC + * + * The MAC filter table is managed by the hypervisor, the guest should + * assume the size is infinite. Filtering should be considered + * non-perfect, ie. based on hypervisor resources, the guest may + * received packets from sources not specified in the filter list. + * + * In addition to the class/cmd header, the TABLE_SET command requires + * two out scatterlists. Each contains a 4 byte count of entries followed + * by a concatenated byte stream of the ETH_ALEN MAC addresses. The + * first sg list contains unicast addresses, the second is for multicast. + * This functionality is present if the VIRTIO_NET_F_CTRL_RX feature + * is available. + * + * The ADDR_SET command requests one out scatterlist, it contains a + * 6 bytes MAC address. This functionality is present if the + * VIRTIO_NET_F_CTRL_MAC_ADDR feature is available. + */ +struct virtio_net_ctrl_mac { + __virtio32 entries; + __u8 macsETH_ALEN; +} __attribute__((packed)); + +#define VIRTIO_NET_CTRL_MAC 1 + #define VIRTIO_NET_CTRL_MAC_TABLE_SET 0 + #define VIRTIO_NET_CTRL_MAC_ADDR_SET 1 + +/* + * Control VLAN filtering + * + * The VLAN filter table is controlled via a simple ADD/DEL interface. + * VLAN IDs not added may be filterd by the hypervisor. Del is the + * opposite of add. Both commands expect an out entry containing a 2 + * byte VLAN ID. VLAN filterting is available with the + * VIRTIO_NET_F_CTRL_VLAN feature bit. + */ +#define VIRTIO_NET_CTRL_VLAN 2 + #define VIRTIO_NET_CTRL_VLAN_ADD 0 + #define VIRTIO_NET_CTRL_VLAN_DEL 1 + +/* + * Control link announce acknowledgement + * + * The command VIRTIO_NET_CTRL_ANNOUNCE_ACK is used to indicate that + * driver has recevied the notification; device would clear the + * VIRTIO_NET_S_ANNOUNCE bit in the status field after it receives + * this command. + */ +#define VIRTIO_NET_CTRL_ANNOUNCE 3 + #define VIRTIO_NET_CTRL_ANNOUNCE_ACK 0 + +/* + * Control Receive Flow Steering + */ +#define VIRTIO_NET_CTRL_MQ 4 +/* + * The command VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET + * enables Receive Flow Steering, specifying the number of the transmit and + * receive queues that will be used. After the command is consumed and acked by + * the device, the device will not steer new packets on receive virtqueues + * other than specified nor read from transmit virtqueues other than specified. + * Accordingly, driver should not transmit new packets on virtqueues other than + * specified. + */ +struct virtio_net_ctrl_mq { + __virtio16 virtqueue_pairs; +}; + + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET 0 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN 1 + #define VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX 0x8000 + +/* + * The command VIRTIO_NET_CTRL_MQ_RSS_CONFIG has the same effect as + * VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET does and additionally configures + * the receive steering to use a hash calculated for incoming packet + * to decide on receive virtqueue to place the packet. The command + * also provides parameters to calculate a hash and receive virtqueue. + */ +struct virtio_net_rss_config { + __le32 hash_types; + __le16 indirection_table_mask; + __le16 unclassified_queue; + __le16 indirection_table1/* + indirection_table_mask */; + __le16 max_tx_vq; + __u8 hash_key_length; + __u8 hash_key_data/* hash_key_length */; +}; + + #define VIRTIO_NET_CTRL_MQ_RSS_CONFIG 1 + +/* + * The command VIRTIO_NET_CTRL_MQ_HASH_CONFIG requests the device + * to include in the virtio header of the packet the value of the + * calculated hash and the report type of hash. It also provides + * parameters for hash calculation. The command requires feature + * VIRTIO_NET_F_HASH_REPORT to be negotiated to extend the + * layout of virtio header as defined in virtio_net_hdr_v1_hash. + */ +struct virtio_net_hash_config { + __le32 hash_types; + /* for compatibility with virtio_net_rss_config */ + __le16 reserved4; + __u8 hash_key_length; + __u8 hash_key_data/* hash_key_length */; +}; + + #define VIRTIO_NET_CTRL_MQ_HASH_CONFIG 2 + +/* + * Control network offloads + * + * Reconfigures the network offloads that Guest can handle. + * + * Available with the VIRTIO_NET_F_CTRL_GUEST_OFFLOADS feature bit. + * + * Command data format matches the feature bit mask exactly. + * + * See VIRTIO_NET_F_GUEST_* for the list of offloads + * that can be enabled/disabled. + */ +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 +#define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 + +/* + * Control notifications coalescing. + * + * Request the device to change the notifications coalescing parameters. + * + * Available with the VIRTIO_NET_F_NOTF_COAL feature bit. + */ +#define VIRTIO_NET_CTRL_NOTF_COAL 6 +/* + * Set the tx-usecs/tx-max-packets parameters. + */ +struct virtio_net_ctrl_coal_tx { + /* Maximum number of packets to send before a TX notification */ + __le32 tx_max_packets; + /* Maximum number of usecs to delay a TX notification */ + __le32 tx_usecs; +}; + +#define VIRTIO_NET_CTRL_NOTF_COAL_TX_SET 0 + +/* + * Set the rx-usecs/rx-max-packets parameters. + */ +struct virtio_net_ctrl_coal_rx { + /* Maximum number of packets to receive before a RX notification */ + __le32 rx_max_packets; + /* Maximum number of usecs to delay a RX notification */ + __le32 rx_usecs; +}; + +#define VIRTIO_NET_CTRL_NOTF_COAL_RX_SET 1 + +#endif /* _LINUX_VIRTIO_NET_H */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/virtio_types.h
Added
@@ -0,0 +1,46 @@ +#ifndef _LINUX_VIRTIO_TYPES_H +#define _LINUX_VIRTIO_TYPES_H +/* Type definitions for virtio implementations. + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright (C) 2014 Red Hat, Inc. + * Author: Michael S. Tsirkin <mst@redhat.com> + */ +#include <linux/types.h> + +/* + * __virtio{16,32,64} have the following meaning: + * - __u{16,32,64} for virtio devices in legacy mode, accessed in native endian + * - __le{16,32,64} for standard-compliant virtio devices + */ + +typedef __u16 __bitwise __virtio16; +typedef __u32 __bitwise __virtio32; +typedef __u64 __bitwise __virtio64; + +#endif /* _LINUX_VIRTIO_TYPES_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/uapi/linux/xfrm.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/uapi/linux/xfrm.h
Changed
@@ -33,7 +33,7 @@ __u8 ctx_alg; __u16 ctx_len; __u32 ctx_sid; - char ctx_str0; + char ctx_str; }; /* Security Context Domains of Interpretation */ @@ -96,27 +96,27 @@ __u32 oseq_hi; __u32 seq_hi; __u32 replay_window; - __u32 bmp0; + __u32 bmp; }; struct xfrm_algo { char alg_name64; unsigned int alg_key_len; /* in bits */ - char alg_key0; + char alg_key; }; struct xfrm_algo_auth { char alg_name64; unsigned int alg_key_len; /* in bits */ unsigned int alg_trunc_len; /* in bits */ - char alg_key0; + char alg_key; }; struct xfrm_algo_aead { char alg_name64; unsigned int alg_key_len; /* in bits */ unsigned int alg_icv_len; /* in bits */ - char alg_key0; + char alg_key; }; struct xfrm_stats { @@ -296,7 +296,7 @@ XFRMA_ETIMER_THRESH, XFRMA_SRCADDR, /* xfrm_address_t */ XFRMA_COADDR, /* xfrm_address_t */ - XFRMA_LASTUSED, /* unsigned long */ + XFRMA_LASTUSED, /* __u64 */ XFRMA_POLICY_TYPE, /* struct xfrm_userpolicy_type */ XFRMA_MIGRATE, XFRMA_ALG_AEAD, /* struct xfrm_algo_aead */ @@ -313,6 +313,7 @@ XFRMA_SET_MARK, /* __u32 */ XFRMA_SET_MARK_MASK, /* __u32 */ XFRMA_IF_ID, /* __u32 */ + XFRMA_MTIMER_THRESH, /* __u32 in seconds for input SA */ __XFRMA_MAX #define XFRMA_OUTPUT_MARK XFRMA_SET_MARK /* Compatibility */ @@ -510,6 +511,12 @@ int ifindex; __u8 flags; }; +/* This flag was exposed without any kernel code that supports it. + * Unfortunately, strongswan has the code that sets this flag, + * which makes it impossible to reuse this bit. + * + * So leave it here to make sure that it won't be reused by mistake. + */ #define XFRM_OFFLOAD_IPV6 1 #define XFRM_OFFLOAD_INBOUND 2
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/utils.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/utils.h
Changed
@@ -36,6 +36,7 @@ extern int batch_mode; extern int numeric; extern bool do_all; +extern int echo_request; #ifndef CONFDIR #define CONFDIR "/etc/iproute2" @@ -198,9 +199,15 @@ int inet_addr_match(const inet_prefix *a, const inet_prefix *b, int bits); int inet_addr_match_rta(const inet_prefix *m, const struct rtattr *rta); +const char *ax25_ntop(int af, const void *addr, char *str, socklen_t len); + +const char *rose_ntop(int af, const void *addr, char *buf, socklen_t buflen); + const char *mpls_ntop(int af, const void *addr, char *str, size_t len); int mpls_pton(int af, const char *src, void *addr, size_t alen); +const char *netrom_ntop(int af, const void *addr, char *str, socklen_t len); + extern int __iproute2_hz_internal; int __get_hz(void); @@ -255,7 +262,9 @@ void print_nlmsg_timestamp(FILE *fp, const struct nlmsghdr *n); unsigned int print_name_and_link(const char *fmt, - const char *name, struct rtattr *tb); + const char *name, struct rtattr *tb) + __attribute__((format(printf, 1, 0))); + #define BIT(nr) (UINT64_C(1) << (nr)) @@ -301,7 +310,7 @@ __u64 get_cgroup2_id(const char *path); char *get_cgroup2_path(__u64 id, bool full); int get_command_name(const char *pid, char *comm, size_t len); -char *get_task_name(pid_t pid); +int get_task_name(pid_t pid, char *name, size_t len); int get_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64, struct rtattr *tb); @@ -361,4 +370,14 @@ void dec_indent(struct indent_mem *mem); void print_indent(struct indent_mem *mem); +struct proto { + int id; + const char *name; +}; + +int proto_a2n(unsigned short *id, const char *buf, + const struct proto *proto_tb, size_t tb_len); +const char *proto_n2a(unsigned short id, char *buf, int len, + const struct proto *proto_tb, size_t tb_len); + #endif /* __UTILS_H__ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/include/version.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/include/version.h
Changed
@@ -1,1 +1,1 @@ -static const char version = "5.15.0"; +static const char version = "6.1.0";
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/Makefile
Changed
@@ -8,17 +8,19 @@ iplink_macvlan.o ipl2tp.o link_vti.o link_vti6.o link_xfrm.o \ iplink_vxlan.o tcp_metrics.o iplink_ipoib.o ipnetconf.o link_ip6tnl.o \ link_iptnl.o link_gre6.o iplink_bond.o iplink_bond_slave.o iplink_hsr.o \ - iplink_bridge.o iplink_bridge_slave.o ipfou.o iplink_ipvlan.o \ + iplink_bridge.o iplink_bridge_slave.o iplink_dsa.o ipfou.o iplink_ipvlan.o \ iplink_geneve.o iplink_vrf.o iproute_lwtunnel.o ipmacsec.o ipila.o \ ipvrf.o iplink_xstats.o ipseg6.o iplink_netdevsim.o iplink_rmnet.o \ - ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o + ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o \ + iplink_amt.o iplink_batadv.o iplink_gtp.o iplink_virt_wifi.o \ + ipstats.o RTMONOBJ=rtmon.o include ../config.mk ALLOBJ=$(IPOBJ) $(RTMONOBJ) -SCRIPTS=ifcfg rtpr routel routef +SCRIPTS=routel TARGETS=ip rtmon all: $(TARGETS) $(SCRIPTS)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ip.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ip.c
Changed
@@ -39,6 +39,7 @@ int brief; int json; int timestamp; +int echo_request; int force; int max_flush_loops = 10; int batch_mode; @@ -64,8 +65,8 @@ fprintf(stderr, "Usage: ip OPTIONS OBJECT { COMMAND | help }\n" " ip -force -batch filename\n" - "where OBJECT := { address | addrlabel | fou | help | ila | ioam | l2tp | link |\n" - " macsec | maddress | monitor | mptcp | mroute | mrule |\n" + "where OBJECT := { address | addrlabel | amt | fou | help | ila | ioam | l2tp |\n" + " link | macsec | maddress | monitor | mptcp | mroute | mrule |\n" " neighbor | neighbour | netconf | netns | nexthop | ntable |\n" " ntbl | route | rule | sr | tap | tcpmetrics |\n" " token | tunnel | tuntap | vrf | xfrm }\n" @@ -123,6 +124,7 @@ { "mptcp", do_mptcp }, { "ioam", do_ioam6 }, { "help", do_help }, + { "stats", do_ipstats }, { 0 } }; @@ -292,6 +294,8 @@ ++numeric; } else if (matches(opt, "-all") == 0) { do_all = true; + } else if (strcmp(opt, "-echo") == 0) { + ++echo_request; } else { fprintf(stderr, "Option \"%s\" is unknown, try \"ip -help\".\n",
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ip_common.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ip_common.h
Changed
@@ -3,6 +3,7 @@ #define _IP_COMMON_H_ #include <stdbool.h> +#include <linux/mpls.h> #include "json_print.h" @@ -53,11 +54,11 @@ int print_rule(struct nlmsghdr *n, void *arg); int print_netconf(struct rtnl_ctrl_data *ctrl, struct nlmsghdr *n, void *arg); -int print_nexthop(struct nlmsghdr *n, void *arg); int print_nexthop_bucket(struct nlmsghdr *n, void *arg); void netns_map_init(void); void netns_nsid_socket_init(void); int print_nsid(struct nlmsghdr *n, void *arg); +int ipstats_print(struct nlmsghdr *n, void *arg); char *get_name_from_nsid(int nsid); int get_netnsid_from_name(const char *name); int set_netnsid_from_name(const char *name, int nsid); @@ -91,6 +92,7 @@ int do_ipnh(int argc, char **argv); int do_mptcp(int argc, char **argv); int do_ioam6(int argc, char **argv); +int do_ipstats(int argc, char **argv); int iplink_get(char *name, __u32 filt_mask); int iplink_ifla_xstats(int argc, char **argv); @@ -140,9 +142,14 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len); int bridge_parse_xstats(struct link_util *lu, int argc, char **argv); int bridge_print_xstats(struct nlmsghdr *n, void *arg); +extern const struct ipstats_stat_desc ipstats_stat_desc_xstats_bridge_group; +extern const struct ipstats_stat_desc ipstats_stat_desc_xstats_slave_bridge_group; +/* iplink_bond.c */ int bond_parse_xstats(struct link_util *lu, int argc, char **argv); int bond_print_xstats(struct nlmsghdr *n, void *arg); +extern const struct ipstats_stat_desc ipstats_stat_desc_xstats_bond_group; +extern const struct ipstats_stat_desc ipstats_stat_desc_xstats_slave_bond_group; /* iproute_lwtunnel.c */ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, @@ -158,6 +165,53 @@ __u32 ipvrf_get_table(const char *name); int name_is_vrf(const char *name); +/* ipstats.c */ +enum ipstats_stat_desc_kind { + IPSTATS_STAT_DESC_KIND_LEAF, + IPSTATS_STAT_DESC_KIND_GROUP, +}; + +struct ipstats_stat_dump_filters; +struct ipstats_stat_show_attrs; + +struct ipstats_stat_desc { + const char *name; + enum ipstats_stat_desc_kind kind; + union { + struct { + const struct ipstats_stat_desc **subs; + size_t nsubs; + }; + struct { + void (*pack)(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc); + int (*show)(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc); + }; + }; +}; + +struct ipstats_stat_desc_xstats { + const struct ipstats_stat_desc desc; + int xstats_at; + int link_type_at; + int inner_max; + int inner_at; + void (*show_cb)(const struct rtattr *at); +}; + +void ipstats_stat_desc_pack_xstats(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc); +int ipstats_stat_desc_show_xstats(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc); + +#define IPSTATS_STAT_DESC_XSTATS_LEAF(NAME) { \ + .name = (NAME), \ + .kind = IPSTATS_STAT_DESC_KIND_LEAF, \ + .show = &ipstats_stat_desc_show_xstats, \ + .pack = &ipstats_stat_desc_pack_xstats, \ + } + #ifndef INFINITY_LIFE_TIME #define INFINITY_LIFE_TIME 0xFFFFFFFFU #endif @@ -168,7 +222,13 @@ void print_num(FILE *fp, unsigned int width, uint64_t count); void print_rt_flags(FILE *fp, unsigned int flags); -void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix); +void print_rta_ifidx(FILE *fp, __u32 ifidx, const char *prefix); +void __print_rta_gateway(FILE *fp, unsigned char family, const char *gateway); void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta); +void size_columns(unsigned int cols, unsigned int n, ...); +void print_stats64(FILE *fp, struct rtnl_link_stats64 *s, + const struct rtattr *carrier_changes, const char *what); +void print_mpls_link_stats(FILE *fp, const struct mpls_link_stats *stats, + const char *indent); #endif /* _IP_COMMON_H_ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipaddress.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipaddress.c
Changed
@@ -60,6 +60,7 @@ " ip address {save|flush} dev IFNAME scope SCOPE-ID \n" " to PREFIX FLAG-LIST label LABEL up\n" " ip address show dev IFNAME scope SCOPE-ID master DEVICE \n" + " nomaster \n" " type TYPE to PREFIX FLAG-LIST \n" " label LABEL up vrf NAME \n" " ip address {showdump|restore}\n" @@ -545,10 +546,10 @@ print_vf_stats64(fp, vfIFLA_VF_STATS); } -static void size_columns(unsigned int cols, unsigned int n, ...) +void size_columns(unsigned int cols, unsigned int n, ...) { unsigned int i, len; - uint64_t val, powi; + uint64_t val; va_list args; va_start(args, n); @@ -559,7 +560,7 @@ if (human_readable) continue; - for (len = 1, powi = 10; powi < val; len++, powi *= 10) + for (len = 1; val > 9; len++, val /= 10) /* nothing */; if (len > colsi) colsi = len; @@ -679,10 +680,10 @@ } } -static void __print_link_stats(FILE *fp, struct rtattr *tb) +void print_stats64(FILE *fp, struct rtnl_link_stats64 *s, + const struct rtattr *carrier_changes, + const char *what) { - const struct rtattr *carrier_changes = tbIFLA_CARRIER_CHANGES; - struct rtnl_link_stats64 _s, *s = &_s; unsigned int cols = { strlen("*X errors:"), strlen("packets"), @@ -691,15 +692,12 @@ strlen("heartbt"), strlen("overrun"), strlen("compressed"), + strlen("otherhost"), }; - int ret; - - ret = get_rtnl_link_stats_rta(s, tb); - if (ret < 0) - return; if (is_json_context()) { - open_json_object((ret == sizeof(*s)) ? "stats64" : "stats"); + if (what) + open_json_object(what); /* RX stats */ open_json_object("rx"); @@ -733,6 +731,10 @@ if (s->rx_nohandler) print_u64(PRINT_JSON, "nohandler", NULL, s->rx_nohandler); + if (s->rx_otherhost_dropped) + print_u64(PRINT_JSON, + "otherhost", NULL, + s->rx_otherhost_dropped); } close_json_object(); @@ -770,28 +772,34 @@ } close_json_object(); - close_json_object(); + if (what) + close_json_object(); } else { + uint64_t zero64 = 0; + size_columns(cols, ARRAY_SIZE(cols), s->rx_bytes, s->rx_packets, s->rx_errors, s->rx_dropped, s->rx_missed_errors, - s->multicast, s->rx_compressed); + s->multicast, s->rx_compressed, zero64); if (show_stats > 1) size_columns(cols, ARRAY_SIZE(cols), 0, s->rx_length_errors, s->rx_crc_errors, s->rx_frame_errors, s->rx_fifo_errors, - s->rx_over_errors, s->rx_nohandler); + s->rx_over_errors, s->rx_nohandler, + s->rx_otherhost_dropped); size_columns(cols, ARRAY_SIZE(cols), s->tx_bytes, s->tx_packets, s->tx_errors, s->tx_dropped, s->tx_carrier_errors, - s->collisions, s->tx_compressed); - if (show_stats > 1) + s->collisions, s->tx_compressed, zero64); + if (show_stats > 1) { + uint64_t cc = carrier_changes ? + rta_getattr_u32(carrier_changes) : 0; + size_columns(cols, ARRAY_SIZE(cols), 0, 0, s->tx_aborted_errors, s->tx_fifo_errors, s->tx_window_errors, - s->tx_heartbeat_errors, - carrier_changes ? - rta_getattr_u32(carrier_changes) : 0); + s->tx_heartbeat_errors, cc, zero64); + } /* RX stats */ fprintf(fp, " RX: %*s %*s %*s %*s %*s %*s %*s%s", @@ -813,11 +821,14 @@ /* RX error stats */ if (show_stats > 1) { fprintf(fp, "%s", _SL_); - fprintf(fp, " RX errors:%*s %*s %*s %*s %*s %*s %*s%s", + fprintf(fp, " RX errors:%*s %*s %*s %*s %*s %*s%*s%*s%s", cols0 - 10, "", cols1, "length", cols2, "crc", cols3, "frame", cols4, "fifo", cols5, "overrun", - cols6, s->rx_nohandler ? "nohandler" : "", + s->rx_nohandler ? cols6 + 1 : 0, + s->rx_nohandler ? " nohandler" : "", + s->rx_otherhost_dropped ? cols7 + 1 : 0, + s->rx_otherhost_dropped ? " otherhost" : "", _SL_); fprintf(fp, "%*s", cols0 + 5, ""); print_num(fp, cols1, s->rx_length_errors); @@ -827,6 +838,8 @@ print_num(fp, cols5, s->rx_over_errors); if (s->rx_nohandler) print_num(fp, cols6, s->rx_nohandler); + if (s->rx_otherhost_dropped) + print_num(fp, cols7, s->rx_otherhost_dropped); } fprintf(fp, "%s", _SL_); @@ -869,6 +882,20 @@ } } +static void __print_link_stats(FILE *fp, struct rtattr *tb) +{ + const struct rtattr *carrier_changes = tbIFLA_CARRIER_CHANGES; + struct rtnl_link_stats64 _s, *s = &_s; + int ret; + + ret = get_rtnl_link_stats_rta(s, tb); + if (ret < 0) + return; + + print_stats64(fp, s, carrier_changes, + (ret == sizeof(*s)) ? "stats64" : "stats"); +} + static void print_link_stats(FILE *fp, struct nlmsghdr *n) { struct ifinfomsg *ifi = NLMSG_DATA(n); @@ -1178,6 +1205,12 @@ " promiscuity %u ", rta_getattr_u32(tbIFLA_PROMISCUITY)); + if (tbIFLA_ALLMULTI) + print_uint(PRINT_ANY, + "allmulti", + " allmulti %u ", + rta_getattr_u32(tbIFLA_ALLMULTI)); + if (tbIFLA_MIN_MTU) print_uint(PRINT_ANY, "min_mtu", "minmtu %u ", @@ -1218,6 +1251,24 @@ "gso_max_segs %u ", rta_getattr_u32(tbIFLA_GSO_MAX_SEGS)); + if (tbIFLA_TSO_MAX_SIZE) + print_uint(PRINT_ANY, + "tso_max_size", + "tso_max_size %u ", + rta_getattr_u32(tbIFLA_TSO_MAX_SIZE)); + + if (tbIFLA_TSO_MAX_SEGS) + print_uint(PRINT_ANY, + "tso_max_segs", + "tso_max_segs %u ", + rta_getattr_u32(tbIFLA_TSO_MAX_SEGS)); + + if (tbIFLA_GRO_MAX_SIZE) + print_uint(PRINT_ANY, + "gro_max_size", + "gro_max_size %u ", + rta_getattr_u32(tbIFLA_GRO_MAX_SIZE)); + if (tbIFLA_PHYS_PORT_NAME) print_string(PRINT_ANY, "phys_port_name", @@ -1541,7 +1592,7 @@ if (!brief) { const char *name; - if (filter.oneline || filter.flushb) { + if (filter.oneline || filter.flushb || echo_request) { const char *dev = ll_index_to_name(ifa->ifa_index); if (is_json_context()) { @@ -2010,8 +2061,10 @@ if (store_nlmsg(answer, linfo) < 0) { fprintf(stderr, "Failed to process link information\n"); + free(answer); return 1; } + free(answer); return 0; } @@ -2123,6 +2176,8 @@ if (!name_is_vrf(*argv)) invarg("Not a valid VRF name\n", *argv); filter.master = ifindex; + } else if (strcmp(*argv, "nomaster") == 0) { + filter.master = -1; } else if (strcmp(*argv, "type") == 0) { int soff; @@ -2340,16 +2395,6 @@ return false; } -static bool is_valid_label(const char *dev, const char *label) -{ - size_t len = strlen(dev); - - if (strncmp(label, dev, len) != 0) - return false; - - return labellen == '\0' || labellen == ':'; -} - static int ipaddr_modify(int cmd, int flags, int argc, char **argv) { struct { @@ -2377,6 +2422,7 @@ __u32 preferred_lft = INFINITY_LIFE_TIME; __u32 valid_lft = INFINITY_LIFE_TIME; unsigned int ifa_flags = 0; + int ret; while (argc > 0) { if (strcmp(*argv, "peer") == 0 || @@ -2492,12 +2538,6 @@ fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); return -1; } - if (l && !is_valid_label(d, l)) { - fprintf(stderr, - "\"label\" (%s) must match \"dev\" (%s) or be prefixed by \"dev\" with a colon.\n", - l, d); - return -1; - } if (peer_len == 0 && local_len) { if (cmd == RTM_DELADDR && lcl.family == AF_INET && !(lcl.flags & PREFIXLEN_SPECIFIED)) { @@ -2564,7 +2604,12 @@ return -1; } - if (rtnl_talk(&rth, &req.n, NULL) < 0) + if (echo_request) + ret = rtnl_echo_talk(&rth, &req.n, json, print_addrinfo); + else + ret = rtnl_talk(&rth, &req.n, NULL); + + if (ret) return -2; return 0;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipl2tp.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipl2tp.c
Changed
@@ -191,8 +191,9 @@ return 0; } -static void print_cookie(const char *name, const char *fmt, - const uint8_t *cookie, int len) +static void __attribute__((format(printf, 2, 0))) +print_cookie(const char *name, const char *fmt, + const uint8_t *cookie, int len) { char abuf32; size_t n; @@ -257,7 +258,7 @@ NULL, p->udp6_csum_tx); print_bool(PRINT_JSON, "checksum_rx", - NULL, p->udp6_csum_tx); + NULL, p->udp6_csum_rx); } else { printf(" UDP checksum: %s%s%s%s\n", p->udp6_csum_tx && p->udp6_csum_rx
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink.c
Changed
@@ -35,9 +35,6 @@ #define IPLINK_IOCTL_COMPAT 1 -#ifndef GSO_MAX_SIZE -#define GSO_MAX_SIZE 65536 -#endif #ifndef GSO_MAX_SEGS #define GSO_MAX_SEGS 65535 #endif @@ -50,14 +47,14 @@ { /* Remember to add new entry here if new type is added. */ fprintf(stderr, - "TYPE := { bareudp | bond | bond_slave | bridge | bridge_slave |\n" - " dummy | erspan | geneve | gre | gretap | ifb |\n" + "TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n" + " dsa | dummy | erspan | geneve | gre | gretap | gtp | ifb |\n" " ip6erspan | ip6gre | ip6gretap | ip6tnl |\n" " ipip | ipoib | ipvlan | ipvtap |\n" " macsec | macvlan | macvtap |\n" " netdevsim | nlmon | rmnet | sit | team | team_slave |\n" " vcan | veth | vlan | vrf | vti | vxcan | vxlan | wwan |\n" - " xfrm }\n"); + " xfrm | virt_wifi }\n"); } void iplink_usage(void) @@ -71,6 +68,7 @@ " mtu MTU index IDX \n" " numtxqueues QUEUE_COUNT \n" " numrxqueues QUEUE_COUNT \n" + " netns { PID | NAME } \n" " type TYPE ARGS \n" "\n" " ip link delete { DEVICE | dev DEVICE | group DEVGROUP } type TYPE ARGS \n" @@ -110,7 +108,11 @@ " node_guid EUI64 \n" " port_guid EUI64 \n" " { xdp | xdpgeneric | xdpdrv | xdpoffload } { off |\n" +#ifdef HAVE_LIBBPF + " object FILE { section | program } NAME verbose |\n" +#else " object FILE section NAME verbose |\n" +#endif " pinned FILE } \n" " master DEVICE vrf NAME \n" " nomaster \n" @@ -118,8 +120,10 @@ " protodown { on | off } \n" " protodown_reason PREASON { on | off } \n" " gso_max_size BYTES | gso_max_segs PACKETS \n" + " gro_max_size BYTES \n" "\n" " ip link show DEVICE | group GROUP up master DEV vrf NAME type TYPE\n" + " nomaster\n" "\n" " ip link xstats type TYPE ARGS \n" "\n" @@ -578,6 +582,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type) { + bool move_netns = false; char *name = NULL; char *dev = NULL; char *link = NULL; @@ -683,6 +688,7 @@ IFLA_NET_NS_PID, &netns, 4); else invarg("Invalid \"netns\" value\n", *argv); + move_netns = true; } else if (strcmp(*argv, "multicast") == 0) { NEXT_ARG(); req->i.ifi_change |= IFF_MULTICAST; @@ -923,8 +929,7 @@ unsigned int max_size; NEXT_ARG(); - if (get_unsigned(&max_size, *argv, 0) || - max_size > GSO_MAX_SIZE) + if (get_unsigned(&max_size, *argv, 0)) invarg("Invalid \"gso_max_size\" value\n", *argv); addattr32(&req->n, sizeof(*req), @@ -939,6 +944,15 @@ *argv); addattr32(&req->n, sizeof(*req), IFLA_GSO_MAX_SEGS, max_segs); + } else if (strcmp(*argv, "gro_max_size") == 0) { + unsigned int max_size; + + NEXT_ARG(); + if (get_unsigned(&max_size, *argv, 0)) + invarg("Invalid \"gro_max_size\" value\n", + *argv); + addattr32(&req->n, sizeof(*req), + IFLA_GRO_MAX_SIZE, max_size); } else if (strcmp(*argv, "parentdev") == 0) { NEXT_ARG(); addattr_l(&req->n, sizeof(*req), IFLA_PARENT_DEV_NAME, @@ -980,9 +994,11 @@ } } - if (!(req->n.nlmsg_flags & NLM_F_CREATE) && index) { + if (index && + (!(req->n.nlmsg_flags & NLM_F_CREATE) && + !move_netns)) { fprintf(stderr, - "index can be used only when creating devices.\n"); + "index can be used only when creating devices or when moving device to another netns.\n"); exit(-1); } @@ -1019,6 +1035,9 @@ /* Not renaming to the same name */ if (name == dev) name = NULL; + + if (index) + addattr32(&req->n, sizeof(*req), IFLA_NEW_IFINDEX, index); } else { if (name != dev) { fprintf(stderr, @@ -1105,7 +1124,12 @@ return -1; } - if (rtnl_talk(&rth, &req.n, NULL) < 0) + if (echo_request) + ret = rtnl_echo_talk(&rth, &req.n, json, print_linkinfo); + else + ret = rtnl_talk(&rth, &req.n, NULL); + + if (ret) return -2; /* remove device from cache; next use can refresh with new data */ @@ -1500,6 +1524,65 @@ } #endif /* IPLINK_IOCTL_COMPAT */ +void print_mpls_link_stats(FILE *fp, const struct mpls_link_stats *stats, + const char *indent) +{ + unsigned int cols = { + strlen("*X: bytes"), + strlen("packets"), + strlen("errors"), + strlen("dropped"), + strlen("noroute"), + }; + + if (is_json_context()) { + /* RX stats */ + open_json_object("rx"); + print_u64(PRINT_JSON, "bytes", NULL, stats->rx_bytes); + print_u64(PRINT_JSON, "packets", NULL, stats->rx_packets); + print_u64(PRINT_JSON, "errors", NULL, stats->rx_errors); + print_u64(PRINT_JSON, "dropped", NULL, stats->rx_dropped); + print_u64(PRINT_JSON, "noroute", NULL, stats->rx_noroute); + close_json_object(); + + /* TX stats */ + open_json_object("tx"); + print_u64(PRINT_JSON, "bytes", NULL, stats->tx_bytes); + print_u64(PRINT_JSON, "packets", NULL, stats->tx_packets); + print_u64(PRINT_JSON, "errors", NULL, stats->tx_errors); + print_u64(PRINT_JSON, "dropped", NULL, stats->tx_dropped); + close_json_object(); + } else { + size_columns(cols, ARRAY_SIZE(cols), stats->rx_bytes, + stats->rx_packets, stats->rx_errors, + stats->rx_dropped, stats->rx_noroute); + size_columns(cols, ARRAY_SIZE(cols), stats->tx_bytes, + stats->tx_packets, stats->tx_errors, + stats->tx_dropped, 0); + + fprintf(fp, "%sRX: %*s %*s %*s %*s %*s%s", indent, + cols0 - 4, "bytes", cols1, "packets", + cols2, "errors", cols3, "dropped", + cols4, "noroute", _SL_); + fprintf(fp, "%s", indent); + print_num(fp, cols0, stats->rx_bytes); + print_num(fp, cols1, stats->rx_packets); + print_num(fp, cols2, stats->rx_errors); + print_num(fp, cols3, stats->rx_dropped); + print_num(fp, cols4, stats->rx_noroute); + print_nl(); + + fprintf(fp, "%sTX: %*s %*s %*s %*s%s", indent, + cols0 - 4, "bytes", cols1, "packets", + cols2, "errors", cols3, "dropped", _SL_); + fprintf(fp, "%s", indent); + print_num(fp, cols0, stats->tx_bytes); + print_num(fp, cols1, stats->tx_packets); + print_num(fp, cols2, stats->tx_errors); + print_num(fp, cols3, stats->tx_dropped); + } +} + static void print_mpls_stats(FILE *fp, struct rtattr *attr) { struct rtattr *mrtbMPLS_STATS_MAX+1; @@ -1511,23 +1594,11 @@ return; stats = RTA_DATA(mrtbMPLS_STATS_LINK); - - fprintf(fp, " mpls:\n"); - fprintf(fp, " RX: bytes packets errors dropped noroute\n"); - fprintf(fp, " "); - print_num(fp, 10, stats->rx_bytes); - print_num(fp, 8, stats->rx_packets); - print_num(fp, 7, stats->rx_errors); - print_num(fp, 8, stats->rx_dropped); - print_num(fp, 7, stats->rx_noroute); - fprintf(fp, "\n"); - fprintf(fp, " TX: bytes packets errors dropped\n"); - fprintf(fp, " "); - print_num(fp, 10, stats->tx_bytes); - print_num(fp, 8, stats->tx_packets); - print_num(fp, 7, stats->tx_errors); - print_num(fp, 7, stats->tx_dropped); - fprintf(fp, "\n"); + print_string(PRINT_FP, NULL, " mpls:", NULL); + print_nl(); + print_mpls_link_stats(fp, stats, " "); + print_string(PRINT_FP, NULL, "%s", "\n"); + fflush(fp); } static void print_af_stats_attr(FILE *fp, int ifindex, struct rtattr *attr) @@ -1543,8 +1614,12 @@ continue; if (!if_printed) { - fprintf(fp, "%u: %s\n", ifindex, - ll_index_to_name(ifindex)); + print_uint(PRINT_ANY, "ifindex", + "%u:", ifindex); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "ifname", "%s", + ll_index_to_name(ifindex)); + print_nl(); if_printed = true; } @@ -1553,7 +1628,7 @@ print_mpls_stats(fp, i); break; default: - fprintf(fp, " unknown af(%d)\n", i->rta_type); + fprintf(stderr, " unknown af(%d)\n", i->rta_type); break; } } @@ -1627,7 +1702,10 @@ } } - if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) { + new_json_obj(json); + + if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask, + NULL, NULL) < 0) { perror("Cannont send dump request"); return 1; } @@ -1637,6 +1715,7 @@ return 1; } + delete_json_obj(); return 0; }
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_amt.c
Added
@@ -0,0 +1,200 @@ +/* + * iplink_amt.c AMT device support + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Authors: Taehee Yoo <ap420073@gmail.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <net/if.h> +#include <linux/ip.h> +#include <linux/if_link.h> +#include <arpa/inet.h> +#include <linux/amt.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +#define AMT_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0) + +static void print_usage(FILE *f) +{ + fprintf(f, + "Usage: ... amt\n" + " discovery IP_ADDRESS \n" + " mode MODE \n" + " local ADDR \n" + " dev PHYS_DEV \n" + " relay_port PORT \n" + " gateway_port PORT \n" + " max_tunnels NUMBER \n" + "\n" + "Where: ADDR := { IP_ADDRESS }\n" + " MODE := { gateway | relay }\n" + ); +} + +static char *modename = {"gateway", "relay"}; + +static void usage(void) +{ + print_usage(stderr); +} + +static void check_duparg(__u64 *attrs, int type, const char *key, + const char *argv) +{ + if (!AMT_ATTRSET(*attrs, type)) { + *attrs |= (1L << type); + return; + } + duparg2(key, argv); +} + +static int amt_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + unsigned int mode, max_tunnels; + inet_prefix saddr, daddr; + __u64 attrs = 0; + __u16 port; + + saddr.family = daddr.family = AF_UNSPEC; + + inet_prefix_reset(&saddr); + inet_prefix_reset(&daddr); + + while (argc > 0) { + if (strcmp(*argv, "mode") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "gateway") == 0) { + mode = 0; + } else if (strcmp(*argv, "relay") == 0) { + mode = 1; + } else { + usage(); + return -1; + } + addattr32(n, 1024, IFLA_AMT_MODE, mode); + } else if (strcmp(*argv, "relay_port") == 0) { + NEXT_ARG(); + if (get_u16(&port, *argv, 0)) + invarg("relay_port", *argv); + addattr16(n, 1024, IFLA_AMT_RELAY_PORT, htons(port)); + } else if (strcmp(*argv, "gateway_port") == 0) { + NEXT_ARG(); + if (get_u16(&port, *argv, 0)) + invarg("gateway_port", *argv); + addattr16(n, 1024, IFLA_AMT_GATEWAY_PORT, htons(port)); + } else if (strcmp(*argv, "max_tunnels") == 0) { + NEXT_ARG(); + if (get_u32(&max_tunnels, *argv, 0)) + invarg("max_tunnels", *argv); + addattr32(n, 1024, IFLA_AMT_MAX_TUNNELS, max_tunnels); + } else if (strcmp(*argv, "dev") == 0) { + unsigned int link; + + NEXT_ARG(); + link = ll_name_to_index(*argv); + if (!link) + exit(nodev(*argv)); + addattr32(n, 1024, IFLA_AMT_LINK, link); + } else if (strcmp(*argv, "local") == 0) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_AMT_LOCAL_IP, "local", *argv); + get_addr(&saddr, *argv, daddr.family); + + if (is_addrtype_inet(&saddr)) + addattr_l(n, 1024, IFLA_AMT_LOCAL_IP, + saddr.data, saddr.bytelen); + } else if (strcmp(*argv, "discovery") == 0) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_AMT_DISCOVERY_IP, + "discovery", *argv); + get_addr(&daddr, *argv, daddr.family); + if (is_addrtype_inet(&daddr)) + addattr_l(n, 1024, IFLA_AMT_DISCOVERY_IP, + daddr.data, daddr.bytelen); + } else if (strcmp(*argv, "help") == 0) { + usage(); + return -1; + } else { + fprintf(stderr, "amt: unknown command \"%s\"?\n", *argv); + usage(); + return -1; + } + argc--, argv++; + } + + return 0; +} + +static void amt_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) +{ + if (!tb) + return; + + if (tbIFLA_AMT_MODE) + print_string(PRINT_ANY, "mode", "%s ", + modenamerta_getattr_u32(tbIFLA_AMT_MODE)); + + if (tbIFLA_AMT_GATEWAY_PORT) + print_uint(PRINT_ANY, "gateway_port", "gateway_port %u ", + rta_getattr_be16(tbIFLA_AMT_GATEWAY_PORT)); + + if (tbIFLA_AMT_RELAY_PORT) + print_uint(PRINT_ANY, "relay_port", "relay_port %u ", + rta_getattr_be16(tbIFLA_AMT_RELAY_PORT)); + + if (tbIFLA_AMT_LOCAL_IP) { + __be32 addr = rta_getattr_u32(tbIFLA_AMT_LOCAL_IP); + + print_string(PRINT_ANY, "local", "local %s ", + format_host(AF_INET, 4, &addr)); + } + + if (tbIFLA_AMT_REMOTE_IP) { + __be32 addr = rta_getattr_u32(tbIFLA_AMT_REMOTE_IP); + + print_string(PRINT_ANY, "remote", "remote %s ", + format_host(AF_INET, 4, &addr)); + } + + if (tbIFLA_AMT_DISCOVERY_IP) { + __be32 addr = rta_getattr_u32(tbIFLA_AMT_DISCOVERY_IP); + + print_string(PRINT_ANY, "discovery", "discovery %s ", + format_host(AF_INET, 4, &addr)); + } + + if (tbIFLA_AMT_LINK) { + unsigned int link = rta_getattr_u32(tbIFLA_AMT_LINK); + + print_string(PRINT_ANY, "link", "dev %s ", + ll_index_to_name(link)); + } + + if (tbIFLA_AMT_MAX_TUNNELS) + print_uint(PRINT_ANY, "max_tunnels", "max_tunnels %u ", + rta_getattr_u32(tbIFLA_AMT_MAX_TUNNELS)); +} + +static void amt_print_help(struct link_util *lu, int argc, char **argv, FILE *f) +{ + print_usage(f); +} + +struct link_util amt_link_util = { + .id = "amt", + .maxattr = IFLA_AMT_MAX, + .parse_opt = amt_parse_opt, + .print_opt = amt_print_opt, + .print_help = amt_print_help, +};
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_batadv.c
Added
@@ -0,0 +1,64 @@ +/* + * iplink_batadv.c Batman-adv support + * + * Authors: Nicolas Escande <nico.escande@gmail.com> + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <linux/batman_adv.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +static void print_explain(FILE *f) +{ + fprintf(f, + "Usage: ... batadv ra ROUTING_ALG \n" + "\n" + "Where: ROUTING_ALG := { BATMAN_IV | BATMAN_V }\n" + ); +} + +static void explain(void) +{ + print_explain(stderr); +} + +static int batadv_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + while (argc > 0) { + if (matches(*argv, "ra") == 0) { + NEXT_ARG(); + addattrstrz(n, 1024, IFLA_BATADV_ALGO_NAME, *argv); + } else if (matches(*argv, "help") == 0) { + explain(); + return -1; + } else { + fprintf(stderr, + "batadv: unknown command \"%s\"?\n", + *argv); + explain(); + return -1; + } + argc--, argv++; + } + + return 0; +} + +static void batadv_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) +{ + print_explain(f); +} + +struct link_util batadv_link_util = { + .id = "batadv", + .maxattr = IFLA_BATADV_MAX, + .parse_opt = batadv_parse_opt, + .print_help = batadv_print_help, +};
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_bond.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_bond.c
Changed
@@ -15,12 +15,14 @@ #include <string.h> #include <linux/if_bonding.h> +#include "list.h" #include "rt_names.h" #include "utils.h" #include "ip_common.h" #include "json_print.h" #define BOND_MAX_ARP_TARGETS 16 +#define BOND_MAX_NS_TARGETS BOND_MAX_ARP_TARGETS static unsigned int xstats_print_attr; static int filter_index; @@ -136,6 +138,7 @@ " arp_validate ARP_VALIDATE \n" " arp_all_targets ARP_ALL_TARGETS \n" " arp_ip_target ARP_IP_TARGET, ... \n" + " ns_ip6_target NS_IP6_TARGET, ... \n" " primary SLAVE_DEV \n" " primary_reselect PRIMARY_RESELECT \n" " fail_over_mac FAIL_OVER_MAC \n" @@ -153,6 +156,7 @@ " ad_user_port_key PORTKEY \n" " ad_actor_sys_prio SYSPRIO \n" " ad_actor_system LLADDR \n" + " arp_missed_max MISSED_MAX \n" "\n" "BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n" "ARP_VALIDATE := none|active|backup|all|filter|filter_active|filter_backup\n" @@ -181,6 +185,7 @@ __u32 miimon, updelay, downdelay, peer_notify_delay, arp_interval, arp_validate; __u32 arp_all_targets, resend_igmp, min_links, lp_interval; __u32 packets_per_slave; + __u8 missed_max; unsigned int ifindex; while (argc > 0) { @@ -246,6 +251,25 @@ addattr_nest_end(n, nest); } addattr_nest_end(n, nest); + } else if (strcmp(*argv, "ns_ip6_target") == 0) { + struct rtattr *nest = addattr_nest(n, 1024, + IFLA_BOND_NS_IP6_TARGET); + if (NEXT_ARG_OK()) { + NEXT_ARG(); + char *targets = strdupa(*argv); + char *target = strtok(targets, ","); + int i; + + for (i = 0; target && i < BOND_MAX_NS_TARGETS; i++) { + inet_prefix ip6_addr; + + get_addr(&ip6_addr, target, AF_INET6); + addattr_l(n, 1024, i, ip6_addr.data, sizeof(struct in6_addr)); + target = strtok(NULL, ","); + } + addattr_nest_end(n, nest); + } + addattr_nest_end(n, nest); } else if (matches(*argv, "arp_validate") == 0) { NEXT_ARG(); if (get_index(arp_validate_tbl, *argv) < 0) @@ -258,6 +282,12 @@ invarg("invalid arp_all_targets", *argv); arp_all_targets = get_index(arp_all_targets_tbl, *argv); addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets); + } else if (strcmp(*argv, "arp_missed_max") == 0) { + NEXT_ARG(); + if (get_u8(&missed_max, *argv, 0)) + invarg("invalid arp_missed_max", *argv); + + addattr8(n, 1024, IFLA_BOND_MISSED_MAX, missed_max); } else if (matches(*argv, "primary") == 0) { NEXT_ARG(); ifindex = ll_name_to_index(*argv); @@ -396,6 +426,8 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) { + int i; + if (!tb) return; @@ -453,9 +485,14 @@ "arp_interval %u ", rta_getattr_u32(tbIFLA_BOND_ARP_INTERVAL)); + if (tbIFLA_BOND_MISSED_MAX) + print_uint(PRINT_ANY, + "arp_missed_max", + "arp_missed_max %u ", + rta_getattr_u8(tbIFLA_BOND_MISSED_MAX)); + if (tbIFLA_BOND_ARP_IP_TARGET) { struct rtattr *iptbBOND_MAX_ARP_TARGETS + 1; - int i; parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, tbIFLA_BOND_ARP_IP_TARGET); @@ -483,6 +520,35 @@ } } + if (tbIFLA_BOND_NS_IP6_TARGET) { + struct rtattr *ip6tbBOND_MAX_NS_TARGETS + 1; + + parse_rtattr_nested(ip6tb, BOND_MAX_NS_TARGETS, + tbIFLA_BOND_NS_IP6_TARGET); + + if (ip6tb0) { + open_json_array(PRINT_JSON, "ns_ip6_target"); + print_string(PRINT_FP, NULL, "ns_ip6_target ", NULL); + } + + for (i = 0; i < BOND_MAX_NS_TARGETS; i++) { + if (ip6tbi) + print_string(PRINT_ANY, + NULL, + "%s", + rt_addr_n2a_rta(AF_INET6, ip6tbi)); + if (!is_json_context() + && i < BOND_MAX_NS_TARGETS-1 + && ip6tbi+1) + fprintf(f, ","); + } + + if (ip6tb0) { + print_string(PRINT_FP, NULL, " ", NULL); + close_json_array(PRINT_JSON, NULL); + } + } + if (tbIFLA_BOND_ARP_VALIDATE) { __u32 arp_v = rta_getattr_u32(tbIFLA_BOND_ARP_VALIDATE); const char *arp_validate = get_name(arp_validate_tbl, arp_v); @@ -696,7 +762,7 @@ fprintf(f, "Usage: ... %s 802.3ad dev DEVICE \n", lu->id); } -static void bond_print_3ad_stats(struct rtattr *lacpattr) +static void bond_print_3ad_stats(const struct rtattr *lacpattr) { struct rtattr *lacptbBOND_3AD_STAT_MAX+1; __u64 val; @@ -847,7 +913,6 @@ return 0; } - struct link_util bond_link_util = { .id = "bond", .maxattr = IFLA_BOND_MAX, @@ -857,3 +922,47 @@ .parse_ifla_xstats = bond_parse_xstats, .print_ifla_xstats = bond_print_xstats, }; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_bond_lacp = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("802.3ad"), + .xstats_at = IFLA_STATS_LINK_XSTATS, + .link_type_at = LINK_XSTATS_TYPE_BOND, + .inner_max = BOND_XSTATS_MAX, + .inner_at = BOND_XSTATS_3AD, + .show_cb = &bond_print_3ad_stats, +}; + +static const struct ipstats_stat_desc * +ipstats_stat_desc_xstats_bond_subs = { + &ipstats_stat_desc_xstats_bond_lacp.desc, +}; + +const struct ipstats_stat_desc ipstats_stat_desc_xstats_bond_group = { + .name = "bond", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_bond_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_bond_subs), +}; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_slave_bond_lacp = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("802.3ad"), + .xstats_at = IFLA_STATS_LINK_XSTATS_SLAVE, + .link_type_at = LINK_XSTATS_TYPE_BOND, + .inner_max = BOND_XSTATS_MAX, + .inner_at = BOND_XSTATS_3AD, + .show_cb = &bond_print_3ad_stats, +}; + +static const struct ipstats_stat_desc * +ipstats_stat_desc_xstats_slave_bond_subs = { + &ipstats_stat_desc_xstats_slave_bond_lacp.desc, +}; + +const struct ipstats_stat_desc ipstats_stat_desc_xstats_slave_bond_group = { + .name = "bond", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_slave_bond_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_slave_bond_subs), +};
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_bond_slave.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_bond_slave.c
Changed
@@ -19,7 +19,7 @@ static void print_explain(FILE *f) { - fprintf(f, "Usage: ... bond_slave queue_id ID \n"); + fprintf(f, "Usage: ... bond_slave queue_id ID prio PRIORITY \n"); } static void explain(void) @@ -120,6 +120,10 @@ "queue_id %d ", rta_getattr_u16(tbIFLA_BOND_SLAVE_QUEUE_ID)); + if (tbIFLA_BOND_SLAVE_PRIO) + print_int(PRINT_ANY, "prio", "prio %d ", + rta_getattr_s32(tbIFLA_BOND_SLAVE_PRIO)); + if (tbIFLA_BOND_SLAVE_AD_AGGREGATOR_ID) print_int(PRINT_ANY, "ad_aggregator_id", @@ -151,6 +155,7 @@ struct nlmsghdr *n) { __u16 queue_id; + int prio; while (argc > 0) { if (matches(*argv, "queue_id") == 0) { @@ -158,6 +163,11 @@ if (get_u16(&queue_id, *argv, 0)) invarg("queue_id is invalid", *argv); addattr16(n, 1024, IFLA_BOND_SLAVE_QUEUE_ID, queue_id); + } else if (strcmp(*argv, "prio") == 0) { + NEXT_ARG(); + if (get_s32(&prio, *argv, 0)) + invarg("prio is invalid", *argv); + addattr32(n, 1024, IFLA_BOND_SLAVE_PRIO, prio); } else { if (matches(*argv, "help") != 0) fprintf(stderr,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_bridge.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_bridge.c
Changed
@@ -37,12 +37,14 @@ " priority PRIORITY \n" " group_fwd_mask MASK \n" " group_address ADDRESS \n" + " no_linklocal_learn NO_LINKLOCAL_LEARN \n" " vlan_filtering VLAN_FILTERING \n" " vlan_protocol VLAN_PROTOCOL \n" " vlan_default_pvid VLAN_DEFAULT_PVID \n" " vlan_stats_enabled VLAN_STATS_ENABLED \n" " vlan_stats_per_port VLAN_STATS_PER_PORT \n" " mcast_snooping MULTICAST_SNOOPING \n" + " mcast_vlan_snooping MULTICAST_VLAN_SNOOPING \n" " mcast_router MULTICAST_ROUTER \n" " mcast_query_use_ifaddr MCAST_QUERY_USE_IFADDR \n" " mcast_querier MULTICAST_QUERIER \n" @@ -83,6 +85,7 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { + struct br_boolopt_multi bm = {}; __u32 val; while (argc > 0) { @@ -157,6 +160,18 @@ if (len < 0) return -1; addattr_l(n, 1024, IFLA_BR_GROUP_ADDR, llabuf, len); + } else if (strcmp(*argv, "no_linklocal_learn") == 0) { + __u32 no_ll_learn_bit = 1 << BR_BOOLOPT_NO_LL_LEARN; + __u8 no_ll_learn; + + NEXT_ARG(); + if (get_u8(&no_ll_learn, *argv, 0)) + invarg("invalid no_linklocal_learn", *argv); + bm.optmask |= 1 << BR_BOOLOPT_NO_LL_LEARN; + if (no_ll_learn) + bm.optval |= no_ll_learn_bit; + else + bm.optval &= ~no_ll_learn_bit; } else if (matches(*argv, "fdb_flush") == 0) { addattr(n, 1024, IFLA_BR_FDB_FLUSH); } else if (matches(*argv, "vlan_default_pvid") == 0) { @@ -200,6 +215,18 @@ invarg("invalid mcast_snooping", *argv); addattr8(n, 1024, IFLA_BR_MCAST_SNOOPING, mcast_snoop); + } else if (strcmp(*argv, "mcast_vlan_snooping") == 0) { + __u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING; + __u8 mcast_vlan_snooping; + + NEXT_ARG(); + if (get_u8(&mcast_vlan_snooping, *argv, 0)) + invarg("invalid mcast_vlan_snooping", *argv); + bm.optmask |= 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING; + if (mcast_vlan_snooping) + bm.optval |= mcvl_bit; + else + bm.optval &= ~mcvl_bit; } else if (matches(*argv, "mcast_query_use_ifaddr") == 0) { __u8 mcast_qui; @@ -379,6 +406,9 @@ argc--, argv++; } + if (bm.optmask) + addattr_l(n, 1024, IFLA_BR_MULTI_BOOLOPT, + &bm, sizeof(bm)); return 0; } @@ -559,6 +589,24 @@ "mcast_snooping %u ", rta_getattr_u8(tbIFLA_BR_MCAST_SNOOPING)); + if (tbIFLA_BR_MULTI_BOOLOPT) { + __u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING; + __u32 no_ll_learn_bit = 1 << BR_BOOLOPT_NO_LL_LEARN; + struct br_boolopt_multi *bm; + + bm = RTA_DATA(tbIFLA_BR_MULTI_BOOLOPT); + if (bm->optmask & no_ll_learn_bit) + print_uint(PRINT_ANY, + "no_linklocal_learn", + "no_linklocal_learn %u ", + !!(bm->optval & no_ll_learn_bit)); + if (bm->optmask & mcvl_bit) + print_uint(PRINT_ANY, + "mcast_vlan_snooping", + "mcast_vlan_snooping %u ", + !!(bm->optval & mcvl_bit)); + } + if (tbIFLA_BR_MCAST_ROUTER) print_uint(PRINT_ANY, "mcast_router", @@ -685,11 +733,140 @@ fprintf(f, "Usage: ... %s igmp dev DEVICE \n", lu->id); } +static void bridge_print_stats_mcast(const struct rtattr *attr) +{ + struct br_mcast_stats *mstats; + + mstats = RTA_DATA(attr); + open_json_object("multicast"); + open_json_object("igmp_queries"); + print_string(PRINT_FP, NULL, + "%-16s IGMP queries:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->igmp_v1queriesBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", + mstats->igmp_v2queriesBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", + mstats->igmp_v3queriesBR_MCAST_DIR_RX); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1queriesBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", + mstats->igmp_v2queriesBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3queriesBR_MCAST_DIR_TX); + close_json_object(); + + open_json_object("igmp_reports"); + print_string(PRINT_FP, NULL, + "%-16s IGMP reports:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->igmp_v1reportsBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", + mstats->igmp_v2reportsBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", + mstats->igmp_v3reportsBR_MCAST_DIR_RX); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->igmp_v1reportsBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", + mstats->igmp_v2reportsBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", + mstats->igmp_v3reportsBR_MCAST_DIR_TX); + close_json_object(); + + open_json_object("igmp_leaves"); + print_string(PRINT_FP, NULL, + "%-16s IGMP leaves: ", ""); + print_u64(PRINT_ANY, "rx", "RX: %llu ", + mstats->igmp_leavesBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "tx", "TX: %llu\n", + mstats->igmp_leavesBR_MCAST_DIR_TX); + close_json_object(); + + print_string(PRINT_FP, NULL, + "%-16s IGMP parse errors: ", ""); + print_u64(PRINT_ANY, "igmp_parse_errors", "%llu\n", + mstats->igmp_parse_errors); + + open_json_object("mld_queries"); + print_string(PRINT_FP, NULL, + "%-16s MLD queries:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->mld_v1queriesBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", + mstats->mld_v2queriesBR_MCAST_DIR_RX); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->mld_v1queriesBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", + mstats->mld_v2queriesBR_MCAST_DIR_TX); + close_json_object(); + + open_json_object("mld_reports"); + print_string(PRINT_FP, NULL, + "%-16s MLD reports:\n", ""); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", + mstats->mld_v1reportsBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", + mstats->mld_v2reportsBR_MCAST_DIR_RX); + print_string(PRINT_FP, NULL, "%-16s ", ""); + print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", + mstats->mld_v1reportsBR_MCAST_DIR_TX); + print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", + mstats->mld_v2reportsBR_MCAST_DIR_TX); + close_json_object(); + + open_json_object("mld_leaves"); + print_string(PRINT_FP, NULL, + "%-16s MLD leaves: ", ""); + print_u64(PRINT_ANY, "rx", "RX: %llu ", + mstats->mld_leavesBR_MCAST_DIR_RX); + print_u64(PRINT_ANY, "tx", "TX: %llu\n", + mstats->mld_leavesBR_MCAST_DIR_TX); + close_json_object(); + + print_string(PRINT_FP, NULL, + "%-16s MLD parse errors: ", ""); + print_u64(PRINT_ANY, "mld_parse_errors", "%llu\n", + mstats->mld_parse_errors); + close_json_object(); +} + +static void bridge_print_stats_stp(const struct rtattr *attr) +{ + struct bridge_stp_xstats *sstats; + + sstats = RTA_DATA(attr); + open_json_object("stp"); + print_string(PRINT_FP, NULL, + "%-16s STP BPDU: ", ""); + print_u64(PRINT_ANY, "rx_bpdu", "RX: %llu ", + sstats->rx_bpdu); + print_u64(PRINT_ANY, "tx_bpdu", "TX: %llu\n", + sstats->tx_bpdu); + print_string(PRINT_FP, NULL, + "%-16s STP TCN: ", ""); + print_u64(PRINT_ANY, "rx_tcn", "RX: %llu ", + sstats->rx_tcn); + print_u64(PRINT_ANY, "tx_tcn", "TX: %llu\n", + sstats->tx_tcn); + print_string(PRINT_FP, NULL, + "%-16s STP Transitions: ", ""); + print_u64(PRINT_ANY, "transition_blk", "Blocked: %llu ", + sstats->transition_blk); + print_u64(PRINT_ANY, "transition_fwd", "Forwarding: %llu\n", + sstats->transition_fwd); + close_json_object(); +} + static void bridge_print_stats_attr(struct rtattr *attr, int ifindex) { struct rtattr *brtbLINK_XSTATS_TYPE_MAX+1; - struct bridge_stp_xstats *sstats; - struct br_mcast_stats *mstats; struct rtattr *i, *list; const char *ifname = ""; int rem; @@ -709,127 +886,10 @@ continue; switch (i->rta_type) { case BRIDGE_XSTATS_MCAST: - mstats = RTA_DATA(i); - open_json_object("multicast"); - open_json_object("igmp_queries"); - print_string(PRINT_FP, NULL, - "%-16s IGMP queries:\n", ""); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", - mstats->igmp_v1queriesBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", - mstats->igmp_v2queriesBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", - mstats->igmp_v3queriesBR_MCAST_DIR_RX); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", - mstats->igmp_v1queriesBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", - mstats->igmp_v2queriesBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", - mstats->igmp_v3queriesBR_MCAST_DIR_TX); - close_json_object(); - - open_json_object("igmp_reports"); - print_string(PRINT_FP, NULL, - "%-16s IGMP reports:\n", ""); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", - mstats->igmp_v1reportsBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v2", "v2 %llu ", - mstats->igmp_v2reportsBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v3", "v3 %llu\n", - mstats->igmp_v3reportsBR_MCAST_DIR_RX); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", - mstats->igmp_v1reportsBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v2", "v2 %llu ", - mstats->igmp_v2reportsBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v3", "v3 %llu\n", - mstats->igmp_v3reportsBR_MCAST_DIR_TX); - close_json_object(); - - open_json_object("igmp_leaves"); - print_string(PRINT_FP, NULL, - "%-16s IGMP leaves: ", ""); - print_u64(PRINT_ANY, "rx", "RX: %llu ", - mstats->igmp_leavesBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "tx", "TX: %llu\n", - mstats->igmp_leavesBR_MCAST_DIR_TX); - close_json_object(); - - print_string(PRINT_FP, NULL, - "%-16s IGMP parse errors: ", ""); - print_u64(PRINT_ANY, "igmp_parse_errors", "%llu\n", - mstats->igmp_parse_errors); - - open_json_object("mld_queries"); - print_string(PRINT_FP, NULL, - "%-16s MLD queries:\n", ""); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", - mstats->mld_v1queriesBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", - mstats->mld_v2queriesBR_MCAST_DIR_RX); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", - mstats->mld_v1queriesBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", - mstats->mld_v2queriesBR_MCAST_DIR_TX); - close_json_object(); - - open_json_object("mld_reports"); - print_string(PRINT_FP, NULL, - "%-16s MLD reports:\n", ""); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "rx_v1", "RX: v1 %llu ", - mstats->mld_v1reportsBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "rx_v2", "v2 %llu\n", - mstats->mld_v2reportsBR_MCAST_DIR_RX); - print_string(PRINT_FP, NULL, "%-16s ", ""); - print_u64(PRINT_ANY, "tx_v1", "TX: v1 %llu ", - mstats->mld_v1reportsBR_MCAST_DIR_TX); - print_u64(PRINT_ANY, "tx_v2", "v2 %llu\n", - mstats->mld_v2reportsBR_MCAST_DIR_TX); - close_json_object(); - - open_json_object("mld_leaves"); - print_string(PRINT_FP, NULL, - "%-16s MLD leaves: ", ""); - print_u64(PRINT_ANY, "rx", "RX: %llu ", - mstats->mld_leavesBR_MCAST_DIR_RX); - print_u64(PRINT_ANY, "tx", "TX: %llu\n", - mstats->mld_leavesBR_MCAST_DIR_TX); - close_json_object(); - - print_string(PRINT_FP, NULL, - "%-16s MLD parse errors: ", ""); - print_u64(PRINT_ANY, "mld_parse_errors", "%llu\n", - mstats->mld_parse_errors); - close_json_object(); + bridge_print_stats_mcast(i); break; case BRIDGE_XSTATS_STP: - sstats = RTA_DATA(i); - open_json_object("stp"); - print_string(PRINT_FP, NULL, - "%-16s STP BPDU: ", ""); - print_u64(PRINT_ANY, "rx_bpdu", "RX: %llu ", - sstats->rx_bpdu); - print_u64(PRINT_ANY, "tx_bpdu", "TX: %llu\n", - sstats->tx_bpdu); - print_string(PRINT_FP, NULL, - "%-16s STP TCN: ", ""); - print_u64(PRINT_ANY, "rx_tcn", "RX: %llu ", - sstats->rx_tcn); - print_u64(PRINT_ANY, "tx_tcn", "TX: %llu\n", - sstats->tx_tcn); - print_string(PRINT_FP, NULL, - "%-16s STP Transitions: ", ""); - print_u64(PRINT_ANY, "transition_blk", "Blocked: %llu ", - sstats->transition_blk); - print_u64(PRINT_ANY, "transition_fwd", "Forwarding: %llu\n", - sstats->transition_fwd); - close_json_object(); + bridge_print_stats_stp(i); break; } } @@ -895,3 +955,69 @@ .parse_ifla_xstats = bridge_parse_xstats, .print_ifla_xstats = bridge_print_xstats, }; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_bridge_stp = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("stp"), + .xstats_at = IFLA_STATS_LINK_XSTATS, + .link_type_at = LINK_XSTATS_TYPE_BRIDGE, + .inner_max = BRIDGE_XSTATS_MAX, + .inner_at = BRIDGE_XSTATS_STP, + .show_cb = &bridge_print_stats_stp, +}; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_bridge_mcast = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("mcast"), + .xstats_at = IFLA_STATS_LINK_XSTATS, + .link_type_at = LINK_XSTATS_TYPE_BRIDGE, + .inner_max = BRIDGE_XSTATS_MAX, + .inner_at = BRIDGE_XSTATS_MCAST, + .show_cb = &bridge_print_stats_mcast, +}; + +static const struct ipstats_stat_desc * +ipstats_stat_desc_xstats_bridge_subs = { + &ipstats_stat_desc_xstats_bridge_stp.desc, + &ipstats_stat_desc_xstats_bridge_mcast.desc, +}; + +const struct ipstats_stat_desc ipstats_stat_desc_xstats_bridge_group = { + .name = "bridge", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_bridge_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_bridge_subs), +}; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_slave_bridge_stp = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("stp"), + .xstats_at = IFLA_STATS_LINK_XSTATS_SLAVE, + .link_type_at = LINK_XSTATS_TYPE_BRIDGE, + .inner_max = BRIDGE_XSTATS_MAX, + .inner_at = BRIDGE_XSTATS_STP, + .show_cb = &bridge_print_stats_stp, +}; + +static const struct ipstats_stat_desc_xstats +ipstats_stat_desc_xstats_slave_bridge_mcast = { + .desc = IPSTATS_STAT_DESC_XSTATS_LEAF("mcast"), + .xstats_at = IFLA_STATS_LINK_XSTATS_SLAVE, + .link_type_at = LINK_XSTATS_TYPE_BRIDGE, + .inner_max = BRIDGE_XSTATS_MAX, + .inner_at = BRIDGE_XSTATS_MCAST, + .show_cb = &bridge_print_stats_mcast, +}; + +static const struct ipstats_stat_desc * +ipstats_stat_desc_xstats_slave_bridge_subs = { + &ipstats_stat_desc_xstats_slave_bridge_stp.desc, + &ipstats_stat_desc_xstats_slave_bridge_mcast.desc, +}; + +const struct ipstats_stat_desc ipstats_stat_desc_xstats_slave_bridge_group = { + .name = "bridge", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_slave_bridge_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_slave_bridge_subs), +};
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_bridge_slave.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_bridge_slave.c
Changed
@@ -37,11 +37,13 @@ " mcast_router MULTICAST_ROUTER \n" " mcast_fast_leave {on | off} \n" " mcast_flood {on | off} \n" + " bcast_flood {on | off} \n" " mcast_to_unicast {on | off} \n" " group_fwd_mask MASK \n" " neigh_suppress {on | off} \n" " vlan_tunnel {on | off} \n" " isolated {on | off} \n" + " locked {on | off} \n" " backup_port DEVICE nobackup_port \n" ); } @@ -250,6 +252,10 @@ print_on_off(PRINT_ANY, "mcast_flood", "mcast_flood %s ", rta_getattr_u8(tbIFLA_BRPORT_MCAST_FLOOD)); + if (tbIFLA_BRPORT_BCAST_FLOOD) + print_on_off(PRINT_ANY, "bcast_flood", "bcast_flood %s ", + rta_getattr_u8(tbIFLA_BRPORT_BCAST_FLOOD)); + if (tbIFLA_BRPORT_MCAST_TO_UCAST) print_on_off(PRINT_ANY, "mcast_to_unicast", "mcast_to_unicast %s ", rta_getattr_u8(tbIFLA_BRPORT_MCAST_TO_UCAST)); @@ -278,6 +284,10 @@ print_on_off(PRINT_ANY, "isolated", "isolated %s ", rta_getattr_u8(tbIFLA_BRPORT_ISOLATED)); + if (tbIFLA_BRPORT_LOCKED) + print_on_off(PRINT_ANY, "locked", "locked %s ", + rta_getattr_u8(tbIFLA_BRPORT_LOCKED)); + if (tbIFLA_BRPORT_BACKUP_PORT) { int backup_p = rta_getattr_u32(tbIFLA_BRPORT_BACKUP_PORT); @@ -350,6 +360,10 @@ NEXT_ARG(); bridge_slave_parse_on_off("mcast_flood", *argv, n, IFLA_BRPORT_MCAST_FLOOD); + } else if (matches(*argv, "bcast_flood") == 0) { + NEXT_ARG(); + bridge_slave_parse_on_off("bcast_flood", *argv, n, + IFLA_BRPORT_BCAST_FLOOD); } else if (matches(*argv, "mcast_to_unicast") == 0) { NEXT_ARG(); bridge_slave_parse_on_off("mcast_to_unicast", *argv, n, @@ -393,6 +407,10 @@ NEXT_ARG(); bridge_slave_parse_on_off("isolated", *argv, n, IFLA_BRPORT_ISOLATED); + } else if (matches(*argv, "locked") == 0) { + NEXT_ARG(); + bridge_slave_parse_on_off("locked", *argv, n, + IFLA_BRPORT_LOCKED); } else if (matches(*argv, "backup_port") == 0) { int ifindex;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_can.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_can.c
Changed
@@ -28,6 +28,7 @@ "\n" "\t dbitrate BITRATE dsample-point SAMPLE-POINT |\n" "\t dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1\n \t dphase-seg2 PHASE-SEG2 dsjw SJW \n" + "\t tdcv TDCV tdco TDCO tdcf TDCF \n" "\n" "\t loopback { on | off } \n" "\t listen-only { on | off } \n" @@ -38,20 +39,24 @@ "\t fd-non-iso { on | off } \n" "\t presume-ack { on | off } \n" "\t cc-len8-dlc { on | off } \n" + "\t tdc-mode { auto | manual | off } \n" "\n" "\t restart-ms TIME-MS \n" "\t restart \n" "\n" "\t termination { 0..65535 } \n" "\n" - "\tWhere: BITRATE := { 1..1000000 }\n" + "\tWhere: BITRATE := { NUMBER in bps }\n" "\t SAMPLE-POINT := { 0.000..0.999 }\n" - "\t TQ := { NUMBER }\n" - "\t PROP-SEG := { 1..8 }\n" - "\t PHASE-SEG1 := { 1..8 }\n" - "\t PHASE-SEG2 := { 1..8 }\n" - "\t SJW := { 1..4 }\n" - "\t RESTART-MS := { 0 | NUMBER }\n" + "\t TQ := { NUMBER in ns }\n" + "\t PROP-SEG := { NUMBER in tq }\n" + "\t PHASE-SEG1 := { NUMBER in tq }\n" + "\t PHASE-SEG2 := { NUMBER in tq }\n" + "\t SJW := { NUMBER in tq }\n" + "\t TDCV := { NUMBER in tc }\n" + "\t TDCO := { NUMBER in tc }\n" + "\t TDCF := { NUMBER in tc }\n" + "\t RESTART-MS := { 0 | NUMBER in ms }\n" ); } @@ -88,34 +93,47 @@ cm->mask |= flags; } -static void print_ctrlmode(FILE *f, __u32 cm) +static void print_flag(enum output_type t, __u32 *flags, __u32 flag, + const char* name) { - open_json_array(PRINT_ANY, is_json_context() ? "ctrlmode" : "<"); -#define _PF(cmflag, cmname) \ - if (cm & cmflag) { \ - cm &= ~cmflag; \ - print_string(PRINT_ANY, NULL, cm ? "%s," : "%s", cmname); \ + if (*flags & flag) { + *flags &= ~flag; + print_string(t, NULL, *flags ? "%s," : "%s", name); } - _PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK"); - _PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY"); - _PF(CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING"); - _PF(CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT"); - _PF(CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING"); - _PF(CAN_CTRLMODE_FD, "FD"); - _PF(CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO"); - _PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK"); - _PF(CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC"); -#undef _PF - if (cm) - print_hex(PRINT_ANY, NULL, "%x", cm); - close_json_array(PRINT_ANY, "> "); +} + +static void print_ctrlmode(enum output_type t, __u32 flags, const char* key) +{ + if (!flags) + return; + + open_json_array(t, is_json_context() ? key : "<"); + + print_flag(t, &flags, CAN_CTRLMODE_LOOPBACK, "LOOPBACK"); + print_flag(t, &flags, CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY"); + print_flag(t, &flags, CAN_CTRLMODE_3_SAMPLES, "TRIPLE-SAMPLING"); + print_flag(t, &flags, CAN_CTRLMODE_ONE_SHOT, "ONE-SHOT"); + print_flag(t, &flags, CAN_CTRLMODE_BERR_REPORTING, "BERR-REPORTING"); + print_flag(t, &flags, CAN_CTRLMODE_FD, "FD"); + print_flag(t, &flags, CAN_CTRLMODE_FD_NON_ISO, "FD-NON-ISO"); + print_flag(t, &flags, CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK"); + print_flag(t, &flags, CAN_CTRLMODE_CC_LEN8_DLC, "CC-LEN8-DLC"); + print_flag(t, &flags, CAN_CTRLMODE_TDC_AUTO, "TDC-AUTO"); + print_flag(t, &flags, CAN_CTRLMODE_TDC_MANUAL, "TDC-MANUAL"); + + if (flags) + print_hex(t, NULL, "%x", flags); + + close_json_array(t, "> "); } static int can_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct can_bittiming bt = {}, dbt = {}; - struct can_ctrlmode cm = {0, 0}; + struct can_ctrlmode cm = { 0 }; + struct rtattr *tdc; + __u32 tdcv = -1, tdco = -1, tdcf = -1; while (argc > 0) { if (matches(*argv, "bitrate") == 0) { @@ -181,6 +199,18 @@ NEXT_ARG(); if (get_u32(&dbt.sjw, *argv, 0)) invarg("invalid \"dsjw\" value\n", *argv); + } else if (matches(*argv, "tdcv") == 0) { + NEXT_ARG(); + if (get_u32(&tdcv, *argv, 0)) + invarg("invalid \"tdcv\" value\n", *argv); + } else if (matches(*argv, "tdco") == 0) { + NEXT_ARG(); + if (get_u32(&tdco, *argv, 0)) + invarg("invalid \"tdco\" value\n", *argv); + } else if (matches(*argv, "tdcf") == 0) { + NEXT_ARG(); + if (get_u32(&tdcf, *argv, 0)) + invarg("invalid \"tdcf\" value\n", *argv); } else if (matches(*argv, "loopback") == 0) { NEXT_ARG(); set_ctrlmode("loopback", *argv, &cm, @@ -217,6 +247,23 @@ NEXT_ARG(); set_ctrlmode("cc-len8-dlc", *argv, &cm, CAN_CTRLMODE_CC_LEN8_DLC); + } else if (matches(*argv, "tdc-mode") == 0) { + NEXT_ARG(); + if (strcmp(*argv, "auto") == 0) { + cm.flags |= CAN_CTRLMODE_TDC_AUTO; + cm.mask |= CAN_CTRLMODE_TDC_AUTO; + } else if (strcmp(*argv, "manual") == 0) { + cm.flags |= CAN_CTRLMODE_TDC_MANUAL; + cm.mask |= CAN_CTRLMODE_TDC_MANUAL; + } else if (strcmp(*argv, "off") == 0) { + cm.mask |= CAN_CTRLMODE_TDC_AUTO | + CAN_CTRLMODE_TDC_MANUAL; + } else { + fprintf(stderr, + "Error: argument of \"tdc-mode\" must be \"auto\", \"manual\" or \"off\", not \"%s\"\n", + *argv); + exit (-1); + } } else if (matches(*argv, "restart") == 0) { __u32 val = 1; @@ -254,6 +301,17 @@ if (cm.mask) addattr_l(n, 1024, IFLA_CAN_CTRLMODE, &cm, sizeof(cm)); + if (tdcv != -1 || tdco != -1 || tdcf != -1) { + tdc = addattr_nest(n, 1024, IFLA_CAN_TDC | NLA_F_NESTED); + if (tdcv != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCV, tdcv); + if (tdco != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCO, tdco); + if (tdcf != -1) + addattr32(n, 1024, IFLA_CAN_TDC_TDCF, tdcf); + addattr_nest_end(n, tdc); + } + return 0; } @@ -266,14 +324,93 @@ CAN_STATE_SLEEPING = "SLEEPING" }; -static void can_print_json_timing_min_max(const char *attr, int min, int max) +static void can_print_nl_indent(void) +{ + print_nl(); + print_string(PRINT_FP, NULL, "%s", "\t "); +} + +static void __attribute__((format(printf, 2, 0))) +can_print_timing_min_max(const char *json_attr, const char *fp_attr, + int min, int max) { - open_json_object(attr); - print_int(PRINT_JSON, "min", NULL, min); - print_int(PRINT_JSON, "max", NULL, max); + print_null(PRINT_FP, NULL, fp_attr, NULL); + open_json_object(json_attr); + print_uint(PRINT_ANY, "min", " %d", min); + print_uint(PRINT_ANY, "max", "..%d", max); + close_json_object(); +} + +static void can_print_tdc_opt(FILE *f, struct rtattr *tdc_attr) +{ + struct rtattr *tbIFLA_CAN_TDC_MAX + 1; + + parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); + if (tbIFLA_CAN_TDC_TDCV || tbIFLA_CAN_TDC_TDCO || + tbIFLA_CAN_TDC_TDCF) { + open_json_object("tdc"); + can_print_nl_indent(); + if (tbIFLA_CAN_TDC_TDCV) { + __u32 *tdcv = RTA_DATA(tbIFLA_CAN_TDC_TDCV); + + print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv); + } + if (tbIFLA_CAN_TDC_TDCO) { + __u32 *tdco = RTA_DATA(tbIFLA_CAN_TDC_TDCO); + + print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco); + } + if (tbIFLA_CAN_TDC_TDCF) { + __u32 *tdcf = RTA_DATA(tbIFLA_CAN_TDC_TDCF); + + print_uint(PRINT_ANY, "tdcf", " tdcf %u", *tdcf); + } + close_json_object(); + } +} + +static void can_print_tdc_const_opt(FILE *f, struct rtattr *tdc_attr) +{ + struct rtattr *tbIFLA_CAN_TDC_MAX + 1; + + parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr); + open_json_object("tdc"); + can_print_nl_indent(); + if (tbIFLA_CAN_TDC_TDCV_MIN && tbIFLA_CAN_TDC_TDCV_MAX) { + __u32 *tdcv_min = RTA_DATA(tbIFLA_CAN_TDC_TDCV_MIN); + __u32 *tdcv_max = RTA_DATA(tbIFLA_CAN_TDC_TDCV_MAX); + + can_print_timing_min_max("tdcv", " tdcv", *tdcv_min, *tdcv_max); + } + if (tbIFLA_CAN_TDC_TDCO_MIN && tbIFLA_CAN_TDC_TDCO_MAX) { + __u32 *tdco_min = RTA_DATA(tbIFLA_CAN_TDC_TDCO_MIN); + __u32 *tdco_max = RTA_DATA(tbIFLA_CAN_TDC_TDCO_MAX); + + can_print_timing_min_max("tdco", " tdco", *tdco_min, *tdco_max); + } + if (tbIFLA_CAN_TDC_TDCF_MIN && tbIFLA_CAN_TDC_TDCF_MAX) { + __u32 *tdcf_min = RTA_DATA(tbIFLA_CAN_TDC_TDCF_MIN); + __u32 *tdcf_max = RTA_DATA(tbIFLA_CAN_TDC_TDCF_MAX); + + can_print_timing_min_max("tdcf", " tdcf", *tdcf_min, *tdcf_max); + } close_json_object(); } +static void can_print_ctrlmode_ext(FILE *f, struct rtattr *ctrlmode_ext_attr, + __u32 cm_flags) +{ + struct rtattr *tbIFLA_CAN_CTRLMODE_MAX + 1; + + parse_rtattr_nested(tb, IFLA_CAN_CTRLMODE_MAX, ctrlmode_ext_attr); + if (tbIFLA_CAN_CTRLMODE_SUPPORTED) { + __u32 *supported = RTA_DATA(tbIFLA_CAN_CTRLMODE_SUPPORTED); + + print_ctrlmode(PRINT_JSON, *supported, "ctrlmode_supported"); + print_ctrlmode(PRINT_JSON, cm_flags & ~*supported, "ctrlmode_static"); + } +} + static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) { if (!tb) @@ -282,8 +419,10 @@ if (tbIFLA_CAN_CTRLMODE) { struct can_ctrlmode *cm = RTA_DATA(tbIFLA_CAN_CTRLMODE); - if (cm->flags) - print_ctrlmode(f, cm->flags); + print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode"); + if (tbIFLA_CAN_CTRLMODE_EXT) + can_print_ctrlmode_ext(f, tbIFLA_CAN_CTRLMODE_EXT, + cm->flags); } if (tbIFLA_CAN_STATE) { @@ -297,56 +436,39 @@ struct can_berr_counter *bc = RTA_DATA(tbIFLA_CAN_BERR_COUNTER); - if (is_json_context()) { - open_json_object("berr_counter"); - print_int(PRINT_JSON, "tx", NULL, bc->txerr); - print_int(PRINT_JSON, "rx", NULL, bc->rxerr); - close_json_object(); - } else { - fprintf(f, "(berr-counter tx %d rx %d) ", - bc->txerr, bc->rxerr); - } + open_json_object("berr_counter"); + print_uint(PRINT_ANY, "tx", "(berr-counter tx %u", bc->txerr); + print_uint(PRINT_ANY, "rx", " rx %u) ", bc->rxerr); + close_json_object(); } if (tbIFLA_CAN_RESTART_MS) { __u32 *restart_ms = RTA_DATA(tbIFLA_CAN_RESTART_MS); - print_int(PRINT_ANY, - "restart_ms", - "restart-ms %d ", - *restart_ms); + print_uint(PRINT_ANY, "restart_ms", "restart-ms %u ", + *restart_ms); } /* bittiming is irrelevant if fixed bitrate is defined */ if (tbIFLA_CAN_BITTIMING && !tbIFLA_CAN_BITRATE_CONST) { struct can_bittiming *bt = RTA_DATA(tbIFLA_CAN_BITTIMING); - - if (is_json_context()) { - json_writer_t *jw; - - open_json_object("bittiming"); - print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate); - jw = get_json_writer(); - jsonw_name(jw, "sample_point"); - jsonw_printf(jw, "%.3f", - (float) bt->sample_point / 1000); - print_int(PRINT_ANY, "tq", NULL, bt->tq); - print_int(PRINT_ANY, "prop_seg", NULL, bt->prop_seg); - print_int(PRINT_ANY, "phase_seg1", - NULL, bt->phase_seg1); - print_int(PRINT_ANY, "phase_seg2", - NULL, bt->phase_seg2); - print_int(PRINT_ANY, "sjw", NULL, bt->sjw); - close_json_object(); - } else { - fprintf(f, "\n bitrate %d sample-point %.3f ", - bt->bitrate, (float) bt->sample_point / 1000.); - fprintf(f, - "\n tq %d prop-seg %d phase-seg1 %d phase-seg2 %d sjw %d", - bt->tq, bt->prop_seg, - bt->phase_seg1, bt->phase_seg2, - bt->sjw); - } + char sp6; + + open_json_object("bittiming"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bitrate", " bitrate %u", bt->bitrate); + snprintf(sp, sizeof(sp), "%.3f", bt->sample_point / 1000.); + print_string(PRINT_ANY, "sample_point", " sample-point %s", sp); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tq", " tq %u", bt->tq); + print_uint(PRINT_ANY, "prop_seg", " prop-seg %u", bt->prop_seg); + print_uint(PRINT_ANY, "phase_seg1", " phase-seg1 %u", + bt->phase_seg1); + print_uint(PRINT_ANY, "phase_seg2", " phase-seg2 %u", + bt->phase_seg2); + print_uint(PRINT_ANY, "sjw", " sjw %u", bt->sjw); + print_uint(PRINT_ANY, "brp", " brp %u", bt->brp); + close_json_object(); } /* bittiming const is irrelevant if fixed bitrate is defined */ @@ -354,28 +476,18 @@ struct can_bittiming_const *btc = RTA_DATA(tbIFLA_CAN_BITTIMING_CONST); - if (is_json_context()) { - open_json_object("bittiming_const"); - print_string(PRINT_JSON, "name", NULL, btc->name); - can_print_json_timing_min_max("tseg1", - btc->tseg1_min, - btc->tseg1_max); - can_print_json_timing_min_max("tseg2", - btc->tseg2_min, - btc->tseg2_max); - can_print_json_timing_min_max("sjw", 1, btc->sjw_max); - can_print_json_timing_min_max("brp", - btc->brp_min, - btc->brp_max); - print_int(PRINT_JSON, "brp_inc", NULL, btc->brp_inc); - close_json_object(); - } else { - fprintf(f, "\n %s: tseg1 %d..%d tseg2 %d..%d " - "sjw 1..%d brp %d..%d brp-inc %d", - btc->name, btc->tseg1_min, btc->tseg1_max, - btc->tseg2_min, btc->tseg2_max, btc->sjw_max, - btc->brp_min, btc->brp_max, btc->brp_inc); - } + open_json_object("bittiming_const"); + can_print_nl_indent(); + print_string(PRINT_ANY, "name", " %s:", btc->name); + can_print_timing_min_max("tseg1", " tseg1", + btc->tseg1_min, btc->tseg1_max); + can_print_timing_min_max("tseg2", " tseg2", + btc->tseg2_min, btc->tseg2_max); + can_print_timing_min_max("sjw", " sjw", 1, btc->sjw_max); + can_print_timing_min_max("brp", " brp", + btc->brp_min, btc->brp_max); + print_uint(PRINT_ANY, "brp_inc", " brp_inc %u", btc->brp_inc); + close_json_object(); } if (tbIFLA_CAN_BITRATE_CONST) { @@ -391,64 +503,52 @@ bitrate = bt->bitrate; } - if (is_json_context()) { - print_uint(PRINT_JSON, - "bittiming_bitrate", - NULL, bitrate); - open_json_array(PRINT_JSON, "bitrate_const"); - for (i = 0; i < bitrate_cnt; ++i) - print_uint(PRINT_JSON, NULL, NULL, - bitrate_consti); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n bitrate %u", bitrate); - fprintf(f, "\n "); - - for (i = 0; i < bitrate_cnt - 1; ++i) { - /* This will keep lines below 80 signs */ - if (!(i % 6) && i) - fprintf(f, "\n "); - - fprintf(f, "%8u, ", bitrate_consti); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bittiming_bitrate", " bitrate %u", + bitrate); + can_print_nl_indent(); + open_json_array(PRINT_ANY, is_json_context() ? + "bitrate_const" : " "); + for (i = 0; i < bitrate_cnt; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) { + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", " "); } - - if (!(i % 6) && i) - fprintf(f, "\n "); - fprintf(f, "%8u ", bitrate_consti); + print_uint(PRINT_ANY, NULL, + i < bitrate_cnt - 1 ? "%8u, " : "%8u", + bitrate_consti); } + close_json_array(PRINT_ANY, " "); } /* data bittiming is irrelevant if fixed bitrate is defined */ if (tbIFLA_CAN_DATA_BITTIMING && !tbIFLA_CAN_DATA_BITRATE_CONST) { struct can_bittiming *dbt = RTA_DATA(tbIFLA_CAN_DATA_BITTIMING); - - if (is_json_context()) { - json_writer_t *jw; - - open_json_object("data_bittiming"); - print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate); - jw = get_json_writer(); - jsonw_name(jw, "sample_point"); - jsonw_printf(jw, "%.3f", - (float) dbt->sample_point / 1000.); - print_int(PRINT_JSON, "tq", NULL, dbt->tq); - print_int(PRINT_JSON, "prop_seg", NULL, dbt->prop_seg); - print_int(PRINT_JSON, "phase_seg1", - NULL, dbt->phase_seg1); - print_int(PRINT_JSON, "phase_seg2", - NULL, dbt->phase_seg2); - print_int(PRINT_JSON, "sjw", NULL, dbt->sjw); - close_json_object(); - } else { - fprintf(f, "\n dbitrate %d dsample-point %.3f ", - dbt->bitrate, - (float) dbt->sample_point / 1000.); - fprintf(f, "\n dtq %d dprop-seg %d dphase-seg1 %d " - "dphase-seg2 %d dsjw %d", - dbt->tq, dbt->prop_seg, dbt->phase_seg1, - dbt->phase_seg2, dbt->sjw); - } + char dsp6; + + open_json_object("data_bittiming"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "bitrate", " dbitrate %u", dbt->bitrate); + snprintf(dsp, sizeof(dsp), "%.3f", dbt->sample_point / 1000.); + print_string(PRINT_ANY, "sample_point", " dsample-point %s", + dsp); + can_print_nl_indent(); + print_uint(PRINT_ANY, "tq", " dtq %u", dbt->tq); + print_uint(PRINT_ANY, "prop_seg", " dprop-seg %u", + dbt->prop_seg); + print_uint(PRINT_ANY, "phase_seg1", " dphase-seg1 %u", + dbt->phase_seg1); + print_uint(PRINT_ANY, "phase_seg2", " dphase-seg2 %u", + dbt->phase_seg2); + print_uint(PRINT_ANY, "sjw", " dsjw %u", dbt->sjw); + print_uint(PRINT_ANY, "brp", " dbrp %u", dbt->brp); + + if (tbIFLA_CAN_TDC) + can_print_tdc_opt(f, tbIFLA_CAN_TDC); + + close_json_object(); } /* data bittiming const is irrelevant if fixed bitrate is defined */ @@ -457,29 +557,22 @@ struct can_bittiming_const *dbtc = RTA_DATA(tbIFLA_CAN_DATA_BITTIMING_CONST); - if (is_json_context()) { - open_json_object("data_bittiming_const"); - print_string(PRINT_JSON, "name", NULL, dbtc->name); - can_print_json_timing_min_max("tseg1", - dbtc->tseg1_min, - dbtc->tseg1_max); - can_print_json_timing_min_max("tseg2", - dbtc->tseg2_min, - dbtc->tseg2_max); - can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max); - can_print_json_timing_min_max("brp", - dbtc->brp_min, - dbtc->brp_max); - - print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc); - close_json_object(); - } else { - fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d " - "dsjw 1..%d dbrp %d..%d dbrp-inc %d", - dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max, - dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max, - dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc); - } + open_json_object("data_bittiming_const"); + can_print_nl_indent(); + print_string(PRINT_ANY, "name", " %s:", dbtc->name); + can_print_timing_min_max("tseg1", " dtseg1", + dbtc->tseg1_min, dbtc->tseg1_max); + can_print_timing_min_max("tseg2", " dtseg2", + dbtc->tseg2_min, dbtc->tseg2_max); + can_print_timing_min_max("sjw", " dsjw", 1, dbtc->sjw_max); + can_print_timing_min_max("brp", " dbrp", + dbtc->brp_min, dbtc->brp_max); + print_uint(PRINT_ANY, "brp_inc", " dbrp_inc %u", dbtc->brp_inc); + + if (tbIFLA_CAN_TDC) + can_print_tdc_const_opt(f, tbIFLA_CAN_TDC); + + close_json_object(); } if (tbIFLA_CAN_DATA_BITRATE_CONST) { @@ -497,30 +590,23 @@ dbitrate = dbt->bitrate; } - if (is_json_context()) { - print_uint(PRINT_JSON, "data_bittiming_bitrate", - NULL, dbitrate); - open_json_array(PRINT_JSON, "data_bitrate_const"); - for (i = 0; i < dbitrate_cnt; ++i) - print_uint(PRINT_JSON, NULL, NULL, - dbitrate_consti); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n dbitrate %u", dbitrate); - fprintf(f, "\n "); - - for (i = 0; i < dbitrate_cnt - 1; ++i) { - /* This will keep lines below 80 signs */ - if (!(i % 6) && i) - fprintf(f, "\n "); - - fprintf(f, "%8u, ", dbitrate_consti); + can_print_nl_indent(); + print_uint(PRINT_ANY, "data_bittiming_bitrate", " dbitrate %u", + dbitrate); + can_print_nl_indent(); + open_json_array(PRINT_ANY, is_json_context() ? + "data_bitrate_const" : " "); + for (i = 0; i < dbitrate_cnt; ++i) { + /* This will keep lines below 80 signs */ + if (!(i % 6) && i) { + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", " "); } - - if (!(i % 6) && i) - fprintf(f, "\n "); - fprintf(f, "%8u ", dbitrate_consti); + print_uint(PRINT_ANY, NULL, + i < dbitrate_cnt - 1 ? "%8u, " : "%8u", + dbitrate_consti); } + close_json_array(PRINT_ANY, " "); } if (tbIFLA_CAN_TERMINATION_CONST && tbIFLA_CAN_TERMINATION) { @@ -530,29 +616,21 @@ sizeof(*trm_const); int i; - if (is_json_context()) { - print_hu(PRINT_JSON, "termination", NULL, *trm); - open_json_array(PRINT_JSON, "termination_const"); - for (i = 0; i < trm_cnt; ++i) - print_hu(PRINT_JSON, NULL, NULL, trm_consti); - close_json_array(PRINT_JSON, NULL); - } else { - fprintf(f, "\n termination %hu ", *trm); - - for (i = 0; i < trm_cnt - 1; ++i) - fprintf(f, "%hu, ", trm_consti); - - fprintf(f, "%hu ", trm_consti); - } + can_print_nl_indent(); + print_hu(PRINT_ANY, "termination", " termination %hu ", *trm); + open_json_array(PRINT_JSON, "termination_const"); + for (i = 0; i < trm_cnt; ++i) + print_hu(PRINT_ANY, NULL, + i < trm_cnt - 1 ? "%hu, " : "%hu", + trm_consti); + close_json_array(PRINT_ANY, " "); } if (tbIFLA_CAN_CLOCK) { struct can_clock *clock = RTA_DATA(tbIFLA_CAN_CLOCK); - print_int(PRINT_ANY, - "clock", - "\n clock %d ", - clock->freq); + can_print_nl_indent(); + print_uint(PRINT_ANY, "clock", " clock %u ", clock->freq); } } @@ -565,31 +643,23 @@ if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) { stats = RTA_DATA(xstats); - if (is_json_context()) { - print_int(PRINT_JSON, "restarts", - NULL, stats->restarts); - print_int(PRINT_JSON, "bus_error", - NULL, stats->bus_error); - print_int(PRINT_JSON, "arbitration_lost", - NULL, stats->arbitration_lost); - print_int(PRINT_JSON, "error_warning", - NULL, stats->error_warning); - print_int(PRINT_JSON, "error_passive", - NULL, stats->error_passive); - print_int(PRINT_JSON, "bus_off", NULL, stats->bus_off); - } else { - fprintf(f, "\n re-started bus-errors arbit-lost " - "error-warn error-pass bus-off"); - fprintf(f, "\n %-10d %-10d %-10d %-10d %-10d %-10d", - stats->restarts, stats->bus_error, - stats->arbitration_lost, stats->error_warning, - stats->error_passive, stats->bus_off); - } + can_print_nl_indent(); + print_string(PRINT_FP, NULL, "%s", + " re-started bus-errors arbit-lost error-warn error-pass bus-off"); + can_print_nl_indent(); + print_uint(PRINT_ANY, "restarts", " %-10u", stats->restarts); + print_uint(PRINT_ANY, "bus_error", " %-10u", stats->bus_error); + print_uint(PRINT_ANY, "arbitration_lost", " %-10u", + stats->arbitration_lost); + print_uint(PRINT_ANY, "error_warning", " %-10u", + stats->error_warning); + print_uint(PRINT_ANY, "error_passive", " %-10u", + stats->error_passive); + print_uint(PRINT_ANY, "bus_off", " %-10u", stats->bus_off); } } -static void can_print_help(struct link_util *lu, int argc, char **argv, - FILE *f) +static void can_print_help(struct link_util *lu, int argc, char **argv, FILE *f) { print_usage(f); }
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_dsa.c
Added
@@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * iplink_dsa.c DSA switch support + */ + +#include "utils.h" +#include "ip_common.h" + +static void print_usage(FILE *f) +{ + fprintf(f, "Usage: ... dsa conduit DEVICE \n"); +} + +static int dsa_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + while (argc > 0) { + if (strcmp(*argv, "conduit") == 0 || + strcmp(*argv, "master") == 0) { + __u32 ifindex; + + NEXT_ARG(); + ifindex = ll_name_to_index(*argv); + if (!ifindex) + invarg("Device does not exist\n", *argv); + addattr_l(n, 1024, IFLA_DSA_MASTER, &ifindex, 4); + } else if (strcmp(*argv, "help") == 0) { + print_usage(stderr); + return -1; + } else { + fprintf(stderr, "dsa: unknown command \"%s\"?\n", *argv); + print_usage(stderr); + return -1; + } + argc--; + argv++; + } + + return 0; +} + +static void dsa_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) +{ + if (!tb) + return; + + if (tbIFLA_DSA_MASTER) { + __u32 conduit = rta_getattr_u32(tbIFLA_DSA_MASTER); + + print_string(PRINT_ANY, + "conduit", "conduit %s ", + ll_index_to_name(conduit)); + } +} + +static void dsa_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) +{ + print_usage(f); +} + +struct link_util dsa_link_util = { + .id = "dsa", + .maxattr = IFLA_DSA_MAX, + .parse_opt = dsa_parse_opt, + .print_opt = dsa_print_opt, + .print_help = dsa_print_help, +};
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_geneve.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_geneve.c
Changed
@@ -31,6 +31,7 @@ " noudpcsum \n" " noudp6zerocsumtx \n" " noudp6zerocsumrx \n" + " innerprotoinherit \n" "\n" "Where: VNI := 0-16777215\n" " ADDR := IP_ADDRESS\n" @@ -72,6 +73,7 @@ __u64 attrs = 0; bool set_op = (n->nlmsg_type == RTM_NEWLINK && !(n->nlmsg_flags & NLM_F_CREATE)); + bool inner_proto_inherit = false; inet_prefix_reset(&daddr); @@ -182,6 +184,10 @@ check_duparg(&attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_RX, *argv, *argv); udp6zerocsumrx = 0; + } else if (!strcmp(*argv, "innerprotoinherit")) { + check_duparg(&attrs, IFLA_GENEVE_INNER_PROTO_INHERIT, + *argv, *argv); + inner_proto_inherit = true; } else if (matches(*argv, "help") == 0) { explain(); return -1; @@ -231,6 +237,8 @@ addattr16(n, 1024, IFLA_GENEVE_PORT, htons(dstport)); if (metadata) addattr(n, 1024, IFLA_GENEVE_COLLECT_METADATA); + if (inner_proto_inherit) + addattr(n, 1024, IFLA_GENEVE_INNER_PROTO_INHERIT); if (GENEVE_ATTRSET(attrs, IFLA_GENEVE_UDP_CSUM)) addattr8(n, 1024, IFLA_GENEVE_UDP_CSUM, udpcsum); if (GENEVE_ATTRSET(attrs, IFLA_GENEVE_UDP_ZERO_CSUM6_TX)) @@ -365,6 +373,11 @@ fputs("udp6zerocsumrx ", f); } } + + if (tbIFLA_GENEVE_INNER_PROTO_INHERIT) { + print_bool(PRINT_ANY, "inner_proto_inherit", + "innerprotoinherit ", true); + } } static void geneve_print_help(struct link_util *lu, int argc, char **argv,
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_gtp.c
Added
@@ -0,0 +1,140 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <stdio.h> + +#include "rt_names.h" +#include "utils.h" +#include "ip_common.h" + +#define GTP_ATTRSET(attrs, type) (((attrs) & (1L << (type))) != 0) + +static void print_explain(FILE *f) +{ + fprintf(f, + "Usage: ... gtp role ROLE\n" + " hsize HSIZE \n" + " restart_count RESTART_COUNT \n" + "\n" + "Where: ROLE := { sgsn | ggsn }\n" + " HSIZE := 1-131071\n" + " RESTART_COUNT := 0-255\n" + ); +} + +static void check_duparg(__u32 *attrs, int type, const char *key, + const char *argv) +{ + if (!GTP_ATTRSET(*attrs, type)) { + *attrs |= (1L << type); + return; + } + duparg2(key, argv); +} + +static int gtp_parse_opt(struct link_util *lu, int argc, char **argv, + struct nlmsghdr *n) +{ + __u32 attrs = 0; + + /* When creating GTP device through ip link, + * this flag has to be set. + */ + addattr8(n, 1024, IFLA_GTP_CREATE_SOCKETS, true); + + while (argc > 0) { + if (!strcmp(*argv, "role")) { + NEXT_ARG(); + check_duparg(&attrs, IFLA_GTP_ROLE, "role", *argv); + if (!strcmp(*argv, "sgsn")) + addattr32(n, 1024, IFLA_GTP_ROLE, GTP_ROLE_SGSN); + else if (!strcmp(*argv, "ggsn")) + addattr32(n, 1024, IFLA_GTP_ROLE, GTP_ROLE_GGSN); + else + invarg("invalid role, use sgsn or ggsn", *argv); + } else if (!strcmp(*argv, "hsize")) { + __u32 hsize; + + NEXT_ARG(); + check_duparg(&attrs, IFLA_GTP_PDP_HASHSIZE, "hsize", *argv); + + if (get_u32(&hsize, *argv, 0)) + invarg("invalid PDP hash size", *argv); + if (hsize >= 1u << 17) + invarg("PDP hash size too big", *argv); + addattr32(n, 1024, IFLA_GTP_PDP_HASHSIZE, hsize); + } else if (!strcmp(*argv, "restart_count")) { + __u8 restart_count; + + NEXT_ARG(); + check_duparg(&attrs, IFLA_GTP_RESTART_COUNT, "restart_count", *argv); + + if (get_u8(&restart_count, *argv, 10)) + invarg("invalid restart_count", *argv); + addattr8(n, 1024, IFLA_GTP_RESTART_COUNT, restart_count); + } else if (!strcmp(*argv, "help")) { + print_explain(stderr); + return -1; + } + argc--, argv++; + } + + if (!GTP_ATTRSET(attrs, IFLA_GTP_ROLE)) { + fprintf(stderr, "gtp: role of the gtp device was not specified\n"); + return -1; + } + + if (!GTP_ATTRSET(attrs, IFLA_GTP_PDP_HASHSIZE)) + addattr32(n, 1024, IFLA_GTP_PDP_HASHSIZE, 1024); + + return 0; +} + +static const char *gtp_role_to_string(__u32 role) +{ + switch (role) { + case GTP_ROLE_GGSN: + return "ggsn"; + case GTP_ROLE_SGSN: + return "sgsn"; + default: + return "unknown"; + } +} + +static void gtp_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb) +{ + + if (tbIFLA_GTP_ROLE) { + __u32 role = rta_getattr_u32(tbIFLA_GTP_ROLE); + + print_string(PRINT_ANY, "role", "role %s ", + gtp_role_to_string(role)); + } + + if (tbIFLA_GTP_PDP_HASHSIZE) { + __u32 hsize = rta_getattr_u32(tbIFLA_GTP_PDP_HASHSIZE); + + print_uint(PRINT_ANY, "hsize", "hsize %u ", hsize); + } + + if (tbIFLA_GTP_RESTART_COUNT) { + __u8 restart_count = rta_getattr_u8(tbIFLA_GTP_RESTART_COUNT); + + print_uint(PRINT_ANY, "restart_count", + "restart_count %u ", restart_count); + } +} + +static void gtp_print_help(struct link_util *lu, int argc, char **argv, + FILE *f) +{ + print_explain(f); +} + +struct link_util gtp_link_util = { + .id = "gtp", + .maxattr = IFLA_GTP_MAX, + .parse_opt = gtp_parse_opt, + .print_opt = gtp_print_opt, + .print_help = gtp_print_help, +};
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_virt_wifi.c
Added
@@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * iplink_virt_wifi.c A fake implementation of cfg80211_ops that can be tacked + * on to an ethernet net_device to make it appear as a + * wireless connection. + * + * Authors: Baligh Gasmi <gasmibal@gmail.com> + */ + +#include <stdio.h> +#include <stdlib.h> + +#include "utils.h" +#include "ip_common.h" + +static void virt_wifi_print_help(struct link_util *lu, + int argc, char **argv, FILE *f) +{ + fprintf(f, "Usage: ... virt_wifi \n"); +} + +struct link_util virt_wifi_link_util = { + .id = "virt_wifi", + .print_help = virt_wifi_print_help, +};
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_vxlan.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_vxlan.c
Changed
@@ -48,6 +48,7 @@ " noudp6zerocsumrx \n" " noremcsumtx noremcsumrx \n" " noexternal gbp gpe \n" + " novnifilter \n" "\n" "Where: VNI := 0-16777215\n" " ADDR := { IP_ADDRESS | any }\n" @@ -81,6 +82,7 @@ __u8 learning = 1; __u16 dstport = 0; __u8 metadata = 0; + __u8 vnifilter = 0; __u64 attrs = 0; bool set_op = (n->nlmsg_type == RTM_NEWLINK && !(n->nlmsg_flags & NLM_F_CREATE)); @@ -330,6 +332,15 @@ } else if (!matches(*argv, "gpe")) { check_duparg(&attrs, IFLA_VXLAN_GPE, *argv, *argv); addattr_l(n, 1024, IFLA_VXLAN_GPE, NULL, 0); + } else if (!strcmp(*argv, "vnifilter")) { + check_duparg(&attrs, IFLA_VXLAN_VNIFILTER, + *argv, *argv); + addattr8(n, 1024, IFLA_VXLAN_VNIFILTER, 1); + vnifilter = 1; + } else if (!strcmp(*argv, "novnifilter")) { + check_duparg(&attrs, IFLA_VXLAN_VNIFILTER, + *argv, *argv); + addattr8(n, 1024, IFLA_VXLAN_VNIFILTER, 0); } else if (matches(*argv, "help") == 0) { explain(); return -1; @@ -341,12 +352,17 @@ argc--, argv++; } + if (!metadata && vnifilter) { + fprintf(stderr, "vxlan: vnifilter is valid only when 'external' is set\n"); + return -1; + } + if (metadata && VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) { fprintf(stderr, "vxlan: both 'external' and vni cannot be specified\n"); return -1; } - if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID) && !set_op) { + if (!metadata && !vnifilter && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID) && !set_op) { fprintf(stderr, "vxlan: missing virtual network identifier\n"); return -1; } @@ -420,6 +436,11 @@ print_bool(PRINT_ANY, "external", "external ", true); } + if (tbIFLA_VXLAN_VNIFILTER && + rta_getattr_u8(tbIFLA_VXLAN_VNIFILTER)) { + print_bool(PRINT_ANY, "vnifilter", "vnifilter", true); + } + if (tbIFLA_VXLAN_ID && RTA_PAYLOAD(tbIFLA_VXLAN_ID) >= sizeof(__u32)) { print_uint(PRINT_ANY, "id", "id %u ", rta_getattr_u32(tbIFLA_VXLAN_ID));
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iplink_xstats.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iplink_xstats.c
Changed
@@ -65,7 +65,8 @@ else filt_mask = IFLA_STATS_FILTER_BIT(IFLA_STATS_LINK_XSTATS); - if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask) < 0) { + if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, filt_mask, + NULL, NULL) < 0) { perror("Cannont send dump request"); return -1; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipmacsec.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipmacsec.c
Changed
@@ -43,11 +43,19 @@ struct sa_desc { __u8 an; - __u32 pn; + union { + __u32 pn32; + __u64 pn64; + } pn; __u8 key_idMACSEC_KEYID_LEN; __u32 key_len; __u8 keyMACSEC_MAX_KEY_LEN; __u8 active; + __u8 saltMACSEC_SALT_LEN; + __u32 ssci; + bool xpn; + bool salt_set; + bool ssci_set; }; struct cipher_args { @@ -98,14 +106,20 @@ " ip macsec show\n" " ip macsec show DEV\n" " ip macsec offload DEV off | phy | mac \n" - "where OPTS := pn <u32> on | off \n" + "where OPTS := pn <u32> | xpn <u64> salt SALT ssci <u32> on | off \n" " ID := 128-bit hex string\n" " KEY := 128-bit or 256-bit hex string\n" - " SCI := { sci <u64> | port { 1..2^16-1 } address <lladdr> }\n"); + " SCI := { sci <u64> | port { 1..2^16-1 } address <lladdr> }\n" + " SALT := 96-bit hex string\n"); exit(-1); } +static bool ciphersuite_is_xpn(__u64 cid) +{ + return (cid == MACSEC_CIPHER_ID_GCM_AES_XPN_128 || cid == MACSEC_CIPHER_ID_GCM_AES_XPN_256); +} + static int get_an(__u8 *val, const char *arg) { int ret = get_u8(val, arg, 0); @@ -124,6 +138,11 @@ return get_be64(sci, arg, 16); } +static int get_ssci(__u32 *ssci, const char *arg) +{ + return get_be32(ssci, arg, 16); +} + static int get_port(__be16 *port, const char *arg) { return get_be16(port, arg, 0); @@ -174,14 +193,42 @@ while (argc > 0) { if (strcmp(*argv, "pn") == 0) { - if (sa->pn != 0) + if (sa->pn.pn64 != 0) duparg2("pn", "pn"); NEXT_ARG(); - ret = get_u32(&sa->pn, *argv, 0); + ret = get_u32(&sa->pn.pn32, *argv, 0); if (ret) invarg("expected pn", *argv); - if (sa->pn == 0) + if (sa->pn.pn32 == 0) invarg("expected pn != 0", *argv); + } else if (strcmp(*argv, "xpn") == 0) { + if (sa->pn.pn64 != 0) + duparg2("xpn", "xpn"); + NEXT_ARG(); + ret = get_u64(&sa->pn.pn64, *argv, 0); + if (ret) + invarg("expected pn", *argv); + if (sa->pn.pn64 == 0) + invarg("expected pn != 0", *argv); + sa->xpn = true; + } else if (strcmp(*argv, "salt") == 0) { + unsigned int len; + + if (sa->salt_set) + duparg2("salt", "salt"); + NEXT_ARG(); + if (!hexstring_a2n(*argv, sa->salt, MACSEC_SALT_LEN, + &len)) + invarg("expected salt", *argv); + sa->salt_set = true; + } else if (strcmp(*argv, "ssci") == 0) { + if (sa->ssci_set) + duparg2("ssci", "ssci"); + NEXT_ARG(); + ret = get_ssci(&sa->ssci, *argv); + if (ret) + invarg("expected ssci", *argv); + sa->ssci_set = true; } else if (strcmp(*argv, "key") == 0) { unsigned int len; @@ -392,9 +439,21 @@ addattr8(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_AN, sa->an); if (c != CMD_DEL) { - if (sa->pn) - addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, - sa->pn); + if (sa->xpn) { + if (sa->pn.pn64) + addattr64(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, + sa->pn.pn64); + if (sa->salt_set) + addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_SALT, + sa->salt, MACSEC_SALT_LEN); + if (sa->ssci_set) + addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_SSCI, + sa->ssci); + } else { + if (sa->pn.pn32) + addattr32(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_PN, + sa->pn.pn32); + } if (sa->key_len) { addattr_l(&req.n, MACSEC_BUFLEN, MACSEC_SA_ATTR_KEYID, @@ -426,7 +485,7 @@ return -1; } - if (sa->pn == 0) { + if (sa->pn.pn64 == 0) { fprintf(stderr, "must specify a packet number != 0\n"); return -1; } @@ -615,6 +674,9 @@ #define CIPHER_NAME_GCM_AES_128 "GCM-AES-128" #define CIPHER_NAME_GCM_AES_256 "GCM-AES-256" +#define CIPHER_NAME_GCM_AES_XPN_128 "GCM-AES-XPN-128" +#define CIPHER_NAME_GCM_AES_XPN_256 "GCM-AES-XPN-256" + #define DEFAULT_CIPHER_NAME CIPHER_NAME_GCM_AES_128 static const char *cs_id_to_name(__u64 cid) @@ -627,6 +689,10 @@ return CIPHER_NAME_GCM_AES_128; case MACSEC_CIPHER_ID_GCM_AES_256: return CIPHER_NAME_GCM_AES_256; + case MACSEC_CIPHER_ID_GCM_AES_XPN_128: + return CIPHER_NAME_GCM_AES_XPN_128; + case MACSEC_CIPHER_ID_GCM_AES_XPN_256: + return CIPHER_NAME_GCM_AES_XPN_256; default: return "(unknown)"; } @@ -846,8 +912,8 @@ } static void print_tx_sc(const char *prefix, __u64 sci, __u8 encoding_sa, - struct rtattr *txsc_stats, struct rtattr *secy_stats, - struct rtattr *sa) + bool is_xpn, struct rtattr *txsc_stats, + struct rtattr *secy_stats, struct rtattr *sa) { struct rtattr *sa_attrMACSEC_SA_ATTR_MAX + 1; struct rtattr *a; @@ -875,8 +941,16 @@ print_string(PRINT_FP, NULL, "%s", prefix); print_uint(PRINT_ANY, "an", "%d:", rta_getattr_u8(sa_attrMACSEC_SA_ATTR_AN)); - print_uint(PRINT_ANY, "pn", " PN %u,", - rta_getattr_u32(sa_attrMACSEC_SA_ATTR_PN)); + if (is_xpn) { + print_uint(PRINT_ANY, "pn", " PN %u,", + rta_getattr_u64(sa_attrMACSEC_SA_ATTR_PN)); + print_0xhex(PRINT_ANY, "ssci", + "SSCI %08x", + ntohl(rta_getattr_u32(sa_attrMACSEC_SA_ATTR_SSCI))); + } else { + print_uint(PRINT_ANY, "pn", " PN %u,", + rta_getattr_u32(sa_attrMACSEC_SA_ATTR_PN)); + } print_bool(PRINT_JSON, "active", NULL, state); print_string(PRINT_FP, NULL, @@ -916,7 +990,8 @@ } static void print_rx_sc(const char *prefix, __be64 sci, __u8 active, - struct rtattr *rxsc_stats, struct rtattr *sa) + bool is_xpn, struct rtattr *rxsc_stats, + struct rtattr *sa) { struct rtattr *sa_attrMACSEC_SA_ATTR_MAX + 1; struct rtattr *a; @@ -943,8 +1018,16 @@ print_string(PRINT_FP, NULL, "%s", prefix); print_uint(PRINT_ANY, "an", "%u:", rta_getattr_u8(sa_attrMACSEC_SA_ATTR_AN)); - print_uint(PRINT_ANY, "pn", " PN %u,", - rta_getattr_u32(sa_attrMACSEC_SA_ATTR_PN)); + if (is_xpn) { + print_uint(PRINT_ANY, "pn", " PN %u,", + rta_getattr_u64(sa_attrMACSEC_SA_ATTR_PN)); + print_0xhex(PRINT_ANY, "ssci", + "SSCI %08x", + ntohl(rta_getattr_u32(sa_attrMACSEC_SA_ATTR_SSCI))); + } else { + print_uint(PRINT_ANY, "pn", " PN %u,", + rta_getattr_u32(sa_attrMACSEC_SA_ATTR_PN)); + } print_bool(PRINT_JSON, "active", NULL, state); print_string(PRINT_FP, NULL, " state %s,", @@ -958,7 +1041,7 @@ close_json_array(PRINT_JSON, NULL); } -static void print_rxsc_list(struct rtattr *sc) +static void print_rxsc_list(struct rtattr *sc, bool is_xpn) { int rem = RTA_PAYLOAD(sc); struct rtattr *c; @@ -973,6 +1056,7 @@ print_rx_sc(" ", rta_getattr_u64(sc_attrMACSEC_RXSC_ATTR_SCI), rta_getattr_u32(sc_attrMACSEC_RXSC_ATTR_ACTIVE), + is_xpn, sc_attrMACSEC_RXSC_ATTR_STATS, sc_attrMACSEC_RXSC_ATTR_SA_LIST); close_json_object(); @@ -989,6 +1073,8 @@ int ifindex; __u64 sci; __u8 encoding_sa; + __u64 cid; + bool is_xpn = false; if (n->nlmsg_type != genl_family) return -1; @@ -1032,13 +1118,15 @@ print_attrs(attrs_secy); - print_tx_sc(" ", sci, encoding_sa, + cid = rta_getattr_u64(attrs_secyMACSEC_SECY_ATTR_CIPHER_SUITE); + is_xpn = ciphersuite_is_xpn(cid); + print_tx_sc(" ", sci, encoding_sa, is_xpn, attrsMACSEC_ATTR_TXSC_STATS, attrsMACSEC_ATTR_SECY_STATS, attrsMACSEC_ATTR_TXSA_LIST); if (attrsMACSEC_ATTR_RXSC_LIST) - print_rxsc_list(attrsMACSEC_ATTR_RXSC_LIST); + print_rxsc_list(attrsMACSEC_ATTR_RXSC_LIST, is_xpn); if (attrsMACSEC_ATTR_OFFLOAD) { struct rtattr *attrs_offloadMACSEC_OFFLOAD_ATTR_MAX + 1; @@ -1245,7 +1333,7 @@ { fprintf(f, "Usage: ... macsec address <lladdr> port { 1..2^16-1 } | sci <u64> \n" - " cipher { default | gcm-aes-128 | gcm-aes-256 } \n" + " cipher { default | gcm-aes-128 | gcm-aes-256 | gcm-aes-xpn-128 | gcm-aes-xpn-256 } \n" " icvlen { 8..16 } \n" " encrypt { on | off } \n" " send_sci { on | off } \n" @@ -1300,9 +1388,15 @@ else if (strcmp(*argv, "gcm-aes-256") == 0 || strcmp(*argv, "GCM-AES-256") == 0) cipher.id = MACSEC_CIPHER_ID_GCM_AES_256; + else if (strcmp(*argv, "gcm-aes-xpn-128") == 0 || + strcmp(*argv, "GCM-AES-XPN-128") == 0) + cipher.id = MACSEC_CIPHER_ID_GCM_AES_XPN_128; + else if (strcmp(*argv, "gcm-aes-xpn-256") == 0 || + strcmp(*argv, "GCM-AES-XPN-256") == 0) + cipher.id = MACSEC_CIPHER_ID_GCM_AES_XPN_256; else - invarg("expected: default, gcm-aes-128 or" - " gcm-aes-256", *argv); + invarg("expected: default, gcm-aes-128, gcm-aes-256," + " gcm-aes-xpn-128 or gcm-aes-xpn-256", *argv); } else if (strcmp(*argv, "icvlen") == 0) { NEXT_ARG(); if (cipher.icv_len)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipmonitor.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipmonitor.c
Changed
@@ -22,6 +22,7 @@ #include "utils.h" #include "ip_common.h" +#include "nh_common.h" static void usage(void) __attribute__((noreturn)); static int prefix_banner; @@ -33,7 +34,7 @@ "Usage: ip monitor all | OBJECTS FILE label all-nsid \n" " dev DEVICE \n" "OBJECTS := address | link | mroute | neigh | netconf |\n" - " nexthop | nsid | prefix | route | rule\n" + " nexthop | nsid | prefix | route | rule | stats\n" "FILE := file FILENAME\n"); exit(-1); } @@ -88,7 +89,7 @@ case RTM_NEWNEXTHOP: case RTM_DELNEXTHOP: print_headers(fp, "NEXTHOP", ctrl); - print_nexthop(n, arg); + print_cache_nexthop(n, arg, true); return 0; case RTM_NEWNEXTHOPBUCKET: @@ -157,6 +158,11 @@ print_nsid(n, arg); return 0; + case RTM_NEWSTATS: + print_headers(fp, "STATS", ctrl); + ipstats_print(n, arg); + return 0; + case NLMSG_ERROR: case NLMSG_NOOP: case NLMSG_DONE: @@ -172,39 +178,28 @@ return 0; } +#define IPMON_LLINK BIT(0) +#define IPMON_LADDR BIT(1) +#define IPMON_LROUTE BIT(2) +#define IPMON_LMROUTE BIT(3) +#define IPMON_LPREFIX BIT(4) +#define IPMON_LNEIGH BIT(5) +#define IPMON_LNETCONF BIT(6) +#define IPMON_LSTATS BIT(7) +#define IPMON_LRULE BIT(8) +#define IPMON_LNSID BIT(9) +#define IPMON_LNEXTHOP BIT(10) + +#define IPMON_L_ALL (~0) + int do_ipmonitor(int argc, char **argv) { - int lnexthop = 0, nh_set = 1; + unsigned int groups = 0, lmask = 0; + /* "needed" mask, failure to enable is an error */ + unsigned int nmask; char *file = NULL; - unsigned int groups = 0; - int llink = 0; - int laddr = 0; - int lroute = 0; - int lmroute = 0; - int lprefix = 0; - int lneigh = 0; - int lnetconf = 0; - int lrule = 0; - int lnsid = 0; int ifindex = 0; - groups |= nl_mgrp(RTNLGRP_LINK); - groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR); - groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR); - groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE); - groups |= nl_mgrp(RTNLGRP_IPV6_ROUTE); - groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE); - groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE); - groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE); - groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX); - groups |= nl_mgrp(RTNLGRP_NEIGH); - groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF); - groups |= nl_mgrp(RTNLGRP_IPV6_NETCONF); - groups |= nl_mgrp(RTNLGRP_IPV4_RULE); - groups |= nl_mgrp(RTNLGRP_IPV6_RULE); - groups |= nl_mgrp(RTNLGRP_NSID); - groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF); - rtnl_close(&rth); while (argc > 0) { @@ -214,44 +209,27 @@ } else if (matches(*argv, "label") == 0) { prefix_banner = 1; } else if (matches(*argv, "link") == 0) { - llink = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LLINK; } else if (matches(*argv, "address") == 0) { - laddr = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LADDR; } else if (matches(*argv, "route") == 0) { - lroute = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LROUTE; } else if (matches(*argv, "mroute") == 0) { - lmroute = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LMROUTE; } else if (matches(*argv, "prefix") == 0) { - lprefix = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LPREFIX; } else if (matches(*argv, "neigh") == 0) { - lneigh = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LNEIGH; } else if (matches(*argv, "netconf") == 0) { - lnetconf = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LNETCONF; } else if (matches(*argv, "rule") == 0) { - lrule = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LRULE; } else if (matches(*argv, "nsid") == 0) { - lnsid = 1; - groups = 0; - nh_set = 0; + lmask |= IPMON_LNSID; } else if (matches(*argv, "nexthop") == 0) { - lnexthop = 1; - groups = 0; + lmask |= IPMON_LNEXTHOP; + } else if (strcmp(*argv, "stats") == 0) { + lmask |= IPMON_LSTATS; } else if (strcmp(*argv, "all") == 0) { prefix_banner = 1; } else if (matches(*argv, "all-nsid") == 0) { @@ -277,15 +255,19 @@ ipneigh_reset_filter(ifindex); ipnetconf_reset_filter(ifindex); - if (llink) + nmask = lmask; + if (!lmask) + lmask = IPMON_L_ALL; + + if (lmask & IPMON_LLINK) groups |= nl_mgrp(RTNLGRP_LINK); - if (laddr) { + if (lmask & IPMON_LADDR) { if (!preferred_family || preferred_family == AF_INET) groups |= nl_mgrp(RTNLGRP_IPV4_IFADDR); if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_IFADDR); } - if (lroute) { + if (lmask & IPMON_LROUTE) { if (!preferred_family || preferred_family == AF_INET) groups |= nl_mgrp(RTNLGRP_IPV4_ROUTE); if (!preferred_family || preferred_family == AF_INET6) @@ -293,20 +275,20 @@ if (!preferred_family || preferred_family == AF_MPLS) groups |= nl_mgrp(RTNLGRP_MPLS_ROUTE); } - if (lmroute) { + if (lmask & IPMON_LMROUTE) { if (!preferred_family || preferred_family == AF_INET) groups |= nl_mgrp(RTNLGRP_IPV4_MROUTE); if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_MROUTE); } - if (lprefix) { + if (lmask & IPMON_LPREFIX) { if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_PREFIX); } - if (lneigh) { + if (lmask & IPMON_LNEIGH) { groups |= nl_mgrp(RTNLGRP_NEIGH); } - if (lnetconf) { + if (lmask & IPMON_LNETCONF) { if (!preferred_family || preferred_family == AF_INET) groups |= nl_mgrp(RTNLGRP_IPV4_NETCONF); if (!preferred_family || preferred_family == AF_INET6) @@ -314,17 +296,15 @@ if (!preferred_family || preferred_family == AF_MPLS) groups |= nl_mgrp(RTNLGRP_MPLS_NETCONF); } - if (lrule) { + if (lmask & IPMON_LRULE) { if (!preferred_family || preferred_family == AF_INET) groups |= nl_mgrp(RTNLGRP_IPV4_RULE); if (!preferred_family || preferred_family == AF_INET6) groups |= nl_mgrp(RTNLGRP_IPV6_RULE); } - if (lnsid) { + if (lmask & IPMON_LNSID) { groups |= nl_mgrp(RTNLGRP_NSID); } - if (nh_set) - lnexthop = 1; if (file) { FILE *fp; @@ -343,11 +323,19 @@ if (rtnl_open(&rth, groups) < 0) exit(1); - if (lnexthop && rtnl_add_nl_group(&rth, RTNLGRP_NEXTHOP) < 0) { + if (lmask & IPMON_LNEXTHOP && + rtnl_add_nl_group(&rth, RTNLGRP_NEXTHOP) < 0) { fprintf(stderr, "Failed to add nexthop group to list\n"); exit(1); } + if (lmask & IPMON_LSTATS && + rtnl_add_nl_group(&rth, RTNLGRP_STATS) < 0 && + nmask & IPMON_LSTATS) { + fprintf(stderr, "Failed to add stats group to list\n"); + exit(1); + } + if (listen_all_nsid && rtnl_listen_all_nsid(&rth) < 0) exit(1);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipmptcp.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipmptcp.c
Changed
@@ -1,31 +1,39 @@ // SPDX-License-Identifier: GPL-2.0 +#include <arpa/inet.h> +#include <netinet/in.h> +#include <stdbool.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> -#include <rt_names.h> -#include <errno.h> #include <linux/genetlink.h> +#include <linux/netlink.h> +#include <linux/rtnetlink.h> #include <linux/mptcp.h> #include "utils.h" #include "ip_common.h" -#include "libgenl.h" #include "json_print.h" +#include "libgenl.h" +#include "libnetlink.h" +#include "ll_map.h" static void usage(void) { fprintf(stderr, "Usage: ip mptcp endpoint add ADDRESS dev NAME id ID \n" " port NR FLAG-LIST \n" - " ip mptcp endpoint delete id ID\n" + " ip mptcp endpoint delete id ID ADDRESS \n" + " ip mptcp endpoint change id ID ADDRESS port NR CHANGE-OPT\n" " ip mptcp endpoint show id ID \n" " ip mptcp endpoint flush\n" " ip mptcp limits set subflows NR add_addr_accepted NR \n" " ip mptcp limits show\n" " ip mptcp monitor\n" "FLAG-LIST := FLAG-LIST FLAG\n" - "FLAG := signal | subflow | backup \n"); + "FLAG := signal | subflow | backup | fullmesh \n" + "CHANGE-OPT := backup | nobackup | fullmesh | nofullmesh \n"); exit(-1); } @@ -39,6 +47,8 @@ GENL_REQUEST(_req, MPTCP_BUFLEN, genl_family, 0, \ MPTCP_PM_VER, _cmd, _flags) +#define MPTCP_PM_ADDR_FLAG_NONE 0x0 + /* Mapping from argument to address flag mask */ static const struct { const char *name; @@ -47,6 +57,9 @@ { "signal", MPTCP_PM_ADDR_FLAG_SIGNAL }, { "subflow", MPTCP_PM_ADDR_FLAG_SUBFLOW }, { "backup", MPTCP_PM_ADDR_FLAG_BACKUP }, + { "fullmesh", MPTCP_PM_ADDR_FLAG_FULLMESH }, + { "nobackup", MPTCP_PM_ADDR_FLAG_NONE }, + { "nofullmesh", MPTCP_PM_ADDR_FLAG_NONE } }; static void print_mptcp_addr_flags(unsigned int flags) @@ -89,9 +102,11 @@ return -1; } -static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n, - bool adding) +static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n, int cmd) { + bool setting = cmd == MPTCP_PM_CMD_SET_FLAGS; + bool adding = cmd == MPTCP_PM_CMD_ADD_ADDR; + bool deling = cmd == MPTCP_PM_CMD_DEL_ADDR; struct rtattr *attr_addr; bool addr_set = false; inet_prefix address; @@ -104,6 +119,17 @@ ll_init_map(&rth); while (argc > 0) { if (get_flags(*argv, &flags) == 0) { + if (adding && + (flags & MPTCP_PM_ADDR_FLAG_SIGNAL) && + (flags & MPTCP_PM_ADDR_FLAG_FULLMESH)) + invarg("flags mustn't have both signal and fullmesh", *argv); + + /* allow changing the 'backup' and 'fullmesh' flags only */ + if (setting && + (flags & ~(MPTCP_PM_ADDR_FLAG_BACKUP | + MPTCP_PM_ADDR_FLAG_FULLMESH))) + invarg("invalid flags, backup and fullmesh only", *argv); + } else if (matches(*argv, "id") == 0) { NEXT_ARG(); @@ -140,12 +166,21 @@ if (!addr_set && adding) missarg("ADDRESS"); - if (!id_set && !adding) + if (!id_set && deling) { missarg("ID"); + } else if (id_set && deling) { + if (id && addr_set) + invarg("invalid for non-zero id address\n", "ADDRESS"); + else if (!id && !addr_set) + invarg("address is needed for deleting id 0 address\n", "ID"); + } - if (port && !(flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) + if (adding && port && !(flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) invarg("flags must have signal when using port", "port"); + if (setting && id_set && port) + invarg("port can't be used with id", "port"); + attr_addr = addattr_nest(n, MPTCP_BUFLEN, MPTCP_PM_ATTR_ADDR | NLA_F_NESTED); if (id_set) @@ -176,7 +211,7 @@ MPTCP_REQUEST(req, cmd, NLM_F_REQUEST); int ret; - ret = mptcp_parse_opt(argc, argv, &req.n, cmd == MPTCP_PM_CMD_ADD_ADDR); + ret = mptcp_parse_opt(argc, argv, &req.n, cmd); if (ret) return ret; @@ -292,14 +327,19 @@ if (argc <= 0) return mptcp_addr_dump(); - ret = mptcp_parse_opt(argc, argv, &req.n, false); + ret = mptcp_parse_opt(argc, argv, &req.n, MPTCP_PM_CMD_GET_ADDR); if (ret) return ret; if (rtnl_talk(&genl_rth, &req.n, &answer) < 0) return -2; - return print_mptcp_addr(answer, stdout); + new_json_obj(json); + ret = print_mptcp_addr(answer, stdout); + delete_json_obj(); + free(answer); + fflush(stdout); + return ret; } static int mptcp_addr_flush(int argc, char **argv) @@ -396,9 +436,13 @@ if (rtnl_talk(&genl_rth, &req.n, do_get ? &answer : NULL) < 0) return -2; - if (do_get) - return print_mptcp_limit(answer, stdout); - return 0; + ret = 0; + if (do_get) { + ret = print_mptcp_limit(answer, stdout); + free(answer); + } + + return ret; } static const char * const event_to_str = { @@ -524,6 +568,9 @@ if (matches(*argv, "add") == 0) return mptcp_addr_modify(argc-1, argv+1, MPTCP_PM_CMD_ADD_ADDR); + if (matches(*argv, "change") == 0) + return mptcp_addr_modify(argc-1, argv+1, + MPTCP_PM_CMD_SET_FLAGS); if (matches(*argv, "delete") == 0) return mptcp_addr_modify(argc-1, argv+1, MPTCP_PM_CMD_DEL_ADDR);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipmroute.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipmroute.c
Changed
@@ -39,9 +39,6 @@ "Usage: ip mroute show to PREFIX from PREFIX iif DEVICE \n" " table TABLE_ID \n" "TABLE_ID := local | main | default | all | NUMBER \n" -#if 0 - "Usage: ip mroute add | del DESTINATION from SOURCE iif DEVICE oif DEVICE \n" -#endif ); exit(-1); } @@ -322,14 +319,7 @@ { if (argc < 1) return mroute_list(0, NULL); -#if 0 - if (matches(*argv, "add") == 0) - return mroute_modify(RTM_NEWADDR, argc-1, argv+1); - if (matches(*argv, "delete") == 0) - return mroute_modify(RTM_DELADDR, argc-1, argv+1); - if (matches(*argv, "get") == 0) - return mroute_get(argc-1, argv+1); -#endif + if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 || matches(*argv, "lst") == 0) return mroute_list(argc-1, argv+1);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipneigh.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipneigh.c
Changed
@@ -51,12 +51,12 @@ fprintf(stderr, "Usage: ip neigh { add | del | change | replace }\n" " { ADDR lladdr LLADDR nud STATE proxy ADDR }\n" - " dev DEV router extern_learn protocol PROTO \n" + " dev DEV router use managed extern_learn \n" + " protocol PROTO \n" "\n" - " ip neigh { show | flush } proxy to PREFIX dev DEV nud STATE \n" - " vrf NAME \n" - "\n" - " ip neigh get { ADDR | proxy ADDR } dev DEV\n" + " ip neigh { show | flush } proxy to PREFIX dev DEV nud STATE \n" + " vrf NAME nomaster \n" + " ip neigh get { ADDR | proxy ADDR } dev DEV\n" "\n" "STATE := { delay | failed | incomplete | noarp | none |\n" " permanent | probe | reachable | stale }\n"); @@ -116,6 +116,7 @@ .ndm.ndm_family = preferred_family, .ndm.ndm_state = NUD_PERMANENT, }; + __u32 ext_flags = 0; char *dev = NULL; int dst_ok = 0; int dev_ok = 0; @@ -149,6 +150,11 @@ req.ndm.ndm_flags |= NTF_PROXY; } else if (strcmp(*argv, "router") == 0) { req.ndm.ndm_flags |= NTF_ROUTER; + } else if (strcmp(*argv, "use") == 0) { + req.ndm.ndm_flags |= NTF_USE; + } else if (strcmp(*argv, "managed") == 0) { + ext_flags |= NTF_EXT_MANAGED; + req.ndm.ndm_state = NUD_NONE; } else if (matches(*argv, "extern_learn") == 0) { req.ndm.ndm_flags |= NTF_EXT_LEARNED; } else if (strcmp(*argv, "dev") == 0) { @@ -184,7 +190,10 @@ req.ndm.ndm_family = dst.family; if (addattr_l(&req.n, sizeof(req), NDA_DST, &dst.data, dst.bytelen) < 0) return -1; - + if (ext_flags && + addattr_l(&req.n, sizeof(req), NDA_FLAGS_EXT, &ext_flags, + sizeof(ext_flags)) < 0) + return -1; if (lla && strcmp(lla, "null")) { char llabuf20; int l; @@ -236,7 +245,7 @@ #define PRINT_FLAG(f) \ if (nud & NUD_##f) { \ nud &= ~NUD_##f; \ - print_string(PRINT_ANY, NULL, " %s", #f); \ + print_string(PRINT_ANY, NULL, "%s ", #f); \ } PRINT_FLAG(INCOMPLETE); @@ -304,6 +313,7 @@ int len = n->nlmsg_len; struct rtattr *tbNDA_MAX+1; static int logit = 1; + __u32 ext_flags = 0; __u8 protocol = 0; if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH && @@ -347,6 +357,8 @@ if (tbNDA_PROTOCOL) protocol = rta_getattr_u8(tbNDA_PROTOCOL); + if (tbNDA_FLAGS_EXT) + ext_flags = rta_getattr_u32(tbNDA_FLAGS_EXT); if (filter.protocol && filter.protocol != protocol) return 0; @@ -424,27 +436,26 @@ fprintf(fp, "lladdr "); print_color_string(PRINT_ANY, COLOR_MAC, - "lladdr", "%s", lladdr); + "lladdr", "%s ", lladdr); } if (r->ndm_flags & NTF_ROUTER) - print_null(PRINT_ANY, "router", " %s", "router"); - + print_null(PRINT_ANY, "router", "%s ", "router"); if (r->ndm_flags & NTF_PROXY) - print_null(PRINT_ANY, "proxy", " %s", "proxy"); - + print_null(PRINT_ANY, "proxy", "%s ", "proxy"); + if (ext_flags & NTF_EXT_MANAGED) + print_null(PRINT_ANY, "managed", "%s ", "managed"); if (r->ndm_flags & NTF_EXT_LEARNED) - print_null(PRINT_ANY, "extern_learn", " %s ", "extern_learn"); - + print_null(PRINT_ANY, "extern_learn", "%s ", "extern_learn"); if (r->ndm_flags & NTF_OFFLOADED) - print_null(PRINT_ANY, "offload", " %s", "offload"); + print_null(PRINT_ANY, "offload", "%s ", "offload"); if (show_stats) { if (tbNDA_CACHEINFO) print_cacheinfo(RTA_DATA(tbNDA_CACHEINFO)); if (tbNDA_PROBES) - print_uint(PRINT_ANY, "probes", " probes %u", + print_uint(PRINT_ANY, "probes", "probes %u ", rta_getattr_u32(tbNDA_PROBES)); } @@ -454,7 +465,7 @@ if (protocol) { SPRINT_BUF(b1); - print_string(PRINT_ANY, "protocol", " proto %s ", + print_string(PRINT_ANY, "protocol", "proto %s ", rtnl_rtprot_n2a(protocol, b1, sizeof(b1))); } @@ -536,6 +547,8 @@ if (!name_is_vrf(*argv)) invarg("Not a valid VRF name\n", *argv); filter.master = ifindex; + } else if (strcmp(*argv, "nomaster") == 0) { + filter.master = -1; } else if (strcmp(*argv, "unused") == 0) { filter.unused_only = 1; } else if (strcmp(*argv, "nud") == 0) { @@ -718,8 +731,10 @@ ipneigh_reset_filter(0); if (print_neigh(answer, stdout) < 0) { fprintf(stderr, "An error :-)\n"); + free(answer); return -1; } + free(answer); return 0; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/ipnexthop.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipnexthop.c
Changed
@@ -6,6 +6,7 @@ */ #include <linux/nexthop.h> +#include <stdint.h> #include <stdio.h> #include <string.h> #include <rt_names.h> @@ -13,6 +14,7 @@ #include "utils.h" #include "ip_common.h" +#include "nh_common.h" static struct { unsigned int flushed; @@ -33,6 +35,9 @@ #define RTM_NHA(h) ((struct rtattr *)(((char *)(h)) + \ NLMSG_ALIGN(sizeof(struct nhmsg)))) +static struct hlist_head nh_cacheNH_CACHE_SIZE; +static struct rtnl_handle nh_cache_rth = { .fd = -1 }; + static void usage(void) __attribute__((noreturn)); static void usage(void) @@ -212,28 +217,29 @@ return rc; } -static void print_nh_group(FILE *fp, const struct rtattr *grps_attr) +static bool __valid_nh_group_attr(const struct rtattr *g_attr) { - struct nexthop_grp *nhg = RTA_DATA(grps_attr); - int num = RTA_PAYLOAD(grps_attr) / sizeof(*nhg); - int i; + int num = RTA_PAYLOAD(g_attr) / sizeof(struct nexthop_grp); - if (!num || num * sizeof(*nhg) != RTA_PAYLOAD(grps_attr)) { - fprintf(fp, "<invalid nexthop group>"); - return; - } + return num && num * sizeof(struct nexthop_grp) == RTA_PAYLOAD(g_attr); +} + +static void print_nh_group(const struct nh_entry *nhe) +{ + int i; open_json_array(PRINT_JSON, "group"); print_string(PRINT_FP, NULL, "%s", "group "); - for (i = 0; i < num; ++i) { + for (i = 0; i < nhe->nh_groups_cnt; ++i) { open_json_object(NULL); if (i) print_string(PRINT_FP, NULL, "%s", "/"); - print_uint(PRINT_ANY, "id", "%u", nhgi.id); - if (nhgi.weight) - print_uint(PRINT_ANY, "weight", ",%u", nhgi.weight + 1); + print_uint(PRINT_ANY, "id", "%u", nhe->nh_groupsi.id); + if (nhe->nh_groupsi.weight) + print_uint(PRINT_ANY, "weight", ",%u", + nhe->nh_groupsi.weight + 1); close_json_object(); } @@ -253,50 +259,59 @@ } } -static void print_nh_group_type(FILE *fp, const struct rtattr *grp_type_attr) +static void print_nh_group_type(__u16 nh_grp_type) { - __u16 type = rta_getattr_u16(grp_type_attr); - - if (type == NEXTHOP_GRP_TYPE_MPATH) + if (nh_grp_type == NEXTHOP_GRP_TYPE_MPATH) /* Do not print type in order not to break existing output. */ return; - print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(type)); + print_string(PRINT_ANY, "type", "type %s ", nh_group_type_name(nh_grp_type)); } -static void print_nh_res_group(FILE *fp, const struct rtattr *res_grp_attr) +static void parse_nh_res_group_rta(const struct rtattr *res_grp_attr, + struct nha_res_grp *res_grp) { struct rtattr *tbNHA_RES_GROUP_MAX + 1; struct rtattr *rta; - struct timeval tv; + memset(res_grp, 0, sizeof(*res_grp)); parse_rtattr_nested(tb, NHA_RES_GROUP_MAX, res_grp_attr); - open_json_object("resilient_args"); - if (tbNHA_RES_GROUP_BUCKETS) - print_uint(PRINT_ANY, "buckets", "buckets %u ", - rta_getattr_u16(tbNHA_RES_GROUP_BUCKETS)); + res_grp->buckets = rta_getattr_u16(tbNHA_RES_GROUP_BUCKETS); if (tbNHA_RES_GROUP_IDLE_TIMER) { rta = tbNHA_RES_GROUP_IDLE_TIMER; - __jiffies_to_tv(&tv, rta_getattr_u32(rta)); - print_tv(PRINT_ANY, "idle_timer", "idle_timer %g ", &tv); + res_grp->idle_timer = rta_getattr_u32(rta); } if (tbNHA_RES_GROUP_UNBALANCED_TIMER) { rta = tbNHA_RES_GROUP_UNBALANCED_TIMER; - __jiffies_to_tv(&tv, rta_getattr_u32(rta)); - print_tv(PRINT_ANY, "unbalanced_timer", "unbalanced_timer %g ", - &tv); + res_grp->unbalanced_timer = rta_getattr_u32(rta); } if (tbNHA_RES_GROUP_UNBALANCED_TIME) { rta = tbNHA_RES_GROUP_UNBALANCED_TIME; - __jiffies_to_tv(&tv, rta_getattr_u32(rta)); - print_tv(PRINT_ANY, "unbalanced_time", "unbalanced_time %g ", - &tv); + res_grp->unbalanced_time = rta_getattr_u64(rta); } +} + +static void print_nh_res_group(const struct nha_res_grp *res_grp) +{ + struct timeval tv; + + open_json_object("resilient_args"); + + print_uint(PRINT_ANY, "buckets", "buckets %u ", res_grp->buckets); + + __jiffies_to_tv(&tv, res_grp->idle_timer); + print_tv(PRINT_ANY, "idle_timer", "idle_timer %g ", &tv); + + __jiffies_to_tv(&tv, res_grp->unbalanced_timer); + print_tv(PRINT_ANY, "unbalanced_timer", "unbalanced_timer %g ", &tv); + + __jiffies_to_tv(&tv, res_grp->unbalanced_time); + print_tv(PRINT_ANY, "unbalanced_time", "unbalanced_time %g ", &tv); close_json_object(); } @@ -328,86 +343,366 @@ close_json_object(); } -int print_nexthop(struct nlmsghdr *n, void *arg) +static void ipnh_destroy_entry(struct nh_entry *nhe) +{ + if (nhe->nh_encap) + free(nhe->nh_encap); + if (nhe->nh_groups) + free(nhe->nh_groups); +} + +/* parse nhmsg into nexthop entry struct which must be destroyed by + * ipnh_destroy_enty when it's not needed anymore + */ +static int ipnh_parse_nhmsg(FILE *fp, const struct nhmsg *nhm, int len, + struct nh_entry *nhe) { - struct nhmsg *nhm = NLMSG_DATA(n); struct rtattr *tbNHA_MAX+1; - FILE *fp = (FILE *)arg; - int len; + int err = 0; - SPRINT_BUF(b1); + memset(nhe, 0, sizeof(*nhe)); + parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED); - if (n->nlmsg_type != RTM_DELNEXTHOP && - n->nlmsg_type != RTM_NEWNEXTHOP) { - fprintf(stderr, "Not a nexthop: %08x %08x %08x\n", - n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); - return -1; + if (tbNHA_ID) + nhe->nh_id = rta_getattr_u32(tbNHA_ID); + + if (tbNHA_OIF) + nhe->nh_oif = rta_getattr_u32(tbNHA_OIF); + + if (tbNHA_GROUP_TYPE) + nhe->nh_grp_type = rta_getattr_u16(tbNHA_GROUP_TYPE); + + if (tbNHA_GATEWAY) { + if (RTA_PAYLOAD(tbNHA_GATEWAY) > sizeof(nhe->nh_gateway)) { + fprintf(fp, "<nexthop id %u invalid gateway length %lu>\n", + nhe->nh_id, RTA_PAYLOAD(tbNHA_GATEWAY)); + err = -EINVAL; + goto out_err; + } + nhe->nh_gateway_len = RTA_PAYLOAD(tbNHA_GATEWAY); + memcpy(&nhe->nh_gateway, RTA_DATA(tbNHA_GATEWAY), + RTA_PAYLOAD(tbNHA_GATEWAY)); } - len = n->nlmsg_len - NLMSG_SPACE(sizeof(*nhm)); - if (len < 0) { - close_json_object(); - fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); - return -1; + if (tbNHA_ENCAP) { + nhe->nh_encap = malloc(RTA_LENGTH(RTA_PAYLOAD(tbNHA_ENCAP))); + if (!nhe->nh_encap) { + err = -ENOMEM; + goto out_err; + } + memcpy(nhe->nh_encap, tbNHA_ENCAP, + RTA_LENGTH(RTA_PAYLOAD(tbNHA_ENCAP))); + memcpy(&nhe->nh_encap_type, tbNHA_ENCAP_TYPE, + sizeof(nhe->nh_encap_type)); } - if (filter.proto && filter.proto != nhm->nh_protocol) - return 0; + if (tbNHA_GROUP) { + if (!__valid_nh_group_attr(tbNHA_GROUP)) { + fprintf(fp, "<nexthop id %u invalid nexthop group>", + nhe->nh_id); + err = -EINVAL; + goto out_err; + } - parse_rtattr_flags(tb, NHA_MAX, RTM_NHA(nhm), len, NLA_F_NESTED); + nhe->nh_groups = malloc(RTA_PAYLOAD(tbNHA_GROUP)); + if (!nhe->nh_groups) { + err = -ENOMEM; + goto out_err; + } + nhe->nh_groups_cnt = RTA_PAYLOAD(tbNHA_GROUP) / + sizeof(struct nexthop_grp); + memcpy(nhe->nh_groups, RTA_DATA(tbNHA_GROUP), + RTA_PAYLOAD(tbNHA_GROUP)); + } - open_json_object(NULL); + if (tbNHA_RES_GROUP) { + parse_nh_res_group_rta(tbNHA_RES_GROUP, &nhe->nh_res_grp); + nhe->nh_has_res_grp = true; + } - if (n->nlmsg_type == RTM_DELNEXTHOP) + nhe->nh_blackhole = !!tbNHA_BLACKHOLE; + nhe->nh_fdb = !!tbNHA_FDB; + + nhe->nh_family = nhm->nh_family; + nhe->nh_protocol = nhm->nh_protocol; + nhe->nh_scope = nhm->nh_scope; + nhe->nh_flags = nhm->nh_flags; + + return 0; + +out_err: + ipnh_destroy_entry(nhe); + return err; +} + +static void __print_nexthop_entry(FILE *fp, const char *jsobj, + struct nh_entry *nhe, + bool deleted) +{ + SPRINT_BUF(b1); + + open_json_object(jsobj); + + if (deleted) print_bool(PRINT_ANY, "deleted", "Deleted ", true); - if (tbNHA_ID) - print_uint(PRINT_ANY, "id", "id %u ", - rta_getattr_u32(tbNHA_ID)); + print_uint(PRINT_ANY, "id", "id %u ", nhe->nh_id); - if (tbNHA_GROUP) - print_nh_group(fp, tbNHA_GROUP); + if (nhe->nh_groups) + print_nh_group(nhe); - if (tbNHA_GROUP_TYPE) - print_nh_group_type(fp, tbNHA_GROUP_TYPE); + print_nh_group_type(nhe->nh_grp_type); - if (tbNHA_RES_GROUP) - print_nh_res_group(fp, tbNHA_RES_GROUP); + if (nhe->nh_has_res_grp) + print_nh_res_group(&nhe->nh_res_grp); - if (tbNHA_ENCAP) - lwt_print_encap(fp, tbNHA_ENCAP_TYPE, tbNHA_ENCAP); + if (nhe->nh_encap) + lwt_print_encap(fp, &nhe->nh_encap_type.rta, nhe->nh_encap); - if (tbNHA_GATEWAY) - print_rta_gateway(fp, nhm->nh_family, tbNHA_GATEWAY); + if (nhe->nh_gateway_len) + __print_rta_gateway(fp, nhe->nh_family, + format_host(nhe->nh_family, + nhe->nh_gateway_len, + &nhe->nh_gateway)); - if (tbNHA_OIF) - print_rta_if(fp, tbNHA_OIF, "dev"); + if (nhe->nh_oif) + print_rta_ifidx(fp, nhe->nh_oif, "dev"); - if (nhm->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) { + if (nhe->nh_scope != RT_SCOPE_UNIVERSE || show_details > 0) { print_string(PRINT_ANY, "scope", "scope %s ", - rtnl_rtscope_n2a(nhm->nh_scope, b1, sizeof(b1))); + rtnl_rtscope_n2a(nhe->nh_scope, b1, sizeof(b1))); } - if (tbNHA_BLACKHOLE) + if (nhe->nh_blackhole) print_null(PRINT_ANY, "blackhole", "blackhole ", NULL); - if (nhm->nh_protocol != RTPROT_UNSPEC || show_details > 0) { + if (nhe->nh_protocol != RTPROT_UNSPEC || show_details > 0) { print_string(PRINT_ANY, "protocol", "proto %s ", - rtnl_rtprot_n2a(nhm->nh_protocol, b1, sizeof(b1))); + rtnl_rtprot_n2a(nhe->nh_protocol, b1, sizeof(b1))); } - print_rt_flags(fp, nhm->nh_flags); + print_rt_flags(fp, nhe->nh_flags); - if (tbNHA_FDB) + if (nhe->nh_fdb) print_null(PRINT_ANY, "fdb", "fdb", NULL); - print_string(PRINT_FP, NULL, "%s", "\n"); close_json_object(); +} + +static int __ipnh_get_id(struct rtnl_handle *rthp, __u32 nh_id, + struct nlmsghdr **answer) +{ + struct { + struct nlmsghdr n; + struct nhmsg nhm; + char buf1024; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = RTM_GETNEXTHOP, + .nhm.nh_family = preferred_family, + }; + + addattr32(&req.n, sizeof(req), NHA_ID, nh_id); + + return rtnl_talk(rthp, &req.n, answer); +} + +static struct hlist_head *ipnh_cache_head(__u32 nh_id) +{ + nh_id ^= nh_id >> 20; + nh_id ^= nh_id >> 10; + + return &nh_cachenh_id % NH_CACHE_SIZE; +} + +static void ipnh_cache_link_entry(struct nh_entry *nhe) +{ + struct hlist_head *head = ipnh_cache_head(nhe->nh_id); + + hlist_add_head(&nhe->nh_hash, head); +} + +static void ipnh_cache_unlink_entry(struct nh_entry *nhe) +{ + hlist_del(&nhe->nh_hash); +} + +static struct nh_entry *ipnh_cache_get(__u32 nh_id) +{ + struct hlist_head *head = ipnh_cache_head(nh_id); + struct nh_entry *nhe; + struct hlist_node *n; + + hlist_for_each(n, head) { + nhe = container_of(n, struct nh_entry, nh_hash); + if (nhe->nh_id == nh_id) + return nhe; + } + + return NULL; +} + +static int __ipnh_cache_parse_nlmsg(const struct nlmsghdr *n, + struct nh_entry *nhe) +{ + int err, len; + + len = n->nlmsg_len - NLMSG_SPACE(sizeof(struct nhmsg)); + if (len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -EINVAL; + } + + err = ipnh_parse_nhmsg(stderr, NLMSG_DATA(n), len, nhe); + if (err) { + fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err)); + return err; + } + + return 0; +} + +static struct nh_entry *ipnh_cache_add(__u32 nh_id) +{ + struct nlmsghdr *answer = NULL; + struct nh_entry *nhe = NULL; + + if (nh_cache_rth.fd < 0 && rtnl_open(&nh_cache_rth, 0) < 0) { + nh_cache_rth.fd = -1; + goto out; + } + + if (__ipnh_get_id(&nh_cache_rth, nh_id, &answer) < 0) + goto out; + + nhe = malloc(sizeof(*nhe)); + if (!nhe) + goto out; + + if (__ipnh_cache_parse_nlmsg(answer, nhe)) + goto out_free_nhe; + + ipnh_cache_link_entry(nhe); + +out: + if (answer) + free(answer); + + return nhe; + +out_free_nhe: + free(nhe); + nhe = NULL; + goto out; +} + +static void ipnh_cache_del(struct nh_entry *nhe) +{ + ipnh_cache_unlink_entry(nhe); + ipnh_destroy_entry(nhe); + free(nhe); +} + +/* update, add or delete a nexthop entry based on nlmsghdr */ +static int ipnh_cache_process_nlmsg(const struct nlmsghdr *n, + struct nh_entry *new_nhe) +{ + struct nh_entry *nhe; + + nhe = ipnh_cache_get(new_nhe->nh_id); + switch (n->nlmsg_type) { + case RTM_DELNEXTHOP: + if (nhe) + ipnh_cache_del(nhe); + ipnh_destroy_entry(new_nhe); + break; + case RTM_NEWNEXTHOP: + if (!nhe) { + nhe = malloc(sizeof(*nhe)); + if (!nhe) { + ipnh_destroy_entry(new_nhe); + return -1; + } + } else { + /* this allows us to save 1 allocation on updates by + * reusing the old nh entry, but we need to cleanup its + * internal storage + */ + ipnh_cache_unlink_entry(nhe); + ipnh_destroy_entry(nhe); + } + memcpy(nhe, new_nhe, sizeof(*nhe)); + ipnh_cache_link_entry(nhe); + break; + } + + return 0; +} + +void print_cache_nexthop_id(FILE *fp, const char *fp_prefix, const char *jsobj, + __u32 nh_id) +{ + struct nh_entry *nhe = ipnh_cache_get(nh_id); + + if (!nhe) { + nhe = ipnh_cache_add(nh_id); + if (!nhe) + return; + } + + if (fp_prefix) + print_string(PRINT_FP, NULL, "%s", fp_prefix); + __print_nexthop_entry(fp, jsobj, nhe, false); +} + +int print_cache_nexthop(struct nlmsghdr *n, void *arg, bool process_cache) +{ + struct nhmsg *nhm = NLMSG_DATA(n); + FILE *fp = (FILE *)arg; + struct nh_entry nhe; + int len, err; + + if (n->nlmsg_type != RTM_DELNEXTHOP && + n->nlmsg_type != RTM_NEWNEXTHOP) { + fprintf(stderr, "Not a nexthop: %08x %08x %08x\n", + n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); + return -1; + } + + len = n->nlmsg_len - NLMSG_SPACE(sizeof(*nhm)); + if (len < 0) { + close_json_object(); + fprintf(stderr, "BUG: wrong nlmsg len %d\n", len); + return -1; + } + + if (filter.proto && filter.proto != nhm->nh_protocol) + return 0; + + err = ipnh_parse_nhmsg(fp, nhm, len, &nhe); + if (err) { + close_json_object(); + fprintf(stderr, "Error parsing nexthop: %s\n", strerror(-err)); + return -1; + } + __print_nexthop_entry(fp, NULL, &nhe, n->nlmsg_type == RTM_DELNEXTHOP); + print_string(PRINT_FP, NULL, "%s", "\n"); fflush(fp); + if (process_cache) + ipnh_cache_process_nlmsg(n, &nhe); + else + ipnh_destroy_entry(&nhe); + return 0; } +static int print_nexthop_nocache(struct nlmsghdr *n, void *arg) +{ + return print_cache_nexthop(n, arg, false); +} + int print_nexthop_bucket(struct nlmsghdr *n, void *arg) { struct nhmsg *nhm = NLMSG_DATA(n); @@ -546,7 +841,7 @@ NEXT_ARG(); if (get_unsigned(&idle_timer, *argv, 0) || - idle_timer >= ~0UL / 100) + idle_timer >= UINT32_MAX / 100) invarg("invalid idle timer value", *argv); addattr32(n, maxlen, NHA_RES_GROUP_IDLE_TIMER, @@ -556,7 +851,7 @@ NEXT_ARG(); if (get_unsigned(&unbalanced_timer, *argv, 0) || - unbalanced_timer >= ~0UL / 100) + unbalanced_timer >= UINT32_MAX / 100) invarg("invalid unbalanced timer value", *argv); addattr32(n, maxlen, NHA_RES_GROUP_UNBALANCED_TIMER, @@ -625,6 +920,7 @@ .nhm.nh_family = preferred_family, }; __u32 nh_flags = 0; + int ret; while (argc > 0) { if (!strcmp(*argv, "id")) { @@ -704,7 +1000,12 @@ req.nhm.nh_flags = nh_flags; - if (rtnl_talk(&rth, &req.n, NULL) < 0) + if (echo_request) + ret = rtnl_echo_talk(&rth, &req.n, json, print_nexthop_nocache); + else + ret = rtnl_talk(&rth, &req.n, NULL); + + if (ret) return -2; return 0; @@ -712,26 +1013,14 @@ static int ipnh_get_id(__u32 id) { - struct { - struct nlmsghdr n; - struct nhmsg nhm; - char buf1024; - } req = { - .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct nhmsg)), - .n.nlmsg_flags = NLM_F_REQUEST, - .n.nlmsg_type = RTM_GETNEXTHOP, - .nhm.nh_family = preferred_family, - }; struct nlmsghdr *answer; - addattr32(&req.n, sizeof(req), NHA_ID, id); - - if (rtnl_talk(&rth, &req.n, &answer) < 0) + if (__ipnh_get_id(&rth, id, &answer) < 0) return -2; new_json_obj(json); - if (print_nexthop(answer, (void *)stdout) < 0) { + if (print_nexthop_nocache(answer, (void *)stdout) < 0) { free(answer); return -1; } @@ -816,7 +1105,7 @@ new_json_obj(json); - if (rtnl_dump_filter(&rth, print_nexthop, stdout) < 0) { + if (rtnl_dump_filter(&rth, print_nexthop_nocache, stdout) < 0) { fprintf(stderr, "Dump terminated\n"); return -2; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iproute.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iproute.c
Changed
@@ -28,6 +28,7 @@ #include "rt_names.h" #include "utils.h" #include "ip_common.h" +#include "nh_common.h" #ifndef RTAX_RTTVAR #define RTAX_RTTVAR RTAX_HOPS @@ -101,18 +102,21 @@ "TIME := NUMBERs|ms\n" "BOOL := 1|0\n" "FEATURES := ecn\n" - "ENCAPTYPE := mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 \n" - "ENCAPHDR := MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR \n" + "ENCAPTYPE := mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 | xfrm \n" + "ENCAPHDR := MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR | XFRMINFO \n" "SEG6HDR := mode SEGMODE segs ADDR1,ADDRi,ADDRn hmac HMACKEYID cleanup\n" - "SEGMODE := encap | inline \n" + "SEGMODE := encap | encap.red | inline | l2encap | l2encap.red \n" "SEG6LOCAL := action ACTION OPTIONS count \n" "ACTION := { End | End.X | End.T | End.DX2 | End.DX6 | End.DX4 |\n" " End.DT6 | End.DT4 | End.DT46 | End.B6 | End.B6.Encaps |\n" " End.BM | End.S | End.AS | End.AM | End.BPF }\n" "OPTIONS := OPTION OPTIONS \n" - "OPTION := { srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |\n" + "OPTION := { flavors FLAVORS | srh SEG6HDR | nh4 ADDR | nh6 ADDR | iif DEV | oif DEV |\n" " table TABLEID | vrftable TABLEID | endpoint PROGNAME }\n" + "FLAVORS := { FLAVOR,FLAVOR }\n" + "FLAVOR := { psp | usp | usd | next-csid }\n" "IOAM6HDR := trace prealloc type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE\n" + "XFRMINFO := if_id IF_ID link_dev LINK \n" "ROUTE_GET_FLAGS := fibmatch \n"); exit(-1); } @@ -410,13 +414,13 @@ } } -void print_rta_if(FILE *fp, const struct rtattr *rta, const char *prefix) +void print_rta_ifidx(FILE *fp, __u32 ifidx, const char *prefix) { - const char *ifname = ll_index_to_name(rta_getattr_u32(rta)); + const char *ifname = ll_index_to_name(ifidx); - if (is_json_context()) + if (is_json_context()) { print_string(PRINT_JSON, prefix, NULL, ifname); - else { + } else { fprintf(fp, "%s ", prefix); color_fprintf(fp, COLOR_IFNAME, "%s ", ifname); } @@ -547,13 +551,11 @@ } } -void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta) +void __print_rta_gateway(FILE *fp, unsigned char family, const char *gateway) { - const char *gateway = format_host_rta(family, rta); - - if (is_json_context()) + if (is_json_context()) { print_string(PRINT_JSON, "gateway", NULL, gateway); - else { + } else { fprintf(fp, "via "); print_color_string(PRINT_FP, ifa_family_color(family), @@ -561,6 +563,13 @@ } } +void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta) +{ + const char *gateway = format_host_rta(family, rta); + + __print_rta_gateway(fp, family, gateway); +} + static void print_rta_via(FILE *fp, const struct rtattr *rta) { size_t len = RTA_PAYLOAD(rta) - 2; @@ -862,7 +871,7 @@ print_rta_via(fp, tbRTA_VIA); if (tbRTA_OIF && filter.oifmask != -1) - print_rta_if(fp, tbRTA_OIF, "dev"); + print_rta_ifidx(fp, rta_getattr_u32(tbRTA_OIF), "dev"); if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb) print_string(PRINT_ANY, @@ -946,7 +955,7 @@ print_rta_metrics(fp, tbRTA_METRICS); if (tbRTA_IIF && filter.iifmask != -1) - print_rta_if(fp, tbRTA_IIF, "iif"); + print_rta_ifidx(fp, rta_getattr_u32(tbRTA_IIF), "iif"); if (tbRTA_PREF) print_rt_pref(fp, rta_getattr_u8(tbRTA_PREF)); @@ -963,6 +972,10 @@ propagate ? "enabled" : "disabled"); } + if (tbRTA_NH_ID && show_details) + print_cache_nexthop_id(fp, "\n\tnh_info ", "nh_info", + rta_getattr_u32(tbRTA_NH_ID)); + if (tbRTA_MULTIPATH) print_rta_multipath(fp, r, tbRTA_MULTIPATH); @@ -1121,6 +1134,7 @@ int raw = 0; int type_ok = 0; __u32 nhid = 0; + int ret; if (cmd != RTM_DELROUTE) { req.r.rtm_protocol = RTPROT_BOOT; @@ -1574,7 +1588,12 @@ if (!type_ok && req.r.rtm_family == AF_MPLS) req.r.rtm_type = RTN_UNICAST; - if (rtnl_talk(&rth, &req.n, NULL) < 0) + if (echo_request) + ret = rtnl_echo_talk(&rth, &req.n, json, print_route); + else + ret = rtnl_talk(&rth, &req.n, NULL); + + if (ret) return -2; return 0;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iproute_lwtunnel.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iproute_lwtunnel.c
Changed
@@ -58,6 +58,8 @@ return "rpl"; case LWTUNNEL_ENCAP_IOAM6: return "ioam6"; + case LWTUNNEL_ENCAP_XFRM: + return "xfrm"; default: return "unknown"; } @@ -96,6 +98,8 @@ return LWTUNNEL_ENCAP_RPL; else if (strcmp(name, "ioam6") == 0) return LWTUNNEL_ENCAP_IOAM6; + else if (strcmp(name, "xfrm") == 0) + return LWTUNNEL_ENCAP_XFRM; else if (strcmp(name, "help") == 0) encap_type_usage(); @@ -135,6 +139,8 @@ SEG6_IPTUN_MODE_INLINE = "inline", SEG6_IPTUN_MODE_ENCAP = "encap", SEG6_IPTUN_MODE_L2ENCAP = "l2encap", + SEG6_IPTUN_MODE_ENCAP_RED = "encap.red", + SEG6_IPTUN_MODE_L2ENCAP_RED = "l2encap.red", }; static const char *format_seg6mode_type(int mode) @@ -157,6 +163,100 @@ return -1; } +static const char *seg6_flavor_namesSEG6_LOCAL_FLV_OP_MAX + 1 = { + SEG6_LOCAL_FLV_OP_PSP = "psp", + SEG6_LOCAL_FLV_OP_USP = "usp", + SEG6_LOCAL_FLV_OP_USD = "usd", + SEG6_LOCAL_FLV_OP_NEXT_CSID = "next-csid" +}; + +static int read_seg6_local_flv_type(const char *name) +{ + int i; + + for (i = 1; i < SEG6_LOCAL_FLV_OP_MAX + 1; ++i) { + if (!seg6_flavor_namesi) + continue; + + if (strcasecmp(seg6_flavor_namesi, name) == 0) + return i; + } + + return -1; +} + +static int parse_seg6local_flavors(const char *buf, __u32 *flv_mask) +{ + unsigned char flavor_okSEG6_LOCAL_FLV_OP_MAX + 1 = { 0, }; + char *wbuf; + __u32 mask = 0; + int index; + char *s; + + /* strtok changes first parameter, so we need to make a local copy */ + wbuf = strdupa(buf); + + if (strlen(wbuf) == 0) + return -1; + + for (s = strtok(wbuf, ","); s; s = strtok(NULL, ",")) { + index = read_seg6_local_flv_type(s); + if (index < 0 || index > SEG6_LOCAL_FLV_OP_MAX) + return -1; + /* we check for duplicates */ + if (flavor_okindex++) + return -1; + + mask |= (1 << index); + } + + *flv_mask = mask; + return 0; +} + +static void print_flavors(FILE *fp, __u32 flavors) +{ + int i, fnumber = 0; + char *flv_name; + + if (is_json_context()) + open_json_array(PRINT_JSON, "flavors"); + else + print_string(PRINT_FP, NULL, "flavors ", NULL); + + for (i = 0; i < SEG6_LOCAL_FLV_OP_MAX + 1; ++i) { + if (flavors & (1 << i)) { + flv_name = (char *) seg6_flavor_namesi; + if (!flv_name) + continue; + + if (is_json_context()) + print_string(PRINT_JSON, NULL, NULL, flv_name); + else { + if (fnumber++ == 0) + print_string(PRINT_FP, NULL, "%s", flv_name); + else + print_string(PRINT_FP, NULL, ",%s", flv_name); + } + } + } + + if (is_json_context()) + close_json_array(PRINT_JSON, NULL); + else + print_string(PRINT_FP, NULL, " ", NULL); +} + +static void print_flavors_attr(FILE *fp, const char *key, __u32 value) +{ + if (is_json_context()) { + print_u64(PRINT_JSON, key, NULL, value); + } else { + print_string(PRINT_FP, NULL, "%s ", key); + print_num(fp, 1, value); + } +} + static void print_encap_seg6(FILE *fp, struct rtattr *encap) { struct rtattr *tbSEG6_IPTUNNEL_MAX+1; @@ -210,16 +310,62 @@ print_rpl_srh(fp, srh); } +static const char *ioam6_mode_typesIOAM6_IPTUNNEL_MODE_MAX + 1 = { + IOAM6_IPTUNNEL_MODE_INLINE = "inline", + IOAM6_IPTUNNEL_MODE_ENCAP = "encap", + IOAM6_IPTUNNEL_MODE_AUTO = "auto", +}; + +static const char *format_ioam6mode_type(int mode) +{ + if (mode < IOAM6_IPTUNNEL_MODE_MIN || + mode > IOAM6_IPTUNNEL_MODE_MAX || + !ioam6_mode_typesmode) + return "<unknown>"; + + return ioam6_mode_typesmode; +} + +static __u8 read_ioam6mode_type(const char *mode) +{ + __u8 i; + + for (i = IOAM6_IPTUNNEL_MODE_MIN; i <= IOAM6_IPTUNNEL_MODE_MAX; i++) { + if (ioam6_mode_typesi && !strcmp(mode, ioam6_mode_typesi)) + return i; + } + + return 0; +} + static void print_encap_ioam6(FILE *fp, struct rtattr *encap) { struct rtattr *tbIOAM6_IPTUNNEL_MAX + 1; struct ioam6_trace_hdr *trace; + __u32 freq_k, freq_n; + __u8 mode; parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap); + if (!tbIOAM6_IPTUNNEL_MODE || !tbIOAM6_IPTUNNEL_TRACE || + !tbIOAM6_IPTUNNEL_FREQ_K || !tbIOAM6_IPTUNNEL_FREQ_N) + return; - if (!tbIOAM6_IPTUNNEL_TRACE) + freq_k = rta_getattr_u32(tbIOAM6_IPTUNNEL_FREQ_K); + freq_n = rta_getattr_u32(tbIOAM6_IPTUNNEL_FREQ_N); + + print_uint(PRINT_ANY, "freqk", "freq %u", freq_k); + print_uint(PRINT_ANY, "freqn", "/%u ", freq_n); + + mode = rta_getattr_u8(tbIOAM6_IPTUNNEL_MODE); + if (!tbIOAM6_IPTUNNEL_DST && mode != IOAM6_IPTUNNEL_MODE_INLINE) return; + print_string(PRINT_ANY, "mode", "mode %s ", format_ioam6mode_type(mode)); + + if (mode != IOAM6_IPTUNNEL_MODE_INLINE) + print_string(PRINT_ANY, "tundst", "tundst %s ", + rt_addr_n2a_rta(AF_INET6, tbIOAM6_IPTUNNEL_DST)); + trace = RTA_DATA(tbIOAM6_IPTUNNEL_TRACE); print_null(PRINT_ANY, "trace", "trace ", NULL); @@ -328,6 +474,30 @@ } } +static void print_seg6_local_flavors(FILE *fp, struct rtattr *encap) +{ + struct rtattr *tbSEG6_LOCAL_FLV_MAX + 1; + __u8 lbl = 0, nfl = 0; + __u32 flavors = 0; + + parse_rtattr_nested(tb, SEG6_LOCAL_FLV_MAX, encap); + + if (tbSEG6_LOCAL_FLV_OPERATION) { + flavors = rta_getattr_u32(tbSEG6_LOCAL_FLV_OPERATION); + print_flavors(fp, flavors); + } + + if (tbSEG6_LOCAL_FLV_LCBLOCK_BITS) { + lbl = rta_getattr_u8(tbSEG6_LOCAL_FLV_LCBLOCK_BITS); + print_flavors_attr(fp, "lblen", lbl); + } + + if (tbSEG6_LOCAL_FLV_LCNODE_FN_BITS) { + nfl = rta_getattr_u8(tbSEG6_LOCAL_FLV_LCNODE_FN_BITS); + print_flavors_attr(fp, "nflen", nfl); + } +} + static void print_encap_seg6local(FILE *fp, struct rtattr *encap) { struct rtattr *tbSEG6_LOCAL_MAX + 1; @@ -390,6 +560,9 @@ if (tbSEG6_LOCAL_COUNTERS && show_stats) print_seg6_local_counters(fp, tbSEG6_LOCAL_COUNTERS); + + if (tbSEG6_LOCAL_FLAVORS) + print_seg6_local_flavors(fp, tbSEG6_LOCAL_FLAVORS); } static void print_encap_mpls(FILE *fp, struct rtattr *encap) @@ -645,6 +818,24 @@ " %u ", rta_getattr_u32(tbLWT_BPF_XMIT_HEADROOM)); } +static void print_encap_xfrm(FILE *fp, struct rtattr *encap) +{ + struct rtattr *tbLWT_XFRM_MAX+1; + + parse_rtattr_nested(tb, LWT_XFRM_MAX, encap); + + if (tbLWT_XFRM_IF_ID) + print_uint(PRINT_ANY, "if_id", "if_id %lu ", + rta_getattr_u32(tbLWT_XFRM_IF_ID)); + + if (tbLWT_XFRM_LINK) { + int link = rta_getattr_u32(tbLWT_XFRM_LINK); + + print_string(PRINT_ANY, "link_dev", "link_dev %s ", + ll_index_to_name(link)); + } +} + void lwt_print_encap(FILE *fp, struct rtattr *encap_type, struct rtattr *encap) { @@ -685,6 +876,9 @@ case LWTUNNEL_ENCAP_IOAM6: print_encap_ioam6(fp, encap); break; + case LWTUNNEL_ENCAP_XFRM: + print_encap_xfrm(fp, encap); + break; } } @@ -881,26 +1075,106 @@ return ret; } +static int parse_ioam6_freq(char *buf, __u32 *freq_k, __u32 *freq_n) +{ + char *s; + int i; + + s = buf; + for (i = 0; *s; *s++ == '/' ? i++ : *s); + if (i != 1) + return 1; + + s = strtok(buf, "/"); + if (!s || get_u32(freq_k, s, 10)) + return 1; + + s = strtok(NULL, "/"); + if (!s || get_u32(freq_n, s, 10)) + return 1; + + s = strtok(NULL, "/"); + if (s) + return 1; + + return 0; +} + static int parse_encap_ioam6(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { + int ns_found = 0, argc = *argcp; + __u16 trace_ns, trace_size = 0; struct ioam6_trace_hdr *trace; char **argv = *argvp; - int argc = *argcp; - int ns_found = 0; - __u16 size = 0; - __u32 type = 0; - __u16 ns; + __u32 trace_type = 0; + __u32 freq_k, freq_n; + char buf16 = {0}; + inet_prefix addr; + __u8 mode; - trace = calloc(1, sizeof(*trace)); - if (!trace) - return -1; + if (strcmp(*argv, "freq") != 0) { + freq_k = IOAM6_IPTUNNEL_FREQ_MIN; + freq_n = IOAM6_IPTUNNEL_FREQ_MIN; + } else { + NEXT_ARG(); + + if (strlen(*argv) > sizeof(buf) - 1) + invarg("Invalid frequency (too long)", *argv); + + strncpy(buf, *argv, sizeof(buf)); + + if (parse_ioam6_freq(buf, &freq_k, &freq_n)) + invarg("Invalid frequency (malformed)", *argv); + + if (freq_k < IOAM6_IPTUNNEL_FREQ_MIN || + freq_k > IOAM6_IPTUNNEL_FREQ_MAX) + invarg("Out of bound \"k\" frequency", *argv); + + if (freq_n < IOAM6_IPTUNNEL_FREQ_MIN || + freq_n > IOAM6_IPTUNNEL_FREQ_MAX) + invarg("Out of bound \"n\" frequency", *argv); + + if (freq_k > freq_n) + invarg("Frequency with k > n is forbidden", *argv); + + NEXT_ARG(); + } + + if (strcmp(*argv, "mode") != 0) { + mode = IOAM6_IPTUNNEL_MODE_INLINE; + } else { + NEXT_ARG(); + + mode = read_ioam6mode_type(*argv); + if (!mode) + invarg("Invalid mode", *argv); - if (strcmp(*argv, "trace")) + NEXT_ARG(); + } + + if (strcmp(*argv, "tundst") != 0) { + if (mode != IOAM6_IPTUNNEL_MODE_INLINE) + missarg("tundst"); + } else { + if (mode == IOAM6_IPTUNNEL_MODE_INLINE) + invarg("Inline mode does not need tundst", *argv); + + NEXT_ARG(); + + get_addr(&addr, *argv, AF_INET6); + if (addr.family != AF_INET6 || addr.bytelen != 16) + invarg("Invalid IPv6 address for tundst", *argv); + + NEXT_ARG(); + } + + if (strcmp(*argv, "trace") != 0) missarg("trace"); NEXT_ARG(); - if (strcmp(*argv, "prealloc")) + + if (strcmp(*argv, "prealloc") != 0) missarg("prealloc"); while (NEXT_ARG_OK()) { @@ -909,63 +1183,60 @@ if (strcmp(*argv, "type") == 0) { NEXT_ARG(); - if (type) + if (trace_type) duparg2("type", *argv); - if (get_u32(&type, *argv, 0) || !type) - invarg("Invalid type", *argv); - - trace->type_be32 = htonl(type << 8); - + if (get_u32(&trace_type, *argv, 0) || !trace_type) + invarg("Invalid trace type", *argv); } else if (strcmp(*argv, "ns") == 0) { NEXT_ARG(); if (ns_found++) duparg2("ns", *argv); - if (!type) - missarg("type"); - - if (get_u16(&ns, *argv, 0)) + if (get_u16(&trace_ns, *argv, 0)) invarg("Invalid namespace ID", *argv); - - trace->namespace_id = htons(ns); - } else if (strcmp(*argv, "size") == 0) { NEXT_ARG(); - if (size) + if (trace_size) duparg2("size", *argv); - if (!type) - missarg("type"); - if (!ns_found) - missarg("ns"); - - if (get_u16(&size, *argv, 0) || !size) - invarg("Invalid size", *argv); + if (get_u16(&trace_size, *argv, 0) || !trace_size) + invarg("Invalid trace size", *argv); - if (size % 4) - invarg("Size must be a 4-octet multiple", *argv); - if (size > IOAM6_TRACE_DATA_SIZE_MAX) - invarg("Size too big", *argv); - - trace->remlen = (__u8)(size / 4); + if (trace_size % 4) + invarg("Trace size must be a 4-octet multiple", + *argv); + if (trace_size > IOAM6_TRACE_DATA_SIZE_MAX) + invarg("Trace size is too big", *argv); } else { break; } } - if (!type) + if (!trace_type) missarg("type"); if (!ns_found) missarg("ns"); - if (!size) + if (!trace_size) missarg("size"); - if (rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, - sizeof(*trace))) { + trace = calloc(1, sizeof(*trace)); + if (!trace) + return -1; + + trace->type_be32 = htonl(trace_type << 8); + trace->namespace_id = htons(trace_ns); + trace->remlen = (__u8)(trace_size / 4); + + if (rta_addattr32(rta, len, IOAM6_IPTUNNEL_FREQ_K, freq_k) || + rta_addattr32(rta, len, IOAM6_IPTUNNEL_FREQ_N, freq_n) || + rta_addattr8(rta, len, IOAM6_IPTUNNEL_MODE, mode) || + (mode != IOAM6_IPTUNNEL_MODE_INLINE && + rta_addattr_l(rta, len, IOAM6_IPTUNNEL_DST, &addr.data, addr.bytelen)) || + rta_addattr_l(rta, len, IOAM6_IPTUNNEL_TRACE, trace, sizeof(*trace))) { free(trace); return -1; } @@ -1052,12 +1323,66 @@ return 0; } +static int seg6local_parse_flavors(struct rtattr *rta, size_t len, + int *argcp, char ***argvp, int attr) +{ + int lbl_ok = 0, nfl_ok = 0; + __u8 lbl = 0, nfl = 0; + struct rtattr *nest; + __u32 flavors = 0; + int ret; + + char **argv = *argvp; + int argc = *argcp; + + nest = rta_nest(rta, len, attr); + + ret = parse_seg6local_flavors(*argv, &flavors); + if (ret < 0) + return ret; + + ret = rta_addattr32(rta, len, SEG6_LOCAL_FLV_OPERATION, flavors); + if (ret < 0) + return ret; + + if (flavors & (1 << SEG6_LOCAL_FLV_OP_NEXT_CSID)) { + NEXT_ARG_FWD(); + if (strcmp(*argv, "lblen") == 0){ + NEXT_ARG(); + if (lbl_ok++) + duparg2("lblen", *argv); + if (get_u8(&lbl, *argv, 0)) + invarg("\"locator-block length\" value is invalid\n", *argv); + ret = rta_addattr8(rta, len, SEG6_LOCAL_FLV_LCBLOCK_BITS, lbl); + NEXT_ARG_FWD(); + } + + if (strcmp(*argv, "nflen") == 0){ + NEXT_ARG(); + if (nfl_ok++) + duparg2("nflen", *argv); + if (get_u8(&nfl, *argv, 0)) + invarg("\"locator-node function length\" value is invalid\n", *argv); + ret = rta_addattr8(rta, len, SEG6_LOCAL_FLV_LCNODE_FN_BITS, nfl); + NEXT_ARG_FWD(); + } + PREV_ARG(); + } + + rta_nest_end(rta, nest); + + *argcp = argc; + *argvp = argv; + + return 0; +} + static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp, char ***argvp) { + int nh4_ok = 0, nh6_ok = 0, iif_ok = 0, oif_ok = 0, flavors_ok = 0; int segs_ok = 0, hmac_ok = 0, table_ok = 0, vrftable_ok = 0; int action_ok = 0, srh_ok = 0, bpf_ok = 0, counters_ok = 0; - int nh4_ok = 0, nh6_ok = 0, iif_ok = 0, oif_ok = 0; __u32 action = 0, table, vrftable, iif, oif; struct ipv6_sr_hdr *srh; char **argv = *argvp; @@ -1127,6 +1452,15 @@ duparg2("count", *argv); ret = seg6local_fill_counters(rta, len, SEG6_LOCAL_COUNTERS); + } else if (strcmp(*argv, "flavors") == 0) { + NEXT_ARG(); + if (flavors_ok++) + duparg2("flavors", *argv); + + if (seg6local_parse_flavors(rta, len, &argc, &argv, + SEG6_LOCAL_FLAVORS)) + invarg("invalid \"flavors\" attribute\n", + *argv); } else if (strcmp(*argv, "srh") == 0) { NEXT_ARG(); if (srh_ok++) @@ -1820,6 +2154,61 @@ return 0; } +static void lwt_xfrm_usage(void) +{ + fprintf(stderr, "Usage: ip route ... encap xfrm if_id IF_ID link_dev LINK \n"); + exit(-1); +} + +static int parse_encap_xfrm(struct rtattr *rta, size_t len, + int *argcp, char ***argvp) +{ + int if_id_ok = 0, link_ok = 0; + char **argv = *argvp; + int argc = *argcp; + int ret = 0; + + while (argc > 0) { + if (!strcmp(*argv, "if_id")) { + __u32 if_id; + + NEXT_ARG(); + if (if_id_ok++) + duparg2("if_id", *argv); + if (get_u32(&if_id, *argv, 0) || if_id == 0) + invarg("\"if_id\" value is invalid\n", *argv); + ret = rta_addattr32(rta, len, LWT_XFRM_IF_ID, if_id); + } else if (!strcmp(*argv, "link_dev")) { + int link; + + NEXT_ARG(); + if (link_ok++) + duparg2("link_dev", *argv); + link = ll_name_to_index(*argv); + if (!link) + exit(nodev(*argv)); + ret = rta_addattr32(rta, len, LWT_XFRM_LINK, link); + } else if (!strcmp(*argv, "help")) { + lwt_xfrm_usage(); + } + if (ret) + break; + argc--; argv++; + } + + if (!if_id_ok) + lwt_xfrm_usage(); + + /* argv is currently the first unparsed argument, + * but the lwt_parse_encap() caller will move to the next, + * so step back + */ + *argcp = argc + 1; + *argvp = argv - 1; + + return ret; +} + int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp, int encap_attr, int encap_type_attr) { @@ -1871,6 +2260,9 @@ case LWTUNNEL_ENCAP_IOAM6: ret = parse_encap_ioam6(rta, len, &argc, &argv); break; + case LWTUNNEL_ENCAP_XFRM: + ret = parse_encap_xfrm(rta, len, &argc, &argv); + break; default: fprintf(stderr, "Error: unsupported encap type\n"); break;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iprule.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iprule.c
Changed
@@ -592,7 +592,8 @@ filter.prefmask = 1; } else if (strcmp(*argv, "not") == 0) { filter.not = 1; - } else if (strcmp(*argv, "tos") == 0) { + } else if (strcmp(*argv, "tos") == 0 || + strcmp(*argv, "dsfield") == 0) { __u32 tos; NEXT_ARG(); @@ -786,6 +787,7 @@ .frh.family = preferred_family, .frh.action = FR_ACT_UNSPEC, }; + int ret; if (cmd == RTM_NEWRULE) { if (argc == 0) { @@ -1015,7 +1017,12 @@ if (!table_ok && cmd == RTM_NEWRULE) req.frh.table = RT_TABLE_MAIN; - if (rtnl_talk(&rth, &req.n, NULL) < 0) + if (echo_request) + ret = rtnl_echo_talk(&rth, &req.n, json, print_rule); + else + ret = rtnl_talk(&rth, &req.n, NULL); + + if (ret) return -2; return 0;
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/ipstats.c
Added
@@ -0,0 +1,1361 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include <alloca.h> +#include <assert.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include "list.h" +#include "utils.h" +#include "ip_common.h" + +struct ipstats_stat_dump_filters { + /* mask0 filters outer attributes. Then individual nests have their + * filtering mask at the index of the nested attribute. + */ + __u32 maskIFLA_STATS_MAX + 1; +}; + +static void +ipstats_stat_desc_enable_bit(struct ipstats_stat_dump_filters *filters, + unsigned int group, unsigned int subgroup) +{ + filters->mask0 |= IFLA_STATS_FILTER_BIT(group); + if (subgroup) + filters->maskgroup |= IFLA_STATS_FILTER_BIT(subgroup); +} + +struct ipstats_stat_show_attrs { + struct if_stats_msg *ifsm; + int len; + + /* tbs0 contains top-level attribute table. Then individual nests have + * their attribute tables at the index of the nested attribute. + */ + struct rtattr **tbsIFLA_STATS_MAX + 1; +}; + +static const char *const ipstats_levels = { + "group", + "subgroup", + "suite", +}; + +enum { + IPSTATS_LEVELS_COUNT = ARRAY_SIZE(ipstats_levels), +}; + +struct ipstats_sel { + const char *selIPSTATS_LEVELS_COUNT; +}; + +struct ipstats_stat_enabled_one { + const struct ipstats_stat_desc *desc; + struct ipstats_sel sel; +}; + +struct ipstats_stat_enabled { + struct ipstats_stat_enabled_one *enabled; + size_t nenabled; +}; + +static const unsigned int ipstats_stat_ifla_max = { + 0 = IFLA_STATS_MAX, + IFLA_STATS_LINK_XSTATS = LINK_XSTATS_TYPE_MAX, + IFLA_STATS_LINK_XSTATS_SLAVE = LINK_XSTATS_TYPE_MAX, + IFLA_STATS_LINK_OFFLOAD_XSTATS = IFLA_OFFLOAD_XSTATS_MAX, + IFLA_STATS_AF_SPEC = AF_MAX - 1, +}; + +static_assert(ARRAY_SIZE(ipstats_stat_ifla_max) == IFLA_STATS_MAX + 1, + "An IFLA_STATS attribute is missing from the ifla_max table"); + +static int +ipstats_stat_show_attrs_alloc_tb(struct ipstats_stat_show_attrs *attrs, + unsigned int group) +{ + unsigned int ifla_max; + int err; + + assert(group < ARRAY_SIZE(ipstats_stat_ifla_max)); + assert(group < ARRAY_SIZE(attrs->tbs)); + ifla_max = ipstats_stat_ifla_maxgroup; + assert(ifla_max != 0); + + if (attrs->tbsgroup) + return 0; + + attrs->tbsgroup = calloc(ifla_max + 1, sizeof(*attrs->tbsgroup)); + if (attrs->tbsgroup == NULL) + return -ENOMEM; + + if (group == 0) + err = parse_rtattr(attrs->tbsgroup, ifla_max, + IFLA_STATS_RTA(attrs->ifsm), attrs->len); + else + err = parse_rtattr_nested(attrs->tbsgroup, ifla_max, + attrs->tbs0group); + + if (err != 0) { + free(attrs->tbsgroup); + attrs->tbsgroup = NULL; + } + return err; +} + +static const struct rtattr * +ipstats_stat_show_get_attr(struct ipstats_stat_show_attrs *attrs, + int group, int subgroup, int *err) +{ + int tmp_err; + + if (err == NULL) + err = &tmp_err; + + *err = 0; + if (subgroup == 0) + return attrs->tbs0group; + + if (attrs->tbs0group == NULL) + return NULL; + + *err = ipstats_stat_show_attrs_alloc_tb(attrs, group); + if (*err != 0) + return NULL; + + return attrs->tbsgroupsubgroup; +} + +static void +ipstats_stat_show_attrs_free(struct ipstats_stat_show_attrs *attrs) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(attrs->tbs); i++) + free(attrs->tbsi); +} + +#define IPSTATS_RTA_PAYLOAD(VAR, AT) \ + do { \ + const struct rtattr *__at = (AT); \ + size_t __at_sz = __at->rta_len - RTA_LENGTH(0); \ + size_t __var_sz = sizeof(VAR); \ + typeof(VAR) *__dest = &VAR; \ + \ + memset(__dest, 0, __var_sz); \ + memcpy(__dest, RTA_DATA(__at), MIN(__at_sz, __var_sz)); \ + } while (0) + +static int ipstats_show_64(struct ipstats_stat_show_attrs *attrs, + unsigned int group, unsigned int subgroup) +{ + struct rtnl_link_stats64 stats; + const struct rtattr *at; + int err; + + at = ipstats_stat_show_get_attr(attrs, group, subgroup, &err); + if (at == NULL) + return err; + + IPSTATS_RTA_PAYLOAD(stats, at); + + open_json_object("stats64"); + print_stats64(stdout, &stats, NULL, NULL); + close_json_object(); + return 0; +} + +static void print_hw_stats64(FILE *fp, struct rtnl_hw_stats64 *s) +{ + unsigned int cols = { + strlen("*X: bytes"), + strlen("packets"), + strlen("errors"), + strlen("dropped"), + strlen("overrun"), + }; + + if (is_json_context()) { + /* RX stats */ + open_json_object("rx"); + print_u64(PRINT_JSON, "bytes", NULL, s->rx_bytes); + print_u64(PRINT_JSON, "packets", NULL, s->rx_packets); + print_u64(PRINT_JSON, "errors", NULL, s->rx_errors); + print_u64(PRINT_JSON, "dropped", NULL, s->rx_dropped); + print_u64(PRINT_JSON, "multicast", NULL, s->multicast); + close_json_object(); + + /* TX stats */ + open_json_object("tx"); + print_u64(PRINT_JSON, "bytes", NULL, s->tx_bytes); + print_u64(PRINT_JSON, "packets", NULL, s->tx_packets); + print_u64(PRINT_JSON, "errors", NULL, s->tx_errors); + print_u64(PRINT_JSON, "dropped", NULL, s->tx_dropped); + close_json_object(); + } else { + size_columns(cols, ARRAY_SIZE(cols), + s->rx_bytes, s->rx_packets, s->rx_errors, + s->rx_dropped, s->multicast); + size_columns(cols, ARRAY_SIZE(cols), + s->tx_bytes, s->tx_packets, s->tx_errors, + s->tx_dropped, 0); + + /* RX stats */ + fprintf(fp, " RX: %*s %*s %*s %*s %*s%s", + cols0 - 4, "bytes", cols1, "packets", + cols2, "errors", cols3, "dropped", + cols4, "mcast", _SL_); + + fprintf(fp, " "); + print_num(fp, cols0, s->rx_bytes); + print_num(fp, cols1, s->rx_packets); + print_num(fp, cols2, s->rx_errors); + print_num(fp, cols3, s->rx_dropped); + print_num(fp, cols4, s->multicast); + fprintf(fp, "%s", _SL_); + + /* TX stats */ + fprintf(fp, " TX: %*s %*s %*s %*s%s", + cols0 - 4, "bytes", cols1, "packets", + cols2, "errors", cols3, "dropped", _SL_); + + fprintf(fp, " "); + print_num(fp, cols0, s->tx_bytes); + print_num(fp, cols1, s->tx_packets); + print_num(fp, cols2, s->tx_errors); + print_num(fp, cols3, s->tx_dropped); + } +} + +static int ipstats_show_hw64(const struct rtattr *at) +{ + struct rtnl_hw_stats64 stats; + + IPSTATS_RTA_PAYLOAD(stats, at); + print_hw_stats64(stdout, &stats); + return 0; +} + +enum ipstats_maybe_on_off { + IPSTATS_MOO_OFF = -1, + IPSTATS_MOO_INVALID, + IPSTATS_MOO_ON, +}; + +static bool ipstats_moo_to_bool(enum ipstats_maybe_on_off moo) +{ + assert(moo != IPSTATS_MOO_INVALID); + return moo + 1; +} + +static int ipstats_print_moo(enum output_type t, const char *key, + const char *fmt, enum ipstats_maybe_on_off moo) +{ + if (!moo) + return 0; + return print_on_off(t, key, fmt, ipstats_moo_to_bool(moo)); +} + +struct ipstats_hw_s_info_one { + enum ipstats_maybe_on_off request; + enum ipstats_maybe_on_off used; +}; + +enum ipstats_hw_s_info_idx { + IPSTATS_HW_S_INFO_IDX_L3_STATS, + IPSTATS_HW_S_INFO_IDX_COUNT +}; + +static const char *const ipstats_hw_s_info_name = { + "l3_stats", +}; + +static_assert(ARRAY_SIZE(ipstats_hw_s_info_name) == + IPSTATS_HW_S_INFO_IDX_COUNT, + "mismatch: enum ipstats_hw_s_info_idx x ipstats_hw_s_info_name"); + +struct ipstats_hw_s_info { + /* Indexed by enum ipstats_hw_s_info_idx. */ + struct ipstats_hw_s_info_one *infosIPSTATS_HW_S_INFO_IDX_COUNT; +}; + +static enum ipstats_maybe_on_off ipstats_dissect_01(int value, const char *what) +{ + switch (value) { + case 0: + return IPSTATS_MOO_OFF; + case 1: + return IPSTATS_MOO_ON; + default: + fprintf(stderr, "Invalid value for %s: expected 0 or 1, got %d.\n", + what, value); + return IPSTATS_MOO_INVALID; + } +} + +static int ipstats_dissect_hw_s_info_one(const struct rtattr *at, + struct ipstats_hw_s_info_one *p_hwsio, + const char *what) +{ + int attr_id_request = IFLA_OFFLOAD_XSTATS_HW_S_INFO_REQUEST; + struct rtattr *tbIFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX + 1; + int attr_id_used = IFLA_OFFLOAD_XSTATS_HW_S_INFO_USED; + struct ipstats_hw_s_info_one hwsio = {}; + int err; + int v; + + err = parse_rtattr_nested(tb, IFLA_OFFLOAD_XSTATS_HW_S_INFO_MAX, at); + if (err) + return err; + + if (tbattr_id_request) { + v = rta_getattr_u8(tbattr_id_request); + hwsio.request = ipstats_dissect_01(v, "request"); + + /* This has to be present & valid. */ + if (!hwsio.request) + return -EINVAL; + } + + if (tbattr_id_used) { + v = rta_getattr_u8(tbattr_id_used); + hwsio.used = ipstats_dissect_01(v, "used"); + } + + *p_hwsio = hwsio; + return 0; +} + +static int ipstats_dissect_hw_s_info(const struct rtattr *at, + struct ipstats_hw_s_info *hwsi) +{ + struct rtattr *tbIFLA_OFFLOAD_XSTATS_MAX + 1; + int attr_id_l3 = IFLA_OFFLOAD_XSTATS_L3_STATS; + struct ipstats_hw_s_info_one *hwsio = NULL; + int err; + + err = parse_rtattr_nested(tb, IFLA_OFFLOAD_XSTATS_MAX, at); + if (err) + return err; + + *hwsi = (struct ipstats_hw_s_info){}; + + if (tbattr_id_l3) { + hwsio = malloc(sizeof(*hwsio)); + if (!hwsio) { + err = -ENOMEM; + goto out; + } + + err = ipstats_dissect_hw_s_info_one(tbattr_id_l3, hwsio, "l3"); + if (err) + goto out; + + hwsi->infosIPSTATS_HW_S_INFO_IDX_L3_STATS = hwsio; + hwsio = NULL; + } + + return 0; + +out: + free(hwsio); + return err; +} + +static void ipstats_fini_hw_s_info(struct ipstats_hw_s_info *hwsi) +{ + int i; + + for (i = 0; i < IPSTATS_HW_S_INFO_IDX_COUNT; i++) + free(hwsi->infosi); +} + +static void +__ipstats_show_hw_s_info_one(const struct ipstats_hw_s_info_one *hwsio) +{ + if (hwsio == NULL) + return; + + ipstats_print_moo(PRINT_ANY, "request", " %s", hwsio->request); + ipstats_print_moo(PRINT_ANY, "used", " used %s", hwsio->used); +} + +static void +ipstats_show_hw_s_info_one(const struct ipstats_hw_s_info *hwsi, + enum ipstats_hw_s_info_idx idx) +{ + const struct ipstats_hw_s_info_one *hwsio = hwsi->infosidx; + const char *name = ipstats_hw_s_info_nameidx; + + if (hwsio == NULL) + return; + + print_string(PRINT_FP, NULL, " %s", name); + open_json_object(name); + __ipstats_show_hw_s_info_one(hwsio); + close_json_object(); +} + +static int __ipstats_show_hw_s_info(const struct rtattr *at) +{ + struct ipstats_hw_s_info hwsi = {}; + int err; + + err = ipstats_dissect_hw_s_info(at, &hwsi); + if (err) + return err; + + open_json_object("info"); + ipstats_show_hw_s_info_one(&hwsi, IPSTATS_HW_S_INFO_IDX_L3_STATS); + close_json_object(); + + ipstats_fini_hw_s_info(&hwsi); + return 0; +} + +static int ipstats_show_hw_s_info(struct ipstats_stat_show_attrs *attrs, + unsigned int group, unsigned int subgroup) +{ + const struct rtattr *at; + int err; + + at = ipstats_stat_show_get_attr(attrs, group, subgroup, &err); + if (at == NULL) + return err; + + print_nl(); + return __ipstats_show_hw_s_info(at); +} + +static int __ipstats_show_hw_stats(const struct rtattr *at_hwsi, + const struct rtattr *at_stats, + enum ipstats_hw_s_info_idx idx) +{ + int err = 0; + + if (at_hwsi != NULL) { + struct ipstats_hw_s_info hwsi = {}; + + err = ipstats_dissect_hw_s_info(at_hwsi, &hwsi); + if (err) + return err; + + open_json_object("info"); + __ipstats_show_hw_s_info_one(hwsi.infosidx); + close_json_object(); + + ipstats_fini_hw_s_info(&hwsi); + } + + if (at_stats != NULL) { + print_nl(); + open_json_object("stats64"); + err = ipstats_show_hw64(at_stats); + close_json_object(); + } + + return err; +} + +static int ipstats_show_hw_stats(struct ipstats_stat_show_attrs *attrs, + unsigned int group, + unsigned int hw_s_info, + unsigned int hw_stats, + enum ipstats_hw_s_info_idx idx) +{ + const struct rtattr *at_stats; + const struct rtattr *at_hwsi; + int err = 0; + + at_hwsi = ipstats_stat_show_get_attr(attrs, group, hw_s_info, &err); + if (at_hwsi == NULL) + return err; + + at_stats = ipstats_stat_show_get_attr(attrs, group, hw_stats, &err); + if (at_stats == NULL && err != 0) + return err; + + return __ipstats_show_hw_stats(at_hwsi, at_stats, idx); +} + +static void +ipstats_stat_desc_pack_cpu_hit(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_CPU_HIT); +} + +static int ipstats_stat_desc_show_cpu_hit(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + print_nl(); + return ipstats_show_64(attrs, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_CPU_HIT); +} + +static const struct ipstats_stat_desc ipstats_stat_desc_offload_cpu_hit = { + .name = "cpu_hit", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_cpu_hit, + .show = &ipstats_stat_desc_show_cpu_hit, +}; + +static void +ipstats_stat_desc_pack_hw_stats_info(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO); +} + +static int +ipstats_stat_desc_show_hw_stats_info(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + return ipstats_show_hw_s_info(attrs, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO); +} + +static const struct ipstats_stat_desc ipstats_stat_desc_offload_hw_s_info = { + .name = "hw_stats_info", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_hw_stats_info, + .show = &ipstats_stat_desc_show_hw_stats_info, +}; + +static void +ipstats_stat_desc_pack_l3_stats(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_L3_STATS); + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO); +} + +static int +ipstats_stat_desc_show_l3_stats(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + return ipstats_show_hw_stats(attrs, + IFLA_STATS_LINK_OFFLOAD_XSTATS, + IFLA_OFFLOAD_XSTATS_HW_S_INFO, + IFLA_OFFLOAD_XSTATS_L3_STATS, + IPSTATS_HW_S_INFO_IDX_L3_STATS); +} + +static const struct ipstats_stat_desc ipstats_stat_desc_offload_l3_stats = { + .name = "l3_stats", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_l3_stats, + .show = &ipstats_stat_desc_show_l3_stats, +}; + +static const struct ipstats_stat_desc *ipstats_stat_desc_offload_subs = { + &ipstats_stat_desc_offload_cpu_hit, + &ipstats_stat_desc_offload_hw_s_info, + &ipstats_stat_desc_offload_l3_stats, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_offload_group = { + .name = "offload", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_offload_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_offload_subs), +}; + +void ipstats_stat_desc_pack_xstats(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + struct ipstats_stat_desc_xstats *xdesc; + + xdesc = container_of(desc, struct ipstats_stat_desc_xstats, desc); + ipstats_stat_desc_enable_bit(filters, xdesc->xstats_at, 0); +} + +int ipstats_stat_desc_show_xstats(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + struct ipstats_stat_desc_xstats *xdesc; + const struct rtattr *at; + struct rtattr **tb; + int err; + + xdesc = container_of(desc, struct ipstats_stat_desc_xstats, desc); + at = ipstats_stat_show_get_attr(attrs, + xdesc->xstats_at, + xdesc->link_type_at, &err); + if (at == NULL) + return err; + + tb = alloca(sizeof(*tb) * (xdesc->inner_max + 1)); + err = parse_rtattr_nested(tb, xdesc->inner_max, at); + if (err != 0) + return err; + + if (tbxdesc->inner_at != NULL) { + print_nl(); + xdesc->show_cb(tbxdesc->inner_at); + } + return 0; +} + +static const struct ipstats_stat_desc *ipstats_stat_desc_xstats_subs = { + &ipstats_stat_desc_xstats_bridge_group, + &ipstats_stat_desc_xstats_bond_group, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_xstats_group = { + .name = "xstats", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_subs), +}; + +static const struct ipstats_stat_desc *ipstats_stat_desc_xstats_slave_subs = { + &ipstats_stat_desc_xstats_slave_bridge_group, + &ipstats_stat_desc_xstats_slave_bond_group, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_xstats_slave_group = { + .name = "xstats_slave", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_xstats_slave_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_xstats_slave_subs), +}; + +static void +ipstats_stat_desc_pack_link(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, + IFLA_STATS_LINK_64, 0); +} + +static int +ipstats_stat_desc_show_link(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + print_nl(); + return ipstats_show_64(attrs, IFLA_STATS_LINK_64, 0); +} + +static const struct ipstats_stat_desc ipstats_stat_desc_toplev_link = { + .name = "link", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_link, + .show = &ipstats_stat_desc_show_link, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_afstats_group; + +static void +ipstats_stat_desc_pack_afstats(struct ipstats_stat_dump_filters *filters, + const struct ipstats_stat_desc *desc) +{ + ipstats_stat_desc_enable_bit(filters, IFLA_STATS_AF_SPEC, 0); +} + +static int +ipstats_stat_desc_show_afstats_mpls(struct ipstats_stat_show_attrs *attrs, + const struct ipstats_stat_desc *desc) +{ + struct rtattr *mrtbMPLS_STATS_MAX+1; + struct mpls_link_stats stats; + const struct rtattr *at; + int err; + + at = ipstats_stat_show_get_attr(attrs, IFLA_STATS_AF_SPEC, + AF_MPLS, &err); + if (at == NULL) + return err; + + parse_rtattr_nested(mrtb, MPLS_STATS_MAX, at); + if (mrtbMPLS_STATS_LINK == NULL) + return -ENOENT; + + IPSTATS_RTA_PAYLOAD(stats, mrtbMPLS_STATS_LINK); + + print_nl(); + open_json_object("mpls_stats"); + print_mpls_link_stats(stdout, &stats, " "); + close_json_object(); + return 0; +} + +static const struct ipstats_stat_desc ipstats_stat_desc_afstats_mpls = { + .name = "mpls", + .kind = IPSTATS_STAT_DESC_KIND_LEAF, + .pack = &ipstats_stat_desc_pack_afstats, + .show = &ipstats_stat_desc_show_afstats_mpls, +}; + +static const struct ipstats_stat_desc *ipstats_stat_desc_afstats_subs = { + &ipstats_stat_desc_afstats_mpls, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_afstats_group = { + .name = "afstats", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_afstats_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_afstats_subs), +}; +static const struct ipstats_stat_desc *ipstats_stat_desc_toplev_subs = { + &ipstats_stat_desc_toplev_link, + &ipstats_stat_desc_xstats_group, + &ipstats_stat_desc_xstats_slave_group, + &ipstats_stat_desc_offload_group, + &ipstats_stat_desc_afstats_group, +}; + +static const struct ipstats_stat_desc ipstats_stat_desc_toplev_group = { + .name = "top-level", + .kind = IPSTATS_STAT_DESC_KIND_GROUP, + .subs = ipstats_stat_desc_toplev_subs, + .nsubs = ARRAY_SIZE(ipstats_stat_desc_toplev_subs), +}; + +static void ipstats_show_group(const struct ipstats_sel *sel) +{ + int i; + + for (i = 0; i < IPSTATS_LEVELS_COUNT; i++) { + if (sel->seli == NULL) + break; + print_string(PRINT_JSON, ipstats_levelsi, NULL, sel->seli); + print_string(PRINT_FP, NULL, " %s ", ipstats_levelsi); + print_string(PRINT_FP, NULL, "%s", sel->seli); + } +} + +static int +ipstats_process_ifsm(struct nlmsghdr *answer, + struct ipstats_stat_enabled *enabled) +{ + struct ipstats_stat_show_attrs show_attrs = {}; + const char *dev; + int err = 0; + int i; + + show_attrs.ifsm = NLMSG_DATA(answer); + show_attrs.len = (answer->nlmsg_len - + NLMSG_LENGTH(sizeof(*show_attrs.ifsm))); + if (show_attrs.len < 0) { + fprintf(stderr, "BUG: wrong nlmsg len %d\n", show_attrs.len); + return -EINVAL; + } + + err = ipstats_stat_show_attrs_alloc_tb(&show_attrs, 0); + if (err != 0) { + fprintf(stderr, "Error parsing netlink answer: %s\n", + strerror(err)); + return err; + } + + dev = ll_index_to_name(show_attrs.ifsm->ifindex); + + for (i = 0; i < enabled->nenabled; i++) { + const struct ipstats_stat_desc *desc = enabled->enabledi.desc; + + open_json_object(NULL); + print_int(PRINT_ANY, "ifindex", "%d:", + show_attrs.ifsm->ifindex); + print_color_string(PRINT_ANY, COLOR_IFNAME, + "ifname", " %s:", dev); + ipstats_show_group(&enabled->enabledi.sel); + err = desc->show(&show_attrs, desc); + if (err != 0) + goto out; + close_json_object(); + print_nl(); + } + +out: + ipstats_stat_show_attrs_free(&show_attrs); + return err; +} + +static bool +ipstats_req_should_filter_at(struct ipstats_stat_dump_filters *filters, int at) +{ + return filters->maskat != 0 && + filters->maskat != (1 << ipstats_stat_ifla_maxat) - 1; +} + +static int +ipstats_req_add_filters(struct ipstats_req *req, void *data) +{ + struct ipstats_stat_dump_filters dump_filters = {}; + struct ipstats_stat_enabled *enabled = data; + bool get_filters = false; + int i; + + for (i = 0; i < enabled->nenabled; i++) + enabled->enabledi.desc->pack(&dump_filters, + enabled->enabledi.desc); + + for (i = 1; i < ARRAY_SIZE(dump_filters.mask); i++) { + if (ipstats_req_should_filter_at(&dump_filters, i)) { + get_filters = true; + break; + } + } + + req->ifsm.filter_mask = dump_filters.mask0; + if (get_filters) { + struct rtattr *nest; + + nest = addattr_nest(&req->nlh, sizeof(*req), + IFLA_STATS_GET_FILTERS | NLA_F_NESTED); + + for (i = 1; i < ARRAY_SIZE(dump_filters.mask); i++) { + if (ipstats_req_should_filter_at(&dump_filters, i)) + addattr32(&req->nlh, sizeof(*req), i, + dump_filters.maski); + } + + addattr_nest_end(&req->nlh, nest); + } + + return 0; +} + +static int +ipstats_show_one(int ifindex, struct ipstats_stat_enabled *enabled) +{ + struct ipstats_req req = { + .nlh.nlmsg_flags = NLM_F_REQUEST, + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct if_stats_msg)), + .nlh.nlmsg_type = RTM_GETSTATS, + .ifsm.family = PF_UNSPEC, + .ifsm.ifindex = ifindex, + }; + struct nlmsghdr *answer; + int err = 0; + + ipstats_req_add_filters(&req, enabled); + if (rtnl_talk(&rth, &req.nlh, &answer) < 0) + return -2; + err = ipstats_process_ifsm(answer, enabled); + free(answer); + + return err; +} + +static int ipstats_dump_one(struct nlmsghdr *n, void *arg) +{ + struct ipstats_stat_enabled *enabled = arg; + int rc; + + rc = ipstats_process_ifsm(n, enabled); + if (rc) + return rc; + + print_nl(); + return 0; +} + +static int ipstats_dump(struct ipstats_stat_enabled *enabled) +{ + int rc = 0; + + if (rtnl_statsdump_req_filter(&rth, PF_UNSPEC, 0, + ipstats_req_add_filters, + enabled) < 0) { + perror("Cannot send dump request"); + return -2; + } + + if (rtnl_dump_filter(&rth, ipstats_dump_one, enabled) < 0) { + fprintf(stderr, "Dump terminated\n"); + rc = -2; + } + + fflush(stdout); + return rc; +} + +static int +ipstats_show_do(int ifindex, struct ipstats_stat_enabled *enabled) +{ + int rc; + + new_json_obj(json); + if (ifindex) + rc = ipstats_show_one(ifindex, enabled); + else + rc = ipstats_dump(enabled); + delete_json_obj(); + + return rc; +} + +static int ipstats_add_enabled(struct ipstats_stat_enabled_one ens, + size_t nens, + struct ipstats_stat_enabled *enabled) +{ + struct ipstats_stat_enabled_one *new_en; + + new_en = realloc(enabled->enabled, + sizeof(*new_en) * (enabled->nenabled + nens)); + if (new_en == NULL) + return -ENOMEM; + + enabled->enabled = new_en; + while (nens-- > 0) + enabled->enabledenabled->nenabled++ = *ens++; + return 0; +} + +static void ipstats_select_push(struct ipstats_sel *sel, const char *name) +{ + int i; + + for (i = 0; i < IPSTATS_LEVELS_COUNT; i++) + if (sel->seli == NULL) { + sel->seli = name; + return; + } + + assert(false); +} + +static int +ipstats_enable_recursively(const struct ipstats_stat_desc *desc, + struct ipstats_stat_enabled *enabled, + const struct ipstats_sel *sel) +{ + bool found = false; + size_t i; + int err; + + if (desc->kind == IPSTATS_STAT_DESC_KIND_LEAF) { + struct ipstats_stat_enabled_one en = {{ + .desc = desc, + .sel = *sel, + }}; + + return ipstats_add_enabled(en, ARRAY_SIZE(en), enabled); + } + + for (i = 0; i < desc->nsubs; i++) { + struct ipstats_sel subsel = *sel; + + ipstats_select_push(&subsel, desc->subsi->name); + err = ipstats_enable_recursively(desc->subsi, enabled, + &subsel); + if (err == -ENOENT) + continue; + if (err != 0) + return err; + found = true; + } + + return found ? 0 : -ENOENT; +} + +static int ipstats_comp_enabled(const void *a, const void *b) +{ + const struct ipstats_stat_enabled_one *en_a = a; + const struct ipstats_stat_enabled_one *en_b = b; + + if (en_a->desc < en_b->desc) + return -1; + if (en_a->desc > en_b->desc) + return 1; + + return 0; +} + +static void ipstats_enabled_free(struct ipstats_stat_enabled *enabled) +{ + free(enabled->enabled); +} + +static const struct ipstats_stat_desc * +ipstats_stat_desc_find(const struct ipstats_stat_desc *desc, + const char *name) +{ + size_t i; + + assert(desc->kind == IPSTATS_STAT_DESC_KIND_GROUP); + for (i = 0; i < desc->nsubs; i++) { + const struct ipstats_stat_desc *sub = desc->subsi; + + if (strcmp(sub->name, name) == 0) + return sub; + } + + return NULL; +} + +static const struct ipstats_stat_desc * +ipstats_enable_find_stat_desc(struct ipstats_sel *sel) +{ + const struct ipstats_stat_desc *toplev = &ipstats_stat_desc_toplev_group; + const struct ipstats_stat_desc *desc = toplev; + int i; + + for (i = 0; i < IPSTATS_LEVELS_COUNT; i++) { + const struct ipstats_stat_desc *next_desc; + + if (sel->seli == NULL) + break; + if (desc->kind == IPSTATS_STAT_DESC_KIND_LEAF) { + fprintf(stderr, "Error: %s %s requested inside leaf %s %s\n", + ipstats_levelsi, sel->seli, + ipstats_levelsi - 1, desc->name); + return NULL; + } + + next_desc = ipstats_stat_desc_find(desc, sel->seli); + if (next_desc == NULL) { + fprintf(stderr, "Error: no %s named %s found inside %s\n", + ipstats_levelsi, sel->seli, desc->name); + return NULL; + } + + desc = next_desc; + } + + return desc; +} + +static int ipstats_enable(struct ipstats_sel *sel, + struct ipstats_stat_enabled *enabled) +{ + struct ipstats_stat_enabled new_enabled = {}; + const struct ipstats_stat_desc *desc; + size_t i, j; + int err = 0; + + desc = ipstats_enable_find_stat_desc(sel); + if (desc == NULL) + return -EINVAL; + + err = ipstats_enable_recursively(desc, &new_enabled, sel); + if (err != 0) + return err; + + err = ipstats_add_enabled(new_enabled.enabled, new_enabled.nenabled, + enabled); + if (err != 0) + goto out; + + qsort(enabled->enabled, enabled->nenabled, sizeof(*enabled->enabled), + ipstats_comp_enabled); + + for (i = 1, j = 1; i < enabled->nenabled; i++) { + if (enabled->enabledi.desc != enabled->enabledj - 1.desc) + enabled->enabledj++ = enabled->enabledi; + } + enabled->nenabled = j; + +out: + ipstats_enabled_free(&new_enabled); + return err; +} + +static int ipstats_enable_check(struct ipstats_sel *sel, + struct ipstats_stat_enabled *enabled) +{ + int err; + int i; + + err = ipstats_enable(sel, enabled); + if (err == -ENOENT) { + fprintf(stderr, "The request for"); + for (i = 0; i < IPSTATS_LEVELS_COUNT; i++) + if (sel->seli != NULL) + fprintf(stderr, " %s %s", + ipstats_levelsi, sel->seli); + else + break; + fprintf(stderr, " did not match any known stats.\n"); + } + + return err; +} + +static int do_help(void) +{ + const struct ipstats_stat_desc *toplev = &ipstats_stat_desc_toplev_group; + int i; + + fprintf(stderr, + "Usage: ip stats help\n" + " ip stats show dev DEV group GROUP subgroup SUBGROUP suite SUITE ... ... ...\n" + " ip stats set dev DEV l3_stats { on | off }\n" + ); + + for (i = 0; i < toplev->nsubs; i++) { + const struct ipstats_stat_desc *desc = toplev->subsi; + + if (i == 0) + fprintf(stderr, "GROUP := { %s", desc->name); + else + fprintf(stderr, " | %s", desc->name); + } + if (i > 0) + fprintf(stderr, " }\n"); + + for (i = 0; i < toplev->nsubs; i++) { + const struct ipstats_stat_desc *desc = toplev->subsi; + bool opened = false; + size_t j; + + if (desc->kind != IPSTATS_STAT_DESC_KIND_GROUP) + continue; + + for (j = 0; j < desc->nsubs; j++) { + size_t k; + + if (j == 0) + fprintf(stderr, "%s SUBGROUP := {", desc->name); + else + fprintf(stderr, " |"); + fprintf(stderr, " %s", desc->subsj->name); + opened = true; + + if (desc->subsj->kind != IPSTATS_STAT_DESC_KIND_GROUP) + continue; + + for (k = 0; k < desc->subsj->nsubs; k++) + fprintf(stderr, " suite %s ", + desc->subsj->subsk->name); + } + if (opened) + fprintf(stderr, " }\n"); + } + + return 0; +} + +static int ipstats_select(struct ipstats_sel *old_sel, + const char *new_sel, int level, + struct ipstats_stat_enabled *enabled) +{ + int err; + int i; + + for (i = 0; i < level; i++) { + if (old_sel->seli == NULL) { + fprintf(stderr, "Error: %s %s requested without selecting a %s first\n", + ipstats_levelslevel, new_sel, + ipstats_levelsi); + return -EINVAL; + } + } + + for (i = level; i < IPSTATS_LEVELS_COUNT; i++) { + if (old_sel->seli != NULL) { + err = ipstats_enable_check(old_sel, enabled); + if (err) + return err; + break; + } + } + + old_sel->sellevel = new_sel; + for (i = level + 1; i < IPSTATS_LEVELS_COUNT; i++) + old_sel->seli = NULL; + + return 0; +} + +static int ipstats_show(int argc, char **argv) +{ + struct ipstats_stat_enabled enabled = {}; + struct ipstats_sel sel = {}; + const char *dev = NULL; + int ifindex; + int err; + int i; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (dev != NULL) + duparg2("dev", *argv); + if (check_ifname(*argv)) + invarg("\"dev\" not a valid ifname", *argv); + dev = *argv; + } else if (strcmp(*argv, "help") == 0) { + do_help(); + return 0; + } else { + bool found_level = false; + + for (i = 0; i < ARRAY_SIZE(ipstats_levels); i++) { + if (strcmp(*argv, ipstats_levelsi) == 0) { + NEXT_ARG(); + err = ipstats_select(&sel, *argv, i, + &enabled); + if (err) + goto err; + + found_level = true; + } + } + + if (!found_level) { + fprintf(stderr, "What is \"%s\"?\n", *argv); + do_help(); + err = -EINVAL; + goto err; + } + } + + NEXT_ARG_FWD(); + } + + /* Push whatever was given. */ + err = ipstats_enable_check(&sel, &enabled); + if (err) + goto err; + + if (dev) { + ifindex = ll_name_to_index(dev); + if (!ifindex) { + err = nodev(dev); + goto err; + } + } else { + ifindex = 0; + } + + + err = ipstats_show_do(ifindex, &enabled); + +err: + ipstats_enabled_free(&enabled); + return err; +} + +static int ipstats_set_do(int ifindex, int at, bool enable) +{ + struct ipstats_req req = { + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct if_stats_msg)), + .nlh.nlmsg_flags = NLM_F_REQUEST, + .nlh.nlmsg_type = RTM_SETSTATS, + .ifsm.family = PF_UNSPEC, + .ifsm.ifindex = ifindex, + }; + + addattr8(&req.nlh, sizeof(req), at, enable); + + if (rtnl_talk(&rth, &req.nlh, NULL) < 0) + return -2; + return 0; +} + +static int ipstats_set(int argc, char **argv) +{ + const char *dev = NULL; + bool enable = false; + int ifindex; + int at = 0; + + while (argc > 0) { + if (strcmp(*argv, "dev") == 0) { + NEXT_ARG(); + if (dev) + duparg2("dev", *argv); + if (check_ifname(*argv)) + invarg("\"dev\" not a valid ifname", *argv); + dev = *argv; + } else if (strcmp(*argv, "l3_stats") == 0) { + int err; + + NEXT_ARG(); + if (at) { + fprintf(stderr, "A statistics suite to toggle was already given.\n"); + return -EINVAL; + } + at = IFLA_STATS_SET_OFFLOAD_XSTATS_L3_STATS; + enable = parse_on_off("l3_stats", *argv, &err); + if (err) + return err; + } else if (strcmp(*argv, "help") == 0) { + do_help(); + return 0; + } else { + fprintf(stderr, "What is \"%s\"?\n", *argv); + do_help(); + return -EINVAL; + } + + NEXT_ARG_FWD(); + } + + if (!dev) { + fprintf(stderr, "Not enough information: \"dev\" argument is required.\n"); + exit(-1); + } + + if (!at) { + fprintf(stderr, "Not enough information: stat type to toggle is required.\n"); + exit(-1); + } + + ifindex = ll_name_to_index(dev); + if (!ifindex) + return nodev(dev); + + return ipstats_set_do(ifindex, at, enable); +} + +int do_ipstats(int argc, char **argv) +{ + int rc; + + if (argc == 0) { + rc = ipstats_show(0, NULL); + } else if (strcmp(*argv, "help") == 0) { + do_help(); + rc = 0; + } else if (strcmp(*argv, "show") == 0) { + /* Invoking "stats show" implies one -s. Passing -d adds one + * more -s. + */ + show_stats += show_details + 1; + rc = ipstats_show(argc-1, argv+1); + } else if (strcmp(*argv, "set") == 0) { + rc = ipstats_set(argc-1, argv+1); + } else { + fprintf(stderr, "Command \"%s\" is unknown, try \"ip stats help\".\n", + *argv); + rc = -1; + } + + return rc; +} + +int ipstats_print(struct nlmsghdr *n, void *arg) +{ + struct ipstats_stat_enabled_one one = { + .desc = &ipstats_stat_desc_offload_hw_s_info, + }; + struct ipstats_stat_enabled enabled = { + .enabled = &one, + .nenabled = 1, + }; + FILE *fp = arg; + int rc; + + rc = ipstats_process_ifsm(n, &enabled); + if (rc) + return rc; + + fflush(fp); + return 0; +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/iptuntap.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/iptuntap.c
Changed
@@ -321,14 +321,16 @@ } else if (err == 2 && !strcmp("iff", key) && !strcmp(name, value)) { - char *pname = get_task_name(pid); + SPRINT_BUF(pname); - print_string(PRINT_ANY, "name", - "%s", pname ? : "<NULL>"); + if (get_task_name(pid, pname, sizeof(pname))) + print_string(PRINT_ANY, "name", + "%s", "<NULL>"); + else + print_string(PRINT_ANY, "name", + "%s", pname); - print_uint(PRINT_ANY, "pid", - "(%d)", pid); - free(pname); + print_uint(PRINT_ANY, "pid", "(%d)", pid); } free(key);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/link_xfrm.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/link_xfrm.c
Changed
@@ -18,8 +18,9 @@ { fprintf(f, "Usage: ... %-4s dev PHYS_DEV if_id IF-ID \n" + " external \n" "\n" - "Where: IF-ID := { 0x0..0xffffffff }\n", + "Where: IF-ID := { 0x1..0xffffffff }\n", lu->id); } @@ -27,6 +28,7 @@ struct nlmsghdr *n) { unsigned int link = 0; + bool metadata = false; __u32 if_id = 0; while (argc > 0) { @@ -39,8 +41,12 @@ NEXT_ARG(); if (get_u32(&if_id, *argv, 0)) invarg("if_id value is invalid", *argv); + else if (!if_id) + invarg("if_id value is invalid", *argv); else addattr32(n, 1024, IFLA_XFRM_IF_ID, if_id); + } else if (!strcmp(*argv, "external")) { + metadata = true; } else { xfrm_print_help(lu, argc, argv, stderr); return -1; @@ -48,6 +54,18 @@ argc--; argv++; } + if (metadata) { + if (if_id || link) { + fprintf(stderr, "xfrmi: both 'external' and if_id/link cannot be specified\n"); + return -1; + } + addattr(n, 1024, IFLA_XFRM_COLLECT_METADATA); + return 0; + } + + if (!if_id) + missarg("IF_ID"); + if (link) addattr32(n, 1024, IFLA_XFRM_LINK, link); @@ -60,6 +78,11 @@ if (!tb) return; + if (tbIFLA_XFRM_COLLECT_METADATA) { + print_bool(PRINT_ANY, "external", "external ", true); + return; + } + if (tbIFLA_XFRM_IF_ID) { __u32 id = rta_getattr_u32(tbIFLA_XFRM_IF_ID);
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/ip/nh_common.h
Added
@@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __NH_COMMON_H__ +#define __NH_COMMON_H__ 1 + +#include <list.h> + +#define NH_CACHE_SIZE 1024 + +struct nha_res_grp { + __u16 buckets; + __u32 idle_timer; + __u32 unbalanced_timer; + __u64 unbalanced_time; +}; + +struct nh_entry { + struct hlist_node nh_hash; + + __u32 nh_id; + __u32 nh_oif; + __u32 nh_flags; + __u16 nh_grp_type; + __u8 nh_family; + __u8 nh_scope; + __u8 nh_protocol; + + bool nh_blackhole; + bool nh_fdb; + + int nh_gateway_len; + union { + __be32 ipv4; + struct in6_addr ipv6; + } nh_gateway; + + struct rtattr *nh_encap; + union { + struct rtattr rta; + __u8 _bufRTA_LENGTH(sizeof(__u16)); + } nh_encap_type; + + bool nh_has_res_grp; + struct nha_res_grp nh_res_grp; + + int nh_groups_cnt; + struct nexthop_grp *nh_groups; +}; + +void print_cache_nexthop_id(FILE *fp, const char *fp_prefix, const char *jsobj, + __u32 nh_id); +int print_cache_nexthop(struct nlmsghdr *n, void *arg, bool process_cache); + +#endif /* __NH_COMMON_H__ */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/routel -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/routel
Changed
@@ -1,72 +1,62 @@ -#!/bin/sh +#! /usr/bin/env python3 # SPDX-License-Identifier: GPL-2.0 - -# -# Script created by: Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 -# Donated to the public domain. -# -# This script transforms the output of "ip" into more readable text. -# "ip" is the Linux-advanced-routing configuration tool part of the -# iproute package. # +# This is simple script to process JSON output from ip route +# command and format it. Based on earlier shell script version. +"""Script to parse ip route output into more readable text.""" + +import sys +import json +import getopt +import subprocess + + +def usage(): + '''Print usage and exit''' + print("Usage: {} tablenr raw ip args...".format(sys.argv0)) + sys.exit(64) + + +def main(): + '''Process the arguments''' + family = 'inet' + try: + opts, args = getopt.getopt(sys.argv1:, "h46f:", "help", "family=") + except getopt.GetoptError as err: + print(err) + usage() + + for opt, arg in opts: + if opt in "-h", "--help": + usage() + elif opt == '-6': + family = 'inet6' + elif opt == "-4": + family = 'inet' + elif opt in "-f", "--family": + family = arg + else: + assert False, "unhandled option" + + if not args: + args = '0' + + cmd = 'ip', '-f', family, '-j', 'route', 'list', 'table' + args + process = subprocess.Popen(cmd, stdout=subprocess.PIPE) + tbl = json.load(process.stdout) + if family == 'inet': + fmt = '{:15} {:15} {:15} {:8} {:8}{:<16} {}' + else: + fmt = '{:32} {:32} {:32} {:8} {:8}{:<16} {}' + + # ip route json keys + keys = 'dst', 'gateway', 'prefsrc', 'protocol', 'scope', 'dev', 'table' + print(fmt.format(*map(lambda x: x.capitalize(), keys))) -test "X-h" = "X$1" && echo "Usage: $0 tablenr raw ip args..." && exit 64 + for record in tbl: + fields = recordk if k in record else '' for k in keys + print(fmt.format(*fields)) -test -z "$*" && set 0 -ip route list table "$@" | - while read network rest - do set xx $rest - shift - proto="" - via="" - dev="" - scope="" - src="" - table="" - case $network in - broadcast|local|unreachable) via=$network - network=$1 - shift - ;; - esac - while test $# != 0 - do - case "$1" in - proto|via|dev|scope|src|table) - key=$1 - val=$2 - eval "$key='$val'" - shift 2 - ;; - dead|onlink|pervasive|offload|notify|linkdown|unresolved) - shift - ;; - *) - # avoid infinite loop on unknown keyword without value at line end - shift - shift - ;; - esac - done - echo "$network $via $src $proto $scope $dev $table" - done | awk -F ' ' ' -BEGIN { - format="%15s%-3s %15s %15s %8s %8s%7s %s\n"; - printf(format,"target","","gateway","source","proto","scope","dev","tbl"); - } - { network=$1; - mask=""; - if(match(network,"/")) - { mask=" "substr(network,RSTART+1); - network=substr(network,0,RSTART); - } - via=$2; - src=$3; - proto=$4; - scope=$5; - dev=$6; - table=$7; - printf(format,network,mask,via,src,proto,scope,dev,table); - } -' +if __name__ == "__main__": + main()
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/tunnel.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/tunnel.c
Changed
@@ -298,14 +298,8 @@ value = "unknown"; } - if (is_json_context()) { - print_string(PRINT_JSON, name, NULL, value); - } else { - SPRINT_BUF(b1); - - snprintf(b1, sizeof(b1), "%s %%s ", name); - print_string(PRINT_FP, NULL, b1, value); - } + print_string_name_value(name, value); + print_string(PRINT_FP, NULL, " ", NULL); } void tnl_print_gre_flags(__u8 proto,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/xfrm.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/xfrm.h
Changed
@@ -132,6 +132,7 @@ void xfrm_policy_info_print(struct xfrm_userpolicy_info *xpinfo, struct rtattr *tb, FILE *fp, const char *prefix, const char *title); +int xfrm_policy_default_print(struct nlmsghdr *n, FILE *fp); int xfrm_id_parse(xfrm_address_t *saddr, struct xfrm_id *id, __u16 *family, int loose, int *argcp, char ***argvp); int xfrm_mode_parse(__u8 *mode, int *argcp, char ***argvp);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/xfrm_monitor.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/xfrm_monitor.c
Changed
@@ -323,6 +323,9 @@ case XFRM_MSG_MAPPING: xfrm_mapping_print(n, arg); return 0; + case XFRM_MSG_GETDEFAULT: + xfrm_policy_default_print(n, arg); + return 0; default: break; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/xfrm_policy.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/xfrm_policy.c
Changed
@@ -66,6 +66,8 @@ "Usage: ip xfrm policy flush ptype PTYPE \n" "Usage: ip xfrm policy count\n" "Usage: ip xfrm policy set hthresh4 LBITS RBITS hthresh6 LBITS RBITS \n" + "Usage: ip xfrm policy setdefault DIR ACTION DIR ACTION DIR ACTION \n" + "Usage: ip xfrm policy getdefault\n" "SELECTOR := src ADDR/PLEN dst ADDR/PLEN dev DEV UPSPEC \n" "UPSPEC := proto { { tcp | udp | sctp | dccp } sport PORT dport PORT |\n" " { icmp | ipv6-icmp | mobility-header } type NUMBER code NUMBER |\n" @@ -1124,6 +1126,133 @@ return 0; } +static int xfrm_str_to_policy(char *name, uint8_t *policy) +{ + if (strcmp(name, "block") == 0) { + *policy = XFRM_USERPOLICY_BLOCK; + return 0; + } else if (strcmp(name, "accept") == 0) { + *policy = XFRM_USERPOLICY_ACCEPT; + return 0; + } + + return -1; +} + +static char *xfrm_policy_to_str(uint8_t policy) +{ + switch (policy) { + case XFRM_USERPOLICY_UNSPEC: + return "unspec"; + case XFRM_USERPOLICY_BLOCK: + return "block"; + case XFRM_USERPOLICY_ACCEPT: + return "accept"; + default: + return "unknown"; + } +} + +static int xfrm_spd_setdefault(int argc, char **argv) +{ + struct rtnl_handle rth; + struct { + struct nlmsghdr n; + struct xfrm_userpolicy_default up; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_default)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = XFRM_MSG_SETDEFAULT, + }; + + while (argc > 0) { + if (strcmp(*argv, "in") == 0) { + if (req.up.in) + duparg("in", *argv); + + NEXT_ARG(); + if (xfrm_str_to_policy(*argv, &req.up.in) < 0) + invarg("in policy value is invalid", *argv); + } else if (strcmp(*argv, "fwd") == 0) { + if (req.up.fwd) + duparg("fwd", *argv); + + NEXT_ARG(); + if (xfrm_str_to_policy(*argv, &req.up.fwd) < 0) + invarg("fwd policy value is invalid", *argv); + } else if (strcmp(*argv, "out") == 0) { + if (req.up.out) + duparg("out", *argv); + + NEXT_ARG(); + if (xfrm_str_to_policy(*argv, &req.up.out) < 0) + invarg("out policy value is invalid", *argv); + } else { + invarg("unknown direction", *argv); + } + + argc--; argv++; + } + + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + + if (rtnl_talk(&rth, &req.n, NULL) < 0) + exit(2); + + rtnl_close(&rth); + + return 0; +} + +int xfrm_policy_default_print(struct nlmsghdr *n, FILE *fp) +{ + struct xfrm_userpolicy_default *up = NLMSG_DATA(n); + int len = n->nlmsg_len - NLMSG_SPACE(sizeof(*up)); + + if (len < 0) { + fprintf(stderr, + "BUG: short nlmsg len %u (expect %lu) for XFRM_MSG_GETDEFAULT\n", + n->nlmsg_len, NLMSG_SPACE(sizeof(*up))); + return -1; + } + + fprintf(fp, "Default policies:\n"); + fprintf(fp, " in: %s\n", xfrm_policy_to_str(up->in)); + fprintf(fp, " fwd: %s\n", xfrm_policy_to_str(up->fwd)); + fprintf(fp, " out: %s\n", xfrm_policy_to_str(up->out)); + fflush(fp); + + return 0; +} + +static int xfrm_spd_getdefault(int argc, char **argv) +{ + struct rtnl_handle rth; + struct { + struct nlmsghdr n; + struct xfrm_userpolicy_default up; + } req = { + .n.nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_userpolicy_default)), + .n.nlmsg_flags = NLM_F_REQUEST, + .n.nlmsg_type = XFRM_MSG_GETDEFAULT, + }; + struct nlmsghdr *answer; + + if (rtnl_open_byproto(&rth, 0, NETLINK_XFRM) < 0) + exit(1); + + if (rtnl_talk(&rth, &req.n, &answer) < 0) + exit(2); + + xfrm_policy_default_print(answer, (FILE *)stdout); + + free(answer); + rtnl_close(&rth); + + return 0; +} + static int xfrm_policy_flush(int argc, char **argv) { struct rtnl_handle rth; @@ -1197,6 +1326,10 @@ return xfrm_spd_getinfo(argc, argv); if (matches(*argv, "set") == 0) return xfrm_spd_setinfo(argc-1, argv+1); + if (matches(*argv, "setdefault") == 0) + return xfrm_spd_setdefault(argc-1, argv+1); + if (matches(*argv, "getdefault") == 0) + return xfrm_spd_getdefault(argc-1, argv+1); if (matches(*argv, "help") == 0) usage(); fprintf(stderr, "Command \"%s\" is unknown, try \"ip xfrm policy help\".\n", *argv);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/ip/xfrm_state.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/ip/xfrm_state.c
Changed
@@ -124,11 +124,6 @@ int len; int slen = strlen(key); -#if 0 - /* XXX: verifying both name and key is required! */ - fprintf(stderr, "warning: ALGO-NAME/ALGO-KEYMAT values will be sent to the kernel promiscuously! (verifying them isn't implemented yet)\n"); -#endif - strlcpy(alg->alg_name, name, sizeof(alg->alg_name)); if (slen > 2 && strncmp(key, "0x", 2) == 0) { @@ -791,12 +786,6 @@ .n.nlmsg_flags = NLM_F_REQUEST, .n.nlmsg_type = XFRM_MSG_ALLOCSPI, .xspi.info.family = preferred_family, -#if 0 - .xspi.lft.soft_byte_limit = XFRM_INF, - .xspi.lft.hard_byte_limit = XFRM_INF, - .xspi.lft.soft_packet_limit = XFRM_INF, - .xspi.lft.hard_packet_limit = XFRM_INF, -#endif }; char *idp = NULL; char *minp = NULL;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/Makefile
Changed
@@ -5,7 +5,7 @@ UTILOBJ = utils.o utils_math.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 \ - names.o color.o bpf_legacy.o bpf_glue.o exec.o fs.o cg_map.o + names.o color.o bpf_legacy.o bpf_glue.o exec.o fs.o cg_map.o ppp_proto.o ifeq ($(HAVE_ELF),y) ifeq ($(HAVE_LIBBPF),y)
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/lib/ax25_ntop.c
Added
@@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include <errno.h> +#include <sys/socket.h> +#include <linux/ax25.h> + +#include "utils.h" + +const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size); + +/* + * AX.25 addresses are based on Amateur radio callsigns followed by an SSID + * like XXXXXX-SS where the callsign consists of up to 6 ASCII characters + * which are either letters or digits and the SSID is a decimal number in the + * range 0..15. + * Amateur radio callsigns are assigned by a country's relevant authorities + * and are 3..6 characters though a few countries have assigned callsigns + * longer than that. AX.25 is not able to handle such longer callsigns. + * There are further restrictions on the format of valid callsigns by + * applicable national and international law. Linux doesn't need to care and + * will happily accept anything that consists of 6 ASCII characters in the + * range of A-Z and 0-9 for a callsign such as the default AX.25 MAC address + * LINUX-1 and the default broadcast address QST-0. + * The SSID is just a number and not encoded in ASCII digits. + * + * Being based on HDLC AX.25 encodes addresses by shifting them one bit left + * thus zeroing bit 0, the HDLC extension bit for all but the last bit of + * a packet's address field but for our purposes here we're not considering + * the HDLC extension bit that is it will always be zero. + * + * Linux' internal representation of AX.25 addresses in Linux is very similar + * to this on the on-air or on-the-wire format. The callsign is padded to + * 6 octets by adding spaces, followed by the SSID octet then all 7 octets + * are left-shifted by one bit. + * + * For example, for the address "LINUX-1" the callsign is LINUX and SSID is 1 + * the internal format is 98:92:9c:aa:b0:40:02. + */ + +const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size) +{ + char c, *s; + int n; + + for (n = 0, s = dst; n < 6; n++) { + c = (src->ax25_calln >> 1) & 0x7f; + if (c != ' ') + *s++ = c; + } + + *s++ = '-'; + + n = ((src->ax25_call6 >> 1) & 0x0f); + if (n > 9) { + *s++ = '1'; + n -= 10; + } + + *s++ = n + '0'; + *s++ = '\0'; + + if (*dst == '\0' || *dst == '-') { + dst0 = '*'; + dst1 = '\0'; + } + + return dst; +} + +const char *ax25_ntop(int af, const void *addr, char *buf, socklen_t buflen) +{ + switch (af) { + case AF_AX25: + errno = 0; + return ax25_ntop1((ax25_address *)addr, buf, buflen); + + default: + errno = EAFNOSUPPORT; + } + + return NULL; +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/bpf_glue.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/bpf_glue.c
Changed
@@ -4,22 +4,24 @@ * Authors: Hangbin Liu <haliu@redhat.com> * */ +#include <sys/syscall.h> #include <limits.h> +#include <unistd.h> +#include <errno.h> #include "bpf_util.h" #ifdef HAVE_LIBBPF #include <bpf/bpf.h> #endif -int bpf_program_load(enum bpf_prog_type type, const struct bpf_insn *insns, - size_t size_insns, const char *license, char *log, - size_t size_log) +int bpf(int cmd, union bpf_attr *attr, unsigned int size) { -#ifdef HAVE_LIBBPF - return bpf_load_program(type, insns, size_insns / sizeof(struct bpf_insn), - license, 0, log, size_log); +#ifdef __NR_bpf + return syscall(__NR_bpf, cmd, attr, size); #else - return bpf_prog_load_dev(type, insns, size_insns, license, 0, log, size_log); + fprintf(stderr, "No bpf syscall, kernel headers too old?\n"); + errno = ENOSYS; + return -1; #endif }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/bpf_legacy.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/bpf_legacy.c
Changed
@@ -33,7 +33,6 @@ #include <sys/un.h> #include <sys/vfs.h> #include <sys/mount.h> -#include <sys/syscall.h> #include <sys/sendfile.h> #include <sys/resource.h> @@ -134,17 +133,6 @@ return (__u64)(unsigned long)ptr; } -static int bpf(int cmd, union bpf_attr *attr, unsigned int size) -{ -#ifdef __NR_bpf - return syscall(__NR_bpf, cmd, attr, size); -#else - fprintf(stderr, "No bpf syscall, kernel headers too old?\n"); - errno = ENOSYS; - return -1; -#endif -} - static int bpf_map_update(int fd, const void *key, const void *value, uint64_t flags) { @@ -203,12 +191,30 @@ if (!ret && len) { int jited = !!info.jited_prog_len; + print_string(PRINT_ANY, "name", "name %s ", info.name); print_string(PRINT_ANY, "tag", "tag %s ", hexstring_n2a(info.tag, sizeof(info.tag), tmp, sizeof(tmp))); print_uint(PRINT_JSON, "jited", NULL, jited); if (jited && !is_json_context()) fprintf(f, "jited "); + + if (show_details) { + if (info.load_time) { + /* ns since boottime */ + print_lluint(PRINT_ANY, "load_time", + "load_time %llu ", info.load_time); + + print_luint(PRINT_ANY, "created_by_uid", + "created_by_uid %lu ", + info.created_by_uid); + } + + if (info.btf_id) + print_luint(PRINT_ANY, "btf_id", "btf_id %lu ", + info.btf_id); + } + dump_ok = 1; } @@ -825,7 +831,7 @@ static int bpf_do_parse(struct bpf_cfg_in *cfg, const bool *opt_tbl) { - const char *file, *section, *uds_name; + const char *file, *section, *uds_name, *prog_name; bool verbose = false; int i, ret, argc; char **argv; @@ -856,7 +862,7 @@ } NEXT_ARG(); - file = section = uds_name = NULL; + file = section = uds_name = prog_name = NULL; if (cfg->mode == EBPF_OBJECT || cfg->mode == EBPF_PINNED) { file = *argv; NEXT_ARG_FWD(); @@ -893,6 +899,12 @@ NEXT_ARG_FWD(); } + if (argc > 0 && strcmp(*argv, "program") == 0) { + NEXT_ARG(); + prog_name = *argv; + NEXT_ARG_FWD(); + } + if (__bpf_prog_metacfg->type.may_uds_export) { uds_name = getenv(BPF_ENV_UDS); if (argc > 0 && !uds_name && @@ -930,6 +942,7 @@ cfg->argc = argc; cfg->argv = argv; cfg->verbose = verbose; + cfg->prog_name = prog_name; return ret; } @@ -1108,6 +1121,13 @@ return bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); } +int bpf_program_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;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/bpf_libbpf.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/bpf_libbpf.c
Changed
@@ -23,12 +23,14 @@ #include "bpf_util.h" -static int verbose_print(enum libbpf_print_level level, const char *format, va_list args) +static int __attribute__((format(printf, 2, 0))) +verbose_print(enum libbpf_print_level level, const char *format, va_list args) { return vfprintf(stderr, format, args); } -static int silent_print(enum libbpf_print_level level, const char *format, va_list args) +static int __attribute__((format(printf, 2, 0))) +silent_print(enum libbpf_print_level level, const char *format, va_list args) { if (level > LIBBPF_WARN) return 0; @@ -52,18 +54,18 @@ static int create_map(const char *name, struct bpf_elf_map *map, __u32 ifindex, int inner_fd) { - struct bpf_create_map_attr map_attr = {}; - - map_attr.name = name; - map_attr.map_type = map->type; - map_attr.map_flags = map->flags; - map_attr.key_size = map->size_key; - map_attr.value_size = map->size_value; - map_attr.max_entries = map->max_elem; - map_attr.map_ifindex = ifindex; - map_attr.inner_map_fd = inner_fd; - - return bpf_create_map_xattr(&map_attr); + union bpf_attr attr = {}; + + attr.map_type = map->type; + strlcpy(attr.map_name, name, sizeof(attr.map_name)); + attr.map_flags = map->flags; + attr.key_size = map->size_key; + attr.value_size = map->size_value; + attr.max_entries = map->max_elem; + attr.map_ifindex = ifindex; + attr.inner_map_fd = inner_fd; + + return bpf(BPF_MAP_CREATE, &attr, sizeof(attr)); } static int create_map_in_map(struct bpf_object *obj, struct bpf_map *map, @@ -149,7 +151,8 @@ return ret; } -static int find_legacy_tail_calls(struct bpf_program *prog, struct bpf_object *obj) +static int find_legacy_tail_calls(struct bpf_program *prog, struct bpf_object *obj, + struct bpf_map **pmap) { unsigned int map_id, key_id; const char *sec_name; @@ -173,8 +176,8 @@ if (!map) return -1; - /* Save the map here for later updating */ - bpf_program__set_priv(prog, map, NULL); + if (pmap) + *pmap = map; return 0; } @@ -188,8 +191,10 @@ struct bpf_map *map; bpf_object__for_each_program(prog, obj) { - map = bpf_program__priv(prog); - if (!map) + /* load_bpf_object has already verified find_legacy_tail_calls + * succeeds when it should + */ + if (find_legacy_tail_calls(prog, obj, &map) < 0) continue; prog_fd = bpf_program__fd(prog); @@ -244,6 +249,27 @@ return ret; } +static bool bpf_map_is_offload_neutral(const struct bpf_map *map) +{ + return bpf_map__type(map) == BPF_MAP_TYPE_PERF_EVENT_ARRAY; +} + +static bool find_prog_to_attach(struct bpf_program *prog, + struct bpf_program *exist_prog, + const char *section, const char *prog_name) +{ + if (exist_prog) + return false; + + /* We have default section name 'prog'. So do not check + * section name if there already has program name. + */ + if (prog_name) + return !strcmp(bpf_program__name(prog), prog_name); + else + return !strcmp(get_bpf_program__section_name(prog), section); +} + static int load_bpf_object(struct bpf_cfg_in *cfg) { struct bpf_program *p, *prog = NULL; @@ -268,12 +294,14 @@ } bpf_object__for_each_program(p, obj) { - bool prog_to_attach = !prog && cfg->section && - !strcmp(get_bpf_program__section_name(p), cfg->section); + bool prog_to_attach = find_prog_to_attach(p, prog, + cfg->section, + cfg->prog_name); /* Only load the programs that will either be subsequently * attached or inserted into a tail call map */ - if (find_legacy_tail_calls(p, obj) < 0 && !prog_to_attach) { + if (find_legacy_tail_calls(p, obj, NULL) < 0 && + !prog_to_attach) { ret = bpf_program__set_autoload(p, false); if (ret) return -EINVAL; @@ -288,12 +316,15 @@ } bpf_object__for_each_map(map, obj) { - if (!bpf_map__is_offload_neutral(map)) + if (!bpf_map_is_offload_neutral(map)) bpf_map__set_ifindex(map, cfg->ifindex); } if (!prog) { - fprintf(stderr, "object file doesn't contain sec %s\n", cfg->section); + if (cfg->prog_name) + fprintf(stderr, "object file doesn't contain prog %s\n", cfg->prog_name); + else + fprintf(stderr, "object file doesn't contain sec %s\n", cfg->section); return -ENOENT; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/fs.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/fs.c
Changed
@@ -342,25 +342,28 @@ return 0; } -char *get_task_name(pid_t pid) +int get_task_name(pid_t pid, char *name, size_t len) { - char *comm; + char pathPATH_MAX; FILE *f; if (!pid) - return NULL; + return -1; - if (asprintf(&comm, "/proc/%d/comm", pid) < 0) - return NULL; + if (snprintf(path, sizeof(path), "/proc/%d/comm", pid) >= sizeof(path)) + return -1; - f = fopen(comm, "r"); + f = fopen(path, "r"); if (!f) - return NULL; + return -1; - if (fscanf(f, "%ms\n", &comm) != 1) - comm = NULL; + if (!fgets(name, len, f)) + return -1; + + /* comm ends in \n, get rid of it */ + namestrcspn(name, "\n") = '\0'; fclose(f); - return comm; + return 0; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/json_print.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/json_print.c
Changed
@@ -299,6 +299,13 @@ return ret; } +/* + * This function does take printf style argument but applying + * format attribute to causes more warnings since the print_XXX + * functions are used with NULL for format if unused. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" int print_color_tv(enum output_type type, enum color_attr color, const char *key, @@ -311,6 +318,7 @@ return print_color_float(type, color, key, fmt, time); } +#pragma GCC diagnostic pop /* Print line separator (if not in JSON mode) */ void print_nl(void)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/json_writer.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/json_writer.c
Changed
@@ -80,9 +80,6 @@ case '"': fputs("\\\"", self->out); break; - case '\'': - fputs("\\\'", self->out); - break; default: putc(*str, self->out); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/libnetlink.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/libnetlink.c
Changed
@@ -129,13 +129,12 @@ return 0; } -int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, unsigned int offset, int error) { struct nlattr *tbNLMSGERR_ATTR_MAX + 1 = {}; - unsigned int hlen = sizeof(int); const char *msg = NULL; - if (mnl_attr_parse(nlh, hlen, err_attr_cb, tb) != MNL_CB_OK) + if (mnl_attr_parse(nlh, offset, err_attr_cb, tb) != MNL_CB_OK) return 0; if (tbNLMSGERR_ATTR_MSG) @@ -159,7 +158,7 @@ return 0; } -int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, int error) +int nl_dump_ext_ack_done(const struct nlmsghdr *nlh, unsigned int offset, int error) { return 0; } @@ -210,13 +209,13 @@ if (setsockopt(rth->fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0) { perror("SO_SNDBUF"); - return -1; + goto err; } if (setsockopt(rth->fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0) { perror("SO_RCVBUF"); - return -1; + goto err; } /* Older kernels may no support extended ACK reporting */ @@ -230,25 +229,28 @@ if (bind(rth->fd, (struct sockaddr *)&rth->local, sizeof(rth->local)) < 0) { perror("Cannot bind netlink socket"); - return -1; + goto err; } addr_len = sizeof(rth->local); if (getsockname(rth->fd, (struct sockaddr *)&rth->local, &addr_len) < 0) { perror("Cannot getsockname"); - return -1; + goto err; } if (addr_len != sizeof(rth->local)) { fprintf(stderr, "Wrong address length %d\n", addr_len); - return -1; + goto err; } if (rth->local.nl_family != AF_NETLINK) { fprintf(stderr, "Wrong address family %d\n", rth->local.nl_family); - return -1; + goto err; } rth->seq = time(NULL); return 0; +err: + rtnl_close(rth); + return -1; } int rtnl_open(struct rtnl_handle *rth, unsigned int subscriptions) @@ -616,12 +618,13 @@ return send(rth->fd, &req, sizeof(req), 0); } -int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, __u32 filt_mask) +int rtnl_statsdump_req_filter(struct rtnl_handle *rth, int fam, + __u32 filt_mask, + int (*filter_fn)(struct ipstats_req *req, + void *data), + void *filter_data) { - struct { - struct nlmsghdr nlh; - struct if_stats_msg ifsm; - } req; + struct ipstats_req req; memset(&req, 0, sizeof(req)); req.nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct if_stats_msg)); @@ -632,6 +635,14 @@ req.ifsm.family = fam; req.ifsm.filter_mask = filt_mask; + if (filter_fn) { + int err; + + err = filter_fn(&req, filter_data); + if (err) + return err; + } + return send(rth->fd, &req, sizeof(req), 0); } @@ -735,7 +746,7 @@ return 0; /* check for any messages returned from kernel */ - if (nl_dump_ext_ack_done(h, len)) + if (nl_dump_ext_ack_done(h, sizeof(int), len)) return len; switch (errno) { @@ -1081,14 +1092,19 @@ rtnl_talk_error(h, err, errfn); } - if (answer) - *answer = (struct nlmsghdr *)buf; - else + if (i < iovlen) { free(buf); - - if (i < iovlen) goto next; - return error ? -i : 0; + } + + if (error) { + free(buf); + return -i; + } + + if (answer) + *answer = (struct nlmsghdr *)buf; + return 0; } if (answer) { @@ -1127,6 +1143,28 @@ return __rtnl_talk_iov(rtnl, &iov, 1, answer, show_rtnl_err, errfn); } +int rtnl_echo_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, int json, + int (*print_info)(struct nlmsghdr *n, void *arg)) +{ + struct nlmsghdr *answer; + int ret; + + n->nlmsg_flags |= NLM_F_ECHO | NLM_F_ACK; + + ret = rtnl_talk(rtnl, n, &answer); + if (ret) + return ret; + + new_json_obj(json); + open_json_object(NULL); + print_info(answer, stdout); + close_json_object(); + delete_json_obj(); + free(answer); + + return 0; +} + int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n, struct nlmsghdr **answer) { @@ -1597,3 +1635,23 @@ } } } + +int rtnl_tunneldump_req(struct rtnl_handle *rth, int family, int ifindex, + __u8 flags) +{ + struct { + struct nlmsghdr nlh; + struct tunnel_msg tmsg; + char buf256; + } req = { + .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tunnel_msg)), + .nlh.nlmsg_type = RTM_GETTUNNEL, + .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST, + .nlh.nlmsg_seq = rth->dump = ++rth->seq, + .tmsg.family = family, + .tmsg.flags = flags, + .tmsg.ifindex = ifindex, + }; + + return send(rth->fd, &req, sizeof(req), 0); +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/ll_addr.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/ll_addr.c
Changed
@@ -39,6 +39,12 @@ if (alen == 16 && (type == ARPHRD_TUNNEL6 || type == ARPHRD_IP6GRE)) return inet_ntop(AF_INET6, addr, buf, blen); + if (alen == 7 && type == ARPHRD_AX25) + return ax25_ntop(AF_AX25, addr, buf, blen); + if (alen == 7 && type == ARPHRD_NETROM) + return netrom_ntop(AF_NETROM, addr, buf, blen); + if (alen == 5 && type == ARPHRD_ROSE) + return rose_ntop(AF_ROSE, addr, buf, blen); snprintf(buf, blen, "%02x", addr0); for (i = 1, l = 2; i < alen && l < blen; i++, l += 3)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/ll_proto.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/ll_proto.c
Changed
@@ -28,10 +28,8 @@ #define __PF(f,n) { ETH_P_##f, #n }, -static const struct { - int id; - const char *name; -} llproto_names = { + +static const struct proto llproto_names = { __PF(LOOP,loop) __PF(PUP,pup) __PF(PUPAT,pupat) @@ -75,7 +73,9 @@ __PF(IRDA,irda) __PF(ECONET,econet) __PF(TIPC,tipc) +__PF(PROFINET,profinet) __PF(AOE,aoe) +__PF(ETHERCAT,ethercat) __PF(8021Q,802.1Q) __PF(8021AD,802.1ad) __PF(MPLS_UC,mpls_uc) @@ -88,31 +88,16 @@ }; #undef __PF - -const char * ll_proto_n2a(unsigned short id, char *buf, int len) +const char *ll_proto_n2a(unsigned short id, char *buf, int len) { - int i; + size_t len_tb = ARRAY_SIZE(llproto_names); - id = ntohs(id); - - for (i=0; !numeric && i<sizeof(llproto_names)/sizeof(llproto_names0); i++) { - if (llproto_namesi.id == id) - return llproto_namesi.name; - } - snprintf(buf, len, "%d", id); - return buf; + return proto_n2a(id, buf, len, llproto_names, len_tb); } int ll_proto_a2n(unsigned short *id, const char *buf) { - int i; - for (i=0; i < sizeof(llproto_names)/sizeof(llproto_names0); i++) { - if (strcasecmp(llproto_namesi.name, buf) == 0) { - *id = htons(llproto_namesi.id); - return 0; - } - } - if (get_be16(id, buf, 0)) - return -1; - return 0; + size_t len_tb = ARRAY_SIZE(llproto_names); + + return proto_a2n(id, buf, llproto_names, len_tb); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/mnl_utils.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/mnl_utils.c
Changed
@@ -79,7 +79,7 @@ if (len < 0) { errno = -len; - nl_dump_ext_ack_done(nlh, len); + nl_dump_ext_ack_done(nlh, sizeof(int), len); return MNL_CB_ERROR; } return MNL_CB_STOP; @@ -110,7 +110,7 @@ return err; } -static int get_family_id_attr_cb(const struct nlattr *attr, void *data) +static int get_family_attrs_cb(const struct nlattr *attr, void *data) { int type = mnl_attr_get_type(attr); const struct nlattr **tb = data; @@ -121,20 +121,26 @@ if (type == CTRL_ATTR_FAMILY_ID && mnl_attr_validate(attr, MNL_TYPE_U16) < 0) return MNL_CB_ERROR; + if (type == CTRL_ATTR_MAXATTR && + mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + return MNL_CB_ERROR; tbtype = attr; return MNL_CB_OK; } -static int get_family_id_cb(const struct nlmsghdr *nlh, void *data) +static int get_family_cb(const struct nlmsghdr *nlh, void *data) { struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); struct nlattr *tbCTRL_ATTR_MAX + 1 = {}; - uint32_t *p_id = data; + struct mnlu_gen_socket *nlg = data; - mnl_attr_parse(nlh, sizeof(*genl), get_family_id_attr_cb, tb); + mnl_attr_parse(nlh, sizeof(*genl), get_family_attrs_cb, tb); if (!tbCTRL_ATTR_FAMILY_ID) return MNL_CB_ERROR; - *p_id = mnl_attr_get_u16(tbCTRL_ATTR_FAMILY_ID); + if (!tbCTRL_ATTR_MAXATTR) + return MNL_CB_ERROR; + nlg->family = mnl_attr_get_u16(tbCTRL_ATTR_FAMILY_ID); + nlg->maxattr = mnl_attr_get_u32(tbCTRL_ATTR_MAXATTR); return MNL_CB_OK; } @@ -159,7 +165,7 @@ err = mnlu_socket_recv_run(nlg->nl, nlh->nlmsg_seq, nlg->buf, MNL_SOCKET_BUFFER_SIZE, - get_family_id_cb, &nlg->family); + get_family_cb, nlg); return err; }
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/lib/netrom_ntop.c
Added
@@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include <sys/socket.h> +#include <errno.h> +#include <linux/ax25.h> + +#include "utils.h" + +const char *ax25_ntop1(const ax25_address *src, char *dst, socklen_t size); + +const char *netrom_ntop(int af, const void *addr, char *buf, socklen_t buflen) +{ + switch (af) { + case AF_NETROM: + errno = 0; + return ax25_ntop1((ax25_address *)addr, buf, buflen); + + default: + errno = EAFNOSUPPORT; + } + + return NULL; +}
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/lib/ppp_proto.c
Added
@@ -0,0 +1,52 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Utilities for translating PPP protocols from strings + * and vice versa. + * + * Authors: Wojciech Drewek <wojciech.drewek@intel.com> + */ + +#include <linux/ppp_defs.h> +#include <linux/if_ether.h> +#include "utils.h" +#include "rt_names.h" + +static const struct proto ppp_proto_names = { + {PPP_IP, "ip"}, + {PPP_AT, "at"}, + {PPP_IPX, "ipx"}, + {PPP_VJC_COMP, "vjc_comp"}, + {PPP_VJC_UNCOMP, "vjc_uncomp"}, + {PPP_MP, "mp"}, + {PPP_IPV6, "ipv6"}, + {PPP_COMPFRAG, "compfrag"}, + {PPP_COMP, "comp"}, + {PPP_MPLS_UC, "mpls_uc"}, + {PPP_MPLS_MC, "mpls_mc"}, + {PPP_IPCP, "ipcp"}, + {PPP_ATCP, "atcp"}, + {PPP_IPXCP, "ipxcp"}, + {PPP_IPV6CP, "ipv6cp"}, + {PPP_CCPFRAG, "ccpfrag"}, + {PPP_CCP, "ccp"}, + {PPP_MPLSCP, "mplscp"}, + {PPP_LCP, "lcp"}, + {PPP_PAP, "pap"}, + {PPP_LQR, "lqr"}, + {PPP_CHAP, "chap"}, + {PPP_CBCP, "cbcp"}, +}; + +const char *ppp_proto_n2a(unsigned short id, char *buf, int len) +{ + size_t len_tb = ARRAY_SIZE(ppp_proto_names); + + return proto_n2a(id, buf, len, ppp_proto_names, len_tb); +} + +int ppp_proto_a2n(unsigned short *id, const char *buf) +{ + size_t len_tb = ARRAY_SIZE(ppp_proto_names); + + return proto_a2n(id, buf, ppp_proto_names, len_tb); +}
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/lib/rose_ntop.c
Added
@@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <string.h> +#include <errno.h> + +#include <linux/netdevice.h> +#include <linux/if_arp.h> +#include <linux/sockios.h> +#include <linux/rose.h> + +#include "rt_names.h" +#include "utils.h" + +static const char *rose_ntop1(const rose_address *src, char *dst, + socklen_t size) +{ + char *p = dst; + int i; + + if (size < 10) + return NULL; + + for (i = 0; i < 5; i++) { + *p++ = '0' + ((src->rose_addri >> 4) & 0xf); + *p++ = '0' + ((src->rose_addri ) & 0xf); + } + + if (size == 10) + return dst; + + *p = '\0'; + + return dst; +} + +const char *rose_ntop(int af, const void *addr, char *buf, socklen_t buflen) +{ + switch (af) { + case AF_ROSE: + errno = 0; + return rose_ntop1((rose_address *)addr, buf, buflen); + + default: + errno = EAFNOSUPPORT; + } + + return NULL; +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/lib/utils.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/lib/utils.c
Changed
@@ -1925,3 +1925,37 @@ if (mem->indent_level) printf("%s", mem->indent_str); } + +const char *proto_n2a(unsigned short id, char *buf, int len, + const struct proto *proto_tb, size_t tb_len) +{ + int i; + + id = ntohs(id); + + for (i = 0; !numeric && i < tb_len; i++) { + if (proto_tbi.id == id) + return proto_tbi.name; + } + + snprintf(buf, len, "%d", id); + + return buf; +} + +int proto_a2n(unsigned short *id, const char *buf, + const struct proto *proto_tb, size_t tb_len) +{ + int i; + + for (i = 0; i < tb_len; i++) { + if (strcasecmp(proto_tbi.name, buf) == 0) { + *id = htons(proto_tbi.id); + return 0; + } + } + if (get_be16(id, buf, 0)) + return -1; + + return 0; +}
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/bridge.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/bridge.8
Changed
@@ -13,7 +13,7 @@ .ti -8 .IR OBJECT " := { " -.BR link " | " fdb " | " mdb " | " vlan " | " monitor " }" +.BR link " | " fdb " | " mdb " | " vlan " | " vni " | " monitor " }" .sp .ti -8 @@ -45,11 +45,15 @@ .BR learning_sync " { " on " | " off " } " .BR flood " { " on " | " off " } " .BR hwmode " { " vepa " | " veb " } " +.BR bcast_flood " { " on " | " off " } " .BR mcast_flood " { " on " | " off " } " +.BR mcast_router +.IR MULTICAST_ROUTER " " .BR mcast_to_unicast " { " on " | " off " } " .BR neigh_suppress " { " on " | " off " } " .BR vlan_tunnel " { " on " | " off " } " .BR isolated " { " on " | " off " } " +.BR locked " { " on " | " off " } " .B backup_port .IR DEVICE " " .BR nobackup_port " " @@ -109,6 +113,19 @@ .BR self " " master " " dynamic " " .ti -8 +.BR "bridge fdb flush" +.B dev +.IR DEV " " +.B brport +.IR DEV " " +.B vlan +.IR VID " " +.BR self " " master " " +.BR nopermanent " | " nostatic " | " nodynamic " " +.BR noadded_by_user " " noextern_learn " " +.BR nosticky " " nooffloaded " " + +.ti -8 .BR "bridge mdb" " { " add " | " del " } " .B dev .I DEV @@ -123,7 +140,7 @@ .IR VID " " .ti -8 -.BR "bridge mdb show " " +.BR "bridge mdb show" " " .B dev .IR DEV " " @@ -145,7 +162,9 @@ .B vid .IR VID " " .B state -.IR STP_STATE " " +.IR STP_STATE " " +.B mcast_router +.IR MULTICAST_ROUTER " " .ti -8 .BR "bridge vlan" " " show " | " tunnelshow " " @@ -153,6 +172,63 @@ .IR DEV " " .ti -8 +.BR "bridge vlan global set" +.B dev +.I DEV +.B vid +.IR VID " " +.B mcast_snooping +.IR MULTICAST_SNOOPING " " +.B mcast_querier +.IR MULTICAST_QUERIER " " +.B mcast_igmp_version +.IR IGMP_VERSION " " +.B mcast_mld_version +.IR MLD_VERSION " " +.B mcast_last_member_count +.IR LAST_MEMBER_COUNT " " +.B mcast_last_member_interval +.IR LAST_MEMBER_INTERVAL " " +.B mcast_startup_query_count +.IR STARTUP_QUERY_COUNT " " +.B mcast_startup_query_interval +.IR STARTUP_QUERY_INTERVAL " " +.B mcast_membership_interval +.IR MEMBERSHIP_INTERVAL " " +.B mcast_querier_interval +.IR QUERIER_INTERVAL " " +.B mcast_query_interval +.IR QUERY_INTERVAL " " +.B mcast_query_response_interval +.IR QUERY_RESPONSE_INTERVAL " " + +.ti -8 +.BR "bridge vlan global" " " show " " +.B dev +.IR DEV " " +.B vid +.IR VID " " + +.ti -8 +.BR "bridge vlan" " show " " +.B dev +.IR DEV " " + +.ti -8 +.BR "bridge vni" " { " add " | " del " } " +.B dev +.I DEV +.B vni +.IR VNI " { " +.B group | remote "} " +.IR IPADDR " " + +.ti -8 +.BR "bridge vni" " show " " +.B dev +.IR DEV " " + +.ti -8 .BR "bridge monitor" " " all " | " neigh " | " link " | " mdb " | " vlan " " .SH OPTIONS @@ -259,6 +335,10 @@ .B vlan - VLAN filter list. +.TP +.B vni +- VNI filter list. + .SS .I COMMAND @@ -422,11 +502,29 @@ - bridging happens in hardware. .TP +.BR "bcast_flood on " or " bcast_flood off " +Controls flooding of broadcast traffic on the given port. +By default this flag is on. + +.TP .BR "mcast_flood on " or " mcast_flood off " Controls whether multicast traffic for which there is no MDB entry will be flooded towards this given port. By default this flag is on. .TP +.BI mcast_router " MULTICAST_ROUTER " +This flag is almost the same as the per-VLAN flag, see below, except its +value can only be set in the range 0-2. The default is +.B 1 +where the bridge figures out automatically where an IGMP/MLD querier, +MRDISC capable device, or PIM router, is located. Setting this flag to +.B 2 +is useful in cases where the multicast router does not indicate its +presence in any meaningful way (e.g. older versions of SMCRoute, or +mrouted), or when there is a need for forwarding both known and unknown +IP multicast to a secondary/backup router. + +.TP .BR "mcast_to_unicast on " or " mcast_to_unicast off " Controls whether a given port will replicate packets using unicast instead of multicast. By default this flag is off. @@ -474,6 +572,16 @@ flag is off. .TP +.BR "locked on " or " locked off " +Controls whether a port will be locked, meaning that hosts behind the +port will not be able to communicate through the port unless an FDB +entry with the units MAC address is in the FDB. +The common use is that hosts are allowed access through authentication +with the IEEE 802.1X protocol or based on whitelists or like setups. +By default this flag is off. + + +.TP .BI backup_port " DEVICE" If the port loses carrier all traffic will be redirected to the configured backup port @@ -687,6 +795,76 @@ .TP .B master - the address is associated with master devices fdb. Usually software (default). + +.SS bridge fdb flush - flush bridge forwarding table entries. + +flush the matching bridge forwarding table entries. Some options below have a negated +form when "no" is prepended to them (e.g. permanent and nopermanent). + +.TP +.BI dev " DEV" +the target device for the operation. If the device is a bridge port and "master" +is set then the operation will be fulfilled by its master device's driver and +all entries pointing to that port will be deleted. + +.TP +.BI brport " DEV" +the target bridge port for the operation. If the bridge device is specified then only +entries pointing to the bridge itself will be deleted. Note that the target device +specified by this option will override the one specified by dev above. + +.TP +.BI vlan " VID" +the target VLAN ID for the operation. Match forwarding table entries only with the +specified VLAN ID. + +.TP +.B self +the operation is fulfilled directly by the driver for the specified network +device. If the network device belongs to a master like a bridge, then the +bridge is bypassed and not notified of this operation. The "bridge fdb flush" +command can also be used on the bridge device itself. The flag is set by default if +"master" is not specified. + +.TP +.B master +if the specified network device is a port that belongs to a master device +such as a bridge, the operation is fulfilled by the master device's driver. + +.TP +.B nopermanent +if specified then only permanent entries will be deleted or respectively if "no" +is prepended then only non-permanent entries will be deleted. + +.TP +.B nostatic +if specified then only static entries will be deleted or respectively if "no" +is prepended then only non-static entries will be deleted. + +.TP +.B nodynamic +if specified then only dynamic entries will be deleted or respectively if "no" +is prepended then only non-dynamic (static or permanent) entries will be deleted. + +.TP +.B noadded_by_user +if specified then only entries with added_by_user flag will be deleted or respectively +if "no" is prepended then only entries without added_by_user flag will be deleted. + +.TP +.B noextern_learn +if specified then only entries with extern_learn flag will be deleted or respectively +if "no" is prepended then only entries without extern_learn flag will be deleted. + +.TP +.B nosticky +if specified then only entries with sticky flag will be deleted or respectively +if "no" is prepended then only entries without sticky flag will be deleted. + +.TP +.B nooffloaded +if specified then only entries with offloaded flag will be deleted or respectively +if "no" is prepended then only entries without offloaded flag will be deleted. .sp .SH bridge mdb - multicast group database management @@ -877,6 +1055,31 @@ STP BPDUs. .sp +.TP +.BI mcast_router " MULTICAST_ROUTER " +configure this vlan and interface's multicast router mode, note that only modes +0 - 2 are available for bridge devices. +A vlan and interface with a multicast router will receive all multicast traffic. +.I MULTICAST_ROUTER +may be either +.sp +.B 0 +- to disable multicast router. +.sp + +.B 1 +- to let the system detect the presence of routers (default). +.sp + +.B 2 +- to permanently enable multicast traffic forwarding on this vlan and interface. +.sp + +.B 3 +- to temporarily mark this vlan and port as having a multicast router, i.e. +enable multicast traffic forwarding. This mode is available only for ports. +.sp + .SS bridge vlan show - list vlan configuration. This command displays the current VLAN filter table. @@ -895,6 +1098,150 @@ This command displays the current vlan tunnel info mapping. +.SS bridge vlan global set - change vlan filter entry's global options + +This command changes vlan filter entry's global options. + +.TP +.BI dev " NAME" +the interface with which this vlan is associated. Only bridge devices are +supported for global options. + +.TP +.BI vid " VID" +the VLAN ID that identifies the vlan. + +.TP +.BI mcast_snooping " MULTICAST_SNOOPING " +turn multicast snooping for VLAN entry with VLAN ID on +.RI ( MULTICAST_SNOOPING " > 0) " +or off +.RI ( MULTICAST_SNOOPING " == 0). Default is on. " + +.TP +.BI mcast_querier " MULTICAST_QUERIER " +enable +.RI ( MULTICAST_QUERIER " > 0) " +or disable +.RI ( MULTICAST_QUERIER " == 0) " +IGMP/MLD querier, ie sending of multicast queries by the bridge. Default is disabled. + +.TP +.BI mcast_igmp_version " IGMP_VERSION " +set the IGMP version. Default is 2. + +.TP +.BI mcast_mld_version " MLD_VERSION " +set the MLD version. Default is 1. + +.TP +.BI mcast_last_member_count " LAST_MEMBER_COUNT " +set multicast last member count, ie the number of queries the bridge +will send before stopping forwarding a multicast group after a "leave" +message has been received. Default is 2. + +.TP +.BI mcast_last_member_interval " LAST_MEMBER_INTERVAL " +interval between queries to find remaining members of a group, +after a "leave" message is received. + +.TP +.BI mcast_startup_query_count " STARTUP_QUERY_COUNT " +set the number of queries to send during startup phase. Default is 2. + +.TP +.BI mcast_startup_query_interval " STARTUP_QUERY_INTERVAL " +interval between queries in the startup phase. + +.TP +.BI mcast_membership_interval " MEMBERSHIP_INTERVAL " +delay after which the bridge will leave a group, +if no membership reports for this group are received. + +.TP +.BI mcast_querier_interval " QUERIER_INTERVAL " +interval between queries sent by other routers. If no queries are seen +after this delay has passed, the bridge will start to send its own queries +(as if +.BI mcast_querier +was enabled). + +.TP +.BI mcast_query_interval " QUERY_INTERVAL " +interval between queries sent by the bridge after the end of the +startup phase. + +.TP +.BI mcast_query_response_interval " QUERY_RESPONSE_INTERVAL " +set the Max Response Time/Maximum Response Delay for IGMP/MLD +queries sent by the bridge. + +.SS bridge vlan global show - list global vlan options. + +This command displays the global VLAN options for each VLAN entry. + +.TP +.BI dev " DEV" +the interface only whose VLAN global options should be listed. Default is to list +all bridge interfaces. + +.TP +.BI vid " VID" +the VLAN ID only whose global options should be listed. Default is to list +all vlans. + +.SH bridge vni - VNI filter list + +.B vni +objects contain known VNI IDs for a dst metadata vxlan link. + +.P +The corresponding commands display vni filter entries, add new entries, +and delete old ones. + +.SS bridge vni add - add a new vni filter entry + +This command creates a new vni filter entry. + +.TP +.BI dev " NAME" +the interface with which this vni is associated. + +.TP +.BI vni " VNI" +the VNI ID that identifies the vni. + +.TP +.BI remote " IPADDR" +specifies the unicast destination IP address to use in outgoing packets +when the destination link layer address is not known in the VXLAN device +forwarding database. This parameter cannot be specified with the group. + +.TP +.BI group " IPADDR" +specifies the multicast IP address to join for this VNI + +.SS bridge vni del - delete a new vni filter entry + +This command removes an existing vni filter entry. + +.PP +The arguments are the same as with +.BR "bridge vni add". + +.SS bridge vni show - list vni filtering configuration. + +This command displays the current vni filter table. + +.PP +With the +.B -statistics +option, the command displays per-vni traffic statistics. + +.TP +.BI dev " NAME" +shows vni filtering table associated with the vxlan device + .SH bridge monitor - state monitoring The
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/dcb-app.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/dcb-app.8
Changed
@@ -170,7 +170,7 @@ \fIDSCP-MAP\fR uses the array parameter syntax, see .BR dcb (8) for details. Keys are DSCP points, values are priorities assigned to -traffic with matching DSCP. DSCP points can be written either direcly as +traffic with matching DSCP. DSCP points can be written either directly as numeric values, or using symbolic names specified in .B /etc/iproute2/rt_dsfield (however note that that file specifies full 8-bit dsfield values, whereas
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/dcb-dcbx.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/dcb-dcbx.8
Changed
@@ -67,7 +67,7 @@ .B cee .TQ .B ieee -The device supports CEE (Converged Enhanced Ethernet) and, respecively, IEEE +The device supports CEE (Converged Enhanced Ethernet) and, respectively, IEEE version of the DCB specification. Typically only one of these will be set, but .B dcb dcbx does not mandate this.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/devlink-dev.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/devlink-dev.8
Changed
@@ -85,6 +85,20 @@ .I ID +.ti -8 +.B devlink dev selftests show + +.I DEV + + +.ti -8 +.B devlink dev selftests run +.I DEV + +.B id +.I ID... + + .SH "DESCRIPTION" .SS devlink dev show - display devlink device attributes @@ -199,7 +213,7 @@ .B limit no_reset - Specifies limitation on reload action. -If this argument is omitted limit is unspecificed and the reload action is not +If this argument is omitted limit is unspecified and the reload action is not limited. In such case driver implementation may include reset or downtime as needed to perform the actions. @@ -236,7 +250,7 @@ .B file .I PATH - Path to the file which will be written into device's flash. The path needs -to be relative to one of the directories searched by the kernel firmware loaded, +to be relative to one of the directories searched by the kernel firmware loader, such as /lib/firmware. .B component @@ -249,6 +263,28 @@ .B "devlink dev info" and may be driver-dependent. +.SS devlink dev selftests show - shows supported selftests on devlink device. + +.PP +.I "DEV" +- specifies the devlink device. +If this argument is omitted all selftests for devlink devices are listed. + +.SS devlink dev selftests run - runs selftests on devlink device. + +.PP +.I "DEV" +- specifies the devlink device to execute selftests. + +.B id +.I ID... +- The value of +.I ID(s) +should match the selftests shown in +.B "devlink dev selftests show" +to execute selftests on the devlink device. +If this argument is omitted all selftests supported by devlink devices are executed. + .SH "EXAMPLES" .PP devlink dev show @@ -296,6 +332,16 @@ .br Flashing done .RE +.PP +devlink dev selftests show pci/0000:01:00.0 +.RS 4 +Shows the supported selftests by the devlink device. +.RE +.PP +devlink dev selftests run pci/0000:01:00.0 id flash +.RS 4 +Perform a flash test on the devlink device. +.RE .SH SEE ALSO .BR devlink (8),
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/devlink-lc.8
Added
@@ -0,0 +1,101 @@ +.TH DEVLINK\-LC 8 "20 Apr 2022" "iproute2" "Linux" +.SH NAME +devlink-lc \- devlink line card configuration +.SH SYNOPSIS +.sp +.ad l +.in +8 +.ti -8 +.B devlink +.RI " " OPTIONS " " +.B lc +.RI " { " COMMAND " | " +.BR help " }" +.sp + +.ti -8 +.IR OPTIONS " := { " +\fB\-V\fR\fIersion\fR } + +.ti -8 +.B "devlink lc set" +.IB DEV " lc " LC_INDEX +.RB " type " { +.IR LC_TYPE " | " +.BR notype " } " + +.ti -8 +.B "devlink lc show" +.RI " " DEV " " +.BI lc " LC_INDEX + + +.ti -8 +.B devlink lc help + +.SH "DESCRIPTION" +.SS devlink lc set - change line card attributes + +.PP +.TP +.I "DEV" +Specifies the devlink device to operate on. + +.in +4 +Format is: +.in +2 +BUS_NAME/BUS_ADDRESS + +.TP +.BI lc " LC_INDEX " +Specifies index of a line card slot to set. + +.TP +.BR type " { " +.IR LC_TYPE " | " +.BR notype " } " +Type of line card to provision. Each driver provides a list of supported line card types which is shown in the output of +.BR "devlink lc show " command. + +.SS devlink lc show - display line card attributes + +.PP +.TP +.I "DEV" +.RB "Specifies the devlink device to operate on. If this and " lc " arguments are omitted all line cards of all devices are listed. + +.TP +.BI lc " LC_INDEX " +Specifies index of a line card slot to show. + +.SH "EXAMPLES" +.PP +devlink lc show +.RS 4 +Shows the state of all line cards on the system. +.RE +.PP +devlink lc show pci/0000:01:00.0 lc 1 +.RS 4 +Shows the state of line card with index 1. +.RE +.PP +devlink lc set pci/0000:01:00.0 lc 1 type 16x100G +.RS 4 +.RI "Sets type of specified line card to type " 16x100G "." +.RE +.PP +devlink lc set pci/0000:01:00.0 lc 1 notype +.RS 4 +Clears provisioning on a line card. +.RE + +.SH SEE ALSO +.BR devlink (8), +.BR devlink-dev (8), +.BR devlink-port (8), +.BR devlink-monitor (8), +.br + +.SH AUTHOR +Jiri Pirko <jiri@nvidia.com>
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/devlink-rate.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/devlink-rate.8
Changed
@@ -63,7 +63,7 @@ parent node name. Rate values printed in SI units which are more suitable to represent specific value. To print values in IEC units \fB-i\fR switch is used. JSON (\fB-j\fR) output always print rate values in bytes per second. Zero -rate values means "unlimited" rates and ommited in output, as well as parent +rate values means "unlimited" rates and omitted in output, as well as parent node name. .SS devlink port function rate set - set rate object parameters.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/devlink-region.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/devlink-region.8
Changed
@@ -23,6 +23,14 @@ .RI " " DEV/REGION " " .ti -8 +.BR "devlink region new" +.RI "" DEV/REGION "" +.BR " " +.BR "snapshot" +.RI "" SNAPSHOT_ID "" +.BR "" + +.ti -8 .BR "devlink region del" .RI "" DEV/REGION "" .BR "snapshot" @@ -56,6 +64,17 @@ .I "DEV/REGION" - specifies the devlink device and address-region to query. +.SS devlink region new - Create a snapshot specified by address-region name and snapshot ID + +.PP +.I "DEV/REGION" +- specifies the devlink device and address-region to snapshot + +.PP +snapshot +.I "SNAPSHOT_ID" +- optionally specifies the snapshot ID to assign. If not specified, devlink will assign a unique ID to the snapshot. + .SS devlink region del - Delete a snapshot specified by address-region name and snapshot ID .PP @@ -106,6 +125,11 @@ List available address regions and snapshot. .RE .PP +devlink region new pci/0000:00:05.0/cr-space +.RS 4 +Create a new snapshot from cr-space address region from device pci/0000:00:05.0. +.RE +.PP devlink region del pci/0000:00:05.0/cr-space snapshot 1 .RS 4 Delete snapshot id 1 from cr-space address region from device pci/0000:00:05.0. @@ -116,7 +140,7 @@ Dump the snapshot taken from cr-space address region with ID 1 .RE .PP -devlink region read pci/0000:00:05.0/cr-space snapshot 1 address 0x10 legth 16 +devlink region read pci/0000:00:05.0/cr-space snapshot 1 address 0x10 length 16 .RS 4 Read from address 0x10, 16 Bytes of snapshot ID 1 taken from cr-space address region .RE
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/devlink.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/devlink.8
Changed
@@ -63,6 +63,10 @@ .BR "\-i", " --iec" Print human readable rates in IEC units (e.g. 1Ki = 1024). +.TP +.BR "\-x", " --hex" +Print dump numbers in hexadecimal format. + .SS .I OBJECT
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-address.8.in -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-address.8.in
Changed
@@ -49,7 +49,8 @@ .IR TYPE " " .B vrf .IR NAME " " -.BR up " " +.BR up " " +.BR nomaster " " .ti -8 .BR "ip address" " { " showdump " | " restore " }" @@ -92,7 +93,7 @@ .ti -8 .IR CONFFLAG " := " -.RB " " home " | " mngtmpaddr " | " nodad " | " optimstic " | " noprefixroute " | " autojoin " " +.RB " " home " | " mngtmpaddr " | " nodad " | " optimistic " | " noprefixroute " | " autojoin " " .ti -8 .IR LIFETIME " := " @@ -194,9 +195,6 @@ .TP .BI label " LABEL" Each address may be tagged with a label string. -In order to preserve compatibility with Linux-2.0 net aliases, -this string must coincide with the name of the device or must be prefixed -with the device name followed by colon. The maximum allowed total length of label is 15 characters. .TP @@ -341,6 +339,10 @@ only list running interfaces. .TP +.B nomaster +only list interfaces with no master. + +.TP .BR dynamic " and " permanent (IPv6 only) only list addresses installed due to stateless address configuration or only list permanent (not dynamic)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-link.8.in -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-link.8.in
Changed
@@ -36,11 +36,16 @@ .RB " " numrxqueues .IR QUEUE_COUNT " " .br -.BR " " gso_max_size +.RB " " gso_max_size .IR BYTES " " .RB " " gso_max_segs .IR SEGMENTS " " .br +.RB " " gro_max_size +.IR BYTES " " +.RB " " netns " {" +.IR PID " | " NETNSNAME " } " +.br .BI type " TYPE" .RI " " ARGS " " @@ -83,6 +88,13 @@ .RB " " txqueuelen .IR PACKETS " " .br +.RB " " max_gso_size +.IR BYTES " " +.RB " " max_gso_segs +.IR SEGMENTS " " +.RB " " max_gro_size +.IR BYTES " " +.br .RB " " name .IR NEWNAME " " .br @@ -139,7 +151,7 @@ .in +8 .BR object .IR FILE -.RB " " section +.RB " { " section " | " program " } " .IR NAME " " .RB " " verbose " |" .br @@ -179,7 +191,8 @@ .B type .IR ETYPE " " .B vrf -.IR NAME " " +.IR NAME " " +.BR nomaster " " .ti -8 .B ip link xstats @@ -197,40 +210,44 @@ .ti -8 .IR TYPE " := " -.BR bridge " | " +.BR amt " | " +.BR bareudp " |" .BR bond " | " +.BR bridge " | " .BR can " | " +.BR dsa " | " .BR dummy " | " -.BR hsr " | " -.BR ifb " | " -.BR ipoib " |" -.BR macvlan " | " -.BR macvtap " | " -.BR vcan " | " -.BR vxcan " | " -.BR veth " | " -.BR vlan " | " -.BR vxlan " |" -.BR ip6tnl " |" -.BR ipip " |" -.BR sit " |" +.BR erspan " |" +.BR geneve " |" .BR gre " |" .BR gretap " |" -.BR erspan " |" +.BR gtp " |" +.BR hsr " | " +.BR ifb " | " +.BR ip6erspan " |" .BR ip6gre " |" .BR ip6gretap " |" -.BR ip6erspan " |" -.BR vti " |" -.BR nlmon " |" +.BR ip6tnl " |" +.BR ipip " |" +.BR ipoib " |" .BR ipvlan " |" .BR ipvtap " |" .BR lowpan " |" -.BR geneve " |" -.BR bareudp " |" -.BR vrf " |" .BR macsec " |" +.BR macvlan " | " +.BR macvtap " | " .BR netdevsim " |" +.BR nlmon " |" .BR rmnet " |" +.BR sit " |" +.BR vcan " | " +.BR veth " | " +.BR virt_wifi " |" +.BR vlan " | " +.BR vrf " |" +.BR vti " |" +.BR vxcan " | " +.BR vxlan " |" .BR xfrm " " .ti -8 @@ -276,44 +293,55 @@ Link types: .in +8 -.B bridge -- Ethernet Bridge device +.BR amt +- Automatic Multicast Tunneling (AMT) +.sp +.BR bareudp +- Bare UDP L3 encapsulation support .sp .B bond - Bonding device +.B bridge +- Ethernet Bridge device +.sp +.B can +- Controller Area Network +.sp +.B dsa +- Distributed Switch Architecture .sp .B dummy - Dummy network interface .sp -.B hsr -- High-availability Seamless Redundancy device +.BR erspan +- Encapsulated Remote SPAN over GRE and IPv4 .sp -.B ifb -- Intermediate Functional Block device +.B geneve +- GEneric NEtwork Virtualization Encapsulation .sp -.B ipoib -- IP over Infiniband device +.B gre +- Virtual tunnel interface GRE over IPv4 .sp -.B macvlan -- Virtual interface base on link layer address (MAC) +.BR gretap +- Virtual L2 tunnel interface GRE over IPv4 .sp -.B macvtap -- Virtual interface based on link layer address (MAC) and TAP. +.BR gtp +- GPRS Tunneling Protocol .sp -.B vcan -- Virtual Controller Area Network interface +.B hsr +- High-availability Seamless Redundancy device .sp -.B vxcan -- Virtual Controller Area Network tunnel interface +.B ifb +- Intermediate Functional Block device .sp -.B veth -- Virtual ethernet interface +.BR ip6erspan +- Encapsulated Remote SPAN over GRE and IPv6 .sp -.BR vlan -- 802.1q tagged virtual LAN interface +.BR ip6gre +- Virtual tunnel interface GRE over IPv6 .sp -.BR vxlan -- Virtual eXtended LAN +.BR ip6gretap +- Virtual L2 tunnel interface GRE over IPv6 .sp .BR ip6tnl - Virtual tunnel interface IPv4|IPv6 over IPv6 @@ -321,62 +349,66 @@ .BR ipip - Virtual tunnel interface IPv4 over IPv4 .sp -.BR sit -- Virtual tunnel interface IPv6 over IPv4 +.B ipoib +- IP over Infiniband device .sp -.BR gre -- Virtual tunnel interface GRE over IPv4 +.BR ipvlan +- Interface for L3 (IPv6/IPv4) based VLANs .sp -.BR gretap -- Virtual L2 tunnel interface GRE over IPv4 +.BR ipvtap +- Interface for L3 (IPv6/IPv4) based VLANs and TAP .sp -.BR erspan -- Encapsulated Remote SPAN over GRE and IPv4 +.BR lowpan +- Interface for 6LoWPAN (IPv6) over IEEE 802.15.4 / Bluetooth .sp -.BR ip6gre -- Virtual tunnel interface GRE over IPv6 +.BR macsec +- Interface for IEEE 802.1AE MAC Security (MACsec) .sp -.BR ip6gretap -- Virtual L2 tunnel interface GRE over IPv6 +.B macvlan +- Virtual interface base on link layer address (MAC) .sp -.BR ip6erspan -- Encapsulated Remote SPAN over GRE and IPv6 +.B macvtap +- Virtual interface based on link layer address (MAC) and TAP. .sp -.BR vti -- Virtual tunnel interface +.BR netdevsim +- Interface for netdev API tests .sp .BR nlmon - Netlink monitoring device .sp -.BR ipvlan -- Interface for L3 (IPv6/IPv4) based VLANs +.BR rmnet +- Qualcomm rmnet device .sp -.BR ipvtap -- Interface for L3 (IPv6/IPv4) based VLANs and TAP +.BR sit +- Virtual tunnel interface IPv6 over IPv4 .sp -.BR lowpan -- Interface for 6LoWPAN (IPv6) over IEEE 802.15.4 / Bluetooth +.B vcan +- Virtual Controller Area Network interface .sp -.BR geneve -- GEneric NEtwork Virtualization Encapsulation +.B veth +- Virtual ethernet interface .sp -.BR bareudp -- Bare UDP L3 encapsulation support +.BR virt_wifi +- rtnetlink wifi simulation device .sp -.BR macsec -- Interface for IEEE 802.1AE MAC Security (MACsec) +.BR vlan +- 802.1q tagged virtual LAN interface .sp .BR vrf - Interface for L3 VRF domains .sp -.BR netdevsim -- Interface for netdev API tests +.BR vti +- Virtual tunnel interface .sp -.BR rmnet -- Qualcomm rmnet device +.B vxcan +- Virtual Controller Area Network tunnel interface +.sp +.BR vxlan +- Virtual eXtended LAN .sp .BR xfrm - Virtual xfrm interface +.sp .in -8 .TP @@ -398,11 +430,20 @@ segments the new device should accept. .TP +.BI gro_max_size " BYTES " +specifies the maximum size of a packet built by GRO stack +on this device. + +.TP .BI index " IDX " specifies the desired index of the new virtual device. The link creation fails, if the index is busy. .TP +.BI netns " { PID | NAME } " +specifies the desired network namespace to create interface in. + +.TP VLAN Type Support For a link of type .I VLAN @@ -457,7 +498,7 @@ passing to the physical device (if this device does not support VLAN offloading), the similar on the RX direction - by default the packet will be untagged before being received by VLAN device. Reordering -allows to accelerate tagging on egress and to hide VLAN header on +allows one to accelerate tagging on egress and to hide VLAN header on ingress so the packet looks like regular Ethernet packet, at the same time it might be confusing for packet capture as the VLAN header does not exist within the packet. @@ -476,11 +517,11 @@ .BR gvrp " { " on " | " off " } " - specifies whether this VLAN should be registered using GARP VLAN - Registration Protocol. +Registration Protocol. .BR mvrp " { " on " | " off " } " - specifies whether this VLAN should be registered using Multiple VLAN - Registration Protocol. +Registration Protocol. .BR loose_binding " { " on " | " off " } " - specifies whether the VLAN device state is bound to the physical device state. @@ -570,6 +611,8 @@ .B gbp .B gpe + +.RB no vnifilter .in +8 @@ -682,11 +725,18 @@ or the internal FDB should be used. .sp +.RB no vnifilter +- specifies whether the vxlan device is capable of vni filtering. Only works with a vxlan +device with external flag set. once enabled, bridge vni command is used to manage the +vni filtering table on the device. The device can only receive packets with vni's configured +in the vni filtering table. + +.sp .B gbp - enables the Group Policy extension (VXLAN-GBP). .in +4 -Allows to transport group policy context across VXLAN network peers. +Allows one to transport group policy context across VXLAN network peers. If enabled, includes the mark of a packet in the VXLAN header for outgoing packets and fills the packet mark based on the information found in the VXLAN header for incoming packets. @@ -1235,6 +1285,8 @@ .RB no udp6zerocsumtx .RB no udp6zerocsumrx + +.B innerprotoinherit .in +8 @@ -1298,6 +1350,10 @@ .RB no udp6zerocsumrx - allow incoming UDP packets over IPv6 with zero checksum field. +.sp +.B innerprotoinherit +- use IPv4/IPv6 as inner protocol instead of Ethernet. + .in -8 .TP @@ -1344,6 +1400,48 @@ by default. .TP +AMT Type Support +For a link of type +.I AMT +the following additional arguments are supported: + +.BI "ip link add " DEVICE +.BI type " AMT " discovery " IPADDR " mode " { " gateway " | " relay " } " +.BI local " IPADDR " dev " PHYS_DEV " +.BI relay_port " PORT " + +.BI gateway_port " PORT " + +.BI max_tunnels " NUMBER " + + +.in +8 +.sp +.BI discovery " IPADDR" +- specifies the unicast discovery IP address to use to find remote IP address. + +.BR mode " { " gateway " | " relay " } " +- specifies the role of AMT, Gateway or Relay + +.BI local " IPADDR " +- specifies the source IP address to use in outgoing packets. + +.BI dev " PHYS_DEV " +- specifies the underlying physical interface from which transform traffic +is sent and received. + +.BI relay_port " PORT " +- specifies the UDP Relay port to communicate to the Relay. + +.BI gateway_port " PORT " +- specifies the UDP Gateway port to communicate to the Gateway. + +.BI max_tunnels " NUMBER " +- specifies the maximum number of tunnels. + +.in -8 + +.TP MACVLAN and MACVTAP Type Support For a link of type .I MACVLAN @@ -1480,6 +1578,8 @@ .BI priority " PRIORITY " +.BI no_linklocal_learn " NO_LINKLOCAL_LEARN " + .BI vlan_filtering " VLAN_FILTERING " .BI vlan_protocol " VLAN_PROTOCOL " @@ -1492,6 +1592,8 @@ .BI mcast_snooping " MULTICAST_SNOOPING " +.BI mcast_vlan_snooping " MULTICAST_VLAN_SNOOPING " + .BI mcast_router " MULTICAST_ROUTER " .BI mcast_query_use_ifaddr " MCAST_QUERY_USE_IFADDR " @@ -1581,6 +1683,14 @@ .I PRIORITY is a 16bit unsigned integer. +.BI no_linklocal_learn " NO_LINKLOCAL_LEARN " +- turn link-local learning on +.RI ( NO_LINKLOCAL_LEARN " == 0) " +or off +.RI ( NO_LINKLOCAL_LEARN " > 0). " +When disabled, the bridge will not learn from link-local frames (default: +enabled). + .BI vlan_filtering " VLAN_FILTERING " - turn VLAN filtering on .RI ( VLAN_FILTERING " > 0) " @@ -1614,6 +1724,12 @@ or off .RI ( MULTICAST_SNOOPING " == 0). " +.BI mcast_vlan_snooping " MULTICAST_VLAN_SNOOPING " +- turn multicast VLAN snooping on +.RI ( MULTICAST_VLAN_SNOOPING " > 0) " +or off +.RI ( MULTICAST_VLAN_SNOOPING " == 0). " + .BI mcast_router " MULTICAST_ROUTER " - set bridge's multicast router if IGMP snooping is enabled. .I MULTICAST_ROUTER @@ -1857,6 +1973,7 @@ the following additional arguments are supported: .BI "ip link add " DEVICE " type xfrm dev " PHYS_DEV " if_id " IF_ID " " +.BR " external " .in +8 .sp @@ -1869,6 +1986,35 @@ policies. Policies must be configured with the same key. If not set, the key defaults to 0 and will match any policies which similarly do not have a lookup key configuration. +.sp +.BI external +- make this device externally controlled. This flag is mutually exclusive with the +.BR dev " and " if_id +options. + +.in -8 + +.TP +GTP Type Support +For a link of type +.I GTP +the following additional arguments are supported: + +.BI "ip link add " DEVICE " type gtp role " ROLE " hsize " HSIZE + +.in +8 +.sp +.BI role " ROLE " +- specifies the role of the GTP device, either sgsn or ggsn + +.sp +.BI hsize " HSIZE " +- specifies size of the hashtable which stores PDP contexts + +.sp +.BI restart_count " RESTART_COUNT " +- GTP instance restart counter + .in -8 .SS ip link delete - delete virtual link @@ -2038,7 +2184,7 @@ To change network namespace for wireless devices the .B iw -tool can be used. But it allows to change network namespace only for +tool can be used. But it allows one to change network namespace only for physical devices and by process .IR PID . @@ -2134,9 +2280,9 @@ .sp .BI query_rss " on|off" - toggle the ability of querying the RSS configuration of a specific - VF. VF RSS information like RSS hash key may be considered sensitive - on some devices where this information is shared between VF and PF - and thus its querying may be prohibited by default. +VF. VF RSS information like RSS hash key may be considered sensitive +on some devices where this information is shared between VF and PF +and thus its querying may be prohibited by default. .sp .BI state " auto|enable|disable" - set the virtual link state as seen by the specified VF. Setting to @@ -2223,6 +2369,13 @@ .B object option. +.BI program " NAME " +- Specifies the BPF program name that need to be attached. When the program +name is specified, the section name parameter will be ignored. This option +only works when iproute2 build with +.B libbpf +support. + .BI verbose - Act in verbose mode. For example, even in case of success, this will print the verifier log in case a program was loaded from a BPF ELF file. @@ -2309,6 +2462,8 @@ .BR mcast_fast_leave " { " on " | " off "}" +.BR bcast_flood " { " on " | " off " }" + .BR mcast_flood " { " on " | " off " }" .BR mcast_to_unicast " { " on " | " off " }" @@ -2321,6 +2476,7 @@ .BR isolated " { " on " | " off " }" +.BR locked " { " on " | " off " }" .BR backup_port " DEVICE" .BR nobackup_port " " @@ -2395,13 +2551,17 @@ .B fastleave option above. +.BR bcast_flood " { " on " | " off " }" +- controls flooding of broadcast traffic on the given port. By default +this flag is on. + .BR mcast_flood " { " on " | " off " }" - controls whether a given port will flood multicast traffic for which - there is no MDB entry. +there is no MDB entry. By default this flag is on. .BR mcast_to_unicast " { " on " | " off " }" - controls whether a given port will replicate packets using unicast - instead of multicast. By default this flag is off. +instead of multicast. By default this flag is off. .BI group_fwd_mask " MASK " - set the group forward mask. This is the bitmask that is applied to @@ -2418,6 +2578,11 @@ - controls whether vlan to tunnel mapping is enabled on the port. By default this flag is off. +.BR locked " { " on " | " off " }" +- sets or unsets a port in locked mode, so that when enabled, hosts +behind the port cannot communicate through the port unless a FDB entry +representing the host is in the FDB. By default this flag is off. + .BI backup_port " DEVICE" - if the port loses carrier all traffic will be redirected to the configured backup port @@ -2436,6 +2601,8 @@ .B "ip link set type bond_slave" .BI queue_id " ID" + +.BI prio " PRIORITY" .in +8 @@ -2443,6 +2610,12 @@ .BI queue_id " ID" - set the slave's queue ID (a 16bit unsigned value). +.sp +.BI prio " PRIORITY" +- set the slave's priority for active slave re-selection during failover +(a 32bit signed value). This option only valid for active-backup(1), +balance-tlb (5) and balance-alb (6) mode. + .in -8 .TP @@ -2491,6 +2664,32 @@ the user understand the setting. .in -8 +.TP +DSA user port support +For a link having the DSA user port type, the following additional arguments +are supported: + +.B "ip link set type dsa " + +.BI conduit " DEVICE" + + +.in +8 +.sp +.BI conduit " DEVICE" +- change the DSA conduit (host network interface) responsible for handling the +locally terminated traffic for the given DSA switch user port. For a +description of which network interfaces are suitable for serving as conduit +interfaces of this user port, please see +https://www.kernel.org/doc/html/latest/networking/dsa/configuration.html#affinity-of-user-ports-to-cpu-ports +as well as what is supported by the driver in use. + +.sp +.BI master " DEVICE" +- this is a synonym for "conduit". + +.in -8 + .SS ip link show - display device attributes .TP @@ -2528,6 +2727,10 @@ didn't filter already. Therefore any string is accepted, but may lead to empty output. +.TP +.B nomaster +only show devices with no master + .SS ip link xstats - display extended statistics .TP @@ -2643,6 +2846,11 @@ .RS 4 Creates a IP6ERSPAN version 2 interface named ip6erspan00. .RE +.PP +ip link set dev swp0 type dsa conduit eth1 +.RS 4 +Changes the conduit interface of the swp0 user port to eth1. +.RE .SH SEE ALSO .br
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-macsec.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-macsec.8
Changed
@@ -10,7 +10,7 @@ | .BI sci " <u64>" -.BR cipher " { " default " | " gcm-aes-128 " | "gcm-aes-256" } " +.BR cipher " { " default " | " gcm-aes-128 " | " gcm-aes-256 " | " gcm-aes-xpn-128 " | " gcm-aes-xpn-256 " } " .BI icvlen " ICVLEN" .BR encrypt " { " on " | " off " } " @@ -63,7 +63,13 @@ .IR OPTS " := " .BR pn " { " -.IR 1..2^32-1 " } " +.IR 1..2^32-1 " } |" +.BR xpn " { " +.IR 1..2^64-1 " } " +.B salt +.IR SALT " " +.B ssci +.IR <u32> " " .BR on " | " off " " .br .IR SCI " := { " @@ -75,6 +81,8 @@ } .br .IR PORT " := { " 1..2^16-1 " } " +.br +.IR SALT " := 96-bit hex string " .SH DESCRIPTION @@ -116,6 +124,29 @@ .nf # ip link add link eth0 macsec0 type macsec port 11 encrypt on offload mac +.SH EXTENDED PACKET NUMBER EXAMPLES +.PP +.SS Create a MACsec device on link eth0 with enabled extended packet number (offload is disabled by default) +.nf +# ip link add link eth0 macsec0 type macsec port 11 encrypt on cipher gcm-aes-xpn-128 +.PP +.SS Configure a secure association on that device +.nf +# ip macsec add macsec0 tx sa 0 xpn 1024 on salt 838383838383838383838383 ssci 123 key 01 81818181818181818181818181818181 +.PP +.SS Configure a receive channel +.nf +# ip macsec add macsec0 rx port 11 address c6:19:52:8f:e6:a0 +.PP +.SS Configure a receive association +.nf +# ip macsec add macsec0 rx port 11 address c6:19:52:8f:e6:a0 sa 0 xpn 1 on salt 838383838383838383838383 ssci 123 key 00 82828282828282828282828282828282 +.PP +.SS Display MACsec configuration +.nf +# ip macsec show +.PP + .SH NOTES This tool can be used to configure the 802.1AE keys of the interface. Note that 802.1AE uses GCM-AES with a initialization vector (IV) derived from the packet number. The same key must not be used @@ -125,6 +156,28 @@ indefinitely. The suggested and standardized way for key management is 802.1X-2010, which is implemented by wpa_supplicant. +.SH EXTENDED PACKET NUMBER NOTES +Passing cipher +.B gcm-aes-xpn-128 +or +.B gcm-aes-xpn-256 +to +.B ip link add +command using the +.I macsec +type requires using the keyword +.B 'xpn' +instead of +.B 'pn' +in addition to providing a salt using the +.B 'salt' +keyword and ssci using the +.B 'ssci' +keyword when using the +.B ip macsec +command. + + .SH SEE ALSO .br .BR ip-link (8)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-monitor.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-monitor.8
Changed
@@ -55,7 +55,7 @@ is the list of object types that we want to monitor. It may contain .BR link ", " address ", " route ", " mroute ", " prefix ", " -.BR neigh ", " netconf ", " rule ", " nsid " and " nexthop "." +.BR neigh ", " netconf ", " rule ", " stats ", " nsid " and " nexthop "." If no .B file argument is given,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-mptcp.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-mptcp.8
Changed
@@ -31,8 +31,21 @@ .RB " " .ti -8 -.BR "ip mptcp endpoint del id " +.BR "ip mptcp endpoint delete id " .I ID +.RB " " +.I IFADDR +.RB " " + +.ti -8 +.BR "ip mptcp endpoint change " +.RB " " id +.I ID +.RB " " +.IR IFADDR +.RB " " port +.IR PORT " " +.RB "CHANGE-OPT" .ti -8 .BR "ip mptcp endpoint show " @@ -53,6 +66,19 @@ .B subflow .RB "|" .B backup +.RB "|" +.B fullmesh +.RB "" + +.ti -8 +.IR CHANGE-OPT " := " +.B backup +.RB "|" +.B nobackup +.RB "|" +.B fullmesh +.RB "|" +.B nofullmesh .RB "" .ti -8 @@ -92,33 +118,63 @@ .TE .TP +.IR IFADDR +An IPv4 or IPv6 address. When used with the +.B delete id +operation, an +.B IFADDR +is only included when the +.B ID +is 0. + +.TP .IR PORT When a port number is specified, incoming MPTCP subflows for already established MPTCP sockets will be accepted on the specified port, regardless the original listener port accepting the first MPTCP subflow and/or this peer being actually on the client side. +.TP .IR ID is a unique numeric identifier for the given endpoint .TP .BR signal -the endpoint will be announced/signalled to each peer via an ADD_ADDR MPTCP -sub-option +The endpoint will be announced/signaled to each peer via an MPTCP ADD_ADDR +sub-option. Upon reception of an ADD_ADDR sub-option, the peer can try to +create additional subflows, see +.BR ADD_ADDR_ACCEPTED_NR. .TP .BR subflow -if additional subflow creation is allowed by MPTCP limits, the endpoint will -be used as the source address to create an additional subflow after that -the MPTCP connection is established. +If additional subflow creation is allowed by the MPTCP limits, the MPTCP +path manager will try to create an additional subflow using this endpoint +as the source address after the MPTCP connection is established. .TP .BR backup -the endpoint will be announced as a backup address, if this is a -.BR signal -endpoint, or the subflow will be created as a backup one if this is a +If this is a +.BR subflow +endpoint, the subflows created using this endpoint will have the backup +flag set during the connection process. This flag instructs the peer to +only send data on a given subflow when all non-backup subflows are +unavailable. This does not affect outgoing data, where subflow priority +is determined by the backup/non-backup flag received from the peer + +.TP +.BR fullmesh +If this is a +.BR subflow +endpoint and additional subflow creation is allowed by the MPTCP limits, +the MPTCP path manager will try to create an additional subflow for each +known peer address, using this endpoint as the source address. This will +occur after the MPTCP connection is established. If the peer did not +announce any additional addresses using the MPTCP ADD_ADDR sub-option, +this will behave the same as a plain .BR subflow -endpoint +endpoint. When the peer does announce addresses, each received ADD_ADDR +sub-option will trigger creation of an additional subflow to generate a +full mesh topology. .sp .PP @@ -136,17 +192,29 @@ .IR SUBFLOW_NR specifies the maximum number of additional subflows allowed for each MPTCP connection. Additional subflows can be created due to: incoming accepted -ADD_ADDR option, local +ADD_ADDR sub-option, local .BR subflow endpoints, additional subflows started by the peer. .TP .IR ADD_ADDR_ACCEPTED_NR -specifies the maximum number of ADD_ADDR suboptions accepted for each MPTCP -connection. The MPTCP path manager will try to create a new subflow for -each accepted ADD_ADDR option, respecting the +specifies the maximum number of incoming ADD_ADDR sub-options accepted for +each MPTCP connection. After receiving the specified number of ADD_ADDR +sub-options, any other incoming one will be ignored for the MPTCP connection +lifetime. When an ADD_ADDR sub-option is accepted and there are no local +.IR fullmesh +endpoints, the MPTCP path manager will try to create a new subflow using the +address in the ADD_ADDR sub-option as the destination address and a source +address determined using local routing resolution +When +.IR fullmesh +endpoints are available, the MPTCP path manager will try to create new subflows +using each +.IR fullmesh +endpoint as a source address and the peer's ADD_ADDR address as the destination. +In both cases the .IR SUBFLOW_NR -limit. +limit is enforced. .sp .PP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-neighbour.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-neighbour.8
Changed
@@ -25,6 +25,8 @@ .B dev .IR DEV " " .BR router " " +.BR use " " +.BR managed " " .BR extern_learn " " .ti -8 @@ -35,7 +37,8 @@ .B nud .IR STATE " " .B vrf -.IR NAME " " +.IR NAME " " +.BR nomaster " " .ti -8 .B ip neigh get @@ -92,6 +95,21 @@ indicates whether neighbour is a router .TP +.BI use +this neigh entry is in "use". This option can be used to indicate to +the kernel that a controller is using this dynamic entry. If the entry +does not exist, the kernel will resolve it. If it exists, an attempt +to refresh the neighbor entry will be triggered. + +.TP +.BI managed +this neigh entry is "managed". This option can be used to indicate to +the kernel that a controller is using this dynamic entry. In contrast +to "use", if the entry does not exist, the kernel will resolve it and +periodically attempt to auto-refresh the neighbor entry such that it +remains in resolved state when possible. + +.TP .BI extern_learn this neigh entry was learned externally. This option can be used to indicate to the kernel that this is a controller learnt dynamic entry. @@ -192,6 +210,10 @@ only list the neighbours for given VRF. .TP +.BI nomaster +only list neighbours attached to an interface with no master. + +.TP .BI proxy list neighbour proxies.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-route.8.in -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-route.8.in
Changed
@@ -229,7 +229,7 @@ .IR ENCAP_SEG6 " := " .B seg6 .BR mode " " -.BR encap " | " inline " | " l2encap " " +.BR encap " | " encap.red " | " inline " | " l2encap " | " l2encap.red " " .B segs .IR SEGMENTS " " .B hmac @@ -245,14 +245,20 @@ .ti -8 .IR ENCAP_IOAM6 " := " -.B ioam6 -.BR trace -.BR prealloc -.BR type +.BR ioam6 " " +.B freq +.IR K "/" N " " +.BR mode " " +.BR inline " | " encap " | " auto " " +.B tundst +.IR ADDRESS " " +.B trace +.B prealloc +.B type .IR IOAM6_TRACE_TYPE -.BR ns +.B ns .IR IOAM6_NAMESPACE -.BR size +.B size .IR IOAM6_TRACE_SIZE .ti -8 @@ -732,6 +738,9 @@ .sp .BI ioam6 - encapsulation type IPv6 IOAM +.sp +.BI xfrm +- encapsulation type XFRM .in -8 .I ENCAPHDR @@ -801,10 +810,22 @@ - Encapsulate packet in an outer IPv6 header with SRH .sp +.B mode encap.red +- Encapsulate packet in an outer IPv6 header with SRH applying the +reduced segment list. When there is only one segment and the HMAC is +not present, the SRH is omitted. +.sp + .B mode l2encap - Encapsulate ingress L2 frame within an outer IPv6 header and SRH .sp +.B mode l2encap.red +- Encapsulate ingress L2 frame within an outer IPv6 header and SRH +applying the reduced segment list. When there is only one segment +and the HMAC is not present, the SRH is omitted. +.sp + .I SEGMENTS - List of comma-separated IPv6 addresses .sp @@ -828,10 +849,14 @@ The following actions are currently supported (\fBLinux 4.14+ only\fR). .in +2 -.B End +.BR End " " flavors +.IR FLAVORS " " - Regular SRv6 processing as intermediate segment endpoint. This action only accepts packets with a non-zero Segments Left -value. Other matching packets are dropped. +value. Other matching packets are dropped. The presence of flavors +can change the regular processing of an End behavior according to +the user-provided Flavor operations and information carried in the packet. +See \fBFlavors parameters\fR section. .B End.X nh6 .I NEXTHOP @@ -911,20 +936,105 @@ followed by the specified SRH. The destination address of the outer IPv6 header is set to the first segment of the new SRH. The source address is set as described in \fBip-sr\fR(8). + +.B Flavors parameters + +The flavors represent additional operations that can modify or extend a +subset of the existing behaviors. +.in +2 + +.B flavors +.IR OPERATION "," OPERATION " " ATTRIBUTES "" +.in +2 + +.IR OPERATION " := { " +.BR psp " | " +.BR usp " | " +.BR usd " | " +.BR next-csid " }" + +.IR ATTRIBUTES " := {" +.IR "KEY VALUE" " } " +.IR ATTRIBUTES " " + +.IR KEY " := { " +.BR lblen " | " +.BR nflen " } " .in -2 +.B psp +- Penultimate Segment Pop of the SRH (not yet supported in kernel) + +.B usp +- Ultimate Segment Pop of the SRH (not yet supported in kernel) + +.B usd +- Ultimate Segment Decapsulation (not yet supported in kernel) + +.B next-csid +- The NEXT-C-SID mechanism offers the possibility of encoding +several SRv6 segments within a single 128 bit SID address. The NEXT-C-SID +flavor can be configured to support user-provided Locator-Block and +Locator-Node Function lengths. If Locator-Block and/or Locator-Node Function +lengths are not provided by the user during configuration of an SRv6 End +behavior instance with NEXT-C-SID flavor, the default value is 32-bit for +Locator-Block and 16-bit for Locator-Node Function. + +.BI lblen " VALUE " +- defines the Locator-Block length for NEXT-C-SID flavor. +The Locator-Block length must be greater than 0 and evenly divisible by 8. This +attribute can be used only with NEXT-C-SID flavor. + +.BI nflen " VALUE " +- defines the Locator-Node Function length for NEXT-C-SID +flavors. The Locator-Node Function length must be greater than 0 and evenly +divisible by 8. This attribute can be used only with NEXT-C-SID flavor. +.in -4 + .B ioam6 .in +2 +.B freq K/N +- Inject IOAM in K packets every N packets (default is 1/1). + +.B mode inline +- Directly insert IOAM after IPv6 header (default mode). +.sp + +.B mode encap +- Encapsulate packet in an outer IPv6 header with IOAM. +.sp + +.B mode auto +- Automatically use inline mode for local packets and encap mode for in-transit +packets. +.sp + +.B tundst +.I ADDRESS +- IPv6 address of the tunnel destination (outer header), not used with inline +mode. + +.B type .I IOAM6_TRACE_TYPE - List of IOAM data required in the trace, represented by a bitfield (24 bits). .sp +.B ns .I IOAM6_NAMESPACE - Numerical value to represent an IOAM namespace. See \fBip-ioam\fR(8). .sp +.B size .I IOAM6_TRACE_SIZE - Size, in octets, of the pre-allocated trace data block. +.in -2 + +.B xfrm +.in +2 +.B if_id +.I IF_ID +.B " link_dev +.IR LINK_DEV " " .in -4 .in -8 @@ -1249,9 +1359,19 @@ Adds an IPv6 route with SRv6 decapsulation and forward with lookup in VRF table. .RE .PP -ip -6 route add 2001:db8:1::/64 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0 +ip -6 route add 2001:db8:1::/64 encap seg6local action End flavors next-csid dev eth0 +.RS 4 +Adds an IPv6 route with SRv6 End behavior with next-csid flavor enabled. +.RE +.PP +ip -6 route add 2001:db8:1::/64 encap seg6local action End flavors next-csid lblen 48 nflen 16 dev eth0 +.RS 4 +Adds an IPv6 route with SRv6 End behavior with next-csid flavor enabled and user-provided Locator-Block and Locator-Node Function lengths. +.RE +.PP +ip -6 route add 2001:db8:1::/64 encap ioam6 freq 2/5 mode encap tundst 2001:db8:42::1 trace prealloc type 0x800000 ns 1 size 12 dev eth0 .RS 4 -Adds an IPv6 route with an IOAM Pre-allocated Trace encapsulation that only includes the hop limit and the node id, configured for the IOAM namespace 1 and a pre-allocated data block of 12 octets. +Adds an IPv6 route with an IOAM Pre-allocated Trace encapsulation (ip6ip6) that only includes the hop limit and the node id, configured for the IOAM namespace 1 and a pre-allocated data block of 12 octets (will be injected in 2 packets every 5 packets). .RE .PP ip route add 10.1.1.0/30 nhid 10
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-stats.8
Added
@@ -0,0 +1,208 @@ +.TH IP\-STATS 8 "16 Mar 2022" "iproute2" "Linux" +.SH NAME +ip-stats \- manage and show interface statistics +.SH SYNOPSIS +.sp +.ad l +.in +8 +.ti -8 +.B ip +.B stats +.RI " { " COMMAND " | " +.BR help " }" +.sp + +.ti -8 +.BR "ip stats show" +.RB " " dev +.IR DEV " " +.RB " " group +.IR GROUP " " +.BI subgroup " SUBGROUP" +.RB " " suite +.IR " SUITE" " ... ... ..." + +.ti -8 +.BR "ip stats set" +.BI dev " DEV" +.BR l3_stats " { " +.BR on " | " off " }" + +.SH DESCRIPTION + +.TP +.B ip stats set +is used for toggling whether a certain HW statistics suite is collected on +a given netdevice. The following statistics suites are supported: + +.in 21 + +.ti 14 +.B l3_stats +L3 stats reflect traffic that takes place in a HW device on an object that +corresponds to the given software netdevice. + +.TP +.B ip stats show +is used for showing stats on a given netdevice, or dumping statistics +across all netdevices. By default, all stats are requested. It is possible +to filter which stats are requested by using the +.B group +and +.B subgroup +keywords. + +It is possible to specify several groups, or several subgroups for one +group. When no subgroups are given for a group, all the subgroups are +requested. + +The following groups are recognized: +.in 21 + +.ti 14 +.B group link +- Link statistics. The same suite that "ip -s link show" shows. + +.ti 14 +.B group offload +- A group that contains a number of HW-oriented statistics. See below for +individual subgroups within this group. + +.ti 14 +.B group xstats +- Extended statistics. A subgroup identifies the type of netdevice to show the +statistics for. + +.ti 14 +.B group xstats_slave +- Extended statistics for the slave of a netdevice of a given type. A subgroup +identifies the type of master netdevice. + +.ti 14 +.B group afstats +- A group for address-family specific netdevice statistics. + +.TQ +.BR "group offload " subgroups: +.in 21 + +.ti 14 +.B subgroup cpu_hit +- The +.B cpu_hit +statistics suite is useful on hardware netdevices. The +.B link +statistics on these devices reflect both the hardware- and +software-datapath traffic. The +.B cpu_hit +statistics then only reflect software-datapath traffic. + +.ti 14 +.B subgroup hw_stats_info +- This suite does not include traffic statistics, but rather communicates +the state of other statistics. Through this subgroup, it is possible to +discover whether a given statistic was enabled, and when it was, whether +any device driver actually configured its device to collect these +statistics. For example, +.B l3_stats +was enabled in the following case, but no driver has installed it: + +# ip stats show dev swp1 group offload subgroup hw_stats_info +.br +56: swp1: group offload subgroup hw_stats_info +.br + l3_stats on used off + +After an L3 address is added to the netdevice, the counter will be +installed: + +# ip addr add dev swp1 192.0.2.1/28 +.br +# ip stats show dev swp1 group offload subgroup hw_stats_info +.br +56: swp1: group offload subgroup hw_stats_info +.br + l3_stats on used on + +.ti 14 +.B subgroup l3_stats +- These statistics reflect L3 traffic that takes place in HW on an object +that corresponds to the netdevice. Note that this suite is disabled by +default and needs to be first enabled through +.B ip stats set\fR. + +For example: + +# ip stats show dev swp2.200 group offload subgroup l3_stats +.br +112: swp2.200: group offload subgroup l3_stats on used on +.br + RX: bytes packets errors dropped mcast +.br + 8900 72 2 0 3 +.br + TX: bytes packets errors dropped +.br + 7176 58 0 0 + +Note how the l3_stats_info for the selected group is also part of the dump. + +.TQ +.BR "group xstats " and " group xstats_slave " subgroups: +.in 21 + +.ti 14 +.B subgroup bridge \fR\fB suite stp \fR \fB suite mcast \fR +- Statistics for STP and, respectively, IGMP / MLD (under the keyword +\fBmcast\fR) traffic on bridges and their slaves. + +.ti 14 +.B subgroup bond \fR\fB suite 802.3ad \fR +- Statistics for LACP traffic on bond devices and their slaves. + +.TQ +.BR "group afstats " subgroups: +.in 21 + +.ti 14 +.B subgroup mpls +- Statistics for MPLS traffic seen on the netdevice. For example: + +# ip stats show dev veth01 group afstats subgroup mpls +.br +3: veth01: group afstats subgroup mpls +.br + RX: bytes packets errors dropped noroute +.br + 0 0 0 0 0 +.br + TX: bytes packets errors dropped +.br + 216 2 0 0 + +.SH EXAMPLES +.PP +# ip stats set dev swp1 l3_stats on +.RS +Enables collection of L3 HW statistics on swp1. +.RE + +.PP +# ip stats show group offload +.RS +Shows all offload statistics on all netdevices. +.RE + +.PP +# ip stats show dev swp1 group link +.RS +Shows link statistics on the given netdevice. +.RE + +.SH SEE ALSO +.br +.BR ip (8), +.BR ip-link (8), + +.SH AUTHOR +Manpage by Petr Machata.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip-xfrm.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip-xfrm.8
Changed
@@ -299,6 +299,18 @@ .IR LBITS " " RBITS " " .ti -8 +.B "ip xfrm policy setdefault" +.IR DIR +.IR ACTION " " +.IR DIR +.IR ACTION " " +.IR DIR +.IR ACTION " " + +.ti -8 +.B "ip xfrm policy getdefault" + +.ti -8 .IR SELECTOR " :=" .RB " " src .IR ADDR "/" PLEN " "
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ip.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ip.8
Changed
@@ -22,7 +22,7 @@ .BR link " | " address " | " addrlabel " | " route " | " rule " | " neigh " | "\ ntable " | " tunnel " | " tuntap " | " maddress " | " mroute " | " mrule " | "\ monitor " | " xfrm " | " netns " | " l2tp " | " tcp_metrics " | " token " | "\ - macsec " | " vrf " | " mptcp " | " ioam " }" + macsec " | " vrf " | " mptcp " | " ioam " | " stats " }" .sp .ti -8 @@ -237,6 +237,10 @@ hard for most users to read. This flag adds indentation for readability. +.TP +.BR "\-echo" +Request the kernel to send the applied configuration back. + .SH IP - COMMAND SYNTAX .SS @@ -303,6 +307,10 @@ - rule in routing policy database. .TP +.B stats +- manage and show interface statistics. + +.TP .B tcp_metrics/tcpmetrics - manage TCP Metrics @@ -419,6 +427,7 @@ .BR ip-ntable (8), .BR ip-route (8), .BR ip-rule (8), +.BR ip-stats (8) .BR ip-tcp_metrics (8), .BR ip-token (8), .BR ip-tunnel (8),
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/rdma-statistic.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/rdma-statistic.8
Changed
@@ -59,6 +59,28 @@ .RI " " OBJECT-ID " " .ti -8 +.B rdma statistic +.B mode +.B "" supported "" +.B link +.RI " " DEV/PORT_INDEX " " + +.ti -8 +.B rdma statistic +.B set +.B link +.RI " " DEV/PORT_INDEX " " +.B optional-counters +.RI " " OPTIONAL-COUNTERS " " + +.ti -8 +.B rdma statistic +.B unset +.B link +.RI " " DEV/PORT_INDEX " " +.B optional-counters + +.ti -8 .IR COUNTER_SCOPE " := " .RB "{ " link " | " dev " }" @@ -100,6 +122,17 @@ - specifies the id of the counter to be bound. If this argument is omitted then a new counter will be allocated. +.SS rdma statistic mode - Display the enabled optional counters for each link. + +.SS rdma statistic mode supported - Display the supported optional counters for each link. + +.SS rdma statistic set - Enable a set of optional counters for a specific device/port. + +.I "OPTIONAL-COUNTERS" +- specifies the name of the optional counters to enable. Optional counters that are not specified will be disabled. Note that optional counters are driver-specific. + +.SS rdma statistic unset - Disable all optional counters for a specific device/port. + .SH "EXAMPLES" .PP rdma statistic show @@ -186,6 +219,26 @@ .RS 4 Dump a specific MR statistics with mrn 6. Dumps nothing if does not exists. .RE +.PP +rdma statistic mode link mlx5_2/1 +.RS 4 +Display the optional counters that was enabled on mlx5_2/1. +.RE +.PP +rdma statistic mode supported link mlx5_2/1 +.RS 4 +Display the optional counters that mlx5_2/1 supports. +.RE +.PP +rdma statistic set link mlx5_2/1 optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts +.RS 4 +Enable the cc_rx_ce_pkts,cc_rx_cnp_pkts counters on device mlx5_2 port 1. +.RE +.PP +rdma statistic unset link mlx5_2/1 optional-counters +.RS 4 +Disable all the optional counters on device mlx5_2 port 1. +.RE .SH SEE ALSO .BR rdma (8), @@ -198,3 +251,5 @@ Mark Zhang <markz@mellanox.com> .br Erez Alfasi <ereza@mellanox.com> +.br +Neta Ostrovsky <netao@nvidia.com>
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/routel.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/routel.8
Changed
@@ -1,25 +1,31 @@ -.TH "ROUTEL" "8" "3 Jan, 2008" "iproute2" "Linux" +.TH ROUTEL 8 "1 Sept, 2021" "iproute2" "Linux" .SH "NAME" -.LP routel \- list routes with pretty output format -.br -routef \- flush routes -.SH "SYNTAX" -.LP -routel \fItablenr\fP \fIraw ip args...\fP -.br -routef +.SH SYNOPSIS +.B routel +.RI " " OPTIONS " " +.RI " " tablenr + \fIip route options...\fR +.P +.ti 8 +.IR OPTIONS " := {" +\fB-h\fR | \fB--help\fR | +{\fB-f\fR | \fB--family\fR } +{\fBinet\fR | \fBinet6\fR } | +\fB-4\fR | \fB-6\fR } + .SH "DESCRIPTION" .LP -These programs are a set of helper scripts you can use instead of raw iproute2 commands. -.br -The routel script will list routes in a format that some might consider easier to interpret then the ip route list equivalent. -.br -The routef script does not take any arguments and will simply flush the routing table down the drain. Beware! This means deleting all routes which will make your network unusable! +The routel script will list routes in a format that some might consider +easier to interpret then the +.B ip +route list equivalent. .SH "AUTHORS" .LP -The routel script was written by Stephen R. van den Berg <srb@cuci.nl>, 1999/04/18 and donated to the public domain. +Rewritten by Stephen Hemminger <stephen@networkplumber.org>. +.br +Original script by Stephen R. van den Berg <srb@cuci.nl>. .br This manual page was written by Andreas Henriksson <andreas@fatal.se>, for the Debian GNU/Linux system. .SH "SEE ALSO"
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/ss.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/ss.8
Changed
@@ -137,7 +137,7 @@ The memory allocated for sending packet (which has not been sent to layer 3) .P .TP -.B <ropt_mem> +.B <opt_mem> The memory used for storing socket option, e.g., the key for TCP MD5 signature .P .TP @@ -155,6 +155,10 @@ .B \-p, \-\-processes Show process using socket. .TP +.B \-T, \-\-threads +Show thread using socket. Implies \-p. +.BR \-p . +.TP .B \-i, \-\-info Show internal TCP information. Below fields may appear: .RS @@ -295,6 +299,11 @@ Cgroup v2 pathname. This pathname is relative to the mount point of the hierarchy. .RE .TP +.B \-\-tipcinfo +Show internal tipc socket information. +.RS +.P +.TP .B \-K, \-\-kill Attempts to forcibly close sockets. This option displays sockets that are successfully closed and silently skips sockets that the kernel does not support @@ -311,7 +320,9 @@ .B \-Z, \-\-context As the .B \-p -option but also shows process security context. +option but also shows process security context. If the +.B \-T +option is used, also shows thread security context. .sp For .BR netlink (7) @@ -373,24 +384,31 @@ .B \-S, \-\-sctp Display SCTP sockets. .TP +.B \-\-tipc +Display tipc sockets (alias for -f tipc). +.TP +.TP .B \-\-vsock Display vsock sockets (alias for -f vsock). .TP .B \-\-xdp Display XDP sockets (alias for -f xdp). .TP +.B \-M, \-\-mptcp +Display MPTCP sockets. +.TP .B \-\-inet-sockopt Display inet socket options. .TP .B \-f FAMILY, \-\-family=FAMILY Display sockets of type FAMILY. Currently the following families are -supported: unix, inet, inet6, link, netlink, vsock, xdp. +supported: unix, inet, inet6, link, netlink, vsock, tipc, xdp. .TP .B \-A QUERY, \-\-query=QUERY, \-\-socket=QUERY List of socket tables to dump, separated by commas. The following identifiers are understood: all, inet, tcp, udp, raw, unix, packet, netlink, unix_dgram, -unix_stream, unix_seqpacket, packet_raw, packet_dgram, dccp, sctp, -vsock_stream, vsock_dgram, xdp Any item in the list may optionally be +unix_stream, unix_seqpacket, packet_raw, packet_dgram, dccp, sctp, tipc, +vsock_stream, vsock_dgram, xdp, mptcp. Any item in the list may optionally be prefixed by an exclamation mark .RB ( ! ) to exclude that socket table from being dumped. @@ -409,7 +427,7 @@ .SH STATE-FILTER .B STATE-FILTER -allows to construct arbitrary set of states to match. Its syntax is +allows one to construct arbitrary set of states to match. Its syntax is sequence of keywords state and exclude followed by identifier of state. .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-actions.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-actions.8
Changed
@@ -52,6 +52,8 @@ .I HWSTATSSPEC .I CONTROL + +.I SKIPSPEC .I ACTISPEC @@ -99,6 +101,11 @@ .IR reclassify " | " pipe " | " drop " | " continue " | " ok } +.I SKIPSPEC +:= { +.IR skip_sw " | " skip_hw +} + .I TC_OPTIONS These are the options that are specific to .B tc @@ -270,6 +277,23 @@ this packet. .RE +.TP +.I SKIPSPEC +The +.I SKIPSPEC +indicates how +.B tc +should proceed when executing the action. Any of the following are valid: +.RS +.TP +.B skip_sw +Do not process action by software. If hardware has no offload support for this +action, operation will fail. +.TP +.B skip_hw +Do not process action by hardware. +.RE + .SH SEE ALSO .BR tc (8), .BR tc-bpf (8),
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-basic.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-basic.8
Changed
@@ -14,7 +14,7 @@ .SH DESCRIPTION The .B basic -filter allows to classify packets using the extended match infrastructure. +filter allows one to classify packets using the extended match infrastructure. .SH OPTIONS .TP .BI action " ACTION_SPEC"
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-bpf.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-bpf.8
Changed
@@ -217,7 +217,7 @@ .SS bytecode is being used for loading cBPF classifier and actions only. The cBPF bytecode is directly passed as a text string in the form of -.B \'s,c t f k,c t f k,c t f k,...\' +.B \(aqs,c t f k,c t f k,c t f k,...' , where .B s denotes the number of subsequent 4-tuples. One such 4-tuple consists of
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-ct.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-ct.8
Changed
@@ -74,8 +74,8 @@ #Add ingress qdisc on eth0 and eth1 interfaces .nf -$ tc qdisc add dev eth0 handle ingress -$ tc qdisc add dev eth1 handle ingress +$ tc qdisc add dev eth0 ingress +$ tc qdisc add dev eth1 ingress #Setup filters on eth0, allowing opening new connections in zone 2, and doing src nat + mark for each new connection $ tc filter add dev eth0 ingress prio 1 chain 0 proto ip flower ip_proto tcp ct_state -trk \\
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-ctinfo.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-ctinfo.8
Changed
@@ -58,7 +58,7 @@ zone is a 16bit unsigned decimal value. Default is 0. .IP CONTROL -The following keywords allow to control how the tree of qdisc, classes, +The following keywords allow one to control how the tree of qdisc, classes, filters and actions is further traversed after this action. .RS .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-flower.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-flower.8
Changed
@@ -40,6 +40,10 @@ .IR PRIORITY " | " .BR cvlan_ethtype " { " ipv4 " | " ipv6 " | " .IR ETH_TYPE " } | " +.B pppoe_sid +.IR PSID " | " +.BR ppp_proto " { " ip " | " ipv6 " | " mpls_uc " | " mpls_mc " | " +.IR PPP_PROTO " } | " .B mpls .IR LSE_LIST " | " .B mpls_label @@ -89,6 +93,8 @@ .B vxlan_opts | .B erspan_opts +| +.B gtp_opts } .IR OPTIONS " | " .BR ip_flags @@ -162,6 +168,11 @@ number of high bits to match. If the mask is missing then a match on all bits is assumed. .TP +.BI num_of_vlans " NUM" +Match on the number of vlan tags in the packet. +.I NUM +can be 0 or small positive integer. Typically in 0-4 range. +.TP .BI vlan_id " VID" Match on vlan tag id. .I VID @@ -195,7 +206,18 @@ may be either .BR ipv4 ", " ipv6 or an unsigned 16bit value in hexadecimal format. - +.TP +.BI pppoe_sid " PSID" +Match on PPPoE session id. +.I PSID +is an unsigned 16bit value in decimal format. +.TP +.BI ppp_proto " PPP_PROTO" +Match on PPP layer three protocol. +.I PPP_PROTO +may be either +.BR ip ", " ipv6 ", " mpls_uc ", " mpls_mc +or an unsigned 16bit value in hexadecimal format. .TP .BI mpls " LSE_LIST" Match on the MPLS label stack. @@ -411,6 +433,8 @@ .BI vxlan_opts " OPTIONS" .TQ .BI erspan_opts " OPTIONS" +.TQ +.BI gtp_opts " OPTIONS" Match on IP tunnel metadata. Key id .I NUMBER is a 32 bit tunnel key id (e.g. VNI for VXLAN tunnel). @@ -446,6 +470,12 @@ represented as a 8bit number, INDEX as an 32bit number, DIR and HWID as a 8bit number. Multiple options is not supported. Note INDEX/INDEX_MASK is used when VERSION is 1, and DIR/DIR_MASK and HWID/HWID_MASK are used when VERSION is 2. +gtp_opts +.I OPTIONS +doesn't support multiple options, and it consists of a key followed by a slash +and corresponding mask. If the mask is missing, \fBtc\fR assumes a full-length +match. The option can be described in the form PDU_TYPE:QFI/PDU_TYPE_MASK:QFI_MASK +where both PDU_TYPE and QFI are represented as a 8bit hexadecimal values. .TP .BI ip_flags " IP_FLAGS" .I IP_FLAGS
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-fq_codel.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-fq_codel.8
Changed
@@ -20,6 +20,8 @@ .B ce_threshold TIME +.B ce_threshold_selector +VALUE/MASK .B memory_limit BYTES @@ -64,7 +66,8 @@ has the same semantics as .B codel and is used to ensure that the measured minimum delay does not become too stale. -The minimum delay must be experienced in the last epoch of length .B interval. +The minimum delay must be experienced in the last epoch of length +.BR interval . It should be set on the order of the worst-case RTT through the bottleneck to give endpoints sufficient time to react. Default value is 100ms. @@ -89,6 +92,22 @@ Experienced. This is useful for DCTCP-style congestion control algorithms that require marking at very shallow queueing thresholds. +.SS ce_threshold_selector +sets a filter so that the +.B ce_threshold +feature is applied to only a subset of the traffic seen by the qdisc. If set, the MASK value +will be applied as a bitwise AND to the diffserv/ECN byte of the IP header, and only if the +result of this masking equals VALUE, will the +.B ce_threshold +logic be applied to the packet. + +.SS drop_batch +sets the maximum number of packets to drop when +.B limit +or +.B memory_limit +is exceeded. Default value is 64. + .SH EXAMPLES #tc qdisc add dev eth0 root fq_codel .br
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-fw.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-fw.8
Changed
@@ -12,13 +12,19 @@ .SH DESCRIPTION the .B fw -filter allows to classify packets based on a previously set +filter allows one to classify packets based on a previously set .BR fwmark " by " iptables . -If it is identical to the filter's +If the masked value of the +.B fwmark +matches the filter's masked .BR handle , -the filter matches. +the filter matches. By default, all 32 bits of the +.B handle +and the +.B fwmark +are masked. .B iptables -allows to mark single packets with the +allows one to mark single packets with the .B MARK target, or whole connections using .BR CONNMARK . @@ -60,7 +66,39 @@ iptables -t mangle -A PREROUTING -i eth0 -j MARK --set-mark 6 .EE .RE + +Specific bits of the packet's +.B fwmark +can be set using the +.B skbedit +action. For example, to only set one bit of the +.B fwmark +without changing any other bit: + +.RS +.EX +tc filter add ... action skbedit mark 0x8/0x8 +.EE +.RE + +The +.B fw +filter can then be used to match on this bit by masking the +.B handle: + +.RS +.EX +tc filter add ... handle 0x8/0x8 fw action drop +.EE +.RE + +This is useful when different bits of the +.B fwmark +are assigned different meanings. +.EE +.RE .SH SEE ALSO .BR tc (8), .BR iptables (8), -.BR iptables-extensions (8) +.BR iptables-extensions (8), +.BR tc-skbedit (8)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-matchall.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-matchall.8
Changed
@@ -15,7 +15,7 @@ .SH DESCRIPTION The .B matchall -filter allows to classify every packet that flows on the port and run a +filter allows one to classify every packet that flows on the port and run a action on it. .SH OPTIONS .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-nat.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-nat.8
Changed
@@ -25,7 +25,7 @@ .SH DESCRIPTION The .B nat -action allows to perform NAT without the overhead of conntrack, which is +action allows one to perform NAT without the overhead of conntrack, which is desirable if the number of flows or addresses to perform NAT on is large. This action is best used in combination with the .B u32
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-netem.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-netem.8
Changed
@@ -67,7 +67,7 @@ .SH DESCRIPTION NetEm is an enhancement of the Linux traffic control facilities -that allow to add delay, packet loss, duplication and more other +that allow one to add delay, packet loss, duplication and more other characteristics to packets outgoing from a selected network interface. NetEm is built using the existing Quality Of Service (QOS) and Differentiated Services (diffserv) facilities in the Linux @@ -82,12 +82,12 @@ .SS delay adds the chosen delay to the packets outgoing to chosen network interface. The -optional parameters allows to introduce a delay variation and a correlation. +optional parameters allows one to introduce a delay variation and a correlation. Delay and jitter values are expressed in ms while correlation is percentage. .SS distribution allow the user to choose the delay distribution. If not specified, the default -distribution is Normal. Additional parameters allow to consider situations in +distribution is Normal. Additional parameters allow one to consider situations in which network has variable delays depending on traffic flows concurring on the same path, that causes several delay peaks and a tail. @@ -99,7 +99,7 @@ .SS loss state adds packet losses according to the 4-state Markov using the transition probabilities as input parameters. The parameter p13 is mandatory and if used -alone corresponds to the Bernoulli model. The optional parameters allows to +alone corresponds to the Bernoulli model. The optional parameters allows one to extend the model to 2-state (p31), 3-state (p23 and p32) and 4-state (p14). State 1 corresponds to good reception, State 4 to independent losses, State 3 to burst losses and State 2 to good reception within a burst.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-pedit.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-pedit.8
Changed
@@ -118,7 +118,7 @@ .BI at " AT " offmask " MASK " shift " SHIFT" This is an optional part of .IR RAW_OP -which allows to have a variable +which allows one to have a variable .I OFFSET depending on packet data at offset .IR AT , @@ -202,7 +202,7 @@ .B icmp_type .TQ .B icmp_code -Again, this allows to change data past the actual IP header itself. It assumes +Again, this allows one to change data past the actual IP header itself. It assumes an ICMP header is present immediately following the (minimal sized) IP header. If it is not or the latter is bigger than the minimum of 20 bytes, this will do unexpected things. These fields are eight-bit values. @@ -300,11 +300,11 @@ .BI retain " RVAL" This optional extra part of .I CMD_SPEC -allows to exclude bits from being changed. Supported only for 32 bits fields +allows one to exclude bits from being changed. Supported only for 32 bits fields or smaller. .TP .I CONTROL -The following keywords allow to control how the tree of qdisc, classes, +The following keywords allow one to control how the tree of qdisc, classes, filters and actions is further traversed after this action. .RS .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-sample.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-sample.8
Changed
@@ -92,8 +92,8 @@ .TP .BI index " INDEX" Is a unique ID for an action. When creating new action instance, this parameter -allows to set the new action index. When using existing action, this parameter -allows to specify the existing action index. The index must 32bit unsigned +allows one to set the new action index. When using existing action, this parameter +allows one to specify the existing action index. The index must 32bit unsigned integer greater than zero. .SH EXAMPLES Sample one of every 100 packets flowing into interface eth0 to psample group 12:
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-skbedit.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-skbedit.8
Changed
@@ -16,9 +16,9 @@ .SH DESCRIPTION The .B skbedit -action allows to change a packet's associated meta data. It complements the +action allows one to change a packet's associated meta data. It complements the .B pedit -action, which in turn allows to change parts of the packet data itself. +action, which in turn allows one to change parts of the packet data itself. The most unique feature of .B skbedit
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-skbmod.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-skbmod.8
Changed
@@ -63,7 +63,7 @@ Does not affect Non ECN-Capable Transport (Non-ECT) packets. .TP .I CONTROL -The following keywords allow to control how the tree of qdisc, classes, +The following keywords allow one to control how the tree of qdisc, classes, filters and actions is further traversed after this action. .RS .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-tcindex.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-tcindex.8
Changed
@@ -16,7 +16,7 @@ .B action .BR ACTION_SPEC " " .SH DESCRIPTION -This filter allows to match packets based on their +This filter allows one to match packets based on their .B tcindex field value, i.e. the combination of the DSCP and ECN fields as present in IPv4 and IPv6 headers.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-tunnel_key.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-tunnel_key.8
Changed
@@ -23,7 +23,7 @@ .SH DESCRIPTION The .B tunnel_key -action combined with a shared IP tunnel device, allows to perform IP tunnel en- +action combined with a shared IP tunnel device, allows one to perform IP tunnel en- or decapsulation on a packet, reflected by the operation modes .IR UNSET " and " SET .
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-u32.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-u32.8
Changed
@@ -150,7 +150,7 @@ .BR at " " nexthdr+ " " .IR int_value " " .SH DESCRIPTION -The Universal/Ugly 32bit filter allows to match arbitrary bitfields in the +The Universal/Ugly 32bit filter allows one to match arbitrary bitfields in the packet. Due to breaking everything down to values, masks and offsets, It is equally powerful and hard to use. Luckily many abstracting directives are present which allow defining rules on a higher level and therefore free the @@ -375,7 +375,7 @@ .BR ip6 ) header. .IR IP / IP6 -then allows to match various header fields: +then allows one to match various header fields: .RS .TP .BI src " ADDR" @@ -427,7 +427,7 @@ IPv4 only, check certain flags and fragment offset values. Match if the packet is not a fragment .RB ( nofrag ), -the first fragment +the first fragment of a fragmented packet .RB ( firstfrag ), if Don't Fragment .RB ( df ) @@ -644,7 +644,7 @@ tc filter add dev eth0 parent 1:0 protocol ip \\ u32 ht 800: \\ match ip protocol 6 FF \\ - match ip firstfrag \\ + match u16 0 1fff at 6 \\ offset at 0 mask 0f00 shift 6 \\ link 1: .EE
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-vlan.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-vlan.8
Changed
@@ -35,7 +35,7 @@ .SH DESCRIPTION The .B vlan -action allows to perform 802.1Q en- or decapsulation on a packet, reflected by +action allows one to perform 802.1Q en- or decapsulation on a packet, reflected by the operation modes .IR POP ", " PUSH " and " MODIFY . The @@ -45,7 +45,7 @@ .IR PUSH " and " MODIFY modes require at least a .I VLANID -and allow to optionally choose the +and allow one to optionally choose the .I VLANPROTO to use.
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc-xt.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc-xt.8
Changed
@@ -10,7 +10,7 @@ .SH DESCRIPTION The .B xt -action allows to call arbitrary iptables targets for packets matching the filter +action allows one to call arbitrary iptables targets for packets matching the filter this action is attached to. .SH OPTIONS .TP
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/tc.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/tc.8
Changed
@@ -21,7 +21,7 @@ .B tc .RI " " OPTIONS " " -.B class add | change | replace | delete dev +.B class add | change | replace | delete | show dev \fIDEV\fR .B parent \fIqdisc-id\fR @@ -343,7 +343,7 @@ .TP netem Network Emulator is an enhancement of the Linux traffic control facilities that -allow to add delay, packet loss, duplication and more other characteristics to +allow one to add delay, packet loss, duplication and more other characteristics to packets outgoing from a selected network interface. .TP pfifo_fast
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/man/man8/vdpa-dev.8 -> _service:tar_scm:iproute2-6.1.0.tar.xz/man/man8/vdpa-dev.8
Changed
@@ -31,11 +31,25 @@ .I NAME .B mgmtdev .I MGMTDEV +.RI " mac " MACADDR " " +.RI " mtu " MTU " " +.RI " max_vqp " MAX_VQ_PAIRS " " .ti -8 .B vdpa dev del .I DEV +.ti -8 +.B vdpa dev config show +.RI " " DEV " " + +.ti -8 +.B vdpa dev vstats show +.I DEV +.B qidx +.I QUEUE_INDEX + + .SH "DESCRIPTION" .SS vdpa dev show - display vdpa device attributes @@ -59,12 +73,43 @@ .BI mgmtdev " MGMTDEV" Name of the management device to use for device addition. +.PP +.BI mac " MACADDR" +- specifies the mac address for the new vdpa device. +This is applicable only for the network type of vdpa device. This is optional. + +.BI mtu " MTU" +- specifies the mtu for the new vdpa device. +This is applicable only for the network type of vdpa device. This is optional. + .SS vdpa dev del - Delete the vdpa device. .PP .I "DEV" - specifies the vdpa device to delete. +.SS vdpa dev config show - Show configuration of specific device or all devices. + +.PP +.I "DEV" +- specifies the vdpa device to show its configuration. +If this argument is omitted all devices configuration is listed. + +.in +4 +Format is: +.in +2 +VDPA_DEVICE_NAME + +.SS vdpa dev vstats show - shows vendor specific statistics for the given device and virtqueue index. The information is presented as name-value pairs where name is the name of the field and value is a numeric value for it. + +.TP +.BI "DEV" +- specifies the vdpa device to query + +.TP +.BI qidx " QUEUE_INDEX" +- specifies the virtqueue index to query + .SH "EXAMPLES" .PP vdpa dev show @@ -82,10 +127,35 @@ Add the vdpa device named foo on the management device vdpa_sim_net. .RE .PP +vdpa dev add name foo mgmtdev vdpa_sim_net mac 00:11:22:33:44:55 +.RS 4 +Add the vdpa device named foo on the management device vdpa_sim_net with mac address of 00:11:22:33:44:55. +.RE +.PP +vdpa dev add name foo mgmtdev vdpa_sim_net mac 00:11:22:33:44:55 mtu 9000 +.RS 4 +Add the vdpa device named foo on the management device vdpa_sim_net with mac address of 00:11:22:33:44:55 and mtu of 9000 bytes. +.RE +.PP +vdpa dev add name foo mgmtdev auxiliary/mlx5_core.sf.1 mac 00:11:22:33:44:55 max_vqp 8 +.RS 4 +Add the vdpa device named foo on the management device auxiliary/mlx5_core.sf.1 with mac address of 00:11:22:33:44:55 and max 8 virtqueue pairs +.RE +.PP vdpa dev del foo .RS 4 Delete the vdpa device named foo which was previously created. .RE +.PP +vdpa dev config show foo +.RS 4 +Shows the vdpa device configuration of device named foo. +.RE +.PP +vdpa dev vstats show vdpa0 qidx 1 +.RS 4 +Shows vendor specific statistics information for vdpa device vdpa0 and virtqueue index 1 +.RE .SH SEE ALSO .BR vdpa (8),
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/misc/ifstat.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/misc/ifstat.c
Changed
@@ -202,7 +202,7 @@ ll_init_map(&rth); filter_mask = IFLA_STATS_FILTER_BIT(filter_type); if (rtnl_statsdump_req_filter(&rth, AF_UNSPEC, - filter_mask) < 0) { + filter_mask, NULL, NULL) < 0) { perror("Cannot send dump request"); exit(1); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/misc/lnstat.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/misc/lnstat.c
Changed
@@ -210,8 +210,9 @@ } ofs += width+1; } + /* fill in spaces */ - for (h = 1; h <= th.num_lines; h++) { + for (h = 1; h < th.num_lines; h++) { for (i = 0; i < ofs; i++) { if (th.hdrhi == '\0') th.hdrhi = ' '; @@ -330,6 +331,7 @@ for (i = 0; i < MAX_FIELDS; i++) fp.paramsi.print.width = len; } + free(tmp); break; default: usage(argv0, 1);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/misc/ss.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/misc/ss.c
Changed
@@ -31,7 +31,6 @@ #include "ss_util.h" #include "utils.h" -#include "rt_names.h" #include "ll_map.h" #include "libnetlink.h" #include "namespace.h" @@ -55,6 +54,11 @@ #include <linux/tls.h> #include <linux/mptcp.h> +#if HAVE_RPC +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#endif + /* AF_VSOCK/PF_VSOCK is only provided since glibc 2.18 */ #ifndef PF_VSOCK #define PF_VSOCK 40 @@ -97,12 +101,18 @@ *context = NULL; return -1; } + +static void freecon(char *context) +{ + free(context); +} #endif int preferred_family = AF_UNSPEC; static int show_options; int show_details; -static int show_users; +static int show_processes; +static int show_threads; static int show_mem; static int show_tcpinfo; static int show_bpf; @@ -187,8 +197,12 @@ } buffer; static const char *TCP_PROTO = "tcp"; -static const char *SCTP_PROTO = "sctp"; static const char *UDP_PROTO = "udp"; +#ifdef HAVE_RPC +static const char *TCP6_PROTO = "tcp6"; +static const char *UDP6_PROTO = "udp6"; +static const char *SCTP_PROTO = "sctp"; +#endif static const char *RAW_PROTO = "raw"; static const char *dg_proto; @@ -410,6 +424,7 @@ ENTRY(packet_dgram, PACKET_DG_DB), ENTRY(p_dgr, PACKET_DG_DB), /* alias for packet_dgram */ ENTRY(netlink, NETLINK_DB), + ENTRY(tipc, TIPC_DB), ENTRY(vsock, VSOCK_ST_DB, VSOCK_DG_DB), ENTRY(vsock_stream, VSOCK_ST_DB), ENTRY(v_str, VSOCK_ST_DB), /* alias for vsock_stream */ @@ -512,9 +527,10 @@ struct user_ent *next; unsigned int ino; int pid; + int tid; int fd; - char *process; - char *process_ctx; + char *task; + char *task_ctx; char *socket_ctx; }; @@ -528,9 +544,9 @@ return val & (USER_ENT_HASH_SIZE - 1); } -static void user_ent_add(unsigned int ino, char *process, - int pid, int fd, - char *proc_ctx, +static void user_ent_add(unsigned int ino, char *task, + int pid, int tid, int fd, + char *task_ctx, char *sock_ctx) { struct user_ent *p, **pp; @@ -543,9 +559,10 @@ p->next = NULL; p->ino = ino; p->pid = pid; + p->tid = tid; p->fd = fd; - p->process = strdup(process); - p->process_ctx = strdup(proc_ctx); + p->task = strdup(task); + p->task_ctx = strdup(task_ctx); p->socket_ctx = strdup(sock_ctx); pp = &user_ent_hashuser_ent_hashfn(ino); @@ -553,6 +570,81 @@ *pp = p; } +#define MAX_PATH_LEN 1024 + +static void user_ent_hash_build_task(char *path, int pid, int tid) +{ + const char *no_ctx = "unavailable"; + char task16 = {'\0', }; + char statMAX_PATH_LEN; + int pos_id, pos_fd; + char *task_context; + struct dirent *d; + DIR *dir; + + if (getpidcon(tid, &task_context) != 0) + task_context = strdup(no_ctx); + + pos_id = strlen(path); /* $PROC_ROOT/$ID/ */ + + snprintf(path + pos_id, MAX_PATH_LEN - pos_id, "fd/"); + dir = opendir(path); + if (!dir) { + freecon(task_context); + return; + } + + pos_fd = strlen(path); /* $PROC_ROOT/$ID/fd/ */ + + while ((d = readdir(dir)) != NULL) { + const char *pattern = "socket:"; + char *sock_context; + unsigned int ino; + ssize_t link_len; + char lnk64; + int fd; + + if (sscanf(d->d_name, "%d%*c", &fd) != 1) + continue; + + snprintf(path + pos_fd, MAX_PATH_LEN - pos_fd, "%d", fd); + + link_len = readlink(path, lnk, sizeof(lnk) - 1); + if (link_len == -1) + continue; + lnklink_len = '\0'; + + if (strncmp(lnk, pattern, strlen(pattern))) + continue; + + if (sscanf(lnk, "socket:%u", &ino) != 1) + continue; + + if (getfilecon(path, &sock_context) <= 0) + sock_context = strdup(no_ctx); + + if (task0 == '\0') { + FILE *fp; + + strlcpy(stat, path, pos_id + 1); + snprintf(stat + pos_id, sizeof(stat) - pos_id, "stat"); + + fp = fopen(stat, "r"); + if (fp) { + if (fscanf(fp, "%*d (%^))", task) < 1) + ; /* ignore */ + fclose(fp); + } + } + + user_ent_add(ino, task, pid, tid, fd, task_context, sock_context); + freecon(sock_context); + } + + freecon(task_context); + closedir(dir); +} + static void user_ent_destroy(void) { struct user_ent *p, *p_next; @@ -561,8 +653,8 @@ while (cnt != USER_ENT_HASH_SIZE) { p = user_ent_hashcnt; while (p) { - free(p->process); - free(p->process_ctx); + free(p->task); + free(p->task_ctx); free(p->socket_ctx); p_next = p->next; free(p); @@ -575,24 +667,14 @@ static void user_ent_hash_build(void) { const char *root = getenv("PROC_ROOT") ? : "/proc/"; + char nameMAX_PATH_LEN; struct dirent *d; - char name1024; int nameoff; DIR *dir; - char *pid_context; - char *sock_context; - const char *no_ctx = "unavailable"; - static int user_ent_hash_build_init; - - /* If show_users & show_proc_ctx set only do this once */ - if (user_ent_hash_build_init != 0) - return; - - user_ent_hash_build_init = 1; strlcpy(name, root, sizeof(name)); - if (strlen(name) == 0 || namestrlen(name)-1 != '/') + if (strlen(name) == 0 || namestrlen(name) - 1 != '/') strcat(name, "/"); nameoff = strlen(name); @@ -602,75 +684,36 @@ return; while ((d = readdir(dir)) != NULL) { - struct dirent *d1; - char process16; - char *p; - int pid, pos; - DIR *dir1; - char crap; + int pid; - if (sscanf(d->d_name, "%d%c", &pid, &crap) != 1) + if (sscanf(d->d_name, "%d%*c", &pid) != 1) continue; - if (getpidcon(pid, &pid_context) != 0) - pid_context = strdup(no_ctx); - - snprintf(name + nameoff, sizeof(name) - nameoff, "%d/fd/", pid); - pos = strlen(name); - if ((dir1 = opendir(name)) == NULL) { - free(pid_context); - continue; - } + snprintf(name + nameoff, sizeof(name) - nameoff, "%d/", pid); + user_ent_hash_build_task(name, pid, pid); - process0 = '\0'; - p = process; + if (show_threads) { + struct dirent *task_d; + DIR *task_dir; - while ((d1 = readdir(dir1)) != NULL) { - const char *pattern = "socket:"; - unsigned int ino; - char lnk64; - int fd; - ssize_t link_len; - char tmp1024; + snprintf(name + nameoff, sizeof(name) - nameoff, "%d/task/", pid); - if (sscanf(d1->d_name, "%d%c", &fd, &crap) != 1) + task_dir = opendir(name); + if (!task_dir) continue; - snprintf(name+pos, sizeof(name) - pos, "%d", fd); + while ((task_d = readdir(task_dir)) != NULL) { + int tid; - link_len = readlink(name, lnk, sizeof(lnk)-1); - if (link_len == -1) - continue; - lnklink_len = '\0'; - - if (strncmp(lnk, pattern, strlen(pattern))) - continue; - - sscanf(lnk, "socket:%u", &ino); - - snprintf(tmp, sizeof(tmp), "%s/%d/fd/%s", - root, pid, d1->d_name); + if (sscanf(task_d->d_name, "%d%*c", &tid) != 1) + continue; + if (tid == pid) + continue; - if (getfilecon(tmp, &sock_context) <= 0) - sock_context = strdup(no_ctx); - - if (*p == '\0') { - FILE *fp; - - snprintf(tmp, sizeof(tmp), "%s/%d/stat", - root, pid); - if ((fp = fopen(tmp, "r")) != NULL) { - if (fscanf(fp, "%*d (%^))", p) < 1) - ; /* ignore */ - fclose(fp); - } + snprintf(name + nameoff, sizeof(name) - nameoff, "%d/", tid); + user_ent_hash_build_task(name, pid, tid); } - user_ent_add(ino, p, pid, fd, - pid_context, sock_context); - free(sock_context); } - free(pid_context); - closedir(dir1); } closedir(dir); } @@ -687,6 +730,7 @@ struct user_ent *p; int cnt = 0; char *ptr; + char thread_info16 = {'\0', }; char *new_buf; int len, new_buf_len; int buf_used = 0; @@ -703,23 +747,27 @@ while (1) { ptr = *buf + buf_used; + + if (show_threads) + snprintf(thread_info, sizeof(thread_info), "tid=%d,", p->tid); + switch (type) { case USERS: len = snprintf(ptr, buf_len - buf_used, - "(\"%s\",pid=%d,fd=%d),", - p->process, p->pid, p->fd); + "(\"%s\",pid=%d,%sfd=%d),", + p->task, p->pid, thread_info, p->fd); break; case PROC_CTX: len = snprintf(ptr, buf_len - buf_used, - "(\"%s\",pid=%d,proc_ctx=%s,fd=%d),", - p->process, p->pid, - p->process_ctx, p->fd); + "(\"%s\",pid=%d,%sproc_ctx=%s,fd=%d),", + p->task, p->pid, thread_info, + p->task_ctx, p->fd); break; case PROC_SOCK_CTX: len = snprintf(ptr, buf_len - buf_used, - "(\"%s\",pid=%d,proc_ctx=%s,fd=%d,sock_ctx=%s),", - p->process, p->pid, - p->process_ctx, p->fd, + "(\"%s\",pid=%d,%sproc_ctx=%s,fd=%d,sock_ctx=%s),", + p->task, p->pid, thread_info, + p->task_ctx, p->fd, p->socket_ctx); break; default: @@ -849,6 +897,8 @@ unsigned int reord_seen; double rcv_rtt; double min_rtt; + unsigned int rcv_ooopack; + unsigned int snd_wnd; int rcv_space; unsigned int rcv_ssthresh; unsigned long long busy_time; @@ -1472,45 +1522,87 @@ static struct scache *rlist; +#ifdef HAVE_RPC +static CLIENT *rpc_client_create(rpcprog_t prog, rpcvers_t vers) +{ + struct netbuf nbuf; + struct sockaddr_un saddr; + int sock; + + memset(&saddr, 0, sizeof(saddr)); + sock = socket(AF_LOCAL, SOCK_STREAM, 0); + if (sock < 0) + return NULL; + + saddr.sun_family = AF_LOCAL; + strcpy(saddr.sun_path, _PATH_RPCBINDSOCK); + nbuf.len = SUN_LEN(&saddr); + nbuf.maxlen = sizeof(struct sockaddr_un); + nbuf.buf = &saddr; + + return clnt_vc_create(sock, &nbuf, prog, vers, 0, 0); +} + static void init_service_resolver(void) { - char buf128; - FILE *fp = popen("/usr/sbin/rpcinfo -p 2>/dev/null", "r"); + struct rpcblist *rhead = NULL; + struct timeval timeout; + struct rpcent *rpc; + enum clnt_stat res; + CLIENT *client; + + timeout.tv_sec = 5; + timeout.tv_usec = 0; - if (!fp) + client = rpc_client_create(PMAPPROG, RPCBVERS4); + if (!client) return; - if (!fgets(buf, sizeof(buf), fp)) { - pclose(fp); + res = clnt_call(client, RPCBPROC_DUMP, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_rpcblist_ptr, (char *)&rhead, + timeout); + if (res != RPC_SUCCESS) return; - } - while (fgets(buf, sizeof(buf), fp) != NULL) { - unsigned int progn, port; - char proto128, prog128 = "rpc."; + + for (; rhead; rhead = rhead->rpcb_next) { + char prog128 = "rpc."; struct scache *c; + int hport, lport, ok; - if (sscanf(buf, "%u %*d %s %u %s", - &progn, proto, &port, prog+4) != 4) + c = malloc(sizeof(*c)); + if (!c) continue; - if (!(c = malloc(sizeof(*c)))) + ok = sscanf(rhead->rpcb_map.r_addr, "::.%d.%d", &hport, &lport); + if (!ok) + ok = sscanf(rhead->rpcb_map.r_addr, "0.0.0.0.%d.%d", + &hport, &lport); + if (!ok) continue; + c->port = hport << 8 | lport; - c->port = port; - c->name = strdup(prog); - if (strcmp(proto, TCP_PROTO) == 0) + if (strcmp(rhead->rpcb_map.r_netid, TCP_PROTO) == 0 || + strcmp(rhead->rpcb_map.r_netid, TCP6_PROTO) == 0) c->proto = TCP_PROTO; - else if (strcmp(proto, UDP_PROTO) == 0) + else if (strcmp(rhead->rpcb_map.r_netid, UDP_PROTO) == 0 || + strcmp(rhead->rpcb_map.r_netid, UDP6_PROTO) == 0) c->proto = UDP_PROTO; - else if (strcmp(proto, SCTP_PROTO) == 0) + else if (strcmp(rhead->rpcb_map.r_netid, SCTP_PROTO) == 0) c->proto = SCTP_PROTO; else - c->proto = NULL; + continue; + + rpc = getrpcbynumber(rhead->rpcb_map.r_prog); + if (rpc) { + strncat(prog, rpc->r_name, 128 - strlen(prog)); + c->name = strdup(prog); + } + c->next = rlist; rlist = c; } - pclose(fp); } +#endif /* Even do not try default linux ephemeral port ranges: * default /etc/services contains so much of useless crap @@ -2356,7 +2448,7 @@ out(" users:(%s)", buf); free(buf); } - } else if (show_users) { + } else if (show_processes || show_threads) { if (find_entry(s->ino, &buf, USERS) > 0) { out(" users:(%s)", buf); free(buf); @@ -2649,6 +2741,10 @@ out(" notsent:%u", s->not_sent); if (s->min_rtt) out(" minrtt:%g", s->min_rtt); + if (s->rcv_ooopack) + out(" rcv_ooopack:%u", s->rcv_ooopack); + if (s->snd_wnd) + out(" snd_wnd:%u", s->snd_wnd); } static void tcp_timer_print(struct tcpstat *s) @@ -2890,6 +2986,12 @@ } } +static void tcp_tls_zc_sendfile(struct rtattr *attr) +{ + if (attr) + out(" zc_ro_tx"); +} + static void mptcp_subflow_info(struct rtattr *tb) { u_int32_t flags = 0; @@ -3083,6 +3185,8 @@ s.reord_seen = info->tcpi_reord_seen; s.bytes_sent = info->tcpi_bytes_sent; s.bytes_retrans = info->tcpi_bytes_retrans; + s.rcv_ooopack = info->tcpi_rcv_ooopack; + s.snd_wnd = info->tcpi_snd_wnd; tcp_stats_print(&s); free(s.dctcp); free(s.bbr_info); @@ -3118,6 +3222,7 @@ tcp_tls_cipher(tlsinfoTLS_INFO_CIPHER); tcp_tls_conf("rxconf", tlsinfoTLS_INFO_RXCONF); tcp_tls_conf("txconf", tlsinfoTLS_INFO_TXCONF); + tcp_tls_zc_sendfile(tlsinfoTLS_INFO_ZC_RO_TX); } if (ulpinfoINET_ULP_INFO_MPTCP) { struct rtattr *sfinfoMPTCP_SUBFLOW_ATTR_MAX + 1 = @@ -4725,7 +4830,7 @@ getpidcon(pid, &pid_context); out(" proc_ctx=%s", pid_context ? : "unavailable"); - free(pid_context); + freecon(pid_context); } if (show_details) { @@ -5245,6 +5350,7 @@ " -e, --extended show detailed socket information\n" " -m, --memory show socket memory usage\n" " -p, --processes show process using socket\n" +" -T, --threads show thread using socket\n" " -i, --info show internal TCP information\n" " --tipcinfo show internal tipc socket information\n" " -s, --summary show socket usage summary\n" @@ -5252,8 +5358,8 @@ " --cgroup show cgroup information\n" " -b, --bpf show bpf filter socket information\n" " -E, --events continually display sockets as they are destroyed\n" -" -Z, --context display process SELinux security contexts\n" -" -z, --contexts display process and socket SELinux security contexts\n" +" -Z, --context display task SELinux security contexts\n" +" -z, --contexts display task and socket SELinux security contexts\n" " -N, --net switch to the specified network namespace name\n" "\n" " -4, --ipv4 display only IP version 4 sockets\n" @@ -5268,6 +5374,7 @@ " -x, --unix display only Unix domain sockets\n" " --tipc display only TIPC sockets\n" " --vsock display only vsock sockets\n" +" --xdp display only XDP sockets\n" " -f, --family=FAMILY display sockets of type FAMILY\n" " FAMILY := {inet|inet6|link|unix|netlink|vsock|tipc|xdp|help}\n" "\n" @@ -5277,7 +5384,7 @@ " --inet-sockopt show various inet socket options\n" "\n" " -A, --query=QUERY, --socket=QUERY\n" -" QUERY := {all|inet|tcp|mptcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|netlink|vsock_stream|vsock_dgram|tipc},QUERY\n" +" QUERY := {all|inet|tcp|mptcp|udp|raw|unix|unix_dgram|unix_stream|unix_seqpacket|packet|packet_raw|packet_dgram|netlink|dccp|sctp|vsock_stream|vsock_dgram|tipc|xdp},QUERY\n" "\n" " -D, --diag=FILE Dump raw information about TCP sockets to FILE\n" " -F, --filter=FILE read filter information from FILE\n" @@ -5374,6 +5481,7 @@ { "memory", 0, 0, 'm' }, { "info", 0, 0, 'i' }, { "processes", 0, 0, 'p' }, + { "threads", 0, 0, 'T' }, { "bpf", 0, 0, 'b' }, { "events", 0, 0, 'E' }, { "dccp", 0, 0, 'd' }, @@ -5424,7 +5532,7 @@ int state_filter = 0; while ((ch = getopt_long(argc, argv, - "dhaletuwxnro460spbEf:mMiA:D:F:vVzZN:KHSO", + "dhaletuwxnro460spTbEf:mMiA:D:F:vVzZN:KHSO", long_opts, NULL)) != EOF) { switch (ch) { case 'n': @@ -5447,8 +5555,10 @@ show_tcpinfo = 1; break; case 'p': - show_users++; - user_ent_hash_build(); + show_processes++; + break; + case 'T': + show_threads++; break; case 'b': show_options = 1; @@ -5583,7 +5693,6 @@ exit(1); } show_proc_ctx++; - user_ent_hash_build(); break; case 'N': if (netns_switch(optarg)) @@ -5618,6 +5727,9 @@ } } + if (show_processes || show_threads || show_proc_ctx || show_sock_ctx) + user_ent_hash_build(); + argc -= optind; argv += optind; @@ -5655,9 +5767,11 @@ filter_states_set(¤t_filter, state_filter); filter_merge_defaults(¤t_filter); +#ifdef HAVE_RPC if (!numeric && resolve_hosts && (current_filter.dbs & (UNIX_DBM|INET_L4_DBM))) init_service_resolver(); +#endif if (current_filter.dbs == 0) { fprintf(stderr, "ss: no socket tables to show with such filter.\n"); @@ -5733,7 +5847,7 @@ if (current_filter.dbs & (1<<MPTCP_DB)) mptcp_show(¤t_filter); - if (show_users || show_proc_ctx || show_sock_ctx) + if (show_processes || show_threads || show_proc_ctx || show_sock_ctx) user_ent_destroy(); render();
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/Makefile
Changed
@@ -1,16 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB include ../config.mk -TARGETS := - -ifeq ($(HAVE_MNL),y) CFLAGS += -I./include/uapi/ RDMA_OBJ = rdma.o utils.o dev.o link.o res.o res-pd.o res-mr.o res-cq.o \ res-cmid.o res-qp.o sys.o stat.o stat-mr.o res-ctx.o res-srq.o TARGETS += rdma -endif all: $(TARGETS) $(LIBS)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/include/uapi/rdma/ib_user_verbs.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/include/uapi/rdma/ib_user_verbs.h
Changed
@@ -158,18 +158,18 @@ struct ib_uverbs_get_context { __aligned_u64 response; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_get_context_resp { __u32 async_fd; __u32 num_comp_vectors; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_device { __aligned_u64 response; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_device_resp { @@ -278,7 +278,7 @@ __aligned_u64 response; __u8 port_num; __u8 reserved7; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_port_resp { @@ -308,12 +308,12 @@ struct ib_uverbs_alloc_pd { __aligned_u64 response; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_alloc_pd_resp { __u32 pd_handle; - __u32 driver_data0; + __u32 driver_data; }; struct ib_uverbs_dealloc_pd { @@ -324,12 +324,12 @@ __aligned_u64 response; __u32 fd; __u32 oflags; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_open_xrcd_resp { __u32 xrcd_handle; - __u32 driver_data0; + __u32 driver_data; }; struct ib_uverbs_close_xrcd { @@ -343,14 +343,14 @@ __aligned_u64 hca_va; __u32 pd_handle; __u32 access_flags; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_reg_mr_resp { __u32 mr_handle; __u32 lkey; __u32 rkey; - __u32 driver_data0; + __u32 driver_data; }; struct ib_uverbs_rereg_mr { @@ -362,13 +362,13 @@ __aligned_u64 hca_va; __u32 pd_handle; __u32 access_flags; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_rereg_mr_resp { __u32 lkey; __u32 rkey; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_dereg_mr { @@ -380,13 +380,13 @@ __u32 pd_handle; __u8 mw_type; __u8 reserved3; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_alloc_mw_resp { __u32 mw_handle; __u32 rkey; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_dealloc_mw { @@ -408,7 +408,7 @@ __u32 comp_vector; __s32 comp_channel; __u32 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; enum ib_uverbs_ex_create_cq_flags { @@ -442,13 +442,13 @@ __aligned_u64 response; __u32 cq_handle; __u32 cqe; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_resize_cq_resp { __u32 cqe; __u32 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_poll_cq { @@ -457,6 +457,17 @@ __u32 ne; }; +enum ib_uverbs_wc_opcode { + IB_UVERBS_WC_SEND = 0, + IB_UVERBS_WC_RDMA_WRITE = 1, + IB_UVERBS_WC_RDMA_READ = 2, + IB_UVERBS_WC_COMP_SWAP = 3, + IB_UVERBS_WC_FETCH_ADD = 4, + IB_UVERBS_WC_BIND_MW = 5, + IB_UVERBS_WC_LOCAL_INV = 6, + IB_UVERBS_WC_TSO = 7, +}; + struct ib_uverbs_wc { __aligned_u64 wr_id; __u32 status; @@ -481,7 +492,7 @@ struct ib_uverbs_poll_cq_resp { __u32 count; __u32 reserved; - struct ib_uverbs_wc wc0; + struct ib_uverbs_wc wc; }; struct ib_uverbs_req_notify_cq { @@ -574,7 +585,7 @@ __u8 qp_type; __u8 is_srq; __u8 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; enum ib_uverbs_create_qp_mask { @@ -585,20 +596,6 @@ IB_UVERBS_CREATE_QP_SUP_COMP_MASK = IB_UVERBS_CREATE_QP_MASK_IND_TABLE, }; -enum { - /* - * This value is equal to IB_QP_DEST_QPN. - */ - IB_USER_LEGACY_LAST_QP_ATTR_MASK = 1ULL << 20, -}; - -enum { - /* - * This value is equal to IB_QP_RATE_LIMIT. - */ - IB_USER_LAST_QP_ATTR_MASK = 1ULL << 25, -}; - struct ib_uverbs_ex_create_qp { __aligned_u64 user_handle; __u32 pd_handle; @@ -627,7 +624,7 @@ __u32 qpn; __u8 qp_type; __u8 reserved7; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; /* also used for open response */ @@ -672,7 +669,7 @@ __aligned_u64 response; __u32 qp_handle; __u32 attr_mask; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_qp_resp { @@ -706,7 +703,7 @@ __u8 alt_timeout; __u8 sq_sig_all; __u8 reserved5; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_modify_qp { @@ -827,7 +824,7 @@ __u32 wr_count; __u32 sge_count; __u32 wqe_size; - struct ib_uverbs_send_wr send_wr0; + struct ib_uverbs_send_wr send_wr; }; struct ib_uverbs_post_send_resp { @@ -846,7 +843,7 @@ __u32 wr_count; __u32 sge_count; __u32 wqe_size; - struct ib_uverbs_recv_wr recv_wr0; + struct ib_uverbs_recv_wr recv_wr; }; struct ib_uverbs_post_recv_resp { @@ -859,7 +856,7 @@ __u32 wr_count; __u32 sge_count; __u32 wqe_size; - struct ib_uverbs_recv_wr recv0; + struct ib_uverbs_recv_wr recv; }; struct ib_uverbs_post_srq_recv_resp { @@ -872,12 +869,12 @@ __u32 pd_handle; __u32 reserved; struct ib_uverbs_ah_attr attr; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_create_ah_resp { __u32 ah_handle; - __u32 driver_data0; + __u32 driver_data; }; struct ib_uverbs_destroy_ah { @@ -889,7 +886,7 @@ __u32 qp_handle; __u16 mlid; __u16 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_detach_mcast { @@ -897,7 +894,7 @@ __u32 qp_handle; __u16 mlid; __u16 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_flow_spec_hdr { @@ -1138,7 +1135,7 @@ * struct ib_flow_spec_xxx * struct ib_flow_spec_yyy */ - struct ib_uverbs_flow_spec_hdr flow_specs0; + struct ib_uverbs_flow_spec_hdr flow_specs; }; struct ib_uverbs_create_flow { @@ -1164,7 +1161,7 @@ __u32 max_wr; __u32 max_sge; __u32 srq_limit; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_create_xsrq { @@ -1178,7 +1175,7 @@ __u32 max_num_tags; __u32 xrcd_handle; __u32 cq_handle; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_create_srq_resp { @@ -1186,7 +1183,7 @@ __u32 max_wr; __u32 max_sge; __u32 srqn; - __u32 driver_data0; + __u32 driver_data; }; struct ib_uverbs_modify_srq { @@ -1194,14 +1191,14 @@ __u32 attr_mask; __u32 max_wr; __u32 srq_limit; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_srq { __aligned_u64 response; __u32 srq_handle; __u32 reserved; - __aligned_u64 driver_data0; + __aligned_u64 driver_data; }; struct ib_uverbs_query_srq_resp { @@ -1272,7 +1269,7 @@ * wq_handle1 * wq_handle2 */ - __u32 wq_handles0; + __u32 wq_handles; }; struct ib_uverbs_ex_create_rwq_ind_table_resp { @@ -1301,4 +1298,46 @@ #define IB_DEVICE_NAME_MAX 64 +/* + * bits 9, 15, 16, 19, 22, 27, 30, 31, 32, 33, 35 and 37 may be set by old + * kernels and should not be used. + */ +enum ib_uverbs_device_cap_flags { + IB_UVERBS_DEVICE_RESIZE_MAX_WR = 1 << 0, + IB_UVERBS_DEVICE_BAD_PKEY_CNTR = 1 << 1, + IB_UVERBS_DEVICE_BAD_QKEY_CNTR = 1 << 2, + IB_UVERBS_DEVICE_RAW_MULTI = 1 << 3, + IB_UVERBS_DEVICE_AUTO_PATH_MIG = 1 << 4, + IB_UVERBS_DEVICE_CHANGE_PHY_PORT = 1 << 5, + IB_UVERBS_DEVICE_UD_AV_PORT_ENFORCE = 1 << 6, + IB_UVERBS_DEVICE_CURR_QP_STATE_MOD = 1 << 7, + IB_UVERBS_DEVICE_SHUTDOWN_PORT = 1 << 8, + /* IB_UVERBS_DEVICE_INIT_TYPE = 1 << 9, (not in use) */ + IB_UVERBS_DEVICE_PORT_ACTIVE_EVENT = 1 << 10, + IB_UVERBS_DEVICE_SYS_IMAGE_GUID = 1 << 11, + IB_UVERBS_DEVICE_RC_RNR_NAK_GEN = 1 << 12, + IB_UVERBS_DEVICE_SRQ_RESIZE = 1 << 13, + IB_UVERBS_DEVICE_N_NOTIFY_CQ = 1 << 14, + IB_UVERBS_DEVICE_MEM_WINDOW = 1 << 17, + IB_UVERBS_DEVICE_UD_IP_CSUM = 1 << 18, + IB_UVERBS_DEVICE_XRC = 1 << 20, + IB_UVERBS_DEVICE_MEM_MGT_EXTENSIONS = 1 << 21, + IB_UVERBS_DEVICE_MEM_WINDOW_TYPE_2A = 1 << 23, + IB_UVERBS_DEVICE_MEM_WINDOW_TYPE_2B = 1 << 24, + IB_UVERBS_DEVICE_RC_IP_CSUM = 1 << 25, + /* Deprecated. Please use IB_UVERBS_RAW_PACKET_CAP_IP_CSUM. */ + IB_UVERBS_DEVICE_RAW_IP_CSUM = 1 << 26, + IB_UVERBS_DEVICE_MANAGED_FLOW_STEERING = 1 << 29, + /* Deprecated. Please use IB_UVERBS_RAW_PACKET_CAP_SCATTER_FCS. */ + IB_UVERBS_DEVICE_RAW_SCATTER_FCS = 1ULL << 34, + IB_UVERBS_DEVICE_PCI_WRITE_END_PADDING = 1ULL << 36, +}; + +enum ib_uverbs_raw_packet_caps { + IB_UVERBS_RAW_PACKET_CAP_CVLAN_STRIPPING = 1 << 0, + IB_UVERBS_RAW_PACKET_CAP_SCATTER_FCS = 1 << 1, + IB_UVERBS_RAW_PACKET_CAP_IP_CSUM = 1 << 2, + IB_UVERBS_RAW_PACKET_CAP_DELAY_DROP = 1 << 3, +}; + #endif /* IB_USER_VERBS_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/include/uapi/rdma/rdma_netlink.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/include/uapi/rdma/rdma_netlink.h
Changed
@@ -297,6 +297,8 @@ RDMA_NLDEV_CMD_RES_SRQ_GET, /* can dump */ + RDMA_NLDEV_CMD_STAT_GET_STATUS, + RDMA_NLDEV_NUM_OPS }; @@ -549,6 +551,9 @@ RDMA_NLDEV_SYS_ATTR_COPY_ON_FORK, /* u8 */ + RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX, /* u32 */ + RDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC, /* u8 */ + /* * Always the end */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/include/uapi/rdma/rdma_user_cm.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/include/uapi/rdma/rdma_user_cm.h
Changed
@@ -164,6 +164,8 @@ __u32 num_paths; __u8 port_num; __u8 reserved3; + __u32 ibdev_index; + __u32 reserved1; }; struct rdma_ucm_query_addr_resp { @@ -175,12 +177,14 @@ __u16 dst_size; struct __kernel_sockaddr_storage src_addr; struct __kernel_sockaddr_storage dst_addr; + __u32 ibdev_index; + __u32 reserved1; }; struct rdma_ucm_query_path_resp { __u32 num_paths; __u32 reserved; - struct ib_path_rec_data path_data0; + struct ib_path_rec_data path_data; }; struct rdma_ucm_conn_param { @@ -206,10 +210,16 @@ __u8 reserved7; }; +struct rdma_ucm_ece { + __u32 vendor_id; + __u32 attr_mod; +}; + struct rdma_ucm_connect { struct rdma_ucm_conn_param conn_param; __u32 id; __u32 reserved; + struct rdma_ucm_ece ece; }; struct rdma_ucm_listen { @@ -222,12 +232,14 @@ struct rdma_ucm_conn_param conn_param; __u32 id; __u32 reserved; + struct rdma_ucm_ece ece; }; struct rdma_ucm_reject { __u32 id; __u8 private_data_len; - __u8 reserved3; + __u8 reason; + __u8 reserved2; __u8 private_dataRDMA_MAX_PRIVATE_DATA; }; @@ -287,6 +299,7 @@ struct rdma_ucm_ud_param ud; } param; __u32 reserved; + struct rdma_ucm_ece ece; }; /* Option levels */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-cmid.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-cmid.c
Changed
@@ -159,8 +159,15 @@ goto out; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, @@ -173,22 +180,16 @@ nla_lineRDMA_NLDEV_ATTR_RES_CM_IDN)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - } - open_json_object(NULL); print_link(rd, idx, name, port, nla_line); - res_print_uint(rd, "cm-idn", cm_idn, + res_print_u32(rd, "cm-idn", cm_idn, nla_lineRDMA_NLDEV_ATTR_RES_CM_IDN); - res_print_uint(rd, "lqpn", lqpn, nla_lineRDMA_NLDEV_ATTR_RES_LQPN); + res_print_u32(rd, "lqpn", lqpn, nla_lineRDMA_NLDEV_ATTR_RES_LQPN); if (nla_lineRDMA_NLDEV_ATTR_RES_TYPE) print_qp_type(rd, type); print_cm_id_state(rd, state); print_ps(rd, ps); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); if (nla_lineRDMA_NLDEV_ATTR_RES_SRC_ADDR) @@ -199,8 +200,7 @@ print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); -out: if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); +out: return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-cq.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-cq.c
Changed
@@ -84,8 +84,15 @@ goto out; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, @@ -103,28 +110,22 @@ nla_lineRDMA_NLDEV_ATTR_RES_CTXN)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "cqn", cqn, nla_lineRDMA_NLDEV_ATTR_RES_CQN); - res_print_uint(rd, "cqe", cqe, nla_lineRDMA_NLDEV_ATTR_RES_CQE); - res_print_uint(rd, "users", users, + res_print_u32(rd, "cqn", cqn, nla_lineRDMA_NLDEV_ATTR_RES_CQN); + res_print_u32(rd, "cqe", cqe, nla_lineRDMA_NLDEV_ATTR_RES_CQE); + res_print_u64(rd, "users", users, nla_lineRDMA_NLDEV_ATTR_RES_USECNT); print_poll_ctx(rd, poll_ctx, nla_lineRDMA_NLDEV_ATTR_RES_POLL_CTX); print_cq_dim_setting(rd, nla_lineRDMA_NLDEV_ATTR_DEV_DIM); - res_print_uint(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); -out: if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); +out: return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-ctx.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-ctx.c
Changed
@@ -18,8 +18,15 @@ return MNL_CB_ERROR; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, @@ -33,23 +40,16 @@ nla_lineRDMA_NLDEV_ATTR_RES_CTXN)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); out: - if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-mr.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-mr.c
Changed
@@ -47,8 +47,15 @@ goto out; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, @@ -67,19 +74,15 @@ nla_lineRDMA_NLDEV_ATTR_RES_PDN)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "mrn", mrn, nla_lineRDMA_NLDEV_ATTR_RES_MRN); + res_print_u32(rd, "mrn", mrn, nla_lineRDMA_NLDEV_ATTR_RES_MRN); print_key(rd, "rkey", rkey, nla_lineRDMA_NLDEV_ATTR_RES_RKEY); print_key(rd, "lkey", lkey, nla_lineRDMA_NLDEV_ATTR_RES_LKEY); print_key(rd, "iova", iova, nla_lineRDMA_NLDEV_ATTR_RES_IOVA); - res_print_uint(rd, "mrlen", mrlen, nla_lineRDMA_NLDEV_ATTR_RES_MRLEN); - res_print_uint(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u64(rd, "mrlen", mrlen, nla_lineRDMA_NLDEV_ATTR_RES_MRLEN); + res_print_u32(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); @@ -87,8 +90,6 @@ newline(rd); out: - if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-pd.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-pd.c
Changed
@@ -34,8 +34,15 @@ nla_lineRDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY); if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, @@ -55,29 +62,23 @@ nla_lineRDMA_NLDEV_ATTR_RES_PDN)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); + res_print_u32(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); print_key(rd, "local_dma_lkey", local_dma_lkey, nla_lineRDMA_NLDEV_ATTR_RES_LOCAL_DMA_LKEY); - res_print_uint(rd, "users", users, + res_print_u64(rd, "users", users, nla_lineRDMA_NLDEV_ATTR_RES_USECNT); print_key(rd, "unsafe_global_rkey", unsafe_global_rkey, nla_lineRDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY); - res_print_uint(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "ctxn", ctxn, nla_lineRDMA_NLDEV_ATTR_RES_CTXN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); -out: if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); +out: return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-qp.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-qp.c
Changed
@@ -146,41 +146,41 @@ goto out; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } if (rd_is_filtered_attr(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID)) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - open_json_object(NULL); print_link(rd, idx, name, port, nla_line); - res_print_uint(rd, "lqpn", lqpn, nla_lineRDMA_NLDEV_ATTR_RES_LQPN); + res_print_u32(rd, "lqpn", lqpn, nla_lineRDMA_NLDEV_ATTR_RES_LQPN); print_rqpn(rd, rqpn, nla_line); print_type(rd, type); print_state(rd, state); print_rqpsn(rd, rq_psn, nla_line); - res_print_uint(rd, "sq-psn", sq_psn, + res_print_u32(rd, "sq-psn", sq_psn, nla_lineRDMA_NLDEV_ATTR_RES_SQ_PSN); print_pathmig(rd, path_mig_state, nla_line); - res_print_uint(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); out: - if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res-srq.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res-srq.c
Changed
@@ -70,9 +70,8 @@ *delimiter, tmp_min_range, tmp_max_range); - if (strlen(qp_str) + strlen(tmp) >= MAX_QP_STR_LEN) - return -EINVAL; - strncat(qp_str, tmp, sizeof(tmp) - 1); + strncat(qp_str, tmp, + MAX_QP_STR_LEN - strlen(qp_str) - 1); memset(tmp, 0, strlen(tmp)); *delimiter = ","; @@ -94,9 +93,7 @@ snprintf(tmp, sizeof(tmp), "%s%d-%d", *delimiter, tmp_min_range, tmp_max_range); - if (strlen(qp_str) + strlen(tmp) >= MAX_QP_STR_LEN) - return -EINVAL; - strncat(qp_str, tmp, sizeof(tmp) - 1); + strncat(qp_str, tmp, MAX_QP_STR_LEN - strlen(qp_str) - 1); *delimiter = ","; return 0; } @@ -137,9 +134,8 @@ qp_lineRDMA_NLDEV_ATTR_RES_LQPN)) continue; snprintf(tmp, sizeof(tmp), "%s%d", delimiter, qpn); - if (strlen(qp_str) + strlen(tmp) >= MAX_QP_STR_LEN) - goto out; - strncat(qp_str, tmp, sizeof(tmp) - 1); + strncat(qp_str, tmp, + MAX_QP_STR_LEN - strlen(qp_str) - 1); delimiter = ","; } else if (qp_lineRDMA_NLDEV_ATTR_MIN_RANGE && qp_lineRDMA_NLDEV_ATTR_MAX_RANGE) { @@ -178,9 +174,17 @@ return MNL_CB_ERROR; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } + if (rd_is_filtered_attr(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID)) goto out; @@ -213,27 +217,20 @@ MNL_CB_OK) goto out; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - /* discard const from mnl_attr_get_str */ - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "srqn", srqn, nla_lineRDMA_NLDEV_ATTR_RES_SRQN); + res_print_u32(rd, "srqn", srqn, nla_lineRDMA_NLDEV_ATTR_RES_SRQN); print_type(rd, type); print_qps(qp_str); - res_print_uint(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); - res_print_uint(rd, "cqn", cqn, nla_lineRDMA_NLDEV_ATTR_RES_CQN); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u32(rd, "pdn", pdn, nla_lineRDMA_NLDEV_ATTR_RES_PDN); + res_print_u32(rd, "cqn", cqn, nla_lineRDMA_NLDEV_ATTR_RES_CQN); + res_print_u32(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); print_driver_table(rd, nla_lineRDMA_NLDEV_ATTR_DRIVER); newline(rd); out: - if (nla_lineRDMA_NLDEV_ATTR_RES_PID) - free(comm); return MNL_CB_OK; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res.c
Changed
@@ -51,7 +51,7 @@ name = mnl_attr_get_str(nla_lineRDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_NAME); curr = mnl_attr_get_u64(nla_lineRDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR); - res_print_uint( + res_print_u64( rd, name, curr, nla_lineRDMA_NLDEV_ATTR_RES_SUMMARY_ENTRY_CURR); } @@ -146,12 +146,12 @@ "RAW_ETHERTYPE", "UNKNOWN", "RAW_PACKET", "XRC_INI", "XRC_TGT", - 0xFF = "DRIVER", }; - if (idx < ARRAY_SIZE(qp_types_str) && qp_types_stridx) + if (idx < ARRAY_SIZE(qp_types_str)) return qp_types_stridx; - return "UNKNOWN"; + + return (idx == 0xFF) ? "DRIVER" : "UNKNOWN"; } void print_comm(struct rd *rd, const char *str, struct nlattr **nla_line) @@ -208,13 +208,22 @@ print_color_hex(PRINT_ANY, COLOR_NONE, name, " 0x%" PRIx64 " ", val); } -void res_print_uint(struct rd *rd, const char *name, uint64_t val, +void res_print_u32(struct rd *rd, const char *name, uint32_t val, struct nlattr *nlattr) { if (!nlattr) return; print_color_uint(PRINT_ANY, COLOR_NONE, name, name, val); - print_color_uint(PRINT_FP, COLOR_NONE, NULL, " %d ", val); + print_color_uint(PRINT_FP, COLOR_NONE, NULL, " %" PRIu32 " ", val); +} + +void res_print_u64(struct rd *rd, const char *name, uint64_t val, + struct nlattr *nlattr) +{ + if (!nlattr) + return; + print_color_u64(PRINT_ANY, COLOR_NONE, name, name, val); + print_color_u64(PRINT_FP, COLOR_NONE, NULL, " %" PRIu64 " ", val); } RES_FUNC(res_no_args, RDMA_NLDEV_CMD_RES_GET, NULL, true, 0);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/res.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/res.h
Changed
@@ -188,7 +188,9 @@ struct nlattr **nla_line); void print_key(struct rd *rd, const char *name, uint64_t val, struct nlattr *nlattr); -void res_print_uint(struct rd *rd, const char *name, uint64_t val, +void res_print_u32(struct rd *rd, const char *name, uint32_t val, + struct nlattr *nlattr); +void res_print_u64(struct rd *rd, const char *name, uint64_t val, struct nlattr *nlattr); void print_comm(struct rd *rd, const char *str, struct nlattr **nla_line); const char *qp_types_to_str(uint8_t idx);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/stat-mr.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/stat-mr.c
Changed
@@ -22,7 +22,7 @@ open_json_object(NULL); print_dev(rd, idx, name); - res_print_uint(rd, "mrn", mrn, nla_lineRDMA_NLDEV_ATTR_RES_MRN); + res_print_u32(rd, "mrn", mrn, nla_lineRDMA_NLDEV_ATTR_RES_MRN); if (nla_lineRDMA_NLDEV_ATTR_STAT_HWCOUNTERS) { ret = res_get_hwcounters(
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/rdma/stat.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/rdma/stat.c
Changed
@@ -20,6 +20,10 @@ pr_out(" %s statistic OBJECT unbind COUNTER_SCOPE DEV/PORT_INDEX COUNTER-ID\n", rd->filename); pr_out(" %s statistic show\n", rd->filename); pr_out(" %s statistic show link DEV/PORT_INDEX \n", rd->filename); + pr_out(" %s statistic mode supported \n", rd->filename); + pr_out(" %s statistic mode supported link DEV/PORT_INDEX \n", rd->filename); + pr_out(" %s statistic set link DEV/PORT_INDEX optional-counters OPTIONAL-COUNTERS \n", rd->filename); + pr_out(" %s statistic unset link DEV/PORT_INDEX optional-counters\n", rd->filename); pr_out("where OBJECT: = { qp }\n"); pr_out(" CRITERIA : = { type }\n"); pr_out(" COUNTER_SCOPE: = { link | dev }\n"); @@ -37,6 +41,12 @@ pr_out(" %s statistic qp unbind link mlx5_2/1 cntn 4 lqpn 178\n", rd->filename); pr_out(" %s statistic show\n", rd->filename); pr_out(" %s statistic show link mlx5_2/1\n", rd->filename); + pr_out(" %s statistic mode\n", rd->filename); + pr_out(" %s statistic mode link mlx5_2/1\n", rd->filename); + pr_out(" %s statistic mode supported\n", rd->filename); + pr_out(" %s statistic mode supported link mlx5_2/1\n", rd->filename); + pr_out(" %s statistic set link mlx5_2/1 optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts\n", rd->filename); + pr_out(" %s statistic unset link mlx5_2/1 optional-counters\n", rd->filename); return 0; } @@ -200,7 +210,7 @@ v = mnl_attr_get_u64(hw_lineRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_VALUE); if (rd->pretty_output && !rd->json_output) newline_indent(rd); - res_print_uint(rd, nm, v, hw_lineRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME); + res_print_u64(rd, nm, v, hw_lineRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME); } return MNL_CB_OK; @@ -238,17 +248,21 @@ return MNL_CB_OK; if (nla_lineRDMA_NLDEV_ATTR_RES_PID) { + SPRINT_BUF(b); + pid = mnl_attr_get_u32(nla_lineRDMA_NLDEV_ATTR_RES_PID); - comm = get_task_name(pid); + if (!get_task_name(pid, b, sizeof(b))) + comm = b; + } else if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) { + /* discard const from mnl_attr_get_str */ + comm = (char *)mnl_attr_get_str( + nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); } + if (rd_is_filtered_attr(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID)) return MNL_CB_OK; - if (nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME) - comm = (char *)mnl_attr_get_str( - nla_lineRDMA_NLDEV_ATTR_RES_KERN_NAME); - mnl_attr_for_each_nested(nla_entry, qp_table) { struct nlattr *qp_lineRDMA_NLDEV_ATTR_MAX = {}; @@ -273,7 +287,7 @@ print_color_uint(PRINT_ANY, COLOR_NONE, "cntn", "cntn %u ", cntn); if (nla_lineRDMA_NLDEV_ATTR_RES_TYPE) print_qp_type(rd, qp_type); - res_print_uint(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); + res_print_u64(rd, "pid", pid, nla_lineRDMA_NLDEV_ATTR_RES_PID); print_comm(rd, comm, nla_line); res_get_hwcounters(rd, hwc_table, true); isfirst = true; @@ -493,6 +507,30 @@ return rd_exec_cmd(rd, cmds, "parameter"); } +static int stat_get_arg_str(struct rd *rd, const char *arg, char **value, bool allow_empty) +{ + int len = 0; + + if (strcmpx(rd_argv(rd), arg) != 0) { + pr_err("Unknown parameter '%s'.\n", rd_argv(rd)); + return -EINVAL; + } + + rd_arg_inc(rd); + if (!rd_no_arg(rd)) { + *value = strdup(rd_argv(rd)); + len = strlen(*value); + rd_arg_inc(rd); + } + + if ((allow_empty && len) || (!allow_empty && !len)) { + stat_help(rd); + return -EINVAL; + } + + return 0; +} + static int stat_get_arg(struct rd *rd, const char *arg) { int value = 0; @@ -715,6 +753,310 @@ return rd_exec_cmd(rd, cmds, "parameter"); } +static int do_stat_mode_parse_cb(const struct nlmsghdr *nlh, void *data, + bool supported) +{ + struct nlattr *tbRDMA_NLDEV_ATTR_MAX = {}; + struct nlattr *nla_entry; + const char *dev, *name; + struct rd *rd = data; + int enabled, err = 0; + bool isfirst = true; + uint32_t port; + + mnl_attr_parse(nlh, 0, rd_attr_cb, tb); + if (!tbRDMA_NLDEV_ATTR_DEV_INDEX || !tbRDMA_NLDEV_ATTR_DEV_NAME || + !tbRDMA_NLDEV_ATTR_PORT_INDEX || + !tbRDMA_NLDEV_ATTR_STAT_HWCOUNTERS) + return MNL_CB_ERROR; + + dev = mnl_attr_get_str(tbRDMA_NLDEV_ATTR_DEV_NAME); + port = mnl_attr_get_u32(tbRDMA_NLDEV_ATTR_PORT_INDEX); + + mnl_attr_for_each_nested(nla_entry, + tbRDMA_NLDEV_ATTR_STAT_HWCOUNTERS) { + struct nlattr *cntRDMA_NLDEV_ATTR_MAX = {}; + + err = mnl_attr_parse_nested(nla_entry, rd_attr_cb, cnt); + if ((err != MNL_CB_OK) || + (!cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME)) + return -EINVAL; + + if (!cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC) + continue; + + enabled = mnl_attr_get_u8(cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC); + name = mnl_attr_get_str(cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME); + if (supported || enabled) { + if (isfirst) { + open_json_object(NULL); + print_color_string(PRINT_ANY, COLOR_NONE, + "ifname", "link %s/", dev); + print_color_uint(PRINT_ANY, COLOR_NONE, "port", + "%u ", port); + if (supported) + open_json_array(PRINT_ANY, + "supported optional-counters"); + else + open_json_array(PRINT_ANY, + "optional-counters"); + print_color_string(PRINT_FP, COLOR_NONE, NULL, + " ", NULL); + isfirst = false; + } else { + print_color_string(PRINT_FP, COLOR_NONE, NULL, + ",", NULL); + } + if (rd->pretty_output && !rd->json_output) + newline_indent(rd); + + print_color_string(PRINT_ANY, COLOR_NONE, NULL, "%s", + name); + } + } + + if (!isfirst) { + close_json_array(PRINT_JSON, NULL); + newline(rd); + } + + return 0; +} + +static int stat_mode_parse_cb(const struct nlmsghdr *nlh, void *data) +{ + return do_stat_mode_parse_cb(nlh, data, false); +} + +static int stat_mode_parse_cb_supported(const struct nlmsghdr *nlh, void *data) +{ + return do_stat_mode_parse_cb(nlh, data, true); +} + +static int stat_one_link_get_status_req(struct rd *rd, uint32_t *seq) +{ + int flags = NLM_F_REQUEST | NLM_F_ACK; + + rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_GET_STATUS, seq, flags); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, rd->dev_idx); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, rd->port_idx); + + return rd_send_msg(rd); +} + +static int stat_one_link_get_mode(struct rd *rd) +{ + uint32_t seq; + int err; + + if (!rd->port_idx) + return 0; + + err = stat_one_link_get_status_req(rd, &seq); + if (err) + return err; + + return rd_recv_msg(rd, stat_mode_parse_cb, rd, seq); +} + +static int stat_one_link_get_mode_supported(struct rd *rd) +{ + uint32_t seq; + int err; + + if (!rd->port_idx) + return 0; + + err = stat_one_link_get_status_req(rd, &seq); + if (err) + return err; + + return rd_recv_msg(rd, stat_mode_parse_cb_supported, rd, seq); +} + +static int stat_link_get_mode(struct rd *rd) +{ + return rd_exec_link(rd, stat_one_link_get_mode, false); +} + +static int stat_link_get_mode_supported(struct rd *rd) +{ + return rd_exec_link(rd, stat_one_link_get_mode_supported, false); +} + +static int stat_mode_supported(struct rd *rd) +{ + const struct rd_cmd cmds = { + { NULL, stat_link_get_mode_supported }, + { "link", stat_link_get_mode_supported }, + { "help", stat_help }, + { 0 }, + }; + return rd_exec_cmd(rd, cmds, "parameter"); +} + +static int stat_mode(struct rd *rd) +{ + const struct rd_cmd cmds = { + { NULL, stat_link_get_mode }, + { "link", stat_link_get_mode }, + { "show", stat_link_get_mode }, + { "supported", stat_mode_supported }, + { "help", stat_help }, + { 0 }, + }; + + return rd_exec_cmd(rd, cmds, "parameter"); +} + +static int stat_one_set_link_opcounters(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tbRDMA_NLDEV_ATTR_MAX = {}; + struct nlattr *nla_entry, *tb_set; + int ret, flags = NLM_F_REQUEST | NLM_F_ACK; + char *opcnt, *opcnts; + struct rd *rd = data; + uint32_t seq; + bool found; + + mnl_attr_parse(nlh, 0, rd_attr_cb, tb); + if (!tbRDMA_NLDEV_ATTR_STAT_HWCOUNTERS) + return MNL_CB_ERROR; + + if (rd_no_arg(rd)) { + stat_help(rd); + return -EINVAL; + } + + ret = stat_get_arg_str(rd, "optional-counters", &opcnts, false); + if (ret) + return ret; + + rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET, &seq, flags); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, + rd->dev_idx); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, + rd->port_idx); + + tb_set = mnl_attr_nest_start(rd->nlh, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS); + + opcnt = strtok(opcnts, ","); + while (opcnt) { + found = false; + mnl_attr_for_each_nested(nla_entry, + tbRDMA_NLDEV_ATTR_STAT_HWCOUNTERS) { + struct nlattr *cntRDMA_NLDEV_ATTR_MAX = {}, *nm, *id; + + if (mnl_attr_parse_nested(nla_entry, rd_attr_cb, + cnt) != MNL_CB_OK) + return -EINVAL; + + nm = cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_ENTRY_NAME; + id = cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX; + if (!nm || ! id) + return -EINVAL; + + if (!cntRDMA_NLDEV_ATTR_STAT_HWCOUNTER_DYNAMIC) + continue; + + if (strcmp(opcnt, mnl_attr_get_str(nm)) == 0) { + mnl_attr_put_u32(rd->nlh, + RDMA_NLDEV_ATTR_STAT_HWCOUNTER_INDEX, + mnl_attr_get_u32(id)); + found = true; + } + } + + if (!found) + return -EINVAL; + + opcnt = strtok(NULL, ","); + } + mnl_attr_nest_end(rd->nlh, tb_set); + + return rd_sendrecv_msg(rd, seq); +} + +static int stat_one_set_link(struct rd *rd) +{ + uint32_t seq; + int err; + + if (!rd->port_idx) + return 0; + + err = stat_one_link_get_status_req(rd, &seq); + if (err) + return err; + + return rd_recv_msg(rd, stat_one_set_link_opcounters, rd, seq); +} + +static int stat_set_link(struct rd *rd) +{ + return rd_exec_link(rd, stat_one_set_link, true); +} + +static int stat_set(struct rd *rd) +{ + const struct rd_cmd cmds = { + { NULL, stat_help }, + { "link", stat_set_link }, + { "help", stat_help }, + { 0 }, + }; + return rd_exec_cmd(rd, cmds, "parameter"); +} + +static int stat_one_unset_link_opcounters(struct rd *rd) +{ + int ret, flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlattr *tbl; + uint32_t seq; + char *opcnts; + + if (rd_no_arg(rd)) { + stat_help(rd); + return -EINVAL; + } + + ret = stat_get_arg_str(rd, "optional-counters", &opcnts, true); + if (ret) + return ret; + + rd_prepare_msg(rd, RDMA_NLDEV_CMD_STAT_SET, &seq, flags); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_DEV_INDEX, + rd->dev_idx); + mnl_attr_put_u32(rd->nlh, RDMA_NLDEV_ATTR_PORT_INDEX, + rd->port_idx); + + tbl = mnl_attr_nest_start(rd->nlh, RDMA_NLDEV_ATTR_STAT_HWCOUNTERS); + mnl_attr_nest_end(rd->nlh, tbl); + + return rd_sendrecv_msg(rd, seq); +} + +static int stat_one_unset_link(struct rd *rd) +{ + return stat_one_unset_link_opcounters(rd); +} + +static int stat_unset_link(struct rd *rd) +{ + return rd_exec_link(rd, stat_one_unset_link, true); +} + +static int stat_unset(struct rd *rd) +{ + const struct rd_cmd cmds = { + { NULL, stat_help }, + { "link", stat_unset_link }, + { "help", stat_help }, + { 0 }, + }; + return rd_exec_cmd(rd, cmds, "parameter"); +} + static int stat_show_parse_cb(const struct nlmsghdr *nlh, void *data) { struct nlattr *tbRDMA_NLDEV_ATTR_MAX = {}; @@ -786,6 +1128,9 @@ { "help", stat_help }, { "qp", stat_qp }, { "mr", stat_mr }, + { "mode", stat_mode }, + { "set", stat_set }, + { "unset", stat_unset }, { 0 } };
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/em_u32.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/em_u32.c
Changed
@@ -84,7 +84,7 @@ char bufa->len - nh_len + 1; offmask = -1; - memcpy(buf, a->data + nh_len, a->len - nh_len); + strncpy(buf, a->data + nh_len, a->len - nh_len + 1); offset = strtoul(buf, NULL, 0); } else if (!bstrcmp(a, "nexthdr+")) { a = bstr_next(a);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_basic.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_basic.c
Changed
@@ -70,14 +70,14 @@ continue; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, MAX_MSG, TCA_BASIC_CLASSID, &handle, 4); + addattr_l(n, MAX_MSG, TCA_BASIC_CLASSID, &classid, 4); } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_BASIC_ACT, n)) { @@ -119,19 +119,22 @@ parse_rtattr_nested(tb, TCA_BASIC_MAX, opt); if (handle) - fprintf(f, "handle 0x%x ", handle); + print_hex(PRINT_ANY, "handle", + "handle 0x%x ", handle); if (tbTCA_BASIC_CLASSID) { + uint32_t classid = rta_getattr_u32(tbTCA_BASIC_CLASSID); SPRINT_BUF(b1); - fprintf(f, "flowid %s ", - sprint_tc_classid(rta_getattr_u32(tbTCA_BASIC_CLASSID), b1)); + + print_string(PRINT_ANY, "flowid", "flowid %s ", + sprint_tc_classid(classid, b1)); } if (tbTCA_BASIC_EMATCHES) print_ematch(f, tbTCA_BASIC_EMATCHES); if (tbTCA_BASIC_POLICE) { - fprintf(f, "\n"); + print_nl(); tc_print_police(f, tbTCA_BASIC_POLICE); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_bpf.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_bpf.c
Changed
@@ -126,14 +126,14 @@ bpf_uds_name = cfg.uds; } else if (matches(*argv, "classid") == 0 || matches(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr32(n, MAX_MSG, TCA_BPF_CLASSID, handle); + addattr32(n, MAX_MSG, TCA_BPF_CLASSID, classid); } else if (matches(*argv, "direct-action") == 0 || matches(*argv, "da") == 0) { bpf_flags |= TCA_BPF_FLAG_ACT_DIRECT;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_flower.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_flower.c
Changed
@@ -20,6 +20,7 @@ #include <linux/ip.h> #include <linux/tc_act/tc_vlan.h> #include <linux/mpls.h> +#include <linux/ppp_defs.h> #include "utils.h" #include "tc_util.h" @@ -48,12 +49,15 @@ "\n" "Where: MATCH-LIST := MATCH-LIST MATCH\n" " MATCH := { indev DEV-NAME |\n" + " num_of_vlans VLANS_COUNT |\n" " vlan_id VID |\n" " vlan_prio PRIORITY |\n" " vlan_ethtype ipv4 | ipv6 | ETH-TYPE |\n" " cvlan_id VID |\n" " cvlan_prio PRIORITY |\n" " cvlan_ethtype ipv4 | ipv6 | ETH-TYPE |\n" + " pppoe_sid PSID |\n" + " ppp_proto ipv4 | ipv6 | mpls_uc | mpls_mc | PPP_PROTO " " dst_mac MASKED-LLADDR |\n" " src_mac MASKED-LLADDR |\n" " ip_proto tcp | udp | sctp | icmp | icmpv6 | IP-PROTO |\n" @@ -84,7 +88,8 @@ " geneve_opts MASKED-OPTIONS |\n" " vxlan_opts MASKED-OPTIONS |\n" " erspan_opts MASKED-OPTIONS |\n" - " ip_flags IP-FLAGS | \n" + " gtp_opts MASKED-OPTIONS |\n" + " ip_flags IP-FLAGS |\n" " enc_dst_port port_number |\n" " ct_state MASKED_CT_STATE |\n" " ct_label MASKED_CT_LABEL |\n" @@ -102,6 +107,19 @@ " to specify different mask, he has to use different prio.\n"); } +/* prints newline, two spaces, name/value */ +static void print_indent_name_value(const char *name, const char *value) +{ + print_string(PRINT_FP, NULL, "%s ", _SL_); + print_string_name_value(name, value); +} + +static void print_uint_indent_name_value(const char *name, unsigned int value) +{ + print_string(PRINT_FP, NULL, " ", NULL); + print_uint_name_value(name, value); +} + static int flower_parse_eth_addr(char *str, int addr_type, int mask_type, struct nlmsghdr *n) { @@ -118,7 +136,7 @@ addattr_l(n, MAX_MSG, addr_type, addr, sizeof(addr)); if (slash) { - unsigned bits; + unsigned int bits; if (!get_unsigned(&bits, slash + 1, 10)) { uint64_t mask; @@ -145,21 +163,23 @@ return err; } -static bool eth_type_vlan(__be16 ethertype) +static bool eth_type_vlan(__be16 ethertype, bool good_num_of_vlans) { return ethertype == htons(ETH_P_8021Q) || - ethertype == htons(ETH_P_8021AD); + ethertype == htons(ETH_P_8021AD) || + good_num_of_vlans; } static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type, __be16 *p_vlan_eth_type, - struct nlmsghdr *n) + struct nlmsghdr *n, bool good_num_of_vlans) { __be16 vlan_eth_type; - if (!eth_type_vlan(eth_type)) { - fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD\n", - type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype"); + if (!eth_type_vlan(eth_type, good_num_of_vlans)) { + fprintf(stderr, "Can't set \"%s\" if ethertype isn't 802.1Q or 802.1AD and num_of_vlans %s\n", + type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "vlan_ethtype" : "cvlan_ethtype", + type == TCA_FLOWER_KEY_VLAN_ETH_TYPE ? "is 0" : "less than 2"); return -1; } @@ -529,8 +549,7 @@ ret = get_u8(&mask, slash + 1, 10); if (ret) goto err; - } - else { + } else { mask = UINT8_MAX; } @@ -1022,6 +1041,52 @@ return 0; } +static int flower_parse_gtp_opt(char *str, struct nlmsghdr *n) +{ + struct rtattr *nest; + char *token; + int arg, err; + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_GTP | NLA_F_NESTED); + + token = strsep(&str, ":"); + for (arg = 1; arg <= TCA_FLOWER_KEY_ENC_OPT_GTP_MAX; arg++) { + switch (arg) { + case TCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE: + { + __u8 pdu_type; + + if (!strlen(token)) + break; + err = get_u8(&pdu_type, token, 16); + if (err) + return err; + addattr8(n, MAX_MSG, arg, pdu_type); + break; + } + case TCA_FLOWER_KEY_ENC_OPT_GTP_QFI: + { + __u8 qfi; + + if (!strlen(token)) + break; + err = get_u8(&qfi, token, 16); + if (err) + return err; + addattr8(n, MAX_MSG, arg, qfi); + break; + } + default: + fprintf(stderr, "Unknown \"gtp_opts\" type\n"); + return -1; + } + token = strsep(&str, ":"); + } + addattr_nest_end(n, nest); + + return 0; +} + static int flower_parse_geneve_opts(char *str, struct nlmsghdr *n) { char *token; @@ -1205,6 +1270,41 @@ return 0; } +static int flower_parse_enc_opts_gtp(char *str, struct nlmsghdr *n) +{ + char keyXATTR_SIZE_MAX, maskXATTR_SIZE_MAX; + struct rtattr *nest; + char *slash; + int err; + + slash = strchr(str, '/'); + if (slash) { + *slash++ = '\0'; + if (strlen(slash) > XATTR_SIZE_MAX) + return -1; + strcpy(mask, slash); + } else + strcpy(mask, "ff:ff"); + + if (strlen(str) > XATTR_SIZE_MAX) + return -1; + strcpy(key, str); + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS | NLA_F_NESTED); + err = flower_parse_gtp_opt(key, n); + if (err) + return err; + addattr_nest_end(n, nest); + + nest = addattr_nest(n, MAX_MSG, TCA_FLOWER_KEY_ENC_OPTS_MASK | NLA_F_NESTED); + err = flower_parse_gtp_opt(mask, n); + if (err) + return err; + addattr_nest_end(n, nest); + + return 0; +} + static int flower_parse_mpls_lse(int *argc_p, char ***argv_p, struct nlmsghdr *nlh) { @@ -1330,6 +1430,7 @@ __be16 tc_proto = TC_H_MIN(t->tcm_info); __be16 eth_type = tc_proto; __be16 vlan_ethtype = 0; + __u8 num_of_vlans = 0; __u8 ip_proto = 0xff; __u32 flags = 0; __u32 mtf = 0; @@ -1354,17 +1455,17 @@ while (argc > 0) { if (matches(*argv, "classid") == 0 || matches(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - ret = get_tc_classid(&handle, *argv); + ret = get_tc_classid(&classid, *argv); if (ret) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4); + addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &classid, 4); } else if (matches(*argv, "hw_tc") == 0) { - unsigned int handle; + unsigned int classid; __u32 tc; char *end; @@ -1378,10 +1479,10 @@ fprintf(stderr, "TC index exceeds max range\n"); return -1; } - handle = TC_H_MAKE(TC_H_MAJ(t->tcm_parent), + classid = TC_H_MAKE(TC_H_MAJ(t->tcm_parent), TC_H_MIN(tc + TC_H_MIN_PRIORITY)); - addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, - sizeof(handle)); + addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &classid, + sizeof(classid)); } else if (matches(*argv, "ip_flags") == 0) { NEXT_ARG(); ret = flower_parse_matching_flags(*argv, @@ -1431,12 +1532,22 @@ if (check_ifname(*argv)) invarg("\"indev\" not a valid ifname", *argv); addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, *argv); + } else if (strcmp(*argv, "num_of_vlans") == 0) { + NEXT_ARG(); + ret = get_u8(&num_of_vlans, *argv, 10); + if (ret < 0) { + fprintf(stderr, "Illegal \"num_of_vlans\"\n"); + return -1; + } + addattr8(n, MAX_MSG, + TCA_FLOWER_KEY_NUM_OF_VLANS, num_of_vlans); } else if (matches(*argv, "vlan_id") == 0) { __u16 vid; NEXT_ARG(); - if (!eth_type_vlan(tc_proto)) { - fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD\n"); + if (!eth_type_vlan(tc_proto, num_of_vlans > 0)) { + fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q or 802.1AD" + " and num_of_vlans is 0\n"); return -1; } ret = get_u16(&vid, *argv, 10); @@ -1449,8 +1560,9 @@ __u8 vlan_prio; NEXT_ARG(); - if (!eth_type_vlan(tc_proto)) { - fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD\n"); + if (!eth_type_vlan(tc_proto, num_of_vlans > 0)) { + fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q or 802.1AD" + " and num_of_vlans is 0\n"); return -1; } ret = get_u8(&vlan_prio, *argv, 10); @@ -1464,7 +1576,7 @@ NEXT_ARG(); ret = flower_parse_vlan_eth_type(*argv, eth_type, TCA_FLOWER_KEY_VLAN_ETH_TYPE, - &vlan_ethtype, n); + &vlan_ethtype, n, num_of_vlans > 0); if (ret < 0) return -1; /* get new ethtype for later parsing */ @@ -1473,8 +1585,9 @@ __u16 vid; NEXT_ARG(); - if (!eth_type_vlan(vlan_ethtype)) { - fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n"); + if (!eth_type_vlan(vlan_ethtype, num_of_vlans > 1)) { + fprintf(stderr, "Can't set \"cvlan_id\" if inner vlan ethertype isn't 802.1Q or 802.1AD" + " and num_of_vlans is less than 2\n"); return -1; } ret = get_u16(&vid, *argv, 10); @@ -1487,8 +1600,9 @@ __u8 cvlan_prio; NEXT_ARG(); - if (!eth_type_vlan(vlan_ethtype)) { - fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD\n"); + if (!eth_type_vlan(vlan_ethtype, num_of_vlans > 1)) { + fprintf(stderr, "Can't set \"cvlan_prio\" if inner vlan ethertype isn't 802.1Q or 802.1AD" + " and num_of_vlans is less than 2\n"); return -1; } ret = get_u8(&cvlan_prio, *argv, 10); @@ -1503,7 +1617,7 @@ /* get new ethtype for later parsing */ ret = flower_parse_vlan_eth_type(*argv, vlan_ethtype, TCA_FLOWER_KEY_CVLAN_ETH_TYPE, - ð_type, n); + ð_type, n, num_of_vlans > 1); if (ret < 0) return -1; } else if (matches(*argv, "mpls") == 0) { @@ -1776,6 +1890,43 @@ fprintf(stderr, "Illegal \"arp_sha\"\n"); return -1; } + + } else if (!strcmp(*argv, "pppoe_sid")) { + __be16 sid; + + NEXT_ARG(); + if (eth_type != htons(ETH_P_PPP_SES)) { + fprintf(stderr, + "Can't set \"pppoe_sid\" if ethertype isn't PPPoE session\n"); + return -1; + } + ret = get_be16(&sid, *argv, 10); + if (ret < 0) { + fprintf(stderr, "Illegal \"pppoe_sid\"\n"); + return -1; + } + addattr16(n, MAX_MSG, TCA_FLOWER_KEY_PPPOE_SID, sid); + } else if (!strcmp(*argv, "ppp_proto")) { + __be16 proto; + + NEXT_ARG(); + if (eth_type != htons(ETH_P_PPP_SES)) { + fprintf(stderr, + "Can't set \"ppp_proto\" if ethertype isn't PPPoE session\n"); + return -1; + } + if (ppp_proto_a2n(&proto, *argv)) + invarg("invalid ppp_proto", *argv); + /* get new ethtype for later parsing */ + if (proto == htons(PPP_IP)) + eth_type = htons(ETH_P_IP); + else if (proto == htons(PPP_IPV6)) + eth_type = htons(ETH_P_IPV6); + else if (proto == htons(PPP_MPLS_UC)) + eth_type = htons(ETH_P_MPLS_UC); + else if (proto == htons(PPP_MPLS_MC)) + eth_type = htons(ETH_P_MPLS_MC); + addattr16(n, MAX_MSG, TCA_FLOWER_KEY_PPP_PROTO, proto); } else if (matches(*argv, "enc_dst_ip") == 0) { NEXT_ARG(); ret = flower_parse_ip_addr(*argv, 0, @@ -1857,6 +2008,13 @@ fprintf(stderr, "Illegal \"erspan_opts\"\n"); return -1; } + } else if (!strcmp(*argv, "gtp_opts")) { + NEXT_ARG(); + ret = flower_parse_enc_opts_gtp(*argv, n); + if (ret < 0) { + fprintf(stderr, "Illegal \"gtp_opts\"\n"); + return -1; + } } else if (matches(*argv, "action") == 0) { NEXT_ARG(); ret = parse_action(&argc, &argv, TCA_FLOWER_ACT, n); @@ -1865,11 +2023,9 @@ return -1; } continue; - } else if (strcmp(*argv, "help") == 0) { - explain(); - return -1; } else { - fprintf(stderr, "What is \"%s\"?\n", *argv); + if (strcmp(*argv, "help") != 0) + fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } @@ -1917,7 +2073,7 @@ bits++; } else if (bits) { hole = true; - } else{ + } else { return -1; } } @@ -1925,10 +2081,9 @@ return bits; } -static void flower_print_eth_addr(char *name, struct rtattr *addr_attr, +static void flower_print_eth_addr(const char *name, struct rtattr *addr_attr, struct rtattr *mask_attr) { - SPRINT_BUF(namefrm); SPRINT_BUF(out); SPRINT_BUF(b1); size_t done; @@ -1949,9 +2104,7 @@ sprintf(out + done, "/%d", bits); } - print_nl(); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + print_indent_name_value(name, out); } static void flower_print_eth_type(__be16 *p_eth_type, @@ -2064,7 +2217,6 @@ { struct rtattr *addr_attr; struct rtattr *mask_attr; - SPRINT_BUF(namefrm); SPRINT_BUF(out); size_t done; int family; @@ -2095,10 +2247,9 @@ else if (bits < len * 8) sprintf(out + done, "/%d", bits); - print_nl(); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + print_indent_name_value(name, out); } + static void flower_print_ip4_addr(char *name, struct rtattr *addr_attr, struct rtattr *mask_attr) { @@ -2124,22 +2275,18 @@ print_hu(PRINT_JSON, "end", NULL, rta_getattr_be16(max_attr)); close_json_object(); } else { - SPRINT_BUF(namefrm); SPRINT_BUF(out); size_t done; done = sprintf(out, "%u", rta_getattr_be16(min_attr)); sprintf(out + done, "-%u", rta_getattr_be16(max_attr)); - print_nl(); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + print_indent_name_value(name, out); } } static void flower_print_tcp_flags(const char *name, struct rtattr *flags_attr, struct rtattr *mask_attr) { - SPRINT_BUF(namefrm); SPRINT_BUF(out); size_t done; @@ -2150,9 +2297,7 @@ if (mask_attr) sprintf(out + done, "/%x", rta_getattr_be16(mask_attr)); - print_nl(); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + print_indent_name_value(name, out); } static void flower_print_ct_state(struct rtattr *flags_attr, @@ -2195,7 +2340,7 @@ const unsigned char *str; bool print_mask = false; int data_len, i; - SPRINT_BUF(out); + char out128; char *p; if (!attr) @@ -2239,14 +2384,11 @@ static void flower_print_key_id(const char *name, struct rtattr *attr) { - SPRINT_BUF(namefrm); - if (!attr) return; print_nl(); - sprintf(namefrm, " %s %%u", name); - print_uint(PRINT_ANY, name, namefrm, rta_getattr_be32(attr)); + print_uint_indent_name_value(name, rta_getattr_be32(attr)); } static void flower_print_geneve_opts(const char *name, struct rtattr *attr, @@ -2342,8 +2484,24 @@ sprintf(strbuf, "%u:%u:%u:%u", ver, idx, dir, hwid); } -static void flower_print_enc_parts(const char *name, const char *namefrm, - struct rtattr *attr, char *key, char *mask) +static void flower_print_gtp_opts(const char *name, struct rtattr *attr, + char *strbuf, int len) +{ + struct rtattr *tbTCA_FLOWER_KEY_ENC_OPT_GTP_MAX + 1; + __u8 pdu_type, qfi; + + parse_rtattr(tb, TCA_FLOWER_KEY_ENC_OPT_GTP_MAX, RTA_DATA(attr), + RTA_PAYLOAD(attr)); + + pdu_type = rta_getattr_u8(tbTCA_FLOWER_KEY_ENC_OPT_GTP_PDU_TYPE); + qfi = rta_getattr_u8(tbTCA_FLOWER_KEY_ENC_OPT_GTP_QFI); + + snprintf(strbuf, len, "%02x:%02x", pdu_type, qfi); +} + +static void __attribute__((format(printf, 2, 0))) +flower_print_enc_parts(const char *name, const char *namefrm, + struct rtattr *attr, char *key, char *mask) { char *key_token, *mask_token, *out; int len; @@ -2373,15 +2531,18 @@ struct rtattr *key_tbTCA_FLOWER_KEY_ENC_OPTS_MAX + 1; struct rtattr *msk_tbTCA_FLOWER_KEY_ENC_OPTS_MAX + 1; char *key, *msk; + int len; if (!attr) return; - key = malloc(RTA_PAYLOAD(attr) * 2 + 1); + len = RTA_PAYLOAD(attr) * 2 + 1; + + key = malloc(len); if (!key) return; - msk = malloc(RTA_PAYLOAD(attr) * 2 + 1); + msk = malloc(len); if (!msk) goto err_key_free; @@ -2418,6 +2579,18 @@ flower_print_enc_parts(name, " erspan_opts %s", attr, key, msk); + } else if (key_tbTCA_FLOWER_KEY_ENC_OPTS_GTP) { + flower_print_gtp_opts("gtp_opt_key", + key_tbTCA_FLOWER_KEY_ENC_OPTS_GTP, + key, len); + + if (msk_tbTCA_FLOWER_KEY_ENC_OPTS_GTP) + flower_print_gtp_opts("gtp_opt_mask", + msk_tbTCA_FLOWER_KEY_ENC_OPTS_GTP, + msk, len); + + flower_print_enc_parts(name, " gtp_opts %s", attr, key, + msk); } free(msk); @@ -2431,7 +2604,6 @@ { const char *value_str = NULL; __u8 value, mask; - SPRINT_BUF(namefrm); SPRINT_BUF(out); size_t done; @@ -2451,9 +2623,7 @@ if (mask != UINT8_MAX) sprintf(out + done, "/%d", mask); - print_nl(); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + print_indent_name_value(name, out); } static void flower_print_u8(const char *name, struct rtattr *attr) @@ -2463,14 +2633,11 @@ static void flower_print_u32(const char *name, struct rtattr *attr) { - SPRINT_BUF(namefrm); - if (!attr) return; print_nl(); - sprintf(namefrm, " %s %%u", name); - print_uint(PRINT_ANY, name, namefrm, rta_getattr_u32(attr)); + print_uint_indent_name_value(name, rta_getattr_u32(attr)); } static void flower_print_mpls_opt_lse(struct rtattr *lse) @@ -2584,6 +2751,14 @@ open_json_object("keys"); + if (tbTCA_FLOWER_KEY_NUM_OF_VLANS) { + struct rtattr *attr = tbTCA_FLOWER_KEY_NUM_OF_VLANS; + + print_nl(); + print_uint(PRINT_ANY, "num_of_vlans", " num_of_vlans %d", + rta_getattr_u8(attr)); + } + if (tbTCA_FLOWER_KEY_VLAN_ID) { struct rtattr *attr = tbTCA_FLOWER_KEY_VLAN_ID; @@ -2716,6 +2891,24 @@ flower_print_eth_addr("arp_tha", tbTCA_FLOWER_KEY_ARP_THA, tbTCA_FLOWER_KEY_ARP_THA_MASK); + if (tbTCA_FLOWER_KEY_PPPOE_SID) { + struct rtattr *attr = tbTCA_FLOWER_KEY_PPPOE_SID; + + print_nl(); + print_uint(PRINT_ANY, "pppoe_sid", " pppoe_sid %u", + rta_getattr_be16(attr)); + } + + if (tbTCA_FLOWER_KEY_PPP_PROTO) { + SPRINT_BUF(buf); + struct rtattr *attr = tbTCA_FLOWER_KEY_PPP_PROTO; + + print_nl(); + print_string(PRINT_ANY, "ppp_proto", " ppp_proto %s", + ppp_proto_n2a(rta_getattr_u16(attr), + buf, sizeof(buf))); + } + flower_print_ip_addr("enc_dst_ip", tbTCA_FLOWER_KEY_ENC_IPV4_DST_MASK ? htons(ETH_P_IP) : htons(ETH_P_IPV6), @@ -2780,8 +2973,7 @@ print_uint(PRINT_ANY, "in_hw_count", " in_hw_count %u", count); } - } - else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) { + } else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) { print_nl(); print_bool(PRINT_ANY, "not_in_hw", " not_in_hw", true); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_fw.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_fw.c
Changed
@@ -70,14 +70,14 @@ while (argc > 0) { if (matches(*argv, "classid") == 0 || matches(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, 4096, TCA_FW_CLASSID, &handle, 4); + addattr_l(n, 4096, TCA_FW_CLASSID, &classid, 4); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_FW_POLICE, n)) {
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_matchall.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_matchall.c
Changed
@@ -63,14 +63,14 @@ while (argc > 0) { if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, MAX_MSG, TCA_MATCHALL_CLASSID, &handle, 4); + addattr_l(n, MAX_MSG, TCA_MATCHALL_CLASSID, &classid, 4); } else if (matches(*argv, "action") == 0) { NEXT_ARG(); if (parse_action(&argc, &argv, TCA_MATCHALL_ACT, n)) {
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_route.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_route.c
Changed
@@ -91,14 +91,14 @@ fh |= (0x8000|id)<<16; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, 4096, TCA_ROUTE4_CLASSID, &handle, 4); + addattr_l(n, 4096, TCA_ROUTE4_CLASSID, &classid, 4); } else if (matches(*argv, "police") == 0) { NEXT_ARG(); if (parse_police(&argc, &argv, TCA_ROUTE4_POLICE, n)) {
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_rsvp.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_rsvp.c
Changed
@@ -230,14 +230,14 @@ pinfo_ok++; } else if (matches(*argv, "classid") == 0 || strcmp(*argv, "flowid") == 0) { - unsigned int handle; + unsigned int classid; NEXT_ARG(); - if (get_tc_classid(&handle, *argv)) { + if (get_tc_classid(&classid, *argv)) { fprintf(stderr, "Illegal \"classid\"\n"); return -1; } - addattr_l(n, 4096, TCA_RSVP_CLASSID, &handle, 4); + addattr_l(n, 4096, TCA_RSVP_CLASSID, &classid, 4); } else if (strcmp(*argv, "tunnelid") == 0) { unsigned int tid;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/f_u32.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/f_u32.c
Changed
@@ -109,7 +109,7 @@ } } if (show_raw) - snprintf(b, bsize, "%08x ", handle); + snprintf(b, bsize, "%08x", handle); return buf; } @@ -824,23 +824,27 @@ { char abuf256; + open_json_object("match"); switch (key->off) { case 0: switch (ntohl(key->mask)) { case 0x0f000000: - fprintf(f, "\n match IP ihl %u", - ntohl(key->val) >> 24); + print_nl(); + print_uint(PRINT_ANY, "ip_ihl", " match IP ihl %u", + ntohl(key->val) >> 24); return; case 0x00ff0000: - fprintf(f, "\n match IP dsfield %#x", - ntohl(key->val) >> 16); + print_nl(); + print_0xhex(PRINT_ANY, "ip_dsfield", " match IP dsfield %#x", + ntohl(key->val) >> 16); return; } break; case 8: if (ntohl(key->mask) == 0x00ff0000) { - fprintf(f, "\n match IP protocol %d", - ntohl(key->val) >> 16); + print_nl(); + print_int(PRINT_ANY, "ip_protocol", " match IP protocol %d", + ntohl(key->val) >> 16); return; } break; @@ -849,11 +853,21 @@ int bits = mask2bits(key->mask); if (bits >= 0) { - fprintf(f, "\n %s %s/%d", - key->off == 12 ? "match IP src" : "match IP dst", - inet_ntop(AF_INET, &key->val, - abuf, sizeof(abuf)), - bits); + const char *addr; + + if (key->off == 12) { + print_nl(); + print_null(PRINT_FP, NULL, " match IP src ", NULL); + open_json_object("src"); + } else { + print_nl(); + print_null(PRINT_FP, NULL, " match IP dst ", NULL); + open_json_object("dst"); + } + addr = inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)); + print_string(PRINT_ANY, "address", "%s", addr); + print_int(PRINT_ANY, "prefixlen", "/%d", bits); + close_json_object(); return; } } @@ -862,45 +876,52 @@ case 20: switch (ntohl(key->mask)) { case 0x0000ffff: - fprintf(f, "\n match dport %u", - ntohl(key->val) & 0xffff); + print_uint(PRINT_ANY, "dport", "match dport %u", + ntohl(key->val) & 0xffff); return; case 0xffff0000: - fprintf(f, "\n match sport %u", - ntohl(key->val) >> 16); + print_nl(); + print_uint(PRINT_ANY, "sport", " match sport %u", + ntohl(key->val) >> 16); return; case 0xffffffff: - fprintf(f, "\n match dport %u, match sport %u", - ntohl(key->val) & 0xffff, - ntohl(key->val) >> 16); - + print_nl(); + print_uint(PRINT_ANY, "dport", " match dport %u, ", + ntohl(key->val) & 0xffff); + print_uint(PRINT_ANY, "sport", "match sport %u", + ntohl(key->val) >> 16); return; } /* XXX: Default print_raw */ } + close_json_object(); } static void print_ipv6(FILE *f, const struct tc_u32_key *key) { char abuf256; + open_json_object("match"); switch (key->off) { case 0: switch (ntohl(key->mask)) { case 0x0f000000: - fprintf(f, "\n match IP ihl %u", - ntohl(key->val) >> 24); + print_nl(); + print_uint(PRINT_ANY, "ip_ihl", " match IP ihl %u", + ntohl(key->val) >> 24); return; case 0x00ff0000: - fprintf(f, "\n match IP dsfield %#x", - ntohl(key->val) >> 16); + print_nl(); + print_0xhex(PRINT_ANY, "ip_dsfield", " match IP dsfield %#x", + ntohl(key->val) >> 16); return; } break; case 8: if (ntohl(key->mask) == 0x00ff0000) { - fprintf(f, "\n match IP protocol %d", - ntohl(key->val) >> 16); + print_nl(); + print_int(PRINT_ANY, "ip_protocol", " match IP protocol %d", + ntohl(key->val) >> 16); return; } break; @@ -909,11 +930,21 @@ int bits = mask2bits(key->mask); if (bits >= 0) { - fprintf(f, "\n %s %s/%d", - key->off == 12 ? "match IP src" : "match IP dst", - inet_ntop(AF_INET, &key->val, - abuf, sizeof(abuf)), - bits); + const char *addr; + + if (key->off == 12) { + print_nl(); + print_null(PRINT_FP, NULL, " match IP src ", NULL); + open_json_object("src"); + } else { + print_nl(); + print_null(PRINT_FP, NULL, " match IP dst ", NULL); + open_json_object("dst"); + } + addr = inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)); + print_string(PRINT_ANY, "address", "%s", addr); + print_int(PRINT_ANY, "prefixlen", "/%d", bits); + close_json_object(); return; } } @@ -922,31 +953,37 @@ case 20: switch (ntohl(key->mask)) { case 0x0000ffff: - fprintf(f, "\n match sport %u", - ntohl(key->val) & 0xffff); + print_nl(); + print_uint(PRINT_ANY, "sport", " match sport %u", + ntohl(key->val) & 0xffff); return; case 0xffff0000: - fprintf(f, "\n match dport %u", - ntohl(key->val) >> 16); + print_uint(PRINT_ANY, "dport", "match dport %u", + ntohl(key->val) >> 16); return; case 0xffffffff: - fprintf(f, "\n match sport %u, match dport %u", - ntohl(key->val) & 0xffff, - ntohl(key->val) >> 16); + print_nl(); + print_uint(PRINT_ANY, "sport", " match sport %u, ", + ntohl(key->val) & 0xffff); + print_uint(PRINT_ANY, "dport", "match dport %u", + ntohl(key->val) >> 16); return; } /* XXX: Default print_raw */ } + close_json_object(); } static void print_raw(FILE *f, const struct tc_u32_key *key) { - fprintf(f, "\n match %08x/%08x at %s%d", - (unsigned int)ntohl(key->val), - (unsigned int)ntohl(key->mask), - key->offmask ? "nexthdr+" : "", - key->off); + open_json_object("match"); + print_nl(); + print_hex(PRINT_ANY, "value", " match %08x", (unsigned int)ntohl(key->val)); + print_hex(PRINT_ANY, "mask", "/%08x ", (unsigned int)ntohl(key->mask)); + print_string(PRINT_ANY, "offmask", "at %s", key->offmask ? "nexthdr+" : ""); + print_int(PRINT_ANY, "off", "%d", key->off); + close_json_object(); } static const struct { @@ -1213,11 +1250,11 @@ if (handle) { SPRINT_BUF(b1); - fprintf(f, "fh %s ", sprint_u32_handle(handle, b1)); + print_string(PRINT_ANY, "fh", "fh %s ", sprint_u32_handle(handle, b1)); } if (TC_U32_NODE(handle)) - fprintf(f, "order %d ", TC_U32_NODE(handle)); + print_int(PRINT_ANY, "order", "order %d ", TC_U32_NODE(handle)); if (tbTCA_U32_SEL) { if (RTA_PAYLOAD(tbTCA_U32_SEL) < sizeof(*sel)) @@ -1227,44 +1264,46 @@ } if (tbTCA_U32_DIVISOR) { - fprintf(f, "ht divisor %d ", - rta_getattr_u32(tbTCA_U32_DIVISOR)); + __u32 htdivisor = rta_getattr_u32(tbTCA_U32_DIVISOR); + + print_int(PRINT_ANY, "ht_divisor", "ht divisor %d ", htdivisor); } else if (tbTCA_U32_HASH) { __u32 htid = rta_getattr_u32(tbTCA_U32_HASH); - - fprintf(f, "key ht %x bkt %x ", TC_U32_USERHTID(htid), - TC_U32_HASH(htid)); + print_hex(PRINT_ANY, "key_ht", "key ht %x ", TC_U32_USERHTID(htid)); + print_hex(PRINT_ANY, "bkt", "bkt %x ", TC_U32_HASH(htid)); } else { - fprintf(f, "??? "); + fprintf(stderr, "divisor and hash missing "); } if (tbTCA_U32_CLASSID) { + __u32 classid = rta_getattr_u32(tbTCA_U32_CLASSID); SPRINT_BUF(b1); - fprintf(f, "%sflowid %s ", - !sel || !(sel->flags & TC_U32_TERMINAL) ? "*" : "", - sprint_tc_classid(rta_getattr_u32(tbTCA_U32_CLASSID), - b1)); - } else if (sel && sel->flags & TC_U32_TERMINAL) { - fprintf(f, "terminal flowid ??? "); + if (sel && (sel->flags & TC_U32_TERMINAL)) + print_string(PRINT_FP, NULL, "*", NULL); + + print_string(PRINT_ANY, "flowid", "flowid %s ", + sprint_tc_classid(classid, b1)); + } else if (sel && (sel->flags & TC_U32_TERMINAL)) { + print_string(PRINT_FP, NULL, "terminal flowid ", NULL); } if (tbTCA_U32_LINK) { SPRINT_BUF(b1); - fprintf(f, "link %s ", - sprint_u32_handle(rta_getattr_u32(tbTCA_U32_LINK), - b1)); + char *link = sprint_u32_handle(rta_getattr_u32(tbTCA_U32_LINK), b1); + + print_string(PRINT_ANY, "link", "link %s ", link); } if (tbTCA_U32_FLAGS) { __u32 flags = rta_getattr_u32(tbTCA_U32_FLAGS); if (flags & TCA_CLS_FLAGS_SKIP_HW) - fprintf(f, "skip_hw "); + print_bool(PRINT_ANY, "skip_hw", "skip_hw ", true); if (flags & TCA_CLS_FLAGS_SKIP_SW) - fprintf(f, "skip_sw "); + print_bool(PRINT_ANY, "skip_sw", "skip_sw ", true); if (flags & TCA_CLS_FLAGS_IN_HW) - fprintf(f, "in_hw "); + print_bool(PRINT_ANY, "in_hw", "in_hw ", true); else if (flags & TCA_CLS_FLAGS_NOT_IN_HW) - fprintf(f, "not_in_hw "); + print_bool(PRINT_ANY, "not_in_hw", "not_in_hw ", true); } if (tbTCA_U32_PCNT) { @@ -1275,10 +1314,10 @@ pf = RTA_DATA(tbTCA_U32_PCNT); } - if (sel && show_stats && NULL != pf) - fprintf(f, " (rule hit %llu success %llu)", - (unsigned long long) pf->rcnt, - (unsigned long long) pf->rhit); + if (sel && show_stats && NULL != pf) { + print_u64(PRINT_ANY, "rule_hit", "(rule hit %llu ", pf->rcnt); + print_u64(PRINT_ANY, "success", "success %llu)", pf->rhit); + } if (tbTCA_U32_MARK) { struct tc_u32_mark *mark = RTA_DATA(tbTCA_U32_MARK); @@ -1286,8 +1325,10 @@ if (RTA_PAYLOAD(tbTCA_U32_MARK) < sizeof(*mark)) { fprintf(f, "\n Invalid mark (kernel&iproute2 mismatch)\n"); } else { - fprintf(f, "\n mark 0x%04x 0x%04x (success %d)", - mark->val, mark->mask, mark->success); + print_nl(); + print_0xhex(PRINT_ANY, "fwmark_value", " mark 0x%04x ", mark->val); + print_0xhex(PRINT_ANY, "fwmark_mask", "0x%04x ", mark->mask); + print_int(PRINT_ANY, "fwmark_success", "(success %d)", mark->success); } } @@ -1298,38 +1339,45 @@ for (i = 0; i < sel->nkeys; i++) { show_keys(f, sel->keys + i); if (show_stats && NULL != pf) - fprintf(f, " (success %llu ) ", - (unsigned long long) pf->kcntsi); + print_u64(PRINT_ANY, "success", " (success %llu ) ", + pf->kcntsi); } } if (sel->flags & (TC_U32_VAROFFSET | TC_U32_OFFSET)) { - fprintf(f, "\n offset "); - if (sel->flags & TC_U32_VAROFFSET) - fprintf(f, "%04x>>%d at %d ", - ntohs(sel->offmask), - sel->offshift, sel->offoff); + print_nl(); + print_string(PRINT_ANY, NULL, "%s", " offset "); + if (sel->flags & TC_U32_VAROFFSET) { + print_hex(PRINT_ANY, "offset_mask", "%04x", ntohs(sel->offmask)); + print_int(PRINT_ANY, "offset_shift", ">>%d ", sel->offshift); + print_int(PRINT_ANY, "offset_off", "at %d ", sel->offoff); + } if (sel->off) - fprintf(f, "plus %d ", sel->off); + print_int(PRINT_ANY, "plus", "plus %d ", sel->off); } if (sel->flags & TC_U32_EAT) - fprintf(f, " eat "); + print_string(PRINT_ANY, NULL, "%s", " eat "); if (sel->hmask) { - fprintf(f, "\n hash mask %08x at %d ", - (unsigned int)htonl(sel->hmask), sel->hoff); + print_nl(); + unsigned int hmask = (unsigned int)htonl(sel->hmask); + + print_hex(PRINT_ANY, "hash_mask", " hash mask %08x ", hmask); + print_int(PRINT_ANY, "hash_off", "at %d ", sel->hoff); } } if (tbTCA_U32_POLICE) { - fprintf(f, "\n"); + print_nl(); tc_print_police(f, tbTCA_U32_POLICE); } if (tbTCA_U32_INDEV) { struct rtattr *idev = tbTCA_U32_INDEV; - - fprintf(f, "\n input dev %s\n", rta_getattr_str(idev)); + print_nl(); + print_string(PRINT_ANY, "input_dev", " input dev %s", + rta_getattr_str(idev)); + print_nl(); } if (tbTCA_U32_ACT)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/m_action.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/m_action.c
Changed
@@ -51,9 +51,10 @@ " FL := ls | list | flush | <ACTNAMESPEC>\n" " ACTNAMESPEC := action <ACTNAME>\n" " ACTISPEC := <ACTNAMESPEC> <INDEXSPEC>\n" - " ACTSPEC := action <ACTDETAIL> INDEXSPEC HWSTATSSPEC\n" + " ACTSPEC := action <ACTDETAIL> INDEXSPEC HWSTATSSPEC SKIPSPEC\n" " INDEXSPEC := index <32 bit indexvalue>\n" " HWSTATSSPEC := hw_stats immediate | delayed | disabled \n" + " SKIPSPEC := skip_sw | skip_hw \n" " ACTDETAIL := <ACTNAME> <ACTPARAMS>\n" " Example ACTNAME is gact, mirred, bpf, etc\n" " Each action has its own parameters (ACTPARAMS)\n" @@ -245,6 +246,8 @@ goto done0; } else { struct action_util *a = NULL; + int skip_loop = 2; + __u32 flag = 0; if (!action_a2n(*argv, NULL, false)) strncpy(k, "gact", sizeof(k) - 1); @@ -314,13 +317,27 @@ } if (*argv && strcmp(*argv, "no_percpu") == 0) { + flag |= TCA_ACT_FLAGS_NO_PERCPU_STATS; + NEXT_ARG_FWD(); + } + + /* we need to parse twice to fix skip flag out of order */ + while (skip_loop--) { + if (*argv && strcmp(*argv, "skip_sw") == 0) { + flag |= TCA_ACT_FLAGS_SKIP_SW; + NEXT_ARG_FWD(); + } else if (*argv && strcmp(*argv, "skip_hw") == 0) { + flag |= TCA_ACT_FLAGS_SKIP_HW; + NEXT_ARG_FWD(); + } + } + + if (flag) { struct nla_bitfield32 flags = - { TCA_ACT_FLAGS_NO_PERCPU_STATS, - TCA_ACT_FLAGS_NO_PERCPU_STATS }; + { flag, flag }; addattr_l(n, MAX_MSG, TCA_ACT_FLAGS, &flags, sizeof(struct nla_bitfield32)); - NEXT_ARG_FWD(); } addattr_nest_end(n, tail); @@ -347,7 +364,7 @@ return -1; } -static int tc_print_one_action(FILE *f, struct rtattr *arg) +static int tc_print_one_action(FILE *f, struct rtattr *arg, bool bind) { struct rtattr *tbTCA_ACT_MAX + 1; @@ -396,14 +413,52 @@ strsz, b1, sizeof(b1))); print_nl(); } - if (tbTCA_ACT_FLAGS) { - struct nla_bitfield32 *flags = RTA_DATA(tbTCA_ACT_FLAGS); + if (tbTCA_ACT_FLAGS || tbTCA_ACT_IN_HW_COUNT) { + bool skip_hw = false; + bool newline = false; - if (flags->selector & TCA_ACT_FLAGS_NO_PERCPU_STATS) - print_bool(PRINT_ANY, "no_percpu", "\tno_percpu", - flags->value & - TCA_ACT_FLAGS_NO_PERCPU_STATS); - print_nl(); + if (tbTCA_ACT_FLAGS) { + struct nla_bitfield32 *flags = RTA_DATA(tbTCA_ACT_FLAGS); + + if (flags->selector & TCA_ACT_FLAGS_NO_PERCPU_STATS) { + newline = true; + print_bool(PRINT_ANY, "no_percpu", "\tno_percpu", + flags->value & + TCA_ACT_FLAGS_NO_PERCPU_STATS); + } + if (!bind) { + if (flags->selector & TCA_ACT_FLAGS_SKIP_HW) { + newline = true; + print_bool(PRINT_ANY, "skip_hw", "\tskip_hw", + flags->value & + TCA_ACT_FLAGS_SKIP_HW); + skip_hw = !!(flags->value & TCA_ACT_FLAGS_SKIP_HW); + } + if (flags->selector & TCA_ACT_FLAGS_SKIP_SW) { + newline = true; + print_bool(PRINT_ANY, "skip_sw", "\tskip_sw", + flags->value & + TCA_ACT_FLAGS_SKIP_SW); + } + } + } + if (tbTCA_ACT_IN_HW_COUNT && !bind && !skip_hw) { + __u32 count = rta_getattr_u32(tbTCA_ACT_IN_HW_COUNT); + + newline = true; + if (count) { + print_bool(PRINT_ANY, "in_hw", "\tin_hw", + true); + print_uint(PRINT_ANY, "in_hw_count", + " in_hw_count %u", count); + } else { + print_bool(PRINT_ANY, "not_in_hw", + "\tnot_in_hw", true); + } + } + + if (newline) + print_nl(); } if (tbTCA_ACT_HW_STATS) print_hw_stats(tbTCA_ACT_HW_STATS, false); @@ -440,8 +495,9 @@ return 0; } -int -tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts) +static int +tc_dump_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts, + bool bind) { int i; @@ -466,10 +522,8 @@ print_nl(); print_uint(PRINT_ANY, "order", "\taction order %u: ", i); - if (tc_print_one_action(f, tbi) < 0) { - print_string(PRINT_FP, NULL, - "Error printing action\n", NULL); - } + if (tc_print_one_action(f, tbi, bind) < 0) + fprintf(stderr, "Error printing action\n"); close_json_object(); } @@ -479,6 +533,12 @@ return 0; } +int +tc_print_action(FILE *f, const struct rtattr *arg, unsigned short tot_acts) +{ + return tc_dump_action(f, arg, tot_acts, true); +} + int print_action(struct nlmsghdr *n, void *arg) { FILE *fp = (FILE *)arg; @@ -529,7 +589,7 @@ } open_json_object(NULL); - tc_print_action(fp, tbTCA_ACT_TAB, tot_acts ? *tot_acts:0); + tc_dump_action(fp, tbTCA_ACT_TAB, tot_acts ? *tot_acts:0, false); close_json_object(); return 0;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/m_ct.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/m_ct.c
Changed
@@ -243,7 +243,7 @@ return -1; } - NEXT_ARG_FWD(); + NEXT_ARG(); if (matches(*argv, "port") != 0) continue;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/m_vlan.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/m_vlan.c
Changed
@@ -279,8 +279,8 @@ ETH_ALEN, 0, b1, sizeof(b1)); print_string(PRINT_ANY, "dst_mac", " dst_mac %s", b1); } - if (tbTCA_VLAN_PUSH_ETH_SRC && - RTA_PAYLOAD(tbTCA_VLAN_PUSH_ETH_SRC) == ETH_ALEN) { + if (tbTCA_VLAN_PUSH_ETH_SRC && + RTA_PAYLOAD(tbTCA_VLAN_PUSH_ETH_SRC) == ETH_ALEN) { ll_addr_n2a(RTA_DATA(tbTCA_VLAN_PUSH_ETH_SRC), ETH_ALEN, 0, b1, sizeof(b1)); print_string(PRINT_ANY, "src_mac", " src_mac %s", b1);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/p_icmp.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/p_icmp.c
Changed
@@ -27,31 +27,7 @@ parse_icmp(int *argc_p, char ***argv_p, struct m_pedit_sel *sel, struct m_pedit_key *tkey) { - int res = -1; -#if 0 - int argc = *argc_p; - char **argv = *argv_p; - - if (argc < 2) - return -1; - - if (strcmp(*argv, "type") == 0) { - NEXT_ARG(); - res = parse_u8(&argc, &argv, 0); - goto done; - } - if (strcmp(*argv, "code") == 0) { - NEXT_ARG(); - res = parse_u8(&argc, &argv, 1); - goto done; - } return -1; - -done: - *argc_p = argc; - *argv_p = argv; -#endif - return res; } struct m_pedit_util p_pedit_icmp = {
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/q_cake.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/q_cake.c
Changed
@@ -95,7 +95,7 @@ bool overhead_override = false; bool overhead_set = false; unsigned int interval = 0; - unsigned int diffserv = 0; + int diffserv = -1; unsigned int memlimit = 0; unsigned int fwmark = 0; unsigned int target = 0; @@ -356,7 +356,7 @@ if (bandwidth || unlimited) addattr_l(n, 1024, TCA_CAKE_BASE_RATE64, &bandwidth, sizeof(bandwidth)); - if (diffserv) + if (diffserv != -1) addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv, sizeof(diffserv)); if (atm != -1)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/q_fq_codel.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/q_fq_codel.c
Changed
@@ -55,6 +55,7 @@ " target TIME interval TIME \n" " quantum BYTES noecn \n" " ce_threshold TIME \n" + " ce_threshold_selector VALUE/MASK \n" " drop_batch SIZE \n"); } @@ -69,6 +70,8 @@ unsigned int quantum = 0; unsigned int ce_threshold = ~0U; unsigned int memory = ~0U; + __u8 ce_threshold_mask = 0; + __u8 ce_threshold_selector = 0xFF; int ecn = -1; struct rtattr *tail; @@ -109,6 +112,24 @@ fprintf(stderr, "Illegal \"ce_threshold\"\n"); return -1; } + } else if (strcmp(*argv, "ce_threshold_selector") == 0) { + char *sep; + + NEXT_ARG(); + sep = strchr(*argv, '/'); + if (!sep) { + fprintf(stderr, "Missing mask for \"ce_threshold_selector\"\n"); + return -1; + } + *sep++ = '\0'; + if (get_u8(&ce_threshold_mask, sep, 0)) { + fprintf(stderr, "Illegal mask for \"ce_threshold_selector\"\n"); + return -1; + } + if (get_u8(&ce_threshold_selector, *argv, 0)) { + fprintf(stderr, "Illegal \"ce_threshold_selector\"\n"); + return -1; + } } else if (strcmp(*argv, "memory_limit") == 0) { NEXT_ARG(); if (get_size(&memory, *argv)) { @@ -152,6 +173,10 @@ if (ce_threshold != ~0U) addattr_l(n, 1024, TCA_FQ_CODEL_CE_THRESHOLD, &ce_threshold, sizeof(ce_threshold)); + if (ce_threshold_selector != 0xFF) { + addattr8(n, 1024, TCA_FQ_CODEL_CE_THRESHOLD_MASK, ce_threshold_mask); + addattr8(n, 1024, TCA_FQ_CODEL_CE_THRESHOLD_SELECTOR, ce_threshold_selector); + } if (memory != ~0U) addattr_l(n, 1024, TCA_FQ_CODEL_MEMORY_LIMIT, &memory, sizeof(memory)); @@ -172,6 +197,8 @@ unsigned int ecn; unsigned int quantum; unsigned int ce_threshold; + __u8 ce_threshold_selector = 0; + __u8 ce_threshold_mask = 0; unsigned int memory_limit; unsigned int drop_batch; @@ -211,6 +238,19 @@ print_string(PRINT_FP, NULL, "ce_threshold %s ", sprint_time(ce_threshold, b1)); } + if (tbTCA_FQ_CODEL_CE_THRESHOLD_SELECTOR && + RTA_PAYLOAD(tbTCA_FQ_CODEL_CE_THRESHOLD_SELECTOR) >= sizeof(__u8)) + ce_threshold_selector = rta_getattr_u8(tbTCA_FQ_CODEL_CE_THRESHOLD_SELECTOR); + if (tbTCA_FQ_CODEL_CE_THRESHOLD_MASK && + RTA_PAYLOAD(tbTCA_FQ_CODEL_CE_THRESHOLD_MASK) >= sizeof(__u8)) + ce_threshold_mask = rta_getattr_u8(tbTCA_FQ_CODEL_CE_THRESHOLD_MASK); + if (ce_threshold_mask || ce_threshold_selector) { + print_hhu(PRINT_ANY, "ce_threshold_selector", "ce_threshold_selector %#x", + ce_threshold_selector); + print_hhu(PRINT_ANY, "ce_threshold_mask", "/%#x ", + ce_threshold_mask); + } + if (tbTCA_FQ_CODEL_INTERVAL && RTA_PAYLOAD(tbTCA_FQ_CODEL_INTERVAL) >= sizeof(__u32)) { interval = rta_getattr_u32(tbTCA_FQ_CODEL_INTERVAL);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/q_gred.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/q_gred.c
Changed
@@ -27,8 +27,7 @@ #include "tc_red.h" - -#if 0 +#ifdef DEBUG #define DPRINTF(format, args...) fprintf(stderr, format, ##args) #else #define DPRINTF(format, args...)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/q_netem.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/q_netem.c
Changed
@@ -1,13 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* - * q_netem.c NETEM. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - * Authors: Stephen Hemminger <shemminger@linux-foundation.org> - * + * Author: Stephen Hemminger <shemminger@linux-foundation.org> */ #include <stdio.h> @@ -30,22 +23,20 @@ static void explain(void) { fprintf(stderr, - "Usage: ... netem limit PACKETS \n" \ - " delay TIME JITTER CORRELATION\n" \ - " distribution {uniform|normal|pareto|paretonormal} \n" \ - " corrupt PERCENT CORRELATION\n" \ - " duplicate PERCENT CORRELATION\n" \ - " loss random PERCENT CORRELATION\n" \ - " loss state P13 P31 P32 P23 P14\n" \ - " loss gemodel PERCENT R 1-H 1-K\n" \ - " ecn \n" \ - " reorder PERCENT CORRELATION gap DISTANCE \n" \ - " rate RATE PACKETOVERHEAD CELLSIZE CELLOVERHEAD\n" \ - " slot MIN_DELAY MAX_DELAY packets MAX_PACKETS" \ - " bytes MAX_BYTES\n" \ - " slot distribution" \ - " {uniform|normal|pareto|paretonormal|custom} DELAY JITTER" \ - " packets MAX_PACKETS bytes MAX_BYTES\n"); + "Usage: ... netem limit PACKETS \n" + " delay TIME JITTER CORRELATION\n" + " distribution {uniform|normal|pareto|paretonormal} \n" + " corrupt PERCENT CORRELATION\n" + " duplicate PERCENT CORRELATION\n" + " loss random PERCENT CORRELATION\n" + " loss state P13 P31 P32 P23 P14\n" + " loss gemodel PERCENT R 1-H 1-K\n" + " ecn \n" + " reorder PERCENT CORRELATION gap DISTANCE \n" + " rate RATE PACKETOVERHEAD CELLSIZE CELLOVERHEAD\n" + " slot MIN_DELAY MAX_DELAY packets MAX_PACKETS bytes MAX_BYTES\n" + " slot distribution {uniform|normal|pareto|paretonormal|custom}\n" + " DELAY JITTER packets MAX_PACKETS bytes MAX_BYTES\n"); } static void explain1(const char *arg) @@ -59,10 +50,12 @@ #define MAX_DIST (16*1024) /* Print values only if they are non-zero */ -static void __print_int_opt(const char *label_json, const char *label_fp, - int val) +static void __attribute__((format(printf, 2, 0))) +__print_int_opt(const char *label_json, const char *label_fp, int val) { - print_int(PRINT_ANY, label_json, val ? label_fp : "", val); + print_int(PRINT_JSON, label_json, NULL, val); + if (val != 0) + print_int(PRINT_FP, NULL, label_fp, val); } #define PRINT_INT_OPT(label, val) \ __print_int_opt(label, " " label " %d", (val)) @@ -70,8 +63,8 @@ /* Time print prints normally with varying units, but for JSON prints * in seconds (1ms vs 0.001). */ -static void __print_time64(const char *label_json, const char *label_fp, - __u64 val) +static void __attribute__((format(printf, 2, 0))) +__print_time64(const char *label_json, const char *label_fp, __u64 val) { SPRINT_BUF(b1); @@ -85,8 +78,8 @@ /* Percent print prints normally in percentage points, but for JSON prints * an absolute value (1% vs 0.01). */ -static void __print_percent(const char *label_json, const char *label_fp, - __u32 per) +static void __attribute__((format(printf, 2, 0))) +__print_percent(const char *label_json, const char *label_fp, __u32 per) { print_float(PRINT_FP, NULL, label_fp, (100. * per) / UINT32_MAX); print_float(PRINT_JSON, label_json, NULL, (1. * per) / UINT32_MAX); @@ -138,7 +131,8 @@ char name128; snprintf(name, sizeof(name), "%s/%s.dist", get_tc_lib(), type); - if ((f = fopen(name, "r")) == NULL) { + f = fopen(name, "r"); + if (f == NULL) { fprintf(stderr, "No distribution data for %s (%s: %s)\n", type, name, strerror(errno)); return -1; @@ -175,8 +169,10 @@ #define NEXT_IS_SIGNED_NUMBER() \ (NEXT_ARG_OK() && (isdigit(argv10) || argv10 == '-')) -/* Adjust for the fact that psched_ticks aren't always usecs - (based on kernel PSCHED_CLOCK configuration */ +/* + * Adjust for the fact that psched_ticks aren't always usecs + * (based on kernel PSCHED_CLOCK configuration + */ static int get_ticks(__u32 *ticks, const char *str) { unsigned int t; @@ -258,7 +254,7 @@ if (!strcmp(*argv, "random")) { NEXT_ARG(); - random_loss_model: +random_loss_model: if (get_percent(&opt.loss, *argv)) { explain1("loss percent"); return -1; @@ -523,6 +519,7 @@ if (NEXT_ARG_OK() && matches(*(argv+1), "bytes") == 0) { unsigned int max_bytes; + NEXT_ARG(); if (!NEXT_ARG_OK() || get_size(&max_bytes, *(argv+1))) { @@ -532,11 +529,9 @@ slot.max_bytes = (int) max_bytes; NEXT_ARG(); } - } else if (strcmp(*argv, "help") == 0) { - explain(); - return -1; } else { - fprintf(stderr, "What is \"%s\"?\n", *argv); + if (strcmp(*argv, "help") != 0) + fprintf(stderr, "What is \"%s\"?\n", *argv); explain(); return -1; } @@ -802,9 +797,10 @@ rate64 = rate64 ? : rate->rate; tc_print_rate(PRINT_ANY, "rate", " rate %s", rate64); PRINT_INT_OPT("packetoverhead", rate->packet_overhead); - print_uint(PRINT_ANY, "cellsize", - rate->cell_size ? " cellsize %u" : "", - rate->cell_size); + + print_uint(PRINT_JSON, "cellsize", NULL, rate->cell_size); + if (rate->cell_size) + print_uint(PRINT_FP, NULL, " cellsize %u", rate->cell_size); PRINT_INT_OPT("celloverhead", rate->cell_overhead); close_json_object(); } @@ -824,9 +820,13 @@ close_json_object(); } - print_bool(PRINT_ANY, "ecn", ecn ? " ecn " : "", ecn); - print_luint(PRINT_ANY, "gap", qopt.gap ? " gap %lu" : "", - (unsigned long)qopt.gap); + print_bool(PRINT_JSON, "ecn", NULL, ecn); + if (ecn) + print_bool(PRINT_FP, NULL, " ecn ", ecn); + + print_luint(PRINT_JSON, "gap", NULL, qopt.gap); + if (qopt.gap) + print_luint(PRINT_FP, NULL, " gap %lu", qopt.gap); return 0; }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_class.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_class.c
Changed
@@ -365,7 +365,7 @@ if (q && q->print_copt) q->print_copt(q, fp, tbTCA_OPTIONS); else - fprintf(fp, "cannot parse class parameters"); + fprintf(stderr, "cannot parse class parameters"); } fprintf(fp, "\n"); if (show_stats) { @@ -474,10 +474,6 @@ return tc_class_modify(RTM_NEWTCLASS, NLM_F_CREATE, argc-1, argv+1); if (matches(*argv, "delete") == 0) return tc_class_modify(RTM_DELTCLASS, 0, argc-1, argv+1); -#if 0 - if (matches(*argv, "get") == 0) - return tc_class_get(RTM_GETTCLASS, 0, argc-1, argv+1); -#endif if (matches(*argv, "list") == 0 || matches(*argv, "show") == 0 || matches(*argv, "lst") == 0) return tc_class_list(argc-1, argv+1);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_common.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_common.h
Changed
@@ -16,7 +16,7 @@ int print_filter(struct nlmsghdr *n, void *arg); int print_qdisc(struct nlmsghdr *n, void *arg); int print_class(struct nlmsghdr *n, void *arg); -void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta); +void print_size_table(struct rtattr *rta); struct tc_estimator; int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_monitor.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_monitor.c
Changed
@@ -42,6 +42,9 @@ if (timestamp) print_timestamp(fp); + if (n->nlmsg_type == NLMSG_DONE) + nl_dump_ext_ack_done(n, 0, 0); + if (n->nlmsg_type == RTM_NEWTFILTER || n->nlmsg_type == RTM_DELTFILTER || n->nlmsg_type == RTM_NEWCHAIN || @@ -64,7 +67,7 @@ } if (n->nlmsg_type != NLMSG_ERROR && n->nlmsg_type != NLMSG_NOOP && n->nlmsg_type != NLMSG_DONE) { - fprintf(fp, "Unknown message: length %08d type %08x flags %08x\n", + fprintf(stderr, "Unknown message: length %08d type %08x flags %08x\n", n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags); } return 0;
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_qdisc.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_qdisc.c
Changed
@@ -329,7 +329,7 @@ print_nl(); if (show_details && tbTCA_STAB) { - print_size_table(fp, " ", tbTCA_STAB); + print_size_table(tbTCA_STAB); print_nl(); }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_stab.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_stab.c
Changed
@@ -103,7 +103,7 @@ return 0; } -void print_size_table(FILE *fp, const char *prefix, struct rtattr *rta) +void print_size_table(struct rtattr *rta) { struct rtattr *tbTCA_STAB_MAX + 1; @@ -117,33 +117,25 @@ memcpy(&s, RTA_DATA(tbTCA_STAB_BASE), MIN(RTA_PAYLOAD(tbTCA_STAB_BASE), sizeof(s))); - fprintf(fp, "%s", prefix); + open_json_object("stab"); + print_string(PRINT_FP, NULL, " ", NULL); + if (s.linklayer) - fprintf(fp, "linklayer %s ", - sprint_linklayer(s.linklayer, b1)); + print_string(PRINT_ANY, "linklayer", + "linklayer %s ", + sprint_linklayer(s.linklayer, b1)); if (s.overhead) - fprintf(fp, "overhead %d ", s.overhead); + print_int(PRINT_ANY, "overhead", + "overhead %d ", s.overhead); if (s.mpu) - fprintf(fp, "mpu %u ", s.mpu); + print_uint(PRINT_ANY, "mpu", + "mpu %u ", s.mpu); if (s.mtu) - fprintf(fp, "mtu %u ", s.mtu); + print_uint(PRINT_ANY, "mtu", + "mtu %u ", s.mtu); if (s.tsize) - fprintf(fp, "tsize %u ", s.tsize); - } - -#if 0 - if (tbTCA_STAB_DATA) { - unsigned int i, j, dlen; - __u16 *data = RTA_DATA(tbTCA_STAB_DATA); - - dlen = RTA_PAYLOAD(tbTCA_STAB_DATA) / sizeof(__u16); - - fprintf(fp, "\n%sstab data:", prefix); - for (i = 0; i < dlen/12; i++) { - fprintf(fp, "\n%s %3u:", prefix, i * 12); - for (j = 0; i * 12 + j < dlen; j++) - fprintf(fp, " %05x", datai * 12 + j); - } + print_uint(PRINT_ANY, "tsize", + "tsize %u ", s.tsize); + close_json_object(); } -#endif }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_util.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_util.c
Changed
@@ -74,7 +74,7 @@ int get_qdisc_handle(__u32 *h, const char *str) { - __u32 maj; + unsigned long maj; char *p; maj = TC_H_UNSPEC; @@ -93,7 +93,7 @@ int get_tc_classid(__u32 *h, const char *str) { - __u32 maj, min; + unsigned long maj, min; char *p; maj = TC_H_ROOT; @@ -247,7 +247,8 @@ return get_rate64(rate, r_str); } -void tc_print_rate(enum output_type t, const char *key, const char *fmt, +void __attribute__((format(printf, 3, 0))) +tc_print_rate(enum output_type t, const char *key, const char *fmt, unsigned long long rate) { print_rate(use_iec, t, key, fmt, rate); @@ -475,8 +476,7 @@ result_p = &result2; NEXT_ARG(); /* fall-through */ - case 0: /* fall-through */ - case 2: + case 0: ret = parse_action_control(&argc, &argv, result_p, allow_num); if (ret) @@ -614,7 +614,7 @@ tm->expires / hz); } -static void print_tcstats_basic_hw(struct rtattr **tbs, char *prefix) +static void print_tcstats_basic_hw(struct rtattr **tbs, const char *prefix) { struct gnet_stats_basic bs_hw; @@ -652,7 +652,8 @@ print_uint(PRINT_ANY, "hw_packets", " %u pkt", bs_hw.packets); } -void print_tcstats2_attr(FILE *fp, struct rtattr *rta, char *prefix, struct rtattr **xstats) +void print_tcstats2_attr(FILE *fp, struct rtattr *rta, + const char *prefix, struct rtattr **xstats) { struct rtattr *tbsTCA_STATS_MAX + 1; @@ -729,7 +730,7 @@ *xstats = tbsTCA_STATS_APP ? : NULL; } -void print_tcstats_attr(FILE *fp, struct rtattr *tb, char *prefix, +void print_tcstats_attr(FILE *fp, struct rtattr *tb, const char *prefix, struct rtattr **xstats) { if (tbTCA_STATS2) { @@ -782,10 +783,7 @@ const char *name, struct rtattr *attr, struct rtattr *mask_attr, bool newline) { - SPRINT_BUF(namefrm); __u32 value, mask; - SPRINT_BUF(out); - size_t done; if (!attr) return; @@ -793,27 +791,18 @@ value = rta_getattr_type(attr); mask = mask_attr ? rta_getattr_type(mask_attr) : type_max; - if (is_json_context()) { - sprintf(namefrm, "\n %s %%u", name); - print_hu(PRINT_ANY, name, namefrm, - rta_getattr_type(attr)); - if (mask != type_max) { - char mask_nameSPRINT_BSIZE-6; - - sprintf(mask_name, "%s_mask", name); - if (newline) - print_string(PRINT_FP, NULL, "%s ", _SL_); - sprintf(namefrm, " %s %%u", mask_name); - print_hu(PRINT_ANY, mask_name, namefrm, mask); - } - } else { - done = sprintf(out, "%u", value); - if (mask != type_max) - sprintf(out + done, "/0x%x", mask); - if (newline) - print_string(PRINT_FP, NULL, "%s ", _SL_); - sprintf(namefrm, " %s %%s", name); - print_string(PRINT_ANY, name, namefrm, out); + if (newline) + print_string(PRINT_FP, NULL, "%s ", _SL_); + else + print_string(PRINT_FP, NULL, " ", _SL_); + + print_uint_name_value(name, value); + + if (mask != type_max) { + char mask_nameSPRINT_BSIZE-6; + + snprintf(mask_name, sizeof(mask_name), "%s_mask", name); + print_hex(PRINT_ANY, mask_name, "/0x%x", mask); } }
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tc/tc_util.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/tc/tc_util.h
Changed
@@ -90,9 +90,9 @@ char *sprint_linklayer(unsigned int linklayer, char *buf); void print_tcstats_attr(FILE *fp, struct rtattr *tb, - char *prefix, struct rtattr **xstats); + const char *prefix, struct rtattr **xstats); void print_tcstats2_attr(FILE *fp, struct rtattr *rta, - char *prefix, struct rtattr **xstats); + const char *prefix, struct rtattr **xstats); int get_tc_classid(__u32 *h, const char *str); int print_tc_classid(char *buf, int len, __u32 h);
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/testsuite/tests/ip/link/add_type_xfrm.t -> _service:tar_scm:iproute2-6.1.0.tar.xz/testsuite/tests/ip/link/add_type_xfrm.t
Changed
@@ -15,18 +15,3 @@ test_on "if_id $IF_ID" ts_ip "$0" "Del $NEW_DEV xfrm interface" link del dev $NEW_DEV - - -ts_log "Testing Add XFRM Interface, No IF-ID" - -PHYS_DEV="lo" -NEW_DEV="$(rand_dev)" -IF_ID="0xf" - -ts_ip "$0" "Add $NEW_DEV xfrm interface" link add dev $NEW_DEV type xfrm dev $PHYS_DEV - -ts_ip "$0" "Show $NEW_DEV xfrm interface" -d link show dev $NEW_DEV -test_on "$NEW_DEV" -test_on_not "if_id $IF_ID" - -ts_ip "$0" "Del $NEW_DEV xfrm interface" link del dev $NEW_DEV
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/testsuite/tests/ip/rule
Added
+(directory)
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/testsuite/tests/ip/rule/dsfield.t
Added
@@ -0,0 +1,29 @@ +#!/bin/sh + +. lib/generic.sh + +ts_log "Testing rule with option dsfield/tos" + +ts_ip "$0" "Add IPv4 rule with dsfield 0x10" -4 rule add dsfield 0x10 +ts_ip "$0" "Show IPv4 rule with dsfield 0x10" -4 rule show dsfield 0x10 +test_on "tos 0x10" +test_lines_count 1 +ts_ip "$0" "Delete IPv4 rule with dsfield 0x10" -4 rule del dsfield 0x10 + +ts_ip "$0" "Add IPv4 rule with tos 0x10" -4 rule add tos 0x10 +ts_ip "$0" "Show IPv4 rule with tos 0x10" -4 rule show tos 0x10 +test_on "tos 0x10" +test_lines_count 1 +ts_ip "$0" "Delete IPv4 rule with tos 0x10" -4 rule del tos 0x10 + +ts_ip "$0" "Add IPv6 rule with dsfield 0x10" -6 rule add dsfield 0x10 +ts_ip "$0" "Show IPv6 rule with dsfield 0x10" -6 rule show dsfield 0x10 +test_on "tos 0x10" +test_lines_count 1 +ts_ip "$0" "Delete IPv6 rule with dsfield 0x10" -6 rule del dsfield 0x10 + +ts_ip "$0" "Add IPv6 rule with tos 0x10" -6 rule add tos 0x10 +ts_ip "$0" "Show IPv6 rule with tos 0x10" -6 rule show tos 0x10 +test_on "tos 0x10" +test_lines_count 1 +ts_ip "$0" "Delete IPv6 rule with tos 0x10" -6 rule del tos 0x10
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/testsuite/tests/tc/vlan.t -> _service:tar_scm:iproute2-6.1.0.tar.xz/testsuite/tests/tc/vlan.t
Changed
@@ -50,7 +50,6 @@ test_on "modify" test_on "id 5" test_on "protocol 802.1Q" -test_on "priority 0" test_on "pipe" reset_qdisc
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/testsuite/tools/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/testsuite/tools/Makefile
Changed
@@ -2,8 +2,8 @@ CFLAGS= include ../../config.mk -generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.c - $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -I../../include -I../../include/uapi -include../../include/uapi/linux/netlink.h -o $@ $^ -lmnl +generate_nlmsg: generate_nlmsg.c ../../lib/libnetlink.a ../../lib/libutil.a + $(QUIET_CC)$(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) -I../../include -I../../include/uapi -include../../include/uapi/linux/netlink.h -o $@ $^ -lmnl -lcap clean: rm -f generate_nlmsg
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tipc/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/tipc/Makefile
Changed
@@ -1,10 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk -TARGETS := - -ifeq ($(HAVE_MNL),y) - TIPCOBJ=bearer.o \ cmdl.o link.o \ media.o misc.o \ @@ -14,8 +10,6 @@ TARGETS += tipc -endif - all: $(TARGETS) $(LIBS) tipc: $(TIPCOBJ)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tipc/link.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tipc/link.c
Changed
@@ -332,7 +332,7 @@ open_json_object(NULL); print_string(PRINT_ANY, "link", "Link <%s>\n", name); - print_string(PRINT_JSON, "state", "", NULL); + print_string(PRINT_JSON, "state", NULL, NULL); open_json_array(PRINT_JSON, NULL); if (attrsTIPC_NLA_LINK_ACTIVE) print_string(PRINT_ANY, NULL, " %s", "ACTIVE");
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/tipc/misc.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/tipc/misc.c
Changed
@@ -113,16 +113,15 @@ } } - if (len > TIPC_AEAD_KEYLEN_MAX) + key->keylen = ishex ? (len + 1) / 2 : len; + if (key->keylen > TIPC_AEAD_KEYLEN_MAX) return -1; /* Obtain key: */ if (!ishex) { - key->keylen = len; memcpy(key->key, str, len); } else { /* Convert hex string to key */ - key->keylen = (len + 1) / 2; for (i = 0; i < key->keylen; i++) { if (i == 0 && len % 2 != 0) { if (sscanf(str, "%1hhx", &key->key0) != 1)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/vdpa/Makefile -> _service:tar_scm:iproute2-6.1.0.tar.xz/vdpa/Makefile
Changed
@@ -1,16 +1,10 @@ # SPDX-License-Identifier: GPL-2.0 include ../config.mk -TARGETS := - -ifeq ($(HAVE_MNL),y) - CFLAGS += -I./include/uapi/ VDPAOBJ = vdpa.o TARGETS += vdpa -endif - all: $(TARGETS) $(LIBS) vdpa: $(VDPAOBJ)
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/vdpa/include/uapi/linux/vdpa.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/vdpa/include/uapi/linux/vdpa.h
Changed
@@ -17,11 +17,16 @@ VDPA_CMD_DEV_NEW, VDPA_CMD_DEV_DEL, VDPA_CMD_DEV_GET, /* can dump */ + VDPA_CMD_DEV_CONFIG_GET, /* can dump */ + VDPA_CMD_DEV_VSTATS_GET, }; enum vdpa_attr { VDPA_ATTR_UNSPEC, + /* Pad attribute for 64b alignment */ + VDPA_ATTR_PAD = VDPA_ATTR_UNSPEC, + /* bus name (optional) + dev name together make the parent device handle */ VDPA_ATTR_MGMTDEV_BUS_NAME, /* string */ VDPA_ATTR_MGMTDEV_DEV_NAME, /* string */ @@ -32,6 +37,26 @@ VDPA_ATTR_DEV_VENDOR_ID, /* u32 */ VDPA_ATTR_DEV_MAX_VQS, /* u32 */ VDPA_ATTR_DEV_MAX_VQ_SIZE, /* u16 */ + VDPA_ATTR_DEV_MIN_VQ_SIZE, /* u16 */ + + VDPA_ATTR_DEV_NET_CFG_MACADDR, /* binary */ + VDPA_ATTR_DEV_NET_STATUS, /* u8 */ + VDPA_ATTR_DEV_NET_CFG_MAX_VQP, /* u16 */ + VDPA_ATTR_DEV_NET_CFG_MTU, /* u16 */ + + VDPA_ATTR_DEV_NEGOTIATED_FEATURES, /* u64 */ + VDPA_ATTR_DEV_MGMTDEV_MAX_VQS, /* u32 */ + /* virtio features that are supported by the vDPA management device */ + VDPA_ATTR_DEV_SUPPORTED_FEATURES, /* u64 */ + + VDPA_ATTR_DEV_QUEUE_INDEX, /* u32 */ + VDPA_ATTR_DEV_VENDOR_ATTR_NAME, /* string */ + VDPA_ATTR_DEV_VENDOR_ATTR_VALUE, /* u64 */ + + VDPA_ATTR_DEV_FEATURES, /* u64 */ + + /* virtio features that are supported by the vDPA device */ + VDPA_ATTR_VDPA_DEV_SUPPORTED_FEATURES, /* u64 */ /* new attributes must be added above here */ VDPA_ATTR_MAX,
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/vdpa/include/uapi/linux/virtio_ids.h -> _service:tar_scm:iproute2-6.1.0.tar.xz/vdpa/include/uapi/linux/virtio_ids.h
Changed
@@ -51,8 +51,34 @@ #define VIRTIO_ID_PSTORE 22 /* virtio pstore device */ #define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */ #define VIRTIO_ID_MEM 24 /* virtio mem */ +#define VIRTIO_ID_SOUND 25 /* virtio sound */ #define VIRTIO_ID_FS 26 /* virtio filesystem */ #define VIRTIO_ID_PMEM 27 /* virtio pmem */ +#define VIRTIO_ID_RPMB 28 /* virtio rpmb */ #define VIRTIO_ID_MAC80211_HWSIM 29 /* virtio mac80211-hwsim */ +#define VIRTIO_ID_VIDEO_ENCODER 30 /* virtio video encoder */ +#define VIRTIO_ID_VIDEO_DECODER 31 /* virtio video decoder */ +#define VIRTIO_ID_SCMI 32 /* virtio SCMI */ +#define VIRTIO_ID_NITRO_SEC_MOD 33 /* virtio nitro secure module*/ +#define VIRTIO_ID_I2C_ADAPTER 34 /* virtio i2c adapter */ +#define VIRTIO_ID_WATCHDOG 35 /* virtio watchdog */ +#define VIRTIO_ID_CAN 36 /* virtio can */ +#define VIRTIO_ID_DMABUF 37 /* virtio dmabuf */ +#define VIRTIO_ID_PARAM_SERV 38 /* virtio parameter server */ +#define VIRTIO_ID_AUDIO_POLICY 39 /* virtio audio policy */ +#define VIRTIO_ID_BT 40 /* virtio bluetooth */ +#define VIRTIO_ID_GPIO 41 /* virtio gpio */ + +/* + * Virtio Transitional IDs + */ + +#define VIRTIO_TRANS_ID_NET 0x1000 /* transitional virtio net */ +#define VIRTIO_TRANS_ID_BLOCK 0x1001 /* transitional virtio block */ +#define VIRTIO_TRANS_ID_BALLOON 0x1002 /* transitional virtio balloon */ +#define VIRTIO_TRANS_ID_CONSOLE 0x1003 /* transitional virtio console */ +#define VIRTIO_TRANS_ID_SCSI 0x1004 /* transitional virtio SCSI */ +#define VIRTIO_TRANS_ID_RNG 0x1005 /* transitional virtio rng */ +#define VIRTIO_TRANS_ID_9P 0x1009 /* transitional virtio 9p console */ #endif /* _LINUX_VIRTIO_IDS_H */
View file
_service:tar_scm:iproute2-6.1.0.tar.xz/vdpa/include/uapi/linux/virtio_ring.h
Added
@@ -0,0 +1,248 @@ +#ifndef _LINUX_VIRTIO_RING_H +#define _LINUX_VIRTIO_RING_H +/* An interface for efficient virtio implementation, currently for use by KVM, + * but hopefully others soon. Do NOT change this since it will + * break existing servers and clients. + * + * This header is BSD licensed so anyone can use the definitions to implement + * compatible drivers/servers. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of IBM nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL IBM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Copyright Rusty Russell IBM Corporation 2007. */ +#include <stdint.h> +#include <linux/types.h> +#include <linux/virtio_types.h> + +/* This marks a buffer as continuing via the next field. */ +#define VRING_DESC_F_NEXT 1 +/* This marks a buffer as write-only (otherwise read-only). */ +#define VRING_DESC_F_WRITE 2 +/* This means the buffer contains a list of buffer descriptors. */ +#define VRING_DESC_F_INDIRECT 4 + +/* + * Mark a descriptor as available or used in packed ring. + * Notice: they are defined as shifts instead of shifted values. + */ +#define VRING_PACKED_DESC_F_AVAIL 7 +#define VRING_PACKED_DESC_F_USED 15 + +/* The Host uses this in used->flags to advise the Guest: don't kick me when + * you add a buffer. It's unreliable, so it's simply an optimization. Guest + * will still kick if it's out of buffers. */ +#define VRING_USED_F_NO_NOTIFY 1 +/* The Guest uses this in avail->flags to advise the Host: don't interrupt me + * when you consume a buffer. It's unreliable, so it's simply an + * optimization. */ +#define VRING_AVAIL_F_NO_INTERRUPT 1 + +/* Enable events in packed ring. */ +#define VRING_PACKED_EVENT_FLAG_ENABLE 0x0 +/* Disable events in packed ring. */ +#define VRING_PACKED_EVENT_FLAG_DISABLE 0x1 +/* + * Enable events for a specific descriptor in packed ring. + * (as specified by Descriptor Ring Change Event Offset/Wrap Counter). + * Only valid if VIRTIO_RING_F_EVENT_IDX has been negotiated. + */ +#define VRING_PACKED_EVENT_FLAG_DESC 0x2 + +/* + * Wrap counter bit shift in event suppression structure + * of packed ring. + */ +#define VRING_PACKED_EVENT_F_WRAP_CTR 15 + +/* We support indirect buffer descriptors */ +#define VIRTIO_RING_F_INDIRECT_DESC 28 + +/* The Guest publishes the used index for which it expects an interrupt + * at the end of the avail ring. Host should ignore the avail->flags field. */ +/* The Host publishes the avail index for which it expects a kick + * at the end of the used ring. Guest should ignore the used->flags field. */ +#define VIRTIO_RING_F_EVENT_IDX 29 + +/* Alignment requirements for vring elements. + * When using pre-virtio 1.0 layout, these fall out naturally. + */ +#define VRING_AVAIL_ALIGN_SIZE 2 +#define VRING_USED_ALIGN_SIZE 4 +#define VRING_DESC_ALIGN_SIZE 16 + +/** + * struct vring_desc - Virtio ring descriptors, + * 16 bytes long. These can chain together via @next. + * + * @addr: buffer address (guest-physical) + * @len: buffer length + * @flags: descriptor flags + * @next: index of the next descriptor in the chain, + * if the VRING_DESC_F_NEXT flag is set. We chain unused + * descriptors via this, too. + */ +struct vring_desc { + __virtio64 addr; + __virtio32 len; + __virtio16 flags; + __virtio16 next; +}; + +struct vring_avail { + __virtio16 flags; + __virtio16 idx; + __virtio16 ring; +}; + +/* u32 is used here for ids for padding reasons. */ +struct vring_used_elem { + /* Index of start of used descriptor chain. */ + __virtio32 id; + /* Total length of the descriptor chain which was used (written to) */ + __virtio32 len; +}; + +typedef struct vring_used_elem __attribute__((aligned(VRING_USED_ALIGN_SIZE))) + vring_used_elem_t; + +struct vring_used { + __virtio16 flags; + __virtio16 idx; + vring_used_elem_t ring; +}; + +/* + * The ring element addresses are passed between components with different + * alignments assumptions. Thus, we might need to decrease the compiler-selected + * alignment, and so must use a typedef to make sure the aligned attribute + * actually takes hold: + * + * https://gcc.gnu.org/onlinedocs//gcc/Common-Type-Attributes.html#Common-Type-Attributes + * + * When used on a struct, or struct member, the aligned attribute can only + * increase the alignment; in order to decrease it, the packed attribute must + * be specified as well. When used as part of a typedef, the aligned attribute + * can both increase and decrease alignment, and specifying the packed + * attribute generates a warning. + */ +typedef struct vring_desc __attribute__((aligned(VRING_DESC_ALIGN_SIZE))) + vring_desc_t; +typedef struct vring_avail __attribute__((aligned(VRING_AVAIL_ALIGN_SIZE))) + vring_avail_t; +typedef struct vring_used __attribute__((aligned(VRING_USED_ALIGN_SIZE))) + vring_used_t; + +struct vring { + unsigned int num; + + vring_desc_t *desc; + + vring_avail_t *avail; + + vring_used_t *used; +}; + +#ifndef VIRTIO_RING_NO_LEGACY + +/* The standard layout for the ring is a continuous chunk of memory which looks + * like this. We assume num is a power of 2. + * + * struct vring + * { + * // The actual descriptors (16 bytes each) + * struct vring_desc descnum; + * + * // A ring of available descriptor heads with free-running index. + * __virtio16 avail_flags; + * __virtio16 avail_idx; + * __virtio16 availablenum; + * __virtio16 used_event_idx; + * + * // Padding to the next align boundary. + * char pad; + * + * // A ring of used descriptor heads with free-running index. + * __virtio16 used_flags; + * __virtio16 used_idx; + * struct vring_used_elem usednum; + * __virtio16 avail_event_idx; + * }; + */ +/* We publish the used event index at the end of the available ring, and vice + * versa. They are at the end for backwards compatibility. */ +#define vring_used_event(vr) ((vr)->avail->ring(vr)->num) +#define vring_avail_event(vr) (*(__virtio16 *)&(vr)->used->ring(vr)->num) + +static __inline__ void vring_init(struct vring *vr, unsigned int num, void *p, + unsigned long align) +{ + vr->num = num; + vr->desc = p; + vr->avail = (struct vring_avail *)((char *)p + num * sizeof(struct vring_desc)); + vr->used = (void *)(((uintptr_t)&vr->avail->ringnum + sizeof(__virtio16) + + align-1) & ~(align - 1)); +} + +static __inline__ unsigned vring_size(unsigned int num, unsigned long align) +{ + return ((sizeof(struct vring_desc) * num + sizeof(__virtio16) * (3 + num) + + align - 1) & ~(align - 1)) + + sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num; +} + +#endif /* VIRTIO_RING_NO_LEGACY */ + +/* The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX */ +/* Assuming a given event_idx value from the other side, if + * we have just incremented index from old to new_idx, + * should we trigger an event? */ +static __inline__ int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old) +{ + /* Note: Xen has similar logic for notification hold-off + * in include/xen/interface/io/ring.h with req_event and req_prod + * corresponding to event_idx + 1 and new_idx respectively. + * Note also that req_event and req_prod in Xen start at 1, + * event indexes in virtio start at 0. */ + return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old); +} + +struct vring_packed_desc_event { + /* Descriptor Ring Change Event Offset/Wrap Counter. */ + __le16 off_wrap; + /* Descriptor Ring Change Event Flags. */ + __le16 flags; +}; + +struct vring_packed_desc { + /* Buffer Address. */ + __le64 addr; + /* Buffer Length. */ + __le32 len; + /* Buffer ID. */ + __le16 id; + /* The flags depending on descriptor type. */ + __le16 flags; +}; + +#endif /* _LINUX_VIRTIO_RING_H */
View file
_service:tar_scm:iproute2-5.15.0.tar.xz/vdpa/vdpa.c -> _service:tar_scm:iproute2-6.1.0.tar.xz/vdpa/vdpa.c
Changed
@@ -4,11 +4,16 @@ #include <getopt.h> #include <errno.h> #include <linux/genetlink.h> +#include <linux/if_ether.h> #include <linux/vdpa.h> #include <linux/virtio_ids.h> +#include <linux/virtio_net.h> #include <linux/netlink.h> #include <libmnl/libmnl.h> +#include <linux/virtio_ring.h> +#include <linux/virtio_config.h> #include "mnl_utils.h" +#include <rt_names.h> #include "version.h" #include "json_print.h" @@ -18,6 +23,10 @@ #define VDPA_OPT_VDEV_MGMTDEV_HANDLE BIT(1) #define VDPA_OPT_VDEV_NAME BIT(2) #define VDPA_OPT_VDEV_HANDLE BIT(3) +#define VDPA_OPT_VDEV_MAC BIT(4) +#define VDPA_OPT_VDEV_MTU BIT(5) +#define VDPA_OPT_MAX_VQP BIT(6) +#define VDPA_OPT_QUEUE_INDEX BIT(7) struct vdpa_opts { uint64_t present; /* flags of present items */ @@ -25,6 +34,10 @@ char *mdev_name; const char *vdev_name; unsigned int device_id; + char macETH_ALEN; + uint16_t mtu; + uint16_t max_vqp; + uint32_t queue_idx; }; struct vdpa { @@ -71,6 +84,9 @@ VDPA_ATTR_DEV_VENDOR_ID = MNL_TYPE_U32, VDPA_ATTR_DEV_MAX_VQS = MNL_TYPE_U32, VDPA_ATTR_DEV_MAX_VQ_SIZE = MNL_TYPE_U16, + VDPA_ATTR_DEV_NEGOTIATED_FEATURES = MNL_TYPE_U64, + VDPA_ATTR_DEV_MGMTDEV_MAX_VQS = MNL_TYPE_U32, + VDPA_ATTR_DEV_SUPPORTED_FEATURES = MNL_TYPE_U64, }; static int attr_cb(const struct nlattr *attr, void *data) @@ -134,6 +150,43 @@ return 0; } +static int vdpa_argv_mac(struct vdpa *vdpa, int argc, char **argv, char *mac) +{ + int alen; + + if (argc <= 0 || *argv == NULL) { + fprintf(stderr, "String parameter expected\n"); + return -EINVAL; + } + + alen = ll_addr_a2n(mac, ETH_ALEN, *argv); + if (alen < 0) + return -EINVAL; + return 0; +} + +static int vdpa_argv_u16(struct vdpa *vdpa, int argc, char **argv, + uint16_t *result) +{ + if (argc <= 0 || *argv == NULL) { + fprintf(stderr, "number expected\n"); + return -EINVAL; + } + + return get_u16(result, *argv, 10); +} + +static int vdpa_argv_u32(struct vdpa *vdpa, int argc, char **argv, + uint32_t *result) +{ + if (argc <= 0 || !*argv) { + fprintf(stderr, "number expected\n"); + return -EINVAL; + } + + return get_u32(result, *argv, 10); +} + struct vdpa_args_metadata { uint64_t o_flag; const char *err_msg; @@ -143,6 +196,7 @@ {VDPA_OPT_VDEV_MGMTDEV_HANDLE, "management device handle not set."}, {VDPA_OPT_VDEV_NAME, "device name is not set."}, {VDPA_OPT_VDEV_HANDLE, "device name is not set."}, + {VDPA_OPT_QUEUE_INDEX, "queue index is not set."}, }; static int vdpa_args_finding_required_validate(uint64_t o_required, @@ -181,13 +235,22 @@ if ((opts->present & VDPA_OPT_VDEV_NAME) || (opts->present & VDPA_OPT_VDEV_HANDLE)) mnl_attr_put_strz(nlh, VDPA_ATTR_DEV_NAME, opts->vdev_name); + if (opts->present & VDPA_OPT_VDEV_MAC) + mnl_attr_put(nlh, VDPA_ATTR_DEV_NET_CFG_MACADDR, + sizeof(opts->mac), opts->mac); + if (opts->present & VDPA_OPT_VDEV_MTU) + mnl_attr_put_u16(nlh, VDPA_ATTR_DEV_NET_CFG_MTU, opts->mtu); + if (opts->present & VDPA_OPT_MAX_VQP) + mnl_attr_put_u16(nlh, VDPA_ATTR_DEV_NET_CFG_MAX_VQP, opts->max_vqp); + if (opts->present & VDPA_OPT_QUEUE_INDEX) + mnl_attr_put_u32(nlh, VDPA_ATTR_DEV_QUEUE_INDEX, opts->queue_idx); } static int vdpa_argv_parse(struct vdpa *vdpa, int argc, char **argv, - uint64_t o_required) + uint64_t o_required, uint64_t o_optional) { + uint64_t o_all = o_required | o_optional; struct vdpa_opts *opts = &vdpa->opts; - uint64_t o_all = o_required; uint64_t o_found = 0; int err; @@ -231,6 +294,41 @@ NEXT_ARG_FWD(); o_found |= VDPA_OPT_VDEV_MGMTDEV_HANDLE; + } else if ((strcmp(*argv, "mac") == 0) && + (o_all & VDPA_OPT_VDEV_MAC)) { + NEXT_ARG_FWD(); + err = vdpa_argv_mac(vdpa, argc, argv, opts->mac); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_VDEV_MAC; + } else if ((strcmp(*argv, "mtu") == 0) && + (o_all & VDPA_OPT_VDEV_MTU)) { + NEXT_ARG_FWD(); + err = vdpa_argv_u16(vdpa, argc, argv, &opts->mtu); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_VDEV_MTU; + } else if ((matches(*argv, "max_vqp") == 0) && (o_optional & VDPA_OPT_MAX_VQP)) { + NEXT_ARG_FWD(); + err = vdpa_argv_u16(vdpa, argc, argv, &opts->max_vqp); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_MAX_VQP; + } else if (!strcmp(*argv, "qidx") && + (o_optional & VDPA_OPT_QUEUE_INDEX)) { + NEXT_ARG_FWD(); + err = vdpa_argv_u32(vdpa, argc, argv, &opts->queue_idx); + if (err) + return err; + + NEXT_ARG_FWD(); + o_found |= VDPA_OPT_QUEUE_INDEX; } else { fprintf(stderr, "Unknown option \"%s\"\n", *argv); return -EINVAL; @@ -244,11 +342,11 @@ static int vdpa_argv_parse_put(struct nlmsghdr *nlh, struct vdpa *vdpa, int argc, char **argv, - uint64_t o_required) + uint64_t o_required, uint64_t o_optional) { int err; - err = vdpa_argv_parse(vdpa, argc, argv, o_required); + err = vdpa_argv_parse(vdpa, argc, argv, o_required, o_optional); if (err) return err; vdpa_opts_put(nlh, vdpa); @@ -329,17 +427,105 @@ return class ? class : "< unknown class >"; } +static const char * const net_feature_strs64 = { + VIRTIO_NET_F_CSUM = "CSUM", + VIRTIO_NET_F_GUEST_CSUM = "GUEST_CSUM", + VIRTIO_NET_F_CTRL_GUEST_OFFLOADS = "CTRL_GUEST_OFFLOADS", + VIRTIO_NET_F_MTU = "MTU", + VIRTIO_NET_F_MAC = "MAC", + VIRTIO_NET_F_GUEST_TSO4 = "GUEST_TSO4", + VIRTIO_NET_F_GUEST_TSO6 = "GUEST_TSO6", + VIRTIO_NET_F_GUEST_ECN = "GUEST_ECN", + VIRTIO_NET_F_GUEST_UFO = "GUEST_UFO", + VIRTIO_NET_F_HOST_TSO4 = "HOST_TSO4", + VIRTIO_NET_F_HOST_TSO6 = "HOST_TSO6", + VIRTIO_NET_F_HOST_ECN = "HOST_ECN", + VIRTIO_NET_F_HOST_UFO = "HOST_UFO", + VIRTIO_NET_F_MRG_RXBUF = "MRG_RXBUF", + VIRTIO_NET_F_STATUS = "STATUS", + VIRTIO_NET_F_CTRL_VQ = "CTRL_VQ", + VIRTIO_NET_F_CTRL_RX = "CTRL_RX", + VIRTIO_NET_F_CTRL_VLAN = "CTRL_VLAN", + VIRTIO_NET_F_CTRL_RX_EXTRA = "CTRL_RX_EXTRA", + VIRTIO_NET_F_GUEST_ANNOUNCE = "GUEST_ANNOUNCE", + VIRTIO_NET_F_MQ = "MQ", + VIRTIO_F_NOTIFY_ON_EMPTY = "NOTIFY_ON_EMPTY", + VIRTIO_NET_F_CTRL_MAC_ADDR = "CTRL_MAC_ADDR", + VIRTIO_F_ANY_LAYOUT = "ANY_LAYOUT", + VIRTIO_NET_F_RSC_EXT = "RSC_EXT", + VIRTIO_NET_F_HASH_REPORT = "HASH_REPORT", + VIRTIO_NET_F_RSS = "RSS", + VIRTIO_NET_F_STANDBY = "STANDBY", + VIRTIO_NET_F_SPEED_DUPLEX = "SPEED_DUPLEX", +}; + +#define VIRTIO_F_IN_ORDER 35 +#define VIRTIO_F_NOTIFICATION_DATA 38 +#define VDPA_EXT_FEATURES_SZ (VIRTIO_TRANSPORT_F_END - \ + VIRTIO_TRANSPORT_F_START + 1) + +static const char * const ext_feature_strsVDPA_EXT_FEATURES_SZ = { + VIRTIO_RING_F_INDIRECT_DESC - VIRTIO_TRANSPORT_F_START = "RING_INDIRECT_DESC", + VIRTIO_RING_F_EVENT_IDX - VIRTIO_TRANSPORT_F_START = "RING_EVENT_IDX", + VIRTIO_F_VERSION_1 - VIRTIO_TRANSPORT_F_START = "VERSION_1", + VIRTIO_F_ACCESS_PLATFORM - VIRTIO_TRANSPORT_F_START = "ACCESS_PLATFORM", + VIRTIO_F_RING_PACKED - VIRTIO_TRANSPORT_F_START = "RING_PACKED", + VIRTIO_F_IN_ORDER - VIRTIO_TRANSPORT_F_START = "IN_ORDER", + VIRTIO_F_ORDER_PLATFORM - VIRTIO_TRANSPORT_F_START = "ORDER_PLATFORM", + VIRTIO_F_SR_IOV - VIRTIO_TRANSPORT_F_START = "SR_IOV", + VIRTIO_F_NOTIFICATION_DATA - VIRTIO_TRANSPORT_F_START = "NOTIFICATION_DATA", +}; + +static const char * const *dev_to_feature_str = { + VIRTIO_ID_NET = net_feature_strs, +}; + +#define NUM_FEATURE_BITS 64 + +static void print_features(struct vdpa *vdpa, uint64_t features, bool mgmtdevf, + uint16_t dev_id) +{ + const char * const *feature_strs = NULL; + const char *s; + int i; + + if (dev_id < ARRAY_SIZE(dev_to_feature_str)) + feature_strs = dev_to_feature_strdev_id; + + if (mgmtdevf) + pr_out_array_start(vdpa, "dev_features"); + else + pr_out_array_start(vdpa, "negotiated_features"); + + for (i = 0; i < NUM_FEATURE_BITS; i++) { + if (!(features & (1ULL << i))) + continue; + + if (i < VIRTIO_TRANSPORT_F_START || i > VIRTIO_TRANSPORT_F_END) + s = feature_strs ? feature_strsi : NULL; + else + s = ext_feature_strsi - VIRTIO_TRANSPORT_F_START; + + if (!s) + print_uint(PRINT_ANY, NULL, " bit_%d", i); + else + print_string(PRINT_ANY, NULL, " %s", s); + } + + pr_out_array_end(vdpa); +} + static void pr_out_mgmtdev_show(struct vdpa *vdpa, const struct nlmsghdr *nlh, struct nlattr **tb) { + uint64_t classes = 0; const char *class; unsigned int i; pr_out_handle_start(vdpa, tb); if (tbVDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES) { - uint64_t classes = mnl_attr_get_u64(tbVDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES); - + classes = mnl_attr_get_u64(tbVDPA_ATTR_MGMTDEV_SUPPORTED_CLASSES); pr_out_array_start(vdpa, "supported_classes"); for (i = 1; i < 64; i++) { @@ -352,6 +538,24 @@ pr_out_array_end(vdpa); } + if (tbVDPA_ATTR_DEV_MGMTDEV_MAX_VQS) { + uint32_t num_vqs; + + print_nl(); + num_vqs = mnl_attr_get_u32(tbVDPA_ATTR_DEV_MGMTDEV_MAX_VQS); + print_uint(PRINT_ANY, "max_supported_vqs", " max_supported_vqs %d", num_vqs); + } + + if (tbVDPA_ATTR_DEV_SUPPORTED_FEATURES) { + uint64_t features; + + features = mnl_attr_get_u64(tbVDPA_ATTR_DEV_SUPPORTED_FEATURES); + if (classes & BIT(VIRTIO_ID_NET)) + print_features(vdpa, features, true, VIRTIO_ID_NET); + else + print_features(vdpa, features, true, 0); + } + pr_out_handle_end(vdpa); } @@ -384,7 +588,7 @@ flags); if (argc > 0) { err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, - VDPA_OPT_MGMTDEV_HANDLE); + VDPA_OPT_MGMTDEV_HANDLE, 0); if (err) return err; } @@ -411,8 +615,11 @@ static void cmd_dev_help(void) { fprintf(stderr, "Usage: vdpa dev show DEV \n"); - fprintf(stderr, " vdpa dev add name NAME mgmtdev MANAGEMENTDEV\n"); + fprintf(stderr, " vdpa dev add name NAME mgmtdev MANAGEMENTDEV mac MACADDR mtu MTU \n"); + fprintf(stderr, " max_vqp MAX_VQ_PAIRS \n"); fprintf(stderr, " vdpa dev del DEV\n"); + fprintf(stderr, "Usage: vdpa dev config COMMAND OPTIONS \n"); + fprintf(stderr, "Usage: vdpa dev vstats COMMAND\n"); } static const char *device_type_name(uint32_t type) @@ -480,7 +687,7 @@ nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_GET, flags); if (argc > 0) { err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, - VDPA_OPT_VDEV_HANDLE); + VDPA_OPT_VDEV_HANDLE, 0); if (err) return err; } @@ -499,7 +706,9 @@ nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_NEW, NLM_F_REQUEST | NLM_F_ACK); err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, - VDPA_OPT_VDEV_MGMTDEV_HANDLE | VDPA_OPT_VDEV_NAME); + VDPA_OPT_VDEV_MGMTDEV_HANDLE | VDPA_OPT_VDEV_NAME, + VDPA_OPT_VDEV_MAC | VDPA_OPT_VDEV_MTU | + VDPA_OPT_MAX_VQP); if (err) return err; @@ -513,13 +722,264 @@ nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_DEL, NLM_F_REQUEST | NLM_F_ACK); - err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, VDPA_OPT_VDEV_HANDLE); + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, VDPA_OPT_VDEV_HANDLE, + 0); if (err) return err; return mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, NULL, NULL); } +static void pr_out_dev_net_config(struct vdpa *vdpa, struct nlattr **tb) +{ + SPRINT_BUF(macaddr); + uint64_t val_u64; + uint16_t val_u16; + + if (tbVDPA_ATTR_DEV_NET_CFG_MACADDR) { + const unsigned char *data; + uint16_t len; + + len = mnl_attr_get_payload_len(tbVDPA_ATTR_DEV_NET_CFG_MACADDR); + data = mnl_attr_get_payload(tbVDPA_ATTR_DEV_NET_CFG_MACADDR); + + print_string(PRINT_ANY, "mac", "mac %s ", + ll_addr_n2a(data, len, 0, macaddr, sizeof(macaddr))); + } + if (tbVDPA_ATTR_DEV_NET_STATUS) { + val_u16 = mnl_attr_get_u16(tbVDPA_ATTR_DEV_NET_STATUS); + print_string(PRINT_ANY, "link ", "link %s ", + (val_u16 & VIRTIO_NET_S_LINK_UP) ? "up" : "down"); + print_bool(PRINT_ANY, "link_announce ", "link_announce %s ", + (val_u16 & VIRTIO_NET_S_ANNOUNCE) ? true : false); + } + if (tbVDPA_ATTR_DEV_NET_CFG_MAX_VQP) { + val_u16 = mnl_attr_get_u16(tbVDPA_ATTR_DEV_NET_CFG_MAX_VQP); + print_uint(PRINT_ANY, "max_vq_pairs", "max_vq_pairs %d ", + val_u16); + } + if (tbVDPA_ATTR_DEV_NET_CFG_MTU) { + val_u16 = mnl_attr_get_u16(tbVDPA_ATTR_DEV_NET_CFG_MTU); + print_uint(PRINT_ANY, "mtu", "mtu %d ", val_u16); + } + if (tbVDPA_ATTR_DEV_NEGOTIATED_FEATURES) { + uint16_t dev_id = 0; + + if (tbVDPA_ATTR_DEV_ID) + dev_id = mnl_attr_get_u32(tbVDPA_ATTR_DEV_ID); + + val_u64 = mnl_attr_get_u64(tbVDPA_ATTR_DEV_NEGOTIATED_FEATURES); + print_features(vdpa, val_u64, false, dev_id); + } +} + +static void pr_out_dev_config(struct vdpa *vdpa, struct nlattr **tb) +{ + uint32_t device_id = mnl_attr_get_u32(tbVDPA_ATTR_DEV_ID); + + pr_out_vdev_handle_start(vdpa, tb); + switch (device_id) { + case VIRTIO_ID_NET: + pr_out_dev_net_config(vdpa, tb); + break; + default: + break; + } + pr_out_vdev_handle_end(vdpa); +} + +static int cmd_dev_config_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tbVDPA_ATTR_MAX + 1 = {}; + struct vdpa *vdpa = data; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tbVDPA_ATTR_DEV_NAME || !tbVDPA_ATTR_DEV_ID) + return MNL_CB_ERROR; + pr_out_dev_config(vdpa, tb); + return MNL_CB_OK; +} + +static int cmd_dev_config_show(struct vdpa *vdpa, int argc, char **argv) +{ + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlmsghdr *nlh; + int err; + + if (argc <= 0) + flags |= NLM_F_DUMP; + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_CONFIG_GET, + flags); + if (argc > 0) { + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, + VDPA_OPT_VDEV_HANDLE, 0); + if (err) + return err; + } + + pr_out_section_start(vdpa, "config"); + err = mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, cmd_dev_config_show_cb, vdpa); + pr_out_section_end(vdpa); + return err; +} + +static void cmd_dev_config_help(void) +{ + fprintf(stderr, "Usage: vdpa dev config show DEV \n"); +} + +static int cmd_dev_config(struct vdpa *vdpa, int argc, char **argv) +{ + if (!argc) + return cmd_dev_config_show(vdpa, argc - 1, argv + 1); + + if (matches(*argv, "help") == 0) { + cmd_dev_config_help(); + return 0; + } else if (matches(*argv, "show") == 0) { + return cmd_dev_config_show(vdpa, argc - 1, argv + 1); + } + fprintf(stderr, "Command \"%s\" not found\n", *argv); + return -ENOENT; +} + +#define MAX_KEY_LEN 200 +/* 5 bytes for format */ +#define MAX_FMT_LEN (MAX_KEY_LEN + 5 + 1) + +static void print_queue_type(struct nlattr *attr, uint16_t max_vqp, uint64_t features) +{ + bool is_ctrl = false; + uint16_t qidx = 0; + + qidx = mnl_attr_get_u16(attr); + is_ctrl = features & BIT(VIRTIO_NET_F_CTRL_VQ) && qidx == 2 * max_vqp; + if (!is_ctrl) { + if (qidx & 1) + print_string(PRINT_ANY, "queue_type", "queue_type %s ", + "tx"); + else + print_string(PRINT_ANY, "queue_type", "queue_type %s ", + "rx"); + } else { + print_string(PRINT_ANY, "queue_type", "queue_type %s ", + "control_vq"); + } +} + +static void pr_out_dev_net_vstats(const struct nlmsghdr *nlh) +{ + const char *name = NULL; + uint64_t features = 0; + char fmtMAX_FMT_LEN; + uint16_t max_vqp = 0; + struct nlattr *attr; + uint64_t v64; + + mnl_attr_for_each(attr, nlh, sizeof(struct genlmsghdr)) { + switch (attr->nla_type) { + case VDPA_ATTR_DEV_NET_CFG_MAX_VQP: + max_vqp = mnl_attr_get_u16(attr); + break; + case VDPA_ATTR_DEV_NEGOTIATED_FEATURES: + features = mnl_attr_get_u64(attr); + break; + case VDPA_ATTR_DEV_QUEUE_INDEX: + print_queue_type(attr, max_vqp, features); + break; + case VDPA_ATTR_DEV_VENDOR_ATTR_NAME: + name = mnl_attr_get_str(attr); + if (strlen(name) > MAX_KEY_LEN) + return; + + strcpy(fmt, name); + strcat(fmt, " %lu "); + break; + case VDPA_ATTR_DEV_VENDOR_ATTR_VALUE: + v64 = mnl_attr_get_u64(attr); + print_u64(PRINT_ANY, name, fmt, v64); + break; + } + } +} + +static void pr_out_dev_vstats(struct vdpa *vdpa, struct nlattr **tb, const struct nlmsghdr *nlh) +{ + uint32_t device_id = mnl_attr_get_u32(tbVDPA_ATTR_DEV_ID); + + pr_out_vdev_handle_start(vdpa, tb); + switch (device_id) { + case VIRTIO_ID_NET: + pr_out_dev_net_vstats(nlh); + break; + default: + break; + } + pr_out_vdev_handle_end(vdpa); +} + +static int cmd_dev_vstats_show_cb(const struct nlmsghdr *nlh, void *data) +{ + struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh); + struct nlattr *tbVDPA_ATTR_MAX + 1 = {}; + struct vdpa *vdpa = data; + + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tbVDPA_ATTR_DEV_NAME || !tbVDPA_ATTR_DEV_ID) + return MNL_CB_ERROR; + pr_out_dev_vstats(vdpa, tb, nlh); + return MNL_CB_OK; +} + +static void cmd_dev_vstats_help(void) +{ + fprintf(stderr, "Usage: vdpa dev vstats show DEV qidx QUEUE_INDEX\n"); +} + +static int cmd_dev_vstats_show(struct vdpa *vdpa, int argc, char **argv) +{ + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + struct nlmsghdr *nlh; + int err; + + if (argc != 1 && argc != 3) { + cmd_dev_vstats_help(); + return -EINVAL; + } + + nlh = mnlu_gen_socket_cmd_prepare(&vdpa->nlg, VDPA_CMD_DEV_VSTATS_GET, + flags); + + err = vdpa_argv_parse_put(nlh, vdpa, argc, argv, + VDPA_OPT_VDEV_HANDLE, VDPA_OPT_QUEUE_INDEX); + if (err) + return err; + + pr_out_section_start(vdpa, "vstats"); + err = mnlu_gen_socket_sndrcv(&vdpa->nlg, nlh, cmd_dev_vstats_show_cb, vdpa); + pr_out_section_end(vdpa); + return 0; +} + +static int cmd_dev_vstats(struct vdpa *vdpa, int argc, char **argv) +{ + if (argc < 1) { + cmd_dev_vstats_help(); + return -EINVAL; + } + + if (!strcmp(*argv, "help")) { + cmd_dev_vstats_help(); + return 0; + } else if (!strcmp(*argv, "show")) { + return cmd_dev_vstats_show(vdpa, argc - 1, argv + 1); + } + fprintf(stderr, "Command \"%s\" not found\n", *argv); + return -ENOENT; +} + static int cmd_dev(struct vdpa *vdpa, int argc, char **argv) { if (!argc) @@ -535,6 +995,10 @@ return cmd_dev_add(vdpa, argc - 1, argv + 1); } else if (matches(*argv, "del") == 0) { return cmd_dev_del(vdpa, argc - 1, argv + 1); + } else if (matches(*argv, "config") == 0) { + return cmd_dev_config(vdpa, argc - 1, argv + 1); + } else if (!strcmp(*argv, "vstats")) { + return cmd_dev_vstats(vdpa, argc - 1, argv + 1); } fprintf(stderr, "Command \"%s\" not found\n", *argv); return -ENOENT; @@ -545,7 +1009,7 @@ fprintf(stderr, "Usage: vdpa OPTIONS OBJECT { COMMAND | help }\n" "where OBJECT := { mgmtdev | dev }\n" - " OPTIONS := { -Version | -no-nice-names | -json | -pretty | -verbose }\n"); + " OPTIONS := { -Version | -no-nice-names | -json | -pretty }\n"); } static int vdpa_cmd(struct vdpa *vdpa, int argc, char **argv)
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2