Compare commits

...

259 Commits

Author SHA1 Message Date
Paul Blakey 73590d9573 tc: flower: Fix buffer overflow on large labels
Buffer is 64bytes, but label printing can take 66bytes printing
in hex, and will overflow when setting the string delimiter ('\0').

Fix that by increasing the print buffer size.

Example of overflowing ct_label:
ct_label 11111111111111111111111111111111/11111111111111111111111111111111

Fixes: 2fffb1c030 ("tc: flower: Add matching on conntrack info")
Signed-off-by: Paul Blakey <paulb@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-12-06 13:44:50 -08:00
Stephen Hemminger 3f77bc6253 uapi: update to if_ether.h
Merged from 5.16-rc3

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-12-03 12:20:02 -08:00
Maxim Petrov 5f8bb902e1 ip/ipnexthop: fix unsigned overflow in parse_nh_group_type_res()
0UL has type 'unsigned long' which is likely to be 64bit on modern machines. At
the same time, the '{idle,unbalanced}_timer' variables are declared as u32, so
these variables cannot be greater than '~0UL / 100' when 'unsigned long' is 64
bits. In such condition it is still possible to pass the check but get the
overflow later when the timers are multiplied by 100 in 'addattr32'.

Fix the possible overflow by changing '~0UL' to 'UINT32_MAX'.

Fixes: 9167671822 ("nexthop: Add support for resilient nexthop groups")
Signed-off-by: Maxim Petrov <mmrmaximuzz@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-18 15:01:48 -08:00
Maxim Petrov 3184de3797 lib/bpf_legacy: remove always-true check
The 'name' field of the 'struct bpf_prog_info' is a plain C array. Thus, the
logical condition in bpf_dump_prog_info() is useless as the array address is
always true, so just remove it.

Signed-off-by: Maxim Petrov <mmrmaximuzz@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-18 15:01:04 -08:00
Stephen Hemminger 79026c1262 rdma: update uapi headers
Update the RDMA uapi headers from 5.16.0-rc1

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-18 10:00:19 -08:00
Stephen Hemminger fa58de9b0c vdpa: align uapi headers
Update vdpa headers based on 5.16.0-rc1 and remove redundant
copy.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-18 09:56:57 -08:00
[200~jiangheng be31c26484 lnstat: fix buffer overflow in header output
Running lnstat will cause core dump from reading past end of array.

Segmentation fault (core dumped)

The maximum  value of th.num_lines is HDR_LINES(10),  h should not be equal to th.num_lines, array th.hdr may be out of bounds.

Signed-off-by jiangheng <jiangheng12@huawei.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-17 13:41:10 -08:00
Maxim Petrov 0e94972590 tc/m_vlan: fix print_vlan() conditional on TCA_VLAN_ACT_PUSH_ETH
Fix the wild bracket in the if clause leading to the error in the condition.

Fixes: d61167dd88 ("m_vlan: add pop_eth and push_eth actions")
Signed-off-by: Maxim Petrov <mmrmaximuzz@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-17 11:13:12 -08:00
Davide Caratti 9bd5ab0f09 mptcp: fix JSON output when dumping endpoints by id
iproute ignores '-j' command line argument when dumping endpoints by id:

 [dcaratti@dcaratti iproute2]$ ./ip/ip -j mptcp endpoint show
 [{"address":"1.2.3.4","id":42,"signal":true,"backup":true}]
 [dcaratti@dcaratti iproute2]$ ./ip/ip -j mptcp endpoint show id 42
 1.2.3.4 id 42 signal backup

fix mptcp_addr_show() to use the proper JSON helpers.

Fixes: 7e0767cd86 ("add support for mptcp netlink interface")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Acked-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-11 10:07:26 -08:00
Anssi Hannula a787d9ae10 man: tc-u32: Fix page to match new firstfrag behavior
Commit 690b11f4a6 ("tc: u32: Fix firstfrag filter.") applied in 2012
changed the "ip firstfrag" selector to not match non-fragmented packets
anymore.

However, the documentation added in f15a23966f ("tc: add a man page
for u32 filter") in 2015 includes an example that relies on the previous
behavior (non-fragmented packet counted as first fragment).

Due to this, the example does not work correctly and does not actually
classify regular SSH packets.

Modify the example to use a raw u16 selector on the fragment offset to
make it work, and also make the firstfrag description more clear about
the current behavior.

Fixes: f15a23966f ("tc: add a man page for u32 filter")
Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi>
Cc: Phil Sutter <phil@nwl.cc>
Cc: Hiroaki SHIMODA <shimoda.hiroaki@gmail.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-09 10:46:17 -08:00
Luca Boccassi af96c7b5dd Fix some typos detected by Lintian in manpages
Signed-off-by: Luca Boccassi <bluca@debian.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-09 10:45:44 -08:00
Stephen Hemminger 35c81b18c4 uapi: update vdpa.h
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-09 10:40:40 -08:00
David Ahern 50b668bdbf Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:45:31 -06:00
David Ahern 9c56d693f6 Merge branch 'can-tdc-plus-cleanups' into next
Vincent Mailhol  says:

====================

The main purpose is to add commandline support for Transmitter Delay
Compensation (TDC) in iproute. Other issues found during the
development of this feature also get addressed.

This patch series contains four patches which respectively:

  1. Correct the bittiming ranges in the print_usage function and add
  the units to give more clarity: some parameters are in milliseconds,
  some in nano seconds, some in time quantum and the newly TDC
  parameters introduced in this series would be in clock period.

  2. Do some code refactoring on function print_ctrlmode().

  3. factorize the many print_*(PRINT_JSON, ...) and fprintf
  occurrences in a single print_*(PRINT_ANY, ...) call and fix the
  signedness while doing that.

  4. report the value of the bitrate prescalers (brp and dbrp).

  5. adds command line support for the TDC in iproute and goes together
  with below series in the kernel:
  https://lore.kernel.org/linux-can/20210814091750.73931-1-mailhol.vincent@wanadoo.fr/T/#t

** Changelog **

>From RFC v5 to v6:
  * Dropped the RFC tag because the related patch series on the kernel
    side were pulled into net-next.
  * Remove the changes in include/uapi/linux/can/netlink.h because
    these should be pulled separately.
  * Add another patch (the second of this series) to do some cleanup
    on function print_ctrlmode().
  * Minor fixes in the patch comments (grammar, rephrasing).

>From RFC v4 to RFC v5:
  * Add the unit (bps, tq, ns or ms) in print_usage()
  * Rewrote void can_print_timing_min_max() to better factorize the
    code.
  * Rewrote the commit message of the two last patches (those related
    to TDC) to either add clarification of fix inacurracies.

>From v3 to RFC v4:
  * Reflect the changes made on the kernel side.

>From RFC v2 to v3:
  * Dropped the RFC tag. Now that the kernel patch reach the testing
    branch, I am finaly ready.
  * Regression fix: configuring a link with only nominal bittiming
    returned -EOPNOTSUPP
  * Added two more patches to the series:
      - iplink_can: fix configuration ranges in print_usage()
      - iplink_can: print brp and dbrp bittiming variables
  * Other small fixes on formatting.

>From RFC v1 to RFC v2:
  * Add an additional patch to the series to fix the issues reported
    by Stephen Hemminger
    Ref: https://lore.kernel.org/linux-can/20210506112007.1666738-1-mailhol.vincent@wanadoo.fr/T/#t

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:44:56 -06:00
Vincent Mailhol 0c263d7c36 iplink_can: add new CAN FD bittiming parameters: Transmitter Delay Compensation (TDC)
At high bit rates, the propagation delay from the TX pin to the RX pin
of the transceiver causes measurement errors: the sample point on the
RX pin might occur on the previous bit.

This issue is addressed in ISO 11898-1 section 11.3.3 "Transmitter
delay compensation" (TDC).

This patch brings command line support to nine TDC parameters which
were recently added to the kernel's CAN netlink interface in order to
implement TDC:
  - IFLA_CAN_TDC_TDCV_MIN: Transmitter Delay Compensation Value
    minimum value
  - IFLA_CAN_TDC_TDCV_MAX: Transmitter Delay Compensation Value
    maximum value
  - IFLA_CAN_TDC_TDCO_MIN: Transmitter Delay Compensation Offset
    minimum value
  - IFLA_CAN_TDC_TDCO_MAX: Transmitter Delay Compensation Offset
    maximum value
  - IFLA_CAN_TDC_TDCF_MIN: Transmitter Delay Compensation Filter
    window minimum value
  - IFLA_CAN_TDC_TDCF_MAX: Transmitter Delay Compensation Filter
    window maximum value
  - IFLA_CAN_TDC_TDCV: Transmitter Delay Compensation Value
  - IFLA_CAN_TDC_TDCO: Transmitter Delay Compensation Offset
  - IFLA_CAN_TDC_TDCF: Transmitter Delay Compensation Filter window

All those new parameters are nested together into the attribute
IFLA_CAN_TDC.

The TDC parameters extend the FD parameters. As such, the TDC
parameters must be specified together the "fd on" flag.

When "fd on" flag is provided, a tdc-mode parameter allows to specify
how to operate.  Valid options for tdc-mode are:

  * auto: the transmitter dynamically measures TDCV for each of the
    transmitted frames. As such, TDCV can not be manually provided. In
    this mode, the user must specify TDCO and may also specify TDCF if
    supported.

  * manual: use a static TDCV provided by the user. In this mode, the
    user must specify both TDCV and TDCO and may also specify TDCF if
    supported.

  * off: TDC is explicitly disabled.

  * tdc-mode parameter omitted (default mode): the kernel decides
    whether TDC should be enabled or not and if so, it calculates the
    TDC values. TDC parameters are an expert option and the average
    user is not expected to provide those, thus the presence of this
    "default mode".

If the fd flag is omitted, all the FD values (including TDC values)
remain unchanged.

If "fd off" flag is specified, all FD values (including TDC values)
are zeroed.

TDCV is always reported in manual mode. In auto mode, TDCV is reported
only if the value is available. Especially, the TDCV might not be
available if the controller has no feature to report it or if the
value in not yet available (i.e. no data sent yet and measurement did
not occur).

TDCF is reported only if tdcf_max is not zero (i.e. if supported by
the controller).

For reference, here are a few samples of how the output looks like:

| $ ip link set can0 type can bitrate 1000000 dbitrate 8000000 fd on tdco 7 tdcf 8 tdc-mode auto

| $ ip --details link show can0
| 1:  can0: <NOARP,ECHO> mtu 72 qdisc noop state DOWN mode DEFAULT group default qlen 10
|     link/can  promiscuity 0 minmtu 0 maxmtu 0
|     can <FD,TDC-AUTO> state STOPPED (berr-counter tx 0 rx 0) restart-ms 0
| 	  bitrate 1000000 sample-point 0.750
| 	  tq 12 prop-seg 29 phase-seg1 30 phase-seg2 20 sjw 1 brp 1
| 	  ES582.1/ES584.1: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp_inc 1
| 	  dbitrate 8000000 dsample-point 0.700
| 	  dtq 12 dprop-seg 3 dphase-seg1 3 dphase-seg2 3 dsjw 1 dbrp 1
| 	  tdco 7 tdcf 8
| 	  ES582.1/ES584.1: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 dbrp_inc 1
| 	  tdco 0..127 tdcf 0..127
| 	  clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

| $ ip --details --json --pretty link show can0
| [ {
|         "ifindex": 1,
|         "ifname": "can0",
|         "flags": [ "NOARP","ECHO" ],
|         "mtu": 72,
|         "qdisc": "noop",
|         "operstate": "DOWN",
|         "linkmode": "DEFAULT",
|         "group": "default",
|         "txqlen": 10,
|         "link_type": "can",
|         "promiscuity": 0,
|         "min_mtu": 0,
|         "max_mtu": 0,
|         "linkinfo": {
|             "info_kind": "can",
|             "info_data": {
|                 "ctrlmode": [ "FD","TDC-AUTO" ],
|                 "state": "STOPPED",
|                 "berr_counter": {
|                     "tx": 0,
|                     "rx": 0
|                 },
|                 "restart_ms": 0,
|                 "bittiming": {
|                     "bitrate": 1000000,
|                     "sample_point": "0.750",
|                     "tq": 12,
|                     "prop_seg": 29,
|                     "phase_seg1": 30,
|                     "phase_seg2": 20,
|                     "sjw": 1,
|                     "brp": 1
|                 },
|                 "bittiming_const": {
|                     "name": "ES582.1/ES584.1",
|                     "tseg1": {
|                         "min": 2,
|                         "max": 256
|                     },
|                     "tseg2": {
|                         "min": 2,
|                         "max": 128
|                     },
|                     "sjw": {
|                         "min": 1,
|                         "max": 128
|                     },
|                     "brp": {
|                         "min": 1,
|                         "max": 512
|                     },
|                     "brp_inc": 1
|                 },
|                 "data_bittiming": {
|                     "bitrate": 8000000,
|                     "sample_point": "0.700",
|                     "tq": 12,
|                     "prop_seg": 3,
|                     "phase_seg1": 3,
|                     "phase_seg2": 3,
|                     "sjw": 1,
|                     "brp": 1,
|                     "tdc": {
|                         "tdco": 7,
|                         "tdcf": 8
|                     }
|                 },
|                 "data_bittiming_const": {
|                     "name": "ES582.1/ES584.1",
|                     "tseg1": {
|                         "min": 2,
|                         "max": 32
|                     },
|                     "tseg2": {
|                         "min": 1,
|                         "max": 16
|                     },
|                     "sjw": {
|                         "min": 1,
|                         "max": 8
|                     },
|                     "brp": {
|                         "min": 1,
|                         "max": 32
|                     },
|                     "brp_inc": 1,
|                     "tdc": {
|                         "tdco": {
|                             "min": 0,
|                             "max": 127
|                         },
|                         "tdcf": {
|                             "min": 0,
|                             "max": 127
|                         }
|                     }
|                 },
|                 "clock": 80000000
|             }
|         },
|         "num_tx_queues": 1,
|         "num_rx_queues": 1,
|         "gso_max_size": 65536,
|         "gso_max_segs": 65535
|     } ]

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:43:10 -06:00
Vincent Mailhol 0f7bb8d842 iplink_can: print brp and dbrp bittiming variables
Report the value of the bit-rate prescaler (brp) for both the nominal
and the data bittiming.

Currently, only the constant brp values (brp_{min,max,inc}) are being
reported. Also, brp is the only member of struct can_bittiming not
being reported.

Noticeably, brp could be calculated by hand from the other bittiming
parameters with below formula:

        brp = clock * tq / 1000000000

with clock in hertz and tq in nano second (thus the need of a 1
billion factor to convert it back to second).

But because above formula is not so trivial to remember and is
subjected to rounding errors, it makes sense to directly output
{d,}bpr.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:42:54 -06:00
Vincent Mailhol 67f3c7a5cc iplink_can: use PRINT_ANY to factorize code and fix signedness
Current implementation heavily relies on some "if (is_json_context())"
switches to decide the context and then does some print_*(PRINT_JSON,
...) when in json context and some fprintf(...) else.

Furthermore, current implementation uses either print_int() or the
conversion specifier %d to print unsigned integers.

This patch factorizes each pairs of print_*(PRINT_JSON, ...) and
fprintf() into a single print_*(PRINT_ANY, ...) call. While doing this
replacement, it uses proper unsigned function print_uint() as well as
the conversion specifier %u when the parameter is an unsigned integer.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:42:50 -06:00
Vincent Mailhol fd5e958c49 iplink_can: code refactoring of print_ctrlmode()
This patch only does cleanup and do not introduce any functional
changes.

We do some code refactoring of print_ctrlmode() in prevision of the
upcoming patch:

  - remove the first argument of print_ctrlmode(). It is a pointer to
    FILE and is never used.

  - add a new function argument: enum output_type t in order to
    specify the output type (i.e. PRINT_{FP,JSON,ANY}).

  - add a new function argument: const char *key in order to specify
    the name of the json array (e.g. "ctrlmode").

  - replace the _PF() macro with the print_flag() function to increase
    readability.

  - directly return if none of the flags are set (previously, this
    check was done before calling the function).

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:42:44 -06:00
Vincent Mailhol 8316df6e6d iplink_can: fix configuration ranges in print_usage() and add unit
The configuration ranges in print_usage() are taken from "Table 8 -
Time segments' minimum configuration ranges" in section 11.3.1.2
"Configuration of the bit time parameters" of ISO 11898-1.

The standard clearly specifies that "implementations may allow time
segments that exceed the minimum required configuration ranges
specified in Table 8".

Because no maximum ranges are given in the standard, all given ranges
{ a..b } are simply replaced with { NUMBER }.

The actual ranges are specific to each device and can be confirmed
doing:

$ ip --details link show can0
1: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 minmtu 0 maxmtu 0
    can state STOPPED restart-ms 0
	  ES582.1/ES584.1: tseg1 2..256 tseg2 2..128 sjw 1..128 brp 1..512 brp-inc 1
	  ES582.1/ES584.1: dtseg1 2..32 dtseg2 1..16 dsjw 1..8 dbrp 1..32 dbrp-inc 1
	  clock 80000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

Finally, the unit (bps, tq, ns or ms) are given. The rationale to add
the units is that the TDC parameters (that will be introduced in the
upcoming patches) are measured in a different unit than the other
bittiming parameters: clock period (a.k.a. minimum time quantum)
instead of time quantum. Adding the units disambiguates things.

For reference, before the change:
$ ip link set can0 type can help
Usage: ip link set DEVICE type can
	[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
	[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
 	  phase-seg2 PHASE-SEG2 [ sjw SJW ] ]

	[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |
	[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1
 	  dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]

	[ loopback { on | off } ]
	[ listen-only { on | off } ]
	[ triple-sampling { on | off } ]
	[ one-shot { on | off } ]
	[ berr-reporting { on | off } ]
	[ fd { on | off } ]
	[ fd-non-iso { on | off } ]
	[ presume-ack { on | off } ]

	[ restart-ms TIME-MS ]
	[ restart ]

	[ termination { 0..65535 } ]

	Where: BITRATE	:= { 1..1000000 }
		  SAMPLE-POINT	:= { 0.000..0.999 }
		  TQ		:= { NUMBER }
		  PROP-SEG	:= { 1..8 }
		  PHASE-SEG1	:= { 1..8 }
		  PHASE-SEG2	:= { 1..8 }
		  SJW		:= { 1..4 }
		  RESTART-MS	:= { 0 | NUMBER }

...and after it:
$ ip link set can0 type can help
Usage: ip link set DEVICE type can
	[ bitrate BITRATE [ sample-point SAMPLE-POINT] ] |
	[ tq TQ prop-seg PROP_SEG phase-seg1 PHASE-SEG1
 	  phase-seg2 PHASE-SEG2 [ sjw SJW ] ]

	[ dbitrate BITRATE [ dsample-point SAMPLE-POINT] ] |
	[ dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1
 	  dphase-seg2 PHASE-SEG2 [ dsjw SJW ] ]

	[ loopback { on | off } ]
	[ listen-only { on | off } ]
	[ triple-sampling { on | off } ]
	[ one-shot { on | off } ]
	[ berr-reporting { on | off } ]
	[ fd { on | off } ]
	[ fd-non-iso { on | off } ]
	[ presume-ack { on | off } ]
	[ cc-len8-dlc { on | off } ]

	[ restart-ms TIME-MS ]
	[ restart ]

	[ termination { 0..65535 } ]

	Where: BITRATE	:= { NUMBER in bps }
		  SAMPLE-POINT	:= { 0.000..0.999 }
		  TQ		:= { NUMBER in ns }
		  PROP-SEG	:= { NUMBER in tq }
		  PHASE-SEG1	:= { NUMBER in tq }
		  PHASE-SEG2	:= { NUMBER in tq }
		  SJW		:= { NUMBER in tq }
		  RESTART-MS	:= { 0 | NUMBER in ms }

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-04 09:42:23 -06:00
Taehee Yoo 6e15d27aae ip: add AMT support
Add basic support for Automatic Multicast Tunneling (AMT) network devices.

Signed-off-by: Taehee Yoo <ap420073@gmail.com>
2021-11-03 13:24:13 -06:00
David Ahern 9cae1de564 Import amt.h
Impor amt.h uapi from last kernel sync point

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-03 13:23:38 -06:00
David Ahern 258e350ca9 Update kernel headers
Update kernel headers to commit:
    cc0356d6a02e ("Merge tag 'x86_core_for_v5.16_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-11-03 13:22:15 -06:00
Moshe Shemesh 047e9ae516 devlink: Fix cmd_dev_param_set() to check configuration mode
This patch is fixing a bug, when param set user command includes
configuration mode which is not supported, the tool may not respond
with error if the requested value is 0. In such case
cmd_dev_param_set_cb() won't find the requested configuration mode and
returns ctx->value as initialized (equal 0). Then cmd_dev_param_set()
may find that requested value equals current value and returns success.

Fixing the bug by adding a flag cmode_found which is set only if
cmd_dev_param_set_cb() finds the requested configuration mode.

Fixes: 13925ae9eb ("devlink: Add param command support")
Signed-off-by: Moshe Shemesh <moshe@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-11-02 08:34:33 -07:00
Stephen Hemminger 7a8b7573a4 v5.15.0 2021-11-01 16:41:02 -07:00
Neta Ostrovsky ad3a118f88 rdma: Fix SRQ resource tracking information json
Fix the json output for the QPs that are associated with the SRQ -
The qpn are now displayed in a json array.

Sample output before the fix:
$ rdma res show srq lqpn 126-141 -j -p
[ {
        "ifindex":0,
	"ifname":"ibp8s0f0",
	"srqn":4,
	"type":"BASIC",
	"lqpn":["126-128,130-140"],
	"pdn":9,
	"pid":3581,
	"comm":"ibv_srq_pingpon"
    },{
	"ifindex":0,
	"ifname":"ibp8s0f0",
	"srqn":5,
	"type":"BASIC",
	"lqpn":["141"],
	"pdn":10,
	"pid":3584,
	"comm":"ibv_srq_pingpon"
    } ]

Sample output after the fix:
$ rdma res show srq lqpn 126-141 -j -p
[ {
        "ifindex":0,
	"ifname":"ibp8s0f0",
	"srqn":4,
	"type":"BASIC",
	"lqpn":["126-128","130-140"],
	"pdn":9,
	"pid":3581,
	"comm":"ibv_srq_pingpon"
    },{
	"ifindex":0,
	"ifname":"ibp8s0f0",
	"srqn":5,
	"type":"BASIC",
	"lqpn":["141"],
	"pdn":10,
	"pid":3584,
	"comm":"ibv_srq_pingpon"
    } ]

Fixes: 9b272e138d ("rdma: Add SRQ resource tracking information")
Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-29 15:04:45 -07:00
Antoine Tenart 7a235a101b man: devlink-port: fix pfnum for devlink port add
When configuring a devlink PCI port, the pfnumber can be specified
using 'pfnum' and not 'pcipf' as stated in the man page. Fix this.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-29 15:03:44 -07:00
David Ahern e2947f6fd8 Merge branch 'managed-neighbor' into next
Daniel Borkmann  says:

====================

iproute2 patches to add support for managed neighbor entries as per recent
net-next commits:

  2ed08b5ead3c ("Merge branch 'Managed-Neighbor-Entries'")
  c47fedba94bc ("Merge branch 'minor-managed-neighbor-follow-ups'")

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-28 09:00:26 -06:00
Daniel Borkmann 9e009e78e7 ip, neigh: Add NTF_EXT_MANAGED support
Currently, ip neigh does not support the NTF_EXT_MANAGED flag. Add cmdline
support.

Usage example:

  # ./ip/ip n replace 192.168.178.30 dev enp5s0 managed extern_learn
  # ./ip/ip n
  192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a managed extern_learn REACHABLE
  [...]

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-28 08:59:03 -06:00
Daniel Borkmann 040e52526c ip, neigh: Add missing NTF_USE support
Currently, ip neigh does not support the NTF_USE flag. Similar to other flags
such as extern_learn, add cmdline support. The flag dump support is explicitly
missing here, since the kernel does not propagate the flag back to user space.

Usage example:

  # ./ip/ip n replace 192.168.178.30 dev enp5s0 use extern_learn
  # ./ip/ip n
  192.168.178.30 dev enp5s0 lladdr f4:8c:50:5e:71:9a extern_learn REACHABLE
  [...]

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-28 08:58:55 -06:00
Daniel Borkmann c76a3849ec ip, neigh: Fix up spacing in netlink dump
Fix up spacing to consistently add a single ' ' after an attribute has
been printed. Currently, it is a bit of a mix of before and after which
can lead to double spacing to be printed.

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-28 08:58:50 -06:00
Nicolas Dichtel 76b30805f9 xfrm: enable to manage default policies
Two new commands to manage default policies:
 - ip xfrm policy setdefault
 - ip xfrm policy getdefault

And the corresponding part in 'ip xfrm monitor'.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-28 08:58:28 -06:00
David Ahern 2be7d99960 Merge branch 'rdma-optional-stats' into next
Mark Zhang  says:

====================

This is supplementary part of kernel series [1], which provides an
extension to the rdma statistics tool that allows to set or list
optional counters dynamically, using netlink.

Thanks

[1] https://www.spinics.net/lists/linux-rdma/msg106283.html

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-16 12:52:02 -06:00
Stephen Hemminger 229eaba507 uapi: pickup fix for xfrm ABI breakage
See kernel
Commit 844f7eaaed9 ("include/uapi/linux/xfrm.h: Fix XFRM_MSG_MAPPING ABI breakage")

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-15 17:40:30 -07:00
Nicolas Dichtel 95cd2a6204 iplink: enable to specify index when changing netns
When an interface is moved to another netns, it's possible to specify a
new ifindex. Let's add this support.

Link: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=eeb85a14ee34
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 18:05:09 -06:00
David Ahern a936a73fc2 Merge branch 'config-libdir' into next
Andrea Claudi  says:

====================

This series add support for the libdir parameter in iproute2 configure
script. The idea is to make use of the fact that packaging systems may
assume that 'configure' comes from autotools allowing a syntax similar
to the autotools one, and using it to tell iproute2 where the distro
expects to find its lib files.

Patches 1-2 fix a parsing issue on current configure options, that may
trigger an endless loop when no value is provided with some options;

Patch 3 fixes a parsing issue bailing out when more than one value is
provided for a single option;

Patch 4 simplifies options parsing, moving semantic checks out of the
while loop processing options;

Patch 5 introduces support for the --opt=value style on current options,
for uniformity;

Patch 6 adds the --prefix option, that may be used by some packaging
systems when calling the configure script;

Patch 7 finally adds the --libdir option, and also drops the static
LIBDIR var from the Makefile.

Changelog:
----------
v4 -> v5
  - bail out when multiple values are provided with a single option
  - simplify option parsing and reduce code duplication, as suggested
    by Phil Sutter
  - remove a nasty eval on libdir option processing

v3 -> v4
  - fix parsing issue on '--include_dir' and '--libbpf_dir'
  - split '--opt value' and '--opt=value' use cases, avoid code
    duplication moving semantic checks on value to dedicated functions

v2 -> v3
  - fix parsing error on prefix and libdir options.

v1 -> v2
  - consolidate '--opt value' and '--opt=value' use cases, as suggested
    by David Ahern.
  - added patch 2 to manage the --prefix option, used by the Debian
    packaging system, as reported by Luca Boccassi, and use it when
    setting lib directory.

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:59:33 -06:00
Andrea Claudi cee0cf84bd configure: add the --libdir option
This commit allows users/packagers to choose a lib directory to store
iproute2 lib files.

At the moment iproute2 ship lib files in /usr/lib and offers no way to
modify this setting. However, according to the FHS, distros may choose
"one or more variants of the /lib directory on systems which support
more than one binary format" (e.g. /usr/lib64 on Fedora).

As Luca states in commit a3272b9372 ("configure: restore backward
compatibility"), packaging systems may assume that 'configure' is from
autotools, and try to pass it some parameters.

Allowing the '--libdir=/path/to/libdir' syntax, we can use this to our
advantage, and let the lib directory to be chosen by the distro
packaging system.

Note that LIBDIR uses "\${prefix}/lib" as default value because autoconf
allows this to be expanded to the --prefix value at configure runtime.
"\${prefix}" is replaced with the PREFIX value in check_lib_dir().

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:57:20 -06:00
Andrea Claudi 0ee1950b5c configure: add the --prefix option
This commit add the '--prefix' option to the iproute2 configure script.

This mimics the '--prefix' option that autotools configure provides, and
will be used later to allow users or packagers to set the lib directory.

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:57:17 -06:00
Andrea Claudi 4b8bca5f9e configure: support --param=value style
This commit makes it possible to specify values for configure params
using the common autotools configure syntax '--param=value'.

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:57:05 -06:00
Andrea Claudi 99245d1741 configure: simplify options parsing
This commit simplifies options parsing moving all the code not related to
parsing out of the case statement.

- The conditional shift after the assignments is moved right after the
  case, reducing code duplication.
- The semantic checks on the LIBBPF_FORCE value is moved after the loop
  like we already did for INCLUDE and LIBBPF_DIR.
- Finally, the loop condition is changed to check remaining arguments, thus
  making it possible to get rid of the null string case break.

As a bonus, now the help message states that on or off should follow
--libbpf_force

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:57:02 -06:00
Andrea Claudi c330d09794 configure: fix parsing issue with more than one value per option
With commit a9c3d70d90 ("configure: add options ability") users are no
more able to provide wrong command lines like:

$ ./configure --include_dir foo bar

The script simply bails out when user provides more than one value for a
single option. However, in doing so, it breaks backward compatibility with
some packaging system, which expects unknown options to be ignored.

Commit a3272b9372 ("configure: restore backward compatibility") fix this
issue, but makes it possible again for users to provide wrong command lines
such as the one above.

This fixes the issue simply ignoring autoconf-like options such as
'--opt=value'.

Fixes: a3272b9372 ("configure: restore backward compatibility")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:56:57 -06:00
Andrea Claudi 48c379bc2a configure: fix parsing issue on libbpf_dir option
configure is stuck in an endless loop if '--libbpf_dir' option is used
without a value:

$ ./configure --libbpf_dir
./configure: line 515: shift: 2: shift count out of range
./configure: line 515: shift: 2: shift count out of range
[...]

Fix it splitting 'shift 2' into two consecutive shifts, and making the
second one conditional to the number of remaining arguments.

A check is also provided after the while loop to verify the libbpf dir
exists; also, as LIBBPF_DIR does not have a default value, configure bails
out if the user does not specify a value after --libbpf_dir, thus avoiding
to produce an erroneous configuration.

Fixes: 7ae2585b86 ("configure: convert LIBBPF environment variables to command-line options")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:56:53 -06:00
Andrea Claudi 1d819dcc74 configure: fix parsing issue on include_dir option
configure is stuck in an endless loop if '--include_dir' option is used
without a value:

$ ./configure --include_dir
./configure: line 506: shift: 2: shift count out of range
./configure: line 506: shift: 2: shift count out of range
[...]

Fix it splitting 'shift 2' into two consecutive shifts, and making the
second one conditional to the number of remaining arguments.

A check is also provided after the while loop to verify the include dir
exists; this avoid to produce an erroneous configuration.

Fixes: a9c3d70d90 ("configure: add options ability")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:56:48 -06:00
Neta Ostrovsky 19ba785f16 rdma: Add optional-counters set/unset support
This patch provides an extension to the rdma statistics tool
that allows to set/unset optional counters set dynamically,
using new netlink commands.
Note that the optional counter statistic implementation is
driver-specific and may impact the performance.

Examples:
To enable a set of optional counters on link rocep8s0f0/1:
    $ sudo rdma statistic set link rocep8s0f0/1 optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts
To disable all optional counters on link rocep8s0f0/1:
    $ sudo rdma statistic unset link rocep8s0f0/1 optional-counters

Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:52:57 -06:00
Neta Ostrovsky 7d5cb70e94 rdma: Add stat "mode" support
This patch introduces the "mode" command, which presents the enabled or
supported (when the "supported" argument is available) optional
counters.

An optional counter is a vendor-specific counter that may be
dynamically enabled/disabled. This enhancement of hwcounters allows
exposing of counters which are for example mutual exclusive and cannot
be enabled at the same time, counters that might degrades performance,
optional debug counters, etc.

Examples:
To present currently enabled optional counters on link rocep8s0f0/1:
    $ rdma statistic mode link rocep8s0f0/1
    link rocep8s0f0/1 optional-counters cc_rx_ce_pkts

To present supported optional counters on link rocep8s0f0/1:
    $ rdma statistic mode supported link rocep8s0f0/1
    link rocep8s0f0/1 supported optional-counters cc_rx_ce_pkts,cc_rx_cnp_pkts,cc_tx_cnp_pkts

Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:52:53 -06:00
Neta Ostrovsky d480cb71f5 rdma: Update uapi headers
Update rdma_netlink.h file upto kernel commit 7301d0a9834c
("RDMA/nldev: Add support to get status of all counters")

Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Mark Zhang <markzhang@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:52:47 -06:00
David Ahern e4ca6a4965 Update kernel headers
Update kernel headers to commit:
    295711fa8fec ("Merge branch 'dpaa2-irq-coalescing'")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:49:19 -06:00
Stephen Hemminger a31e7b7967 mptcp: cleanup include section.
David reported ipmptcp breaks hard the build when updating the
relevant kernel headers.

We should be more careful in the header section, explicitly
including all the required dependencies respecting the usual order
between systems and local headers.

Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-15 17:48:36 -06:00
Paul Chaignon a500c5ac87 lib/bpf: fix map-in-map creation without prepopulation
When creating map-in-maps, the outer map can be prepopulated using the
inner_idx field of inner maps. That field defines the index of the inner
map in the outer map. It is ignored if set to -1.

Commit 6d61a2b557 ("lib: add libbpf support") however started using
that field to identify inner maps. While iterating over all maps looking
for inner maps, maps with inner_idx set to -1 are erroneously skipped.
As a result, trying to create a map-in-map with prepopulation disabled
fails because the inner_id of the outer map is not correctly set.

This bug can be observed with strace -ebpf (notice the zero inner_map_fd
for the outer map creation):

    bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_ARRAY, key_size=4, value_size=130996, max_entries=1, map_flags=0, inner_map_fd=0, map_name="maglev_inner", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 128) = 32
    bpf(BPF_MAP_CREATE, {map_type=BPF_MAP_TYPE_HASH_OF_MAPS, key_size=2, value_size=4, max_entries=65536, map_flags=BPF_F_NO_PREALLOC, inner_map_fd=0, map_name="maglev_outer", map_ifindex=0, btf_fd=0, btf_key_type_id=0, btf_value_type_id=0}, 128) = -1 EINVAL (Invalid argument)

Fixes: 6d61a2b557 ("lib: add libbpf support")
Signed-off-by: Paul Chaignon <paul@isovalent.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-14 14:37:51 -07:00
Antoine Tenart 7c032cac10 man: devlink-port: remove extra .br
br. were added between options of the same command. That is not needed
and makes the output to be one 3 lines for no particular reason.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-11 19:27:12 -07:00
Antoine Tenart 04ee8e6f06 man: devlink-port: fix style
Values should be .I, square brackets should be used for optional values,
curly brackets for lists. Follow this in the devlink-port man page.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-11 19:27:12 -07:00
Antoine Tenart 14802d84d3 man: devlink-port: fix the devlink port add synopsis
When configuring a devlink PCI SF port, the sfnumber can be specified
using 'sfnum' and not 'pcisf' as stated in the man page. Fix this.

Signed-off-by: Antoine Tenart <atenart@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-11 19:27:12 -07:00
David Ahern 8cd517a805 Merge branch 'main' into next
Conflicts:
	ip/ipneigh.c

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-09 17:47:47 -06:00
David Ahern 763fd793fe Merge branch 'ioam-encap-modes' into next
Justin Iurman  says:

====================

Following the series applied to net-next (see [1]), here are the corresponding
changes to iproute2.

In the current implementation, IOAM can only be inserted directly (i.e., only
inside packets generated locally) by default, to be compliant with RFC8200.

This patch adds support for in-transit packets and provides the ip6ip6
encapsulation of IOAM (RFC8200 compliant). Therefore, three ioam6 encap modes
are defined:

 - inline: directly inserts IOAM inside packets (by default).

 - encap:  ip6ip6 encapsulation of IOAM inside packets.

 - auto:   either inline mode for packets generated locally or encap mode for
           in-transit packets.

With current iproute2 implementation, it is configured this way:

$ ip -6 r [...] encap ioam6 trace prealloc [...]

The old syntax does not change (for backwards compatibility) and implicitly uses
the inline mode. With the new syntax, an encap mode can be specified:

(inline mode)
$ ip -6 r [...] encap ioam6 mode inline trace prealloc [...]

(encap mode)
$ ip -6 r [...] encap ioam6 mode encap tundst fc00::2 trace prealloc [...]

(auto mode)
$ ip -6 r [...] encap ioam6 mode auto tundst fc00::2 trace prealloc [...]

A tunnel destination address must be configured when using the encap mode or the
auto mode.

  [1] https://lore.kernel.org/netdev/163335001045.30570.12527451523558030753.git-patchwork-notify@kernel.org/T/#m3b428d4142ee3a414ec803466c211dfdec6e0c09

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-09 17:37:12 -06:00
Justin Iurman 41020eb0fd Update documentation
This patch updates the IOAM documentation (ip-route man page) to reflect the
three encap modes that were introduced.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-09 17:35:54 -06:00
Justin Iurman 8fb522cde3 Add support for IOAM encap modes
This patch adds support for the three IOAM encap modes that were introduced:
inline, encap and auto.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-09 17:35:29 -06:00
Frank Villaro-Dixon 897772a735 cmd: use spaces instead of tabs for usage indentation
Fix rogue "tab after spaces" used for indentation of the documentation.
This causes rendering issues on terminals using a non-standard tab width.

Signed-off-by: Frank Villaro-Dixon <frank.villaro@infomaniak.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-10-06 10:00:49 -07:00
Nikolay Aleksandrov b840c620fe ip: nexthop: keep cache netlink socket open
Since we use the cache netlink socket for each nexthop we can keep it open
instead of opening and closing it on every add call. The socket is opened
once, on the first add call and then reused for the rest.

Suggested-by: David Ahern <dsahern@gmail.com>
Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-05 08:34:29 -06:00
Jacob Keller b90174354d devlink: print maximum number of snapshots if available
Recently the kernel gained ability to report the maximum number of
snapshots a region can have. Print this value out if it was reported.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-05 08:31:30 -06:00
David Ahern 6448ed373c Update kernel headers
Update kernel headers to commit:
    49ed8dde3715 ("net: usb: use eth_hw_addr_set() for dev->addr_len cases")

Update to linux/mptcp.h is removed because it breaks compilation
of ipmptcp.c in a nontrivial way.

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-05 08:28:28 -06:00
Davide Caratti e7a98a96f0 mptcp: unbreak JSON endpoint list
the following command:

 # ip -j mptcp endpoint show

prints a JSON array that misses the terminating bracket. Fix this calling
delete_json_obj() to balance the call to new_json_obj().

Fixes: 7e0767cd86 ("add support for mptcp netlink interface")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Acked-by: Andrea Claudi <aclaudi@redhat.com>
2021-10-04 14:07:09 -07:00
David Ahern ec703e0629 Merge branch 'nexthop-cache' into next
Nikolay Aleksandrov  says:

====================

This set tries to help with an old ask that we've had for some time
which is to print nexthop information while monitoring or dumping routes.
The core problem is that people cannot follow nexthop changes while
monitoring route changes, by the time they check the nexthop it could be
deleted or updated to something else. In order to help them out I've
added a nexthop cache which is populated (only used if -d / show_details
is specified) while decoding routes and kept up to date while monitoring.
The nexthop information is printed on its own line starting with the
"nh_info" attribute and its embedded inside it if printing JSON. To
cache the nexthop entries I parse them into structures, in order to
reuse most of the code the print helpers have been altered so they rely
on prepared structures. Nexthops are now always parsed into a structure,
even if they won't be cached, that structure is later used to print the
nexthop and destroyed if not going to be cached. New nexthops (not found
in the cache) are retrieved from the kernel using a private netlink
socket so they don't disrupt an ongoing dump, similar to how interfaces
are retrieved and cached.

I have tested the set with the kernel forwarding selftests and also by
stressing it with nexthop create/update/delete in loops while monitoring.

Comments are very welcome as usual. :)

Changes since RFC:
 - reordered parse/print splits, in order to do that I have to parse
   resilient groups first, then add nh entry parsing so code has been
   reordered as well and patch order has changed, but there have been
   no functional changes (as before refactoring of old code is done in
   the first 8 patches and then patches 9-12 add the new cache and use it)
 - re-run all tests above

Patch breakdown:
Patches 1-2: update current route helpers to take parsed arguments so we
             can directly pass them from the nh_entry structure later
Patch     3: adds new nha_res_grp structure which describes a resilient
             nexhtop group
Patch     4: splits print_nh_res_group into a parse and print parts
             which use the new nha_res_grp structure
Patch     5: adds new nh_entry structure which describes a nexthop
Patch     6: factors out print_nexthop's attribute parsing into nh_entry
             structure used before printing
Patch     7: factors out print_nexthop's nh_entry structure printing
Patch     8: factors out ipnh_get's rtnl talk part and allows to use a
             different rt handle for the communication
Patch     9: adds nexthop cache and helpers to manage it, it uses the
             new __ipnh_get to retrieve nexthops
Patch    10: adds a new helper print_cache_nexthop_id that prints nexthop
             information from its id, if the nexthop is not found in the
             cache it fetches it
Patch    11: the new print_cache_nexthop_id helper is used when printing
             routes with show_details (-d) to output detailed nexthop
             information, the format after nh_info is the same as
             ip nexthop show
Patch    12: changes print_nexthop into print_cache_nexthop which always
             outputs the nexthop information and can also update the cache
             (based on process_cache argument), it's used to keep the
             cache up to date while monitoring

Example outputs (monitor):
[NEXTHOP]id 101 via 169.254.2.22 dev veth2 scope link proto unspec
[NEXTHOP]id 102 via 169.254.3.23 dev veth4 scope link proto unspec
[NEXTHOP]id 103 group 101/102 type resilient buckets 512 idle_timer 0 unbalanced_timer 0 unbalanced_time 0 scope global proto unspec
[ROUTE]unicast 192.0.2.0/24 nhid 203 table 4 proto boot scope global
	nh_info id 203 group 201/202 type resilient buckets 512 idle_timer 0 unbalanced_timer 0 unbalanced_time 0 scope global proto unspec
	nexthop via 169.254.2.12 dev veth3 weight 1
	nexthop via 169.254.3.13 dev veth5 weight 1

[NEXTHOP]id 204 via fe80:2::12 dev veth3 scope link proto unspec
[NEXTHOP]id 205 via fe80:3::13 dev veth5 scope link proto unspec
[NEXTHOP]id 206 group 204/205 type resilient buckets 512 idle_timer 0 unbalanced_timer 0 unbalanced_time 0 scope global proto unspec
[ROUTE]unicast 2001:db8:1::/64 nhid 206 table 4 proto boot scope global metric 1024 pref medium
	nh_info id 206 group 204/205 type resilient buckets 512 idle_timer 0 unbalanced_timer 0 unbalanced_time 0 scope global proto unspec
	nexthop via fe80:2::12 dev veth3 weight 1
	nexthop via fe80:3::13 dev veth5 weight 1

[NEXTHOP]id 2  encap mpls  200/300 via 10.1.1.1 dev ens20 scope link proto unspec onlink
[ROUTE]unicast 2.3.4.10 nhid 2 table main proto boot scope global
	nh_info id 2  encap mpls  200/300 via 10.1.1.1 dev ens20 scope link proto unspec onlink

JSON:
 {
        "type": "unicast",
        "dst": "198.51.100.0/24",
        "nhid": 103,
        "table": "3",
        "protocol": "boot",
        "scope": "global",
        "flags": [ ],
        "nh_info": {
            "id": 103,
            "group": [ {
                    "id": 101,
                    "weight": 11
                },{
                    "id": 102,
                    "weight": 45
                } ],
            "type": "resilient",
            "resilient_args": {
                "buckets": 512,
                "idle_timer": 0,
                "unbalanced_timer": 0,
                "unbalanced_time": 0
            },
            "scope": "global",
            "protocol": "unspec",
            "flags": [ ]
        },
        "nexthops": [ {
                "gateway": "169.254.2.22",
                "dev": "veth2",
                "weight": 11,
                "flags": [ ]
            },{
                "gateway": "169.254.3.23",
                "dev": "veth4",
                "weight": 45,
                "flags": [ ]
            } ]
  }

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:31:44 -06:00
Nikolay Aleksandrov 7ca868a7aa ip: nexthop: add print_cache_nexthop which prints and manages the nh cache
Add a new helper print_cache_nexthop replacing print_nexthop which can
update the nexthop cache if the process_cache argument is true. It is
used when monitoring netlink messages to keep the nexthop cache up to
date with nexthop changes happening. For the old callers and anyone
who's just dumping nexthops its _nocache version is used which is a
wrapper for print_cache_nexthop.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:59 -06:00
Nikolay Aleksandrov 5d5dc549ce ip: route: print and cache detailed nexthop information when requested
If -d (show_details) is used when printing/monitoring routes then print
detailed nexthop information in the field "nh_info". The nexthop is also
cached for future searches.

Output looks like:
 unicast 198.51.100.0/24 nhid 103 table 3 proto boot scope global
	 nh_info id 103 group 101/102 type resilient buckets 512 idle_timer 0 unbalanced_timer 0 unbalanced_time 0 scope global proto unspec
	 nexthop via 169.254.2.22 dev veth2 weight 1
	 nexthop via 169.254.3.23 dev veth4 weight 1

The nh_info field has the same format as ip -d nexthop show would've had
for the same nexthop id.

For completeness the JSON version looks like:
 {
        "type": "unicast",
        "dst": "198.51.100.0/24",
        "nhid": 103,
        "table": "3",
        "protocol": "boot",
        "scope": "global",
        "flags": [ ],
        "nh_info": {
            "id": 103,
            "group": [ {
                    "id": 101
                },{
                    "id": 102
                } ],
            "type": "resilient",
            "resilient_args": {
                "buckets": 512,
                "idle_timer": 0,
                "unbalanced_timer": 0,
                "unbalanced_time": 0
            },
            "scope": "global",
            "protocol": "unspec",
            "flags": [ ]
        },
        "nexthops": [ {
                "gateway": "169.254.2.22",
                "dev": "veth2",
                "weight": 1,
                "flags": [ ]
            },{
                "gateway": "169.254.3.23",
                "dev": "veth4",
                "weight": 1,
                "flags": [ ]
            } ]
 }

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:55 -06:00
Nikolay Aleksandrov cb3d18c29e ip: nexthop: add a helper which retrieves and prints cached nh entry
Add a helper which looks for a nexthop in the cache and if not found
reads the entry from the kernel and caches it. Finally the entry is
printed.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:51 -06:00
Nikolay Aleksandrov 60a9703032 ip: nexthop: add cache helpers
Add a static nexthop cache in a hash with 1024 buckets and helpers to
manage it (link, unlink, find, add nexthop, del nexthop). Adding new
nexthops is done by creating a new rtnl handle and using it to retrieve
the nexthop so the helper is safe to use while already reading a
response (i.e. using the global rth).

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:41 -06:00
Nikolay Aleksandrov 53d7c43bd3 ip: nexthop: factor out ipnh_get_id rtnl talk into a helper
Factor out ipnh_get_id's rtnl talk portion into a separate helper which
will be reused later to retrieve nexthops for caching.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:36 -06:00
Nikolay Aleksandrov a2ca431215 ip: nexthop: factor out print_nexthop's nh entry printing
Factor out nexthop entry structure printing from print_nexthop,
effectively splitting it into parse and print parts.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:32 -06:00
Nikolay Aleksandrov 945c26db68 ip: nexthop: parse attributes into nh entry structure before printing
Factor out the nexthop attribute parsing and parse attributes into a
nexthop entry structure which is then used to print.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:28 -06:00
Nikolay Aleksandrov 7ec1cee630 ip: nexthop: add nh entry structure
Add a structure which describes a nexthop, it will be later used to
parse, print and cache nexthops.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:24 -06:00
Nikolay Aleksandrov 60a7515b89 ip: nexthop: split print_nh_res_group into parse and print parts
Now that we have resilient group structure split print_nh_res_group into
a parse and print functions, print_nexthop calls the parse function
first to parse the attributes into the structure and then uses the print
function to print the parsed structure.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:19 -06:00
Nikolay Aleksandrov cfb0a8729e ip: nexthop: add resilient group structure
Add a structure which describes a resilient nexthop group. It will be
later used for parsing.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:11 -06:00
Nikolay Aleksandrov 371e889da7 ip: export print_rta_gateway version which outputs prepared gateway string
Export a new __print_rta_gateway that takes a prepared gateway string to
print which is also used by print_rta_gateway for consistent format.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:24:06 -06:00
Nikolay Aleksandrov f72789965e ip: print_rta_if takes ifindex as device argument instead of attribute
We need print_rta_if() to take ifindex directly so later we can use it
with cached converted nexthop objects.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-10-03 18:23:31 -06:00
David Ahern c8c9111a4c Merge branch 'ax.25-netrom-rose' into next
Ralf Baechle  says:

====================

net-tools contain support for these three protocol but are deprecated and
no longer installed by default by many distributions.  Iproute2 otoh has
no support at all and will dump the addresses of these protocols which
actually are pretty human readable as hex numbers:

 # ip link show dev bpq0
3: bpq0: <UP,LOWER_UP> mtu 256 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ax25 88:98:60:a0:92:40:02 brd a2:a6:a8:40:40:40:00
 # ip link show dev nr0
4: nr0: <NOARP,UP,LOWER_UP> mtu 236 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/netrom 88:98:60:a0:92:40:0a brd 00:00:00:00:00:00:00
 # ip link show dev rose0
8: rose0: <NOARP,UP,LOWER_UP> mtu 249 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/rose 65:09:33:30:00 brd 00:00:00:00:00

This series adds basic support for the three protocols to print addresses:

 # ip link show dev bpq0
3: bpq0: <UP,LOWER_UP> mtu 256 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/ax25 DL0PI-1 brd QST-0
 # ip link show dev nr0
4: nr0: <NOARP,UP,LOWER_UP> mtu 236 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/netrom DL0PI-5 brd *
 # ip link show dev rose0
8: rose0: <NOARP,UP,LOWER_UP> mtu 249 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/rose 6509333000 brd 0000000000

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:03:11 -06:00
Ralf Baechle e2cc9840ea ROSE: Print decoded addresses rather than hex numbers.
NETROM is a OSI layer 3 protocol sitting on top of AX.25.  It uses BCD-
encoded 10 digit telephone numbers as addresses.  Without this ip will
print a ROSE addresses like

  link/rose 12:34:56:78:90 brd 00:00:00:00:00

which is readable but ugly.  With this applied it ROSE addresses will be
printed as

  link/rose 1234567890 brd 0000000000

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:51 -06:00
Ralf Baechle 26c5782fab ROSE: Add rose_ntop implementation.
ROSE addresses are ten digit numbers, basically like North American
telephone numbers.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:45 -06:00
Ralf Baechle fd4c1c8168 NETROM: Print decoded addresses rather than hex numbers.
NETROM is an OSI layer 3 protocol sitting on top of AX.25.  It also uses
AX.25 addresses.  Without this commit ip will print NETROM address like

  link/generic 98:92:9c:aa:b0:40:02 brd 00:00:00:00:00:00:00

while with this commit the decoded result

  link/generic LINUX-1 brd *

is much more eye friendly.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:40 -06:00
Ralf Baechle c63b769ad4 NETROM: Add netrom_ntop implementation.
NETROM uses AX.25 addresses so this is a simple wrapper around ax25_ntop1.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:37 -06:00
Ralf Baechle 399ae00af5 AX.25: Print decoded addresses rather than hex numbers.
Before this, ip would have printed the AX.25 address configured for an
AX.25 interface's default addresses as:

  link/ax25 98:92:9c:aa:b0:40:02 brd a2:a6:a8:40:40:40:00

which is pretty unreadable.  With this commit ip will decode AX.25
addresses like

  link/ax25 LINUX-1 brd QST-0

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:34 -06:00
Ralf Baechle 3a92669b3a AX.25: Add ax25_ntop implementation.
AX.25 addresses are based on Amateur radio callsigns followed by an SSID
like XXXXXX-SS where the callsign is up to 6 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.

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 byte.

This for example turns "LINUX-1" where the callsign is LINUX and SSID is 1
into 98:92:9c:aa:b0:40:02.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-23 20:02:30 -06:00
Andrea Claudi 2f5825cb38 lib: bpf_legacy: fix bpffs mount when /sys/fs/bpf exists
bpf selftests using iproute2 fails with:

$ ip link set dev veth0 xdp object ../bpf/xdp_dummy.o section xdp_dummy
Continuing without mounted eBPF fs. Too old kernel?
mkdir (null)/globals failed: No such file or directory
Unable to load program

This happens when the /sys/fs/bpf directory exists. In this case, mkdir
in bpf_mnt_check_target() fails with errno == EEXIST, and the function
returns -1. Thus bpf_get_work_dir() does not call bpf_mnt_fs() and the
bpffs is not mounted.

Fix this in bpf_mnt_check_target(), returning 0 when the mountpoint
exists.

Fixes: d4fcdbbec9 ("lib/bpf: Fix and simplify bpf_mnt_check_target()")
Reported-by: Mingyu Shi <mshi@redhat.com>
Reported-by: Jiri Benc <jbenc@redhat.com>
Suggested-by: Jiri Benc <jbenc@redhat.com>
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-22 17:30:52 -07:00
Puneet Sharma d756c08a3d tc/f_flower: fix port range parsing
Provided port range in tc rule are parsed incorrectly.
Even though range is passed as min-max. It throws an error.

$ tc filter add dev eth0 ingress handle 100 priority 10000 protocol ipv4 flower ip_proto tcp dst_port 10368-61000 action pass
max value should be greater than min value
Illegal "dst_port"

Fixes: 8930840e67 ("tc: flower: Classify packets based port ranges")
Signed-off-by: Puneet Sharma <pusharma@akamai.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-22 17:28:48 -07:00
Gokul Sivakumar ebbb701714 lib: bpf_legacy: add prog name, load time, uid and btf id in prog info dump
The BPF program name is included when dumping the BPF program info and the
kernel only stores the first (BPF_PROG_NAME_LEN - 1) bytes for the program
name.

$ sudo ip link show dev docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:4c:df:a4:54 brd ff:ff:ff:ff:ff:ff
    prog/xdp id 789 name xdp_drop_func tag 57cd311f2e27366b jited

The BPF program load time (ns since boottime), UID of the user who loaded
the program and the BTF ID are also included when dumping the BPF program
information when the user expects a detailed ip link info output.

$ sudo ip -details link show dev docker0
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric qdisc noqueue state UP mode DEFAULT group default
    link/ether 02:42:4c:df:a4:54 brd ff:ff:ff:ff:ff:ff promiscuity 0 minmtu 68 maxmtu 65535
    bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time 30000 stp_state 0 priority 32768 vlan_filt
ering 0 vlan_protocol 802.1Q bridge_id 8000.2:42:4c:df:a4:54 designated_root 8000.2:42:4c:df:a4:54 root_port 0 r
oot_path_cost 0 topology_change 0 topology_change_detected 0 hello_timer    0.00 tcn_timer    0.00 topology_chan
ge_timer    0.00 gc_timer  265.36 vlan_default_pvid 1 vlan_stats_enabled 0 vlan_stats_per_port 0 group_fwd_mask
0 group_address 01:80:c2:00:00:00 mcast_snooping 1 mcast_router 1 mcast_query_use_ifaddr 0 mcast_querier 0 mcast
_hash_elasticity 16 mcast_hash_max 4096 mcast_last_member_count 2 mcast_startup_query_count 2 mcast_last_member_
interval 100 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query
_response_interval 1000 mcast_startup_query_interval 3124 mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_v
ersion 1 nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 addrgenmode eui64 numtxqueues 1 numrxqueues
1 gso_max_size 65536 gso_max_segs 65535
    prog/xdp id 789 name xdp_drop_func tag 57cd311f2e27366b jited load_time 2676682607316255 created_by_uid 0 btf_id 708

Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-21 09:16:32 -06:00
David Ahern 75c5054e7a Merge branch 'main' into next
Conflicts:
	include/uapi/linux/virtio_ids.h

Signed-off-by: David Ahern <dsahern@gmail.com>
2021-09-14 10:46:48 -06:00
Stephen Hemminger 92e32f7791 uapi: updates from 5.15-rc1
Small changes to virtio etc.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-13 15:07:58 -07:00
Lahav Schlesinger 0431e1e724 ip: Support filter links/neighs with no master
Commit d3432bf10f17 ("net: Support filtering interfaces on no master")
in the kernel added support for filtering interfaces/neighbours that
have no master interface.

This patch completes it and adds this support to iproute2:
1. ip link show nomaster
2. ip address show nomaster
3. ip neighbour {show | flush} nomaster

Signed-off-by: Lahav Schlesinger <lschlesinger@drivenets.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
2021-09-12 11:17:18 -06:00
Lennert Buytenhek 12b3d6a2ad man: ip-macsec: fix gcm-aes-256 formatting issue
The 'ip link add' invocation template at the top of the ip-macsec man
page formats with a pair of extra double quotes:

   ip  link  add  link DEVICE name NAME type macsec [ [ address <lladdr> ]
   port PORT | sci <u64> ]  [  cipher  {  default  |  gcm-aes-128  |  gcm-
   aes-256"}][" icvlen ICVLEN ] [ encrypt { on | off } ] [ send_sci { on |

This is due to missing whitespace around the gcm-aes-256 identifier
in the source file.

Fixes: b16f525323 ("Add support for configuring MACsec gcm-aes-256 cipher type.")
Signed-off-by: Lennert Buytenhek <buytenh@wantstofly.org>
Signed-off-by: David Ahern <dsahern@gmail.com>
2021-09-12 11:13:26 -06:00
David Ahern 917d913b2e Merge branch 'main' into next
Conflicts:
	include/uapi/linux/virtio_ids.h

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-08 15:13:49 -06:00
David Ahern d0cba0d1f6 Merge branch 'bridge-mcast_router' into next
Nikolay Aleksandrov  says:

====================

This set adds support for vlan port/bridge multicast router option. It is
similar to the already existing bridge-wide mcast_router control. Patch 01
moves attribute adding and parsing together for vlan option setting,
similar to global vlan option setting. It simplifies adding new options
because we can avoid reserved values and additional checks. Patch 02
adds the new mcast_router option and updates the related man page.

Example:
 # mark port ens16 as a permanent mcast router for vlan 100
 $ bridge vlan set dev ens16 vid 100 mcast_router 2
 # disable mcast router for port ens16 and vlan 200
 $ bridge vlan set dev ens16 vid 200 mcast_router 0
 $ bridge -d vlan show
 port              vlan-id
 ens16             1 PVID Egress Untagged
                     state forwarding mcast_router 1
                   100
                     state forwarding mcast_router 2
                   200
                     state forwarding mcast_router 0

Note that this set depends on the latest kernel uapi headers.

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 17:03:58 -06:00
Nikolay Aleksandrov ae895504c6 bridge: vlan: add support for mcast_router option
Add support for setting and dumping per-vlan/interface mcast_router
option. It controls the mcast router mode of a vlan/interface pair.
For bridge devices only modes 0 - 2 are allowed. The possible modes
are:
 0 - disabled
 1 - automatic router presence detection (default)
 2 - permanent router
 3 - temporary router (available only for ports)

Example:
 # mark port ens16 as a permanent mcast router for vlan 100
 $ bridge vlan set dev ens16 vid 100 mcast_router 2
 # disable mcast router for port ens16 and vlan 200
 $ bridge vlan set dev ens16 vid 200 mcast_router 0
 $ bridge -d vlan show
 port              vlan-id
 ens16             1 PVID Egress Untagged
                     state forwarding mcast_router 1
                   100
                     state forwarding mcast_router 2
                   200
                     state forwarding mcast_router 0

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 17:00:31 -06:00
Nikolay Aleksandrov 12fbe3e4eb bridge: vlan: set vlan option attributes while parsing
Set vlan option attributes immediately while parsing to simplify the
checks, avoid having reserved values (e.g. -1 for unset var) and have
more limited scope for the variables. This is also similar to how global
vlan options are set. The attribute setting and checks are moved with
option parsing, no functional changes intended.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 17:00:31 -06:00
David Ahern db28c944d8 Update kernel headers
Update kernel headers to commit:
    27151f177827 ("Merge tag 'perf-tools-for-v5.15-2021-09-04' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 16:59:38 -06:00
Stephen Hemminger 6d676ad934 ip: rewrite routel in python
Not sure if anyone uses the routel script. The script was
a combination of ip route, shell and awk doing command scraping.
It is now possible to do this much better using the JSON
output formats and python.

Rewriting also fixes the bug where the old script could not parse
the current output format.  At the end was getting:
/usr/bin/routel: 48: shift: can't shift that many

The new script also has IPv6 as option.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 16:31:24 -06:00
Stephen Hemminger 1eaebad2c5 ip: remove routef script
This script is old and limited to IPv4.
Using ip route command directly is better option.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 16:31:23 -06:00
Stephen Hemminger adddf30cd8 ip: remove ifcfg script
This script was from olden days of ifcfg.
I don't see any distribution using it and it is time to put
it out to pasture.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 16:31:19 -06:00
Stephen Hemminger 2c8110881b ip: remove old rtpr script
This script was a one off hack for a special case.
Now that ip commands have better formatting, there is no
real reason for it.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-06 16:30:36 -06:00
David Marchand e7e0e2ce65 iptuntap: fix multi-queue flag display
When creating a tap with multi_queue flag, this flag is not displayed
when dumping:

$ ip tuntap add tap23 mode tap multi_queue
$ ip tuntap
tap23: tap persist0x100

While at it, add a space between known flags and hexdump of unknown
ones.

Fixes: c41e038f48 ("iptuntap: allow creation of multi-queue tun/tap device")
Signed-off-by: David Marchand <david.marchand@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-02 08:41:17 -07:00
Nikolay Aleksandrov deef844b1e man: ip-link: remove double of
Remove double "of".

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-02 08:40:36 -07:00
Luca Boccassi a3272b9372 configure: restore backward compatibility
Commit a9c3d70d90 broke backward compatibility
by making 'configure' error out if parameters are passed, instead of
ignoring them.
Sometimes packaging systems detect 'configure' and assume it's from
autotools, and pass a bunch of options. Eg:

 dh_auto_configure
	./configure --build=x86_64-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-option-checking --disable-silent-rules --libdir=${prefix}/lib/x86_64-linux-gnu --runstatedir=/run --disable-maintainer-mode --disable-dependency-tracking

Ignore unknown options again instead of erroring out.

Fixes: a9c3d70d90 ("configure: add options ability")

Signed-off-by: Luca Boccassi <bluca@debian.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-02 08:39:48 -07:00
Luca Boccassi ceba59308d tree-wide: fix some typos found by Lintian
Signed-off-by: Luca Boccassi <bluca@debian.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-02 08:39:48 -07:00
Stephen Hemminger 7a70524270 ip: remove leftovers from IPX and DECnet
Iproute2 has not supported DECnet or IPX since version 5.0.
There were some leftover support in the ip options flags
and parsing, remove these.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-01 14:03:53 -07:00
Stephen Hemminger 8ab1834e56 uapi: update headers from 5.15 merge
New headers from 5.15 early merge.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-09-01 14:02:50 -07:00
Hangbin Liu 6d0d35bab9 ip/bond: add lacp active support
lacp_active specifies whether to send LACPDU frames periodically.
If set on, the LACPDU frames are sent along with the configured lacp_rate
setting. If set off, the LACPDU frames acts as "speak when spoken to".

v2: use strcmp instead of match for new options.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
2021-09-01 12:51:44 -07:00
David Ahern 926ad64104 Update kernel headers
Update kernel headers to commit:
    88be32634905 ("Merge branch 'dsa-tagger-helpers'")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Ilya Dmitrichenko c730bd0b11 ip/tunnel: always print all known attributes
Presently, if a Geneve or VXLAN interface was created with 'external',
it's not possible for a user to determine e.g. the value of 'dstport'
after creation. This change fixes that by avoiding early returns.

This change partly reverts commit 00ff4b8e31 ("ip/tunnel: Be consistent
when printing tunnel collect metadata").

Signed-off-by: Ilya Dmitrichenko <errordeveloper@gmail.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Justin Iurman df8912ede2 ipioam6: use print_nl instead of print_null
This patch addresses Stephen's comment:

"""
> +        print_null(PRINT_ANY, "", "\n", NULL);

Use print_nl() since it handles the case of oneline output.
Plus in JSON the newline is meaningless.
"""

It also removes two useless print_null's.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Peilin Ye 7e7270bb1f tc/skbmod: Introduce SKBMOD_F_ECN option
Recently we added SKBMOD_F_ECN option support to the kernel; support it in
the tc-skbmod(8) front end, and update its man page accordingly.

The 2 least significant bits of the Traffic Class field in IPv4 and IPv6
headers are used to represent different ECN states [1]:

	0b00: "Non ECN-Capable Transport", Non-ECT
	0b10: "ECN Capable Transport", ECT(0)
	0b01: "ECN Capable Transport", ECT(1)
	0b11: "Congestion Encountered", CE

This new option, "ecn", marks ECT(0) and ECT(1) IPv{4,6} packets as CE,
which is useful for ECN-based rate limiting.  For example:

	$ tc filter add dev eth0 parent 1: protocol ip prio 10 \
		u32 match ip protocol 1 0xff flowid 1:2 \
		action skbmod \
		ecn

The updated tc-skbmod SYNOPSIS looks like the following:

	tc ... action skbmod { set SETTABLE | swap SWAPPABLE | ecn } ...

Only one of "set", "swap" or "ecn" shall be used in a single tc-skbmod
command.  Trying to use more than one of them at a time is considered
undefined behavior; pipe multiple tc-skbmod commands together instead.
"set" and "swap" only affect Ethernet packets, while "ecn" only affects
IP packets.

Depends on kernel patch "net/sched: act_skbmod: Add SKBMOD_F_ECN option
support", as well as iproute2 patch "tc/skbmod: Remove misinformation
about the swap action".

[1] https://en.wikipedia.org/wiki/Explicit_Congestion_Notification

Reviewed-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Justin Iurman 86c596ed91 IOAM man8
This patch provides man8 documentation for IOAM inside ip, ip-ioam and ip-route.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Justin Iurman 2d83c71082 New IOAM6 encap type for routes
This patch provides a new encap type for routes to insert an IOAM pre-allocated
trace:

$ ip -6 ro ad fc00::1/128 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0

where:
 - "trace" and "prealloc" may appear as useless but just anticipate for future
   implementations of other ioam option types.
 - "type" is a bitfield (=u32) defining the IOAM pre-allocated trace type (see
   the corresponding uapi).
 - "ns" is an IOAM namespace ID attached to the pre-allocated trace.
 - "size" is the trace pre-allocated size in bytes; must be a 4-octet multiple;
   limited size (see IOAM6_TRACE_DATA_SIZE_MAX).

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Justin Iurman f0b3808afa Add, show, link, remove IOAM namespaces and schemas
This patch provides support for adding, listing and removing IOAM namespaces
and schemas with iproute2. When adding an IOAM namespace, both "data" (=u32)
and "wide" (=u64) are optional. Therefore, you can either have none, one of
them, or both at the same time. When adding an IOAM schema, there is no
restriction on "DATA" except its size (see IOAM6_MAX_SCHEMA_DATA_LEN). By
default, an IOAM namespace has no active IOAM schema (meaning an IOAM namespace
is not linked to an IOAM schema), and an IOAM schema is not considered
as "active" (meaning an IOAM schema is not linked to an IOAM namespace). It is
possible to link an IOAM namespace with an IOAM schema, thanks to the last
command below (meaning the IOAM schema will be considered as "active" for the
specific IOAM namespace).

$ ip ioam
Usage:	ip ioam { COMMAND | help }
	ip ioam namespace show
	ip ioam namespace add ID [ data DATA32 ] [ wide DATA64 ]
	ip ioam namespace del ID
	ip ioam schema show
	ip ioam schema add ID DATA
	ip ioam schema del ID
	ip ioam namespace set ID schema { ID | none }

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
David Ahern acbdef9386 Import ioam6 uapi headers
Import ioam6 uapi headers from kernel headers at last sync commit.

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
David Ahern 2d6fa30bb8 Update kernel headers
Update kernel headers to commit:
    1187c8c4642d ("net: phy: mscc: make some arrays static const, makes object smaller")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
Gokul Sivakumar 508ad89c82 ipneigh: add support to print brief output of neigh cache in tabular format
Make use of the already available brief flag and print the basic details of
the IPv4 or IPv6 neighbour cache in a tabular format for better readability
when the brief output is expected.

$ ip -br neigh
172.16.12.100                           bridge0          b0:fc:36:2f:07:43
172.16.12.174                           bridge0          8c:16:45:2f:bc:1c
172.16.12.250                           bridge0          04:d9:f5:c1:0c:74
fe80::267b:9f70:745e:d54d               bridge0          b0:fc:36:2f:07:43
fd16:a115:6a62:0:8744:efa1:9933:2c4c    bridge0          8c:16:45:2f:bc:1c
fe80::6d9:f5ff:fec1:c74                 bridge0          04:d9:f5:c1:0c:74

And add "ip neigh show" to the list of ip sub commands mentioned in the man
page that support the brief output in tabular format.

Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-09-01 12:51:44 -07:00
David Ahern fb843668fb Merge branch 'bridge-vlan-global-mcast' into next
Nikolay Aleksandrov  says:

====================

This set adds support for vlan multicast options. The feature is
globally controlled by a new bridge option called mcast_vlan_snooping
which is added by patch 01. Then patches 2-5 add support for dumping
global vlan options and filtering on vlan id. Patch 06 adds support for
setting global vlan options and then patches 07-18 add all the new
global vlan options, finally patch 19 adds support for dumping vlan
multicast router ports. These options are identical in meaning, names and
functionality as the bridge-wide ones.

All the new vlan global commands are under the global keyword:
 $ bridge vlan global show [ vid VID dev DEVICE ]
 $ bridge vlan global set vid VID dev DEVICE ...

I've added command examples in each commit message. The patch-set is a
bit bigger but the global options follow the same pattern so I don't see
a point in breaking them. All man page descriptions have been taken from
the same current bridge-wide mcast options. The only additional iproute2
change which is left to do is the per-vlan mcast router control which
I'll send separately. Note to properly use this set you'll need the
updated kernel headers where mcast router was moved from a global option
to per-vlan/per-device one (changed uapi enum which was in net-next).

Example:
 # enable vlan mcast snooping globally
 $ ip link set dev bridge type bridge mcast_vlan_snooping 1
 # enable mcast querier on vlan 100
 $ bridge vlan global set dev bridge vid 100 mcast_querier 1
 # show vlan 100's global options
 $ bridge -s vlan global show vid 100
port              vlan-id
bridge            100
                    mcast_snooping 1 mcast_querier 1 mcast_igmp_version 2 mcast_mld_version 1 mcast_last_member_count 2 mcast_last_member_interval 100 mcast_startup_query_count 2 mcast_startup_query_interval 3125 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000

A following kernel patch-set will add selftests which use these commands.

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:32:31 -06:00
Nikolay Aleksandrov 72222cd467 bridge: vlan: add support for dumping router ports
Add dump support for vlan multicast router ports and their details if
requested. If details are requested we print 1 entry per line, otherwise
we print all router ports on a single line similar to how mdb prints
them.

Looks like:
$ bridge vlan global show vid 100
 port              vlan-id
 bridge            100
                     mcast_snooping 1 mcast_querier 0 mcast_igmp_version 2 mcast_mld_version 1 mcast_last_member_count 2 mcast_last_member_interval 100 mcast_startup_query_count 2 mcast_startup_query_interval 3125 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000
                     router ports: ens20 ens16

Looks like (with -s):
 $ bridge -s vlan global show vid 100
 port              vlan-id
 bridge            100
                     mcast_snooping 1 mcast_querier 0 mcast_igmp_version 2 mcast_mld_version 1 mcast_last_member_count 2 mcast_last_member_interval 100 mcast_startup_query_count 2 mcast_startup_query_interval 3125 mcast_membership_interval 26000 mcast_querier_interval 25500 mcast_query_interval 12500 mcast_query_response_interval 1000
                     router ports: ens20   187.57 temp
                                   ens16   118.27 temp

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:29:31 -06:00
Nikolay Aleksandrov 7ad5505bb5 bridge: vlan: add global mcast_querier option
Add control and dump support for the global mcast_querier option which
controls if the bridge will act as a multicast querier for that vlan.
Syntax: $ bridge vlan global set dev bridge vid 1 mcast_querier 1

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:29:26 -06:00
Nikolay Aleksandrov 061da2e222 bridge: vlan: add global mcast_startup_query_interval option
Add control and dump support for the global mcast_startup_query_interval
option which controls the interval between queries in the startup phase.
To be consistent with the same bridge-wide option the value is reported
with USER_HZ granularity and the same granularity is expected when setting
it.
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_startup_query_interval 15000

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:29:12 -06:00
Nikolay Aleksandrov 60dcd5c318 bridge: vlan: add global mcast_query_response_interval option
Add control and dump support for the global mcast_query_response_interval
option which sets the Max Response Time/Maximum Response Delay for IGMP/MLD
queries sent by the bridge. To be consistent with the same bridge-wide
option the value is reported with USER_HZ granularity and the same
granularity is expected when setting it.
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_query_response_interval 13000

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:28:47 -06:00
Nikolay Aleksandrov 0e4cfa0370 bridge: vlan: add global mcast_query_interval option
Add control and dump support for the global mcast_query_interval
option which controls the interval between queries sent by the bridge
after the end of the startup phase. To be consistent with the same
bridge-wide option the value is reported with USER_HZ granularity and
the same granularity is expected when setting it.
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_query_interval 13000

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:28:29 -06:00
Nikolay Aleksandrov ebcee09ca1 bridge: vlan: add global mcast_querier_interval option
Add control and dump support for the global mcast_querier_interval
option which controls the interval after which if no other router
queries are seen the bridge will start sending its own queries.
To be consistent with the same bridge-wide option the value is reported
with USER_HZ granularity and the same granularity is expected when
setting it.
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_querier_interval 13000

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:28:12 -06:00
Nikolay Aleksandrov 3ae784f589 bridge: vlan: add global mcast_membership_interval option
Add control and dump support for the global mcast_membership_interval
option which controls the interval after which the bridge will leave a
group if no reports have been received for it. To be consistent with the
same bridge-wide option the value is reported with USER_HZ granularity and
the same granularity is expected when setting it.
The default is 26000 (260 seconds).
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_membership_interval 13000

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:27:56 -06:00
Nikolay Aleksandrov 2b6cc38d52 bridge: vlan: add global mcast_last_member_interval option
Add control and dump support for the global mcast_last_member_interval
option which controls the interval between queries to find remaining
members of a group after a leave message. To be consistent with the same
bridge-wide option the value is reported with USER_HZ granularity and
the same granularity is expected when setting it.
The default is 100 (1 second).
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_last_member_interval 200

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:27:45 -06:00
Nikolay Aleksandrov 7cc7dbf447 bridge: vlan: add global mcast_startup_query_count option
Add control and dump support for the global mcast_startup_query_count
option which controls the number of queries the bridge will send on the
vlan during startup phase (default 2).
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_startup_query_count 5

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:27:28 -06:00
Nikolay Aleksandrov 3399c0759f bridge: vlan: add global mcast_last_member_count option
Add control and dump support for the global mcast_last_member_count option
which controls the number of queries the bridge will send on the vlan after
a leave is received (default 2).
Syntax:
 $ bridge vlan global set dev bridge vid 1 mcast_last_member_count 10

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:26:07 -06:00
Nikolay Aleksandrov a8d7212a4f bridge: vlan: add global mcast_mld_version option
Add control and dump support for the global mcast_mld_version option
which controls the MLD version on the vlan (default 1).
Syntax: $ bridge vlan global set dev bridge vid 1 mcast_mld_version 2

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:25:17 -06:00
Nikolay Aleksandrov 29fada0f41 bridge: vlan: add global mcast_igmp_version option
Add control and dump support for the global mcast_igmp_version option
which controls the IGMP version on the vlan (default 2).
Syntax: $ bridge vlan global set dev bridge vid 1 mcast_igmp_version 3

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:24:09 -06:00
Nikolay Aleksandrov 1f608d590c bridge: vlan: add global mcast_snooping option
Add control and dump support for the global mcast_snooping option which
controls if multicast snooping is enabled or disabled for a single vlan.
Syntax: $ bridge vlan global set dev bridge vid 1 mcast_snooping 1

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:23:26 -06:00
Nikolay Aleksandrov dee5eb05e5 bridge: vlan: add support to set global vlan options
Add support to change global vlan options via a new vlan global
set subcommand similar to the current vlan set subcommand. The man page
and help are updated accordingly. The command works only with bridge
devices. It doesn't support any options yet.

Syntax: $ bridge vlan global set vid VID dev DEV

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:21:13 -06:00
Nikolay Aleksandrov ecf6d8b4a1 bridge: vlan: add support for vlan filtering when dumping options
In order to allow vlan filtering when dumping options we need to move
all print operations into the option dumping functions and add the
filtering after we've parsed the nested attributes so we can extract the
start and end vlan ids.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:21:09 -06:00
Nikolay Aleksandrov 720f8613bd bridge: vlan: add support to show global vlan options
Add support for new bridge vlan command grouping called global which
operates on global options. The first command it supports is "show".
To do that we update print_vlan_rtm to recognize the global vlan options
attribute and parse it properly.
Man page and help are also updated with the new command.

Syntax is: $ bridge vlan global show [ vid VID ] [ dev DEV ]

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:21:04 -06:00
Nikolay Aleksandrov d3a961a9b1 bridge: vlan: skip unknown attributes when printing options
Skip unknown attributes when printing vlan options in print_vlan_rtm.
Make sure print_vlan_opts doesn't accept attributes it doesn't understand.
Currently we print only one type, later global vlan options support will
be added.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:21:00 -06:00
Nikolay Aleksandrov 312e22fe79 bridge: vlan: factor out vlan option printing
Factor out the code which prints current per-vlan options from
print_vlan_rtm without any changes, later we'll filter based on the vlan
attribute and add support for global vlan option printing.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:20:53 -06:00
Nikolay Aleksandrov d2eecb9d1d ip: bridge: add support for mcast_vlan_snooping
Add support for mcast_vlan_snooping option which controls per-vlan
multicast snooping, also update the man page.
Syntax: $ ip link set dev bridge type bridge mcast_vlan_snooping 0/1

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-31 21:20:03 -06:00
Stephen Hemminger 169f36a0c9 v5.14.0 2021-08-31 11:57:59 -07:00
Jakub Kicinski 85b0e73c77 ss: fix fallback to procfs for raw sockets
Jonas reports that ss -awp does not display any RAW sockets
on a Knoppix 4.4 kernel.

sockdiag_send() diverts to tcpdiag_send() to try the older
netlink interface. tcpdiag_send() works for TCP and DCCP
but not other protocols. Instead of rejecting unsupported
protocols (and missing RAW and SCTP) match on supported ones.

Link: https://lore.kernel.org/netdev/20210815231738.7b42bad4@mmluhan/
Reported-and-tested-by: Jonas Bechtel <post@jbechtel.de>
Fixes: 41fe6c34de ("ss: Add inet raw sockets information gathering via netlink diag interface")
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 15:03:46 -07:00
Stephen Hemminger 1afde09498 uapi: update neighbour.h
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 14:09:34 -07:00
Gokul Sivakumar 10ecd12690 man: bridge: fix the typo to change "-c[lor]" into "-c[olor]" in man page
Fixes: 3a1ca9a5b ("bridge: update man page for new color and json changes")
Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 14:04:53 -07:00
Gokul Sivakumar 057d3c6d37 bridge: fdb: don't colorize the "dev" & "dst" keywords in "bridge -c fdb"
To be consistent with the colorized output of "ip" command and to increase
readability, stop highlighting the "dev" & "dst" keywords in the colorized
output of "bridge -c fdb" cmd.

Example: in the following "bridge -c fdb" entry, only "00:00:00:00:00:00",
"vxlan100" and "2001:db8:2::1" fields should be highlighted in color.

00:00:00:00:00:00 dev vxlan100 dst 2001:db8:2::1 self permanent

Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 14:04:53 -07:00
Gokul Sivakumar 82149efee9 bridge: reorder cmd line arg parsing to let "-c" detected as "color" option
As per the man/man8/bridge.8 page, the shorthand cmd line arg "-c" can be
used to colorize the bridge cmd output. But while parsing the args in while
loop, matches() detects "-c" as "-compressedvlans" instead of "-color", so
fix this by doing the check for "-color" option first before checking for
"-compressedvlans".

Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 14:04:53 -07:00
Hangbin Liu 3a09567f7d ip/bond: add arp_validate filter support
Add arp_validate filter support based on kernel commit 896149ff1b2c
("bonding: extend arp_validate to be able to receive unvalidated arp-only traffic")

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-18 14:02:44 -07:00
Parav Pandit 355c49ffa5 devlink: Show port state values in man page and in the help command
Port function state can have either of the two values - active or
inactive. Update the documentation and help command for these two
values to tell user about it.

With the introduction of state, hw_addr and state are optional.
Hence mark them as optional in man page that also aligns with the help
command output.

Fixes: bdfb9f1bd6 ("devlink: Support set of port function state")
Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-11 15:02:30 -07:00
Hangbin Liu ebaa603b30 ip/bond: add lacp active support
lacp_active specifies whether to send LACPDU frames periodically.
If set on, the LACPDU frames are sent along with the configured lacp_rate
setting. If set off, the LACPDU frames acts as "speak when spoken to".

v2: use strcmp instead of match for new options.

Signed-off-by: Hangbin Liu <liuhangbin@gmail.com>
2021-08-11 12:26:20 -06:00
David Ahern 8d6134b204 Update kernel headers
Update kernel headers to commit:
    88be32634905 ("Merge branch 'dsa-tagger-helpers'")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-11 12:23:33 -06:00
Ilya Dmitrichenko 51d8fc708c ip/tunnel: always print all known attributes
Presently, if a Geneve or VXLAN interface was created with 'external',
it's not possible for a user to determine e.g. the value of 'dstport'
after creation. This change fixes that by avoiding early returns.

This change partly reverts commit 00ff4b8e31 ("ip/tunnel: Be consistent
when printing tunnel collect metadata").

Signed-off-by: Ilya Dmitrichenko <errordeveloper@gmail.com>
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-11 12:17:52 -06:00
Justin Iurman 71ba9c18e0 ipioam6: use print_nl instead of print_null
This patch addresses Stephen's comment:

"""
> +        print_null(PRINT_ANY, "", "\n", NULL);

Use print_nl() since it handles the case of oneline output.
Plus in JSON the newline is meaningless.
"""

It also removes two useless print_null's.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-11 12:16:09 -06:00
Phil Sutter 9b7ea92b9e tc: u32: Fix key folding in sample option
In between Linux kernel 2.4 and 2.6, key folding for hash tables changed
in kernel space. When iproute2 dropped support for the older algorithm,
the wrong code was removed and kernel 2.4 folding method remained in
place. To get things functional for recent kernels again, restoring the
old code alone was not sufficient - additional byteorder fixes were
needed.

While being at it, make use of ffs() and thereby align the code with how
kernel determines the shift width.

Fixes: 267480f553 ("Backout the 2.4 utsname hash patch.")
Signed-off-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-10 20:02:43 -07:00
Andrea Claudi d1eacf12b5 lib: bpf_glue: remove useless assignment
The value of s used inside the cycle is the result of strstr(), so this
assignment is useless.

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-10 20:01:54 -07:00
Andrea Claudi 50a4127022 lib: bpf_legacy: fix potential NULL-pointer dereference
If bpf_map_fetch_name() returns NULL, strlen() hits a NULL-pointer
dereference on outer_map_name.

Fix this checking outer_map_name value, and returning false when NULL,
as already done for inner_map_name before.

Fixes: 6d61a2b557 ("lib: add libbpf support")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-10 19:55:12 -07:00
Jacob Keller 954a0077c8 devlink: fix infinite loop on flash update for drivers without status
When processing device flash update, cmd_dev_flash function waits until
the flash process has completed. This requires the following two
conditions to both be true:

a) we've received an exit status from the child process
b) we've received the DEVLINK_CMD_FLASH_UPDATE_END *or*
   we haven't received any status notifications from the driver.

The original devlink flash status monitoring code in 9b13cddfe2
("devlink: implement flash status monitoring") was written assuming that
a driver will either send no status updates, or it will send at least
one DEVLINK_CMD_FLASH_UPDATE_STATUS before DEVLINK_CMD_FLASH_UPDATE_END.

Newer versions of the kernel since commit 52cc5f3a166a ("devlink: move flash
end and begin to core devlink") in v5.10 moved handling of the
DEVLINK_CMD_FLASH_UPDATE_END into the core stack, and will send this
regardless of whether or not the driver sends any of its own status
notifications.

The handling of DEVLINK_CMD_FLASH_UPDATE_END in cmd_dev_flash_status_cb
has an additional condition that it must not be the first message.
Otherwise, it falls back to treating it like
a DEVLINK_CMD_FLASH_UPDATE_STATUS.

This is wrong because it can lead to an infinite loop if a driver does
not send any status updates.

In this case, the kernel will send DEVLINK_CMD_FLASH_UPDATE_END without
any DEVLINK_CMD_FLASH_UPDATE_STATUS. The devlink application will see
that ctx->not_first is false, and will treat this like any other status
message. Thus, ctx->not_first will be set to 1.

The loop condition to exit flash update will thus never be true, since
we will wait forever, because ctx->not_first is true, and
ctx->received_end is false.

This leads to the application appearing to process the flash update, but
it will never exit.

Fix this by simply always treating DEVLINK_CMD_FLASH_UPDATE_END the same
regardless of whether its the first message or not.

This is obviously the correct thing to do: once we've received the
DEVLINK_CMD_FLASH_UPDATE_END the flash update must be finished. For new
kernels this is always true, because we send this message in the core
stack after the driver flash update routine finishes.

For older kernels, some drivers may not have sent any
DEVLINK_CMD_FLASH_UPDATE_STATUS or DEVLINK_CMD_FLASH_UPDATE_END. This is
handled by the while loop conditional that exits if we get a return
value from the child process without having received any status
notifications.

An argument could be made that we should exit immediately when we get
either the DEVLINK_CMD_FLASH_UPDATE_END or an exit code from the child
process. However, at a minimum it makes no sense to ever process
DEVLINK_CMD_FLASH_UPDATE_END as if it were a DEVLINK_CMD_FLASH_UPDATE_STATUS.

This is easy to test as it is triggered by the selftests for the
netdevsim driver, which has a test case for both with and without status
notifications.

Fixes: 9b13cddfe2 ("devlink: implement flash status monitoring")
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-10 19:54:39 -07:00
Feng Zhou be99929d60 lib/bpf: Fix btf_load error lead to enable debug log
Use tc with no verbose, when bpf_btf_attach fail,
the conditions:
"if (fd < 0 && (errno == ENOSPC || !ctx->log_size))"
will make ctx->log_size != 0. And then, bpf_prog_attach,
ctx->log_size != 0. so enable debug log.
The verifier log sometimes is so chatty on larger programs.
bpf_prog_attach is failed.
"Log buffer too small to dump verifier log 16777215 bytes (9 tries)!"

BTF load failure does not affect prog load. prog still work.
So when BTF/PROG load fail, enlarge log_size and re-fail with
having verbose.

Signed-off-by: Feng Zhou <zhoufeng.zf@bytedance.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-08-10 19:53:54 -07:00
Peilin Ye e78411948d tc/skbmod: Introduce SKBMOD_F_ECN option
Recently we added SKBMOD_F_ECN option support to the kernel; support it in
the tc-skbmod(8) front end, and update its man page accordingly.

The 2 least significant bits of the Traffic Class field in IPv4 and IPv6
headers are used to represent different ECN states [1]:

	0b00: "Non ECN-Capable Transport", Non-ECT
	0b10: "ECN Capable Transport", ECT(0)
	0b01: "ECN Capable Transport", ECT(1)
	0b11: "Congestion Encountered", CE

This new option, "ecn", marks ECT(0) and ECT(1) IPv{4,6} packets as CE,
which is useful for ECN-based rate limiting.  For example:

	$ tc filter add dev eth0 parent 1: protocol ip prio 10 \
		u32 match ip protocol 1 0xff flowid 1:2 \
		action skbmod \
		ecn

The updated tc-skbmod SYNOPSIS looks like the following:

	tc ... action skbmod { set SETTABLE | swap SWAPPABLE | ecn } ...

Only one of "set", "swap" or "ecn" shall be used in a single tc-skbmod
command.  Trying to use more than one of them at a time is considered
undefined behavior; pipe multiple tc-skbmod commands together instead.
"set" and "swap" only affect Ethernet packets, while "ecn" only affects
IP packets.

Depends on kernel patch "net/sched: act_skbmod: Add SKBMOD_F_ECN option
support", as well as iproute2 patch "tc/skbmod: Remove misinformation
about the swap action".

[1] https://en.wikipedia.org/wiki/Explicit_Congestion_Notification

Reviewed-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-08 11:56:55 -06:00
David Ahern 09d8ce3db1 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-04 09:24:12 -06:00
David Ahern e8763fc9ab Merge branch 'ipv6-oam' into next
Justin Iurman says:

====================

The IOAM patchset was merged recently (see net-next commits [1,2,3,4,5,6]).
Therefore, this patchset provides support for IOAM inside iproute2, as well as
manpage documentation. Here is a summary of added features inside iproute2.

(1) configure IOAM namespaces and schemas:

$ ip ioam
Usage:  ip ioam { COMMAND | help }
        ip ioam namespace show
        ip ioam namespace add ID [ data DATA32 ] [ wide DATA64 ]
        ip ioam namespace del ID
        ip ioam schema show
        ip ioam schema add ID DATA
        ip ioam schema del ID
        ip ioam namespace set ID schema { ID | none }

(2) provide a new encap type to insert the IOAM pre-allocated trace:

$ ip -6 ro ad fc00::1/128 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0

  [1] db67f219fc9365a0c456666ed7c134d43ab0be8a
  [2] 9ee11f0fff205b4b3df9750bff5e94f97c71b6a0
  [3] 8c6f6fa6772696be0c047a711858084b38763728
  [4] 3edede08ff37c6a9370510508d5eeb54890baf47
  [5] de8e80a54c96d2b75377e0e5319a64d32c88c690
  [6] 968691c777af78d2daa2ee87cfaeeae825255a58

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 11:34:09 -06:00
Justin Iurman 78832863ef IOAM man8
This patch provides man8 documentation for IOAM inside ip, ip-ioam and ip-route.

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 11:33:35 -06:00
Justin Iurman 32f4969d44 New IOAM6 encap type for routes
This patch provides a new encap type for routes to insert an IOAM pre-allocated
trace:

$ ip -6 ro ad fc00::1/128 encap ioam6 trace prealloc type 0x800000 ns 1 size 12 dev eth0

where:
 - "trace" and "prealloc" may appear as useless but just anticipate for future
   implementations of other ioam option types.
 - "type" is a bitfield (=u32) defining the IOAM pre-allocated trace type (see
   the corresponding uapi).
 - "ns" is an IOAM namespace ID attached to the pre-allocated trace.
 - "size" is the trace pre-allocated size in bytes; must be a 4-octet multiple;
   limited size (see IOAM6_TRACE_DATA_SIZE_MAX).

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 11:33:31 -06:00
Justin Iurman 2909812583 Add, show, link, remove IOAM namespaces and schemas
This patch provides support for adding, listing and removing IOAM namespaces
and schemas with iproute2. When adding an IOAM namespace, both "data" (=u32)
and "wide" (=u64) are optional. Therefore, you can either have none, one of
them, or both at the same time. When adding an IOAM schema, there is no
restriction on "DATA" except its size (see IOAM6_MAX_SCHEMA_DATA_LEN). By
default, an IOAM namespace has no active IOAM schema (meaning an IOAM namespace
is not linked to an IOAM schema), and an IOAM schema is not considered
as "active" (meaning an IOAM schema is not linked to an IOAM namespace). It is
possible to link an IOAM namespace with an IOAM schema, thanks to the last
command below (meaning the IOAM schema will be considered as "active" for the
specific IOAM namespace).

$ ip ioam
Usage:	ip ioam { COMMAND | help }
	ip ioam namespace show
	ip ioam namespace add ID [ data DATA32 ] [ wide DATA64 ]
	ip ioam namespace del ID
	ip ioam schema show
	ip ioam schema add ID DATA
	ip ioam schema del ID
	ip ioam namespace set ID schema { ID | none }

Signed-off-by: Justin Iurman <justin.iurman@uliege.be>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 11:33:05 -06:00
David Ahern e53f4cd504 Import ioam6 uapi headers
Import ioam6 uapi headers from kernel headers at last sync commit.

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 11:32:26 -06:00
David Ahern 236696e52c Update kernel headers
Update kernel headers to commit:
    1187c8c4642d ("net: phy: mscc: make some arrays static const, makes object smaller")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 10:25:09 -06:00
Gokul Sivakumar cf866f0a5a ipneigh: add support to print brief output of neigh cache in tabular format
Make use of the already available brief flag and print the basic details of
the IPv4 or IPv6 neighbour cache in a tabular format for better readability
when the brief output is expected.

$ ip -br neigh
172.16.12.100                           bridge0          b0:fc:36:2f:07:43
172.16.12.174                           bridge0          8c:16:45:2f:bc:1c
172.16.12.250                           bridge0          04:d9:f5:c1:0c:74
fe80::267b:9f70:745e:d54d               bridge0          b0:fc:36:2f:07:43
fd16:a115:6a62:0:8744:efa1:9933:2c4c    bridge0          8c:16:45:2f:bc:1c
fe80::6d9:f5ff:fec1:c74                 bridge0          04:d9:f5:c1:0c:74

And add "ip neigh show" to the list of ip sub commands mentioned in the man
page that support the brief output in tabular format.

Signed-off-by: Gokul Sivakumar <gokulkumar792@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-08-02 10:14:50 -06:00
Peilin Ye c06d313d86 tc/skbmod: Remove misinformation about the swap action
Currently man 8 tc-skbmod says that "...the swap action will occur after
any smac/dmac substitutions are executed, if they are present."

This is false.  In fact, trying to "set" and "swap" in a single skbmod
command causes the "set" part to be completely ignored.  As an example:

	$ tc filter add dev eth0 parent 1: protocol ip prio 10 \
		matchall action skbmod \
        	set dmac AA:AA:AA:AA:AA:AA smac BB:BB:BB:BB:BB:BB \
        	swap mac

The above command simply does a "swap", without setting DMAC or SMAC to
AA's or BB's.  The root cause of this is in the kernel, see
net/sched/act_skbmod.c:tcf_skbmod_init():

	parm = nla_data(tb[TCA_SKBMOD_PARMS]);
	index = parm->index;
	if (parm->flags & SKBMOD_F_SWAPMAC)
		lflags = SKBMOD_F_SWAPMAC;
		^^^^^^^^^^^^^^^^^^^^^^^^^^

Doing a "=" instead of "|=" clears all other "set" flags when doing a
"swap".  Discourage using "set" and "swap" in the same command by
documenting it as undefined behavior, and update the "SYNOPSIS" section
as well as tc -help text accordingly.

If one really needs to e.g. "set" DMAC to all AA's then "swap" DMAC and
SMAC, one should do two separate commands and "pipe" them together.

Reviewed-by: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Peilin Ye <peilin.ye@bytedance.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-22 15:14:29 -07:00
Roi Dayan 71d36000dc police: Fix normal output back to what it was
With the json support fix the normal output was
changed. set it back to what it was.
Print overhead with print_size().
Print newline before ref.

Fixes: 0d5cf51e0d ("police: Add support for json output")
Signed-off-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-17 11:14:30 -07:00
Lahav Schlesinger f760bff328 ipmonitor: Fix recvmsg with ancillary data
A successful call to recvmsg() causes msg.msg_controllen to contain the length
of the received ancillary data. However, the current code in the 'ip' utility
doesn't reset this value after each recvmsg().

This means that if a call to recvmsg() doesn't have ancillary data, then
'msg.msg_controllen' will be set to 0, causing future recvmsg() which do
contain ancillary data to get MSG_CTRUNC set in msg.msg_flags.

This fixes 'ip monitor' running with the all-nsid option - With this option the
kernel passes the nsid as ancillary data. If while 'ip monitor' is running an
even on the current netns is received, then no ancillary data will be sent,
causing 'msg.msg_controllen' to be set to 0, which causes 'ip monitor' to
indefinitely print "[nsid current]" instead of the real nsid.

Fixes: 449b824ad1 ("ipmonitor: allows to monitor in several netns")
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Lahav Schlesinger <lschlesinger@drivenets.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-17 11:13:36 -07:00
Stephen Hemminger 7a7e9ed98f uapi: headers update
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-17 11:12:47 -07:00
Christian Schürmann 1f2c908d53 man8/ip-tunnel.8: fix typo, 'encaplim' is not a valid option
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-15 09:31:51 -07:00
Alexander Mikhalitsyn 115e987035 libnetlink: check error handler is present before a call
Fix nullptr dereference of errhndlr from rtnl_dump_filter_arg
struct in rtnl_dump_done and rtnl_dump_error functions.

Fixes: 459ce6e3d7 ("ip route: ignore ENOENT during save if RT_TABLE_MAIN is being dumped")
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Roi Dayan <roid@nvidia.com>
Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Reported-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-11 10:33:44 -07:00
Stephen Hemminger 0015ada629 libnetlink: cosmetic changes
Don't initialize arguments that are NULL, and format initialization
in a more logical way.

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-07 07:39:07 -07:00
Alexander Mikhalitsyn 459ce6e3d7 ip route: ignore ENOENT during save if RT_TABLE_MAIN is being dumped
We started to use in-kernel filtering feature which allows to get only
needed tables (see iproute_dump_filter()). From the kernel side it's
implemented in net/ipv4/fib_frontend.c (inet_dump_fib), net/ipv6/ip6_fib.c
(inet6_dump_fib). The problem here is that behaviour of "ip route save"
was changed after
c7e6371bc ("ip route: Add protocol, table id and device to dump request").
If filters are used, then kernel returns ENOENT error if requested table
is absent, but in newly created net namespace even RT_TABLE_MAIN table
doesn't exist. It is really allocated, for instance, after issuing
"ip l set lo up".

Reproducer is fairly simple:
$ unshare -n ip route save > dump
Error: ipv4: FIB table does not exist.
Dump terminated

Expected result here is to get empty dump file (as it was before this
change).

v2: reworked, so, now it takes into account NLMSGERR_ATTR_MSG
(see nl_dump_ext_ack_done() function). We want to suppress error messages
in stderr about absent FIB table from kernel too.

v3: reworked to make code clearer. Introduced rtnl_suppressed_errors(),
rtnl_suppress_error() helpers. User may suppress up to 3 errors (may be
easily extended by changing SUPPRESS_ERRORS_INIT macro).

v4: reworked, rtnl_dump_filter_errhndlr() was introduced. Thanks
to Stephen Hemminger for comments and suggestions

v5: space fixes, commit message reformat, empty initializers

Fixes: c7e6371bc ("ip route: Add protocol, table id and device to dump request")
Cc: David Ahern <dsahern@gmail.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Cc: Andrei Vagin <avagin@gmail.com>
Cc: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-07 07:32:56 -07:00
Stephen Hemminger 8f85d085fe uapi: update kernel headers from 5.14-rc1
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-06 17:07:24 -07:00
Martynas Pumputis 83d4d61bc9 libbpf: fix attach of prog with multiple sections
When BPF programs which consists of multiple executable sections via
iproute2+libbpf (configured with LIBBPF_FORCE=on), we noticed that a
wrong section can be attached to a device. E.g.:

    # tc qdisc replace dev lxc_health clsact
    # tc filter replace dev lxc_health ingress prio 1 \
        handle 1 bpf da obj bpf_lxc.o sec from-container
    # tc filter show dev lxc_health ingress filter protocol all
        pref 1 bpf chain 0 filter protocol all pref 1 bpf chain 0
        handle 0x1 bpf_lxc.o:[__send_drop_notify] <-- WRONG SECTION
        direct-action not_in_hw id 38 tag 7d891814eda6809e jited

After taking a closer look into load_bpf_object() in lib/bpf_libbpf.c,
we noticed that the filter used in the program iterator does not check
whether a program section name matches a requested section name
(cfg->section). This can lead to a wrong prog FD being used to attach
the program.

Fixes: 6d61a2b557 ("lib: add libbpf support")
Signed-off-by: Martynas Pumputis <m@lambda.lt>
Acked-by: Hangbin Liu <haliu@redhat.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-07-06 16:59:39 -07:00
David Ahern 02c06ffc13 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-07-01 14:29:42 +00:00
Stephen Hemminger fc3511962d lib: remove blank line at eof
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-29 13:20:44 -07:00
Stephen Hemminger 0e7ea3e8fe v5.13.0 2021-06-29 11:24:17 -07:00
Ben Hutchings 33cf9306c8 devlink: Fix printf() type mismatches on 32-bit architectures
devlink currently uses "%lu" to format values of type uint64_t,
but on 32-bit architectures uint64_t is defined as unsigned
long long and this does not work correctly.

Fix this by using the standard macro PRIu64 instead.

Signed-off-by: Ben Hutchings <ben.hutchings@mind.be>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-29 11:10:14 -07:00
Ben Hutchings 4ac0383a59 utils: Fix BIT() to support up to 64 bits on all architectures
devlink and vdpa use BIT() together with 64-bit flag fields.  devlink
is already using bit numbers greater than 31 and so does not work
correctly on 32-bit architectures.

Fix this by making BIT() use uint64_t instead of unsigned long.

Signed-off-by: Ben Hutchings <ben.hutchings@mind.be>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-29 11:10:14 -07:00
Stephen Hemminger c73fb66070 uapi: update headers to 5.13
Final 5.13 header update

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-28 10:19:08 -07:00
Roi Dayan 6f15c21719 devlink: Fix link errors on some systems
On some systems we fail to link because of missing math lib.
add -lm to devlink.

    LINK     devlink
../lib/libutil.a(utils_math.o): In function `get_rate':
utils_math.c:(.text+0xcc): undefined reference to `floor'
../lib/libutil.a(utils_math.o): In function `get_size':
utils_math.c:(.text+0x384): undefined reference to `floor'
collect2: error: ld returned 1 exit status
make[1]: *** [Makefile:16: devlink] Error 1
make: *** [Makefile:64: all] Error 2

Fixes: 6c70aca76e ("devlink: Add port func rate support")
Signed-off-by: Roi Dayan <roid@nvidia.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-26 14:57:27 -07:00
Asbjørn Sloth Tønnesen 2ff4761db4 tc: pedit: add decrement operation
Implement a decrement operation for ttl and hoplimit.

Since this is just syntactic sugar, it goes that:

  tc filter add ... action pedit ex munge ip ttl dec ...
  tc filter add ... action pedit ex munge ip6 hoplimit dec ...

is just a more readable version of this:

  tc filter add ... action pedit ex munge ip ttl add 0xff ...
  tc filter add ... action pedit ex munge ip6 hoplimit add 0xff ...

This feature was suggested by some pseudo tc examples in Mellanox's
documentation[1], but wasn't present in neither their mlnx-iproute2
nor iproute2.

Tested with skip_sw on Mellanox ConnectX-6 Dx.

[1] https://docs.mellanox.com/pages/viewpage.action?pageId=47033989

v3:
   - Use dedicated flags argument in parse_cmd() (David Ahern)
   - Minor rewording of the man page

v2:
   - Fix whitespace issue (Stephen Hemminger)
   - Add to usage info in explain()

Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.st>
Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-26 04:45:19 +00:00
Asbjørn Sloth Tønnesen bc5e8473aa tc: pedit: parse_cmd: add flags argument
This patch just prepares the flags argument, so it's
available to the next patch.

Signed-off-by: Asbjørn Sloth Tønnesen <asbjorn@asbjorn.st>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-26 04:44:35 +00:00
Sergey Ryazanov 6acccd52a2 iplink: support for WWAN devices
The WWAN subsystem has been extended to generalize the per data channel
network interfaces management. This change implements support for WWAN
links handling. And actively uses the earlier introduced ip-link
capability to specify the parent by its device name.

The WWAN interface for a new data channel should be created with a
command like this:

ip link add dev wwan0-2 parentdev wwan0 type wwan linkid 2

Where: wwan0 is the modem HW device name (should be taken from
/sys/class/wwan) and linkid is an identifier of the opened data
channel.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-26 04:40:57 +00:00
Sergey Ryazanov 362da458a4 iplink: add support for parent device
Add support for specifying a parent device (struct device) by its name
during the link creation and printing parent name in the links list.
This option will be used to create WWAN links and possibly by other
device classes that do not have a "natural parent netdev".

Add the parent device bus name printing for links list info
completeness. But do not add a corresponding command line argument, as
we do not have a use case for this attribute.

Signed-off-by: Sergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-26 04:40:22 +00:00
David Ahern 083e2706e1 Import wwan.h uapi file
Import wwan.h uapi file at version from last kernel headers sync.

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-26 04:39:47 +00:00
Stephen Hemminger 8316825a52 man: fix syntax for ip link property
The ip link property add/delete requires a device; but the
device argument was not show on the man page.
It is correct in the usage message.

Fixes: 3aa0e51be6 ("ip: add support for alternative name addition/deletion/list")
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-24 11:54:04 -07:00
Paolo Lungaroni 3e26254f31 seg6: add support for SRv6 End.DT46 Behavior
We introduce the new "End.DT46" action for supporting the SRv6 End.DT46
Behavior in iproute2.
The SRv6 End.DT46 Behavior, defined in RFC 8986 [1] section 4.8, can be
used to implement L3 VPNs based on Segment Routing over IPv6 networks in
multi-tenants environments and it is capable of handling both IPv4 and
IPv6 tenant traffic at the same time.
The SRv6 End.DT46 Behavior decapsulates the received packets and it
performs the IPv4 or IPv6 routing lookup in the routing table of the
tenant.

As for the End.DT4 and for the End.DT6 in VRF mode, the SRv6 End.DT46
Behavior leverages a VRF device in order to force the routing lookup into
the associated routing table using the "vrftable" attribute.

To make the End.DT46 work properly, it must be guaranteed that the
routing table used for routing lookup operations is bound to one and
only one VRF during the tunnel creation. Such constraint has to be
enforced by enabling the VRF strict_mode sysctl parameter, i.e.:

 $ sysctl -wq net.vrf.strict_mode=1

Note that the same approach is used for the End.DT4 Behavior and for the
End.DT6 Behavior in VRF mode.

An SRv6 End.DT46 Behavior instance can be created as follows:

 $ ip -6 route add 2001:db8::1 encap seg6local action End.DT46 vrftable 100 dev vrf100

Standard Output:
 $ ip -6 route show 2001:db8::1
 2001:db8::1  encap seg6local action End.DT46 vrftable 100 dev vrf100 metric 1024 pref medium

JSON Output:
$ ip -6 -j -p route show 2001:db8::1
[ {
        "dst": "2001:db8::1",
        "encap": "seg6local",
        "action": "End.DT46",
        "vrftable": 100,
        "dev": "vrf100",
        "metric": 1024,
        "flags": [ ],
        "pref": "medium"
} ]

This patch updates the route.8 man page and the ip route help with the
information related to End.DT46.
Considering that the same information was missing for the SRv6 End.DT4 and
the End.DT6 Behaviors, we have also added it.

[1] https://www.rfc-editor.org/rfc/rfc8986.html#name-enddt46-decapsulation-and-s

Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Signed-off-by: Paolo Lungaroni <paolo.lungaroni@uniroma2.it>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-22 15:36:17 +00:00
David Ahern 1d11326a57 Update kernel headers
Update kernel headers to commit:
    ef2c3ddaa4ed ("ibmvnic: Use strscpy() instead of strncpy()")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-22 15:33:45 +00:00
Guillaume Nault f8879e85f0 utils: bump max args number to 512 for batch files
Large tc filters can have many arguments. For example the following
filter matches the first 7 MPLS LSEs, pops all of them, then updates
the Ethernet header and redirects the resulting packet to eth1.

filter add dev eth0 ingress handle 44 priority 100 \
  protocol mpls_uc flower mpls                     \
    lse depth 1 label 1040076 tc 4 bos 0 ttl 175   \
    lse depth 2 label 89648 tc 2 bos 0 ttl 9       \
    lse depth 3 label 63417 tc 5 bos 0 ttl 185     \
    lse depth 4 label 593135 tc 5 bos 0 ttl 67     \
    lse depth 5 label 857021 tc 0 bos 0 ttl 181    \
    lse depth 6 label 239239 tc 1 bos 0 ttl 254    \
    lse depth 7 label 30 tc 7 bos 1 ttl 237        \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol mpls_uc pipe            \
  action mpls pop protocol ipv6 pipe               \
  action vlan pop_eth pipe                         \
  action vlan push_eth                             \
    dst_mac 00:00:5e:00:53:7e                      \
    src_mac 00:00:5e:00:53:03 pipe                 \
  action mirred egress redirect dev eth1

This filter has 149 arguments, so it can't be used with tc -batch
which is limited to a 100.

Let's bump the limit to 512. That should leave a lot of room for big
batch commands.

v2:
   -Define the limit in utils.h (Stephen Hemminger)
   -Bump the limit even higher (256 -> 512) (Stephen Hemminger)

Signed-off-by: Guillaume Nault <gnault@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-18 02:57:05 +00:00
Stephen Hemminger e1d3ac755d uapi: update kernel headers to 5.13-rc6
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-17 15:54:05 -07:00
David Ahern d8b3b9d32d Merge branch 'devlink-rate-support' into next
Dmytro Linkin says:

====================

Series implements devlink rate commands, which are:
- Dump particular or all rate objects (JSON or non-JSON)
- Add/Delete node rate object
- Set tx rate share/max values for rate object
- Set/Unset parent rate object for other rate object

Examples:

Display all rate objects:

    # devlink port function rate show
    pci/0000:03:00.0/1 type leaf parent some_group
    pci/0000:03:00.0/2 type leaf tx_share 12Mbit
    pci/0000:03:00.0/some_group type node tx_share 1Gbps tx_max 5Gbps

Display leaf rate object bound to the 1st devlink port of the
pci/0000:03:00.0 device:

    # devlink port function rate show pci/0000:03:00.0/1
    pci/0000:03:00.0/1 type leaf

Display node rate object with name some_group of the pci/0000:03:00.0
device:

    # devlink port function rate show pci/0000:03:00.0/some_group
    pci/0000:03:00.0/some_group type node

Display leaf rate object rate values using IEC units:

    # devlink -i port function rate show pci/0000:03:00.0/2
    pci/0000:03:00.0/2 type leaf 11718Kibit

Display pci/0000:03:00.0/2 leaf rate object as pretty JSON output:

    # devlink -jp port function rate show pci/0000:03:00.0/2
    {
        "rate": {
            "pci/0000:03:00.0/2": {
                "type": "leaf",
                "tx_share": 1500000
            }
        }
    }

Create node rate object with name "1st_group" on pci/0000:03:00.0 device:

    # devlink port function rate add pci/0000:03:00.0/1st_group

Create node rate object with specified parameters:

    # devlink port function rate add pci/0000:03:00.0/2nd_group \
        tx_share 10Mbit tx_max 30Mbit parent 1st_group

Set parameters to the specified leaf rate object:

    # devlink port function rate set pci/0000:03:00.0/1 \
        tx_share 2Mbit tx_max 10Mbit

Set leaf's parent to "1st_group":

    # devlink port function rate set pci/0000:03:00.0/1 parent 1st_group

Unset leaf's parent:

    # devlink port function rate set pci/0000:03:00.0/1 noparent

Delete node rate object:

    # devlink port function rate del pci/0000:03:00.0/2nd_group

Rate values can be specified in bits or bytes per second (bit|bps), with
any SI (k, m, g, t) or IEC (ki, mi, gi, ti) prefix. Bare number means
bits per second. Units also printed in "show" command output, but not
necessarily the same which were specified with "set" or "add" command.
-i/--iec switch force output in IEC units. JSON output always print
values as bytes per sec.

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-12 04:38:34 +00:00
Dmytro Linkin dedf895184 devlink: Add ISO/IEC switch
Add -i/--iec switch to print rate values using binary prefixes.
Update devlink(8) and devlink-rate(8) pages.

Signed-off-by: Dmytro Linkin <dlinkin@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-12 04:38:13 +00:00
Dmytro Linkin 6c70aca76e devlink: Add port func rate support
Implement user commands to manage devlink port func rate objects.
List all rate commands:

    $ devlink port func rate help

or just

    $ devlink port func rate

To list all OR particular rate object:

    $ devlink port func rate show
    pci/0000:03:00.0/some_group: type node
    pci/0000:03:00.0/0: type leaf
    pci/0000:03:00.0/1: type leaf

    $ devlink prot func rate show pci/0000:03:00.0/1
    pci/0000:03:00.0/0: type leaf

    $ devlink prot func rate show pci/0000:03:00.0/some_group
    pci/0000:03:00.0/some_group: type node

Rate object of type "leaf" created by it's driver where name is the name
of corresponding devlink port. Rate object of type "node" represents
rate group created by the user using commands:

    $ devlink port func rate add pci/0000:03:00.0/some_group

or with defining tx rate limits

    $ devlink port func rate add pci/0000:03:00.0/some_group \
        tx_shara 10kbit tx_max 100mbit

NOTE: node name cannot be a decimal value because it conflicts with
devlink port indexes.

To delete node object:

    $ devlink port func rate del pci/0000:03:00.0/some_group

Set rate limits of existing rate object:

    $ devlink prot func rate set pci/0000:03:00.0/0 \
        tx_share 5MBps tx_max 25GBps

    $ devlink prot func rate set pci/0000:03:00.0/some_group \
        tx_share 0

Both SET and ADD commands accept any units of rates defined in IEC
60027-2 standard.

NOTE: rate value 0 means that rate is unlimited. Such value is also
ommited in show command output.

NOTE: In SHOW command output rate values will be printed with suffixes
as well, but in JSON output they are always units of Bps.

Set or unset parent of existing rate object:

    $ devlink prot func rate set pci/0000:03:00.0/0 parent some_group

    $ devlink port func rate set pci/0000:03:00.0/0 noparent

NOTE: Setting parent to empty ("") name due to kernel logic means unset
parent and shouldn't be used to avoid unexpected parent unsets.

Signed-off-by: Dmytro Linkin <dlinkin@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-12 04:38:06 +00:00
Dmytro Linkin 95339955c5 devlink: Add helper function to validate object handler
Every handler argument validated in two steps, first of which, form
checking, expects identifier is few words separated by slashes.
For device and region handlers just checked if identifier have expected
number of slashes.
Add generic function to do that and make code cleaner & consistent.

Signed-off-by: Dmytro Linkin <dlinkin@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-12 04:37:21 +00:00
David Ahern 85903c9a29 Update kernel headers
Update kernel headers to commit:
    76cf404c40ae ("Merge branch 'ipa-mem-2'")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-11 02:38:23 +00:00
Parav Pandit fbd4b581cb devlink: Add optional controller user input
A user optionally provides the external controller number when user
wants to create devlink port for the external controller.

An example on eswitch system:
$ devlink dev eswitch set pci/0033:01:00.0 mode switchdev

$ devlink port show
pci/0033:01:00.0/196607: type eth netdev enP51p1s0f0np0 flavour physical port 0 splittable false
pci/0033:01:00.0/131072: type eth netdev eth0 flavour pcipf controller 1 pfnum 0 external true splittable false
  function:
    hw_addr 00:00:00:00:00:00

$ devlink port add pci/0033:01:00.0 flavour pcisf pfnum 0 sfnum 77 controller 1
pci/0033:01:00.0/163840: type eth netdev eth1 flavour pcisf controller 1 pfnum 0 sfnum 77 external true splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-11 02:28:49 +00:00
Roi Dayan 0d5cf51e0d police: Add support for json output
Change to use the print wrappers instead of fprintf().

This is example output of the options part before this commit:

        "options": {
            "handle": 1,
            "in_hw": true,
            "actions": [ {
                    "order": 1 police 0x2 ,
                    "control_action": {
                        "type": "drop"
                    },
                    "control_action": {
                        "type": "continue"
                    }overhead 0b linklayer unspec
        ref 1 bind 1
,
                    "used_hw_stats": [ "delayed" ]
                } ]
        }

This is the output of the same dump with this commit:

        "options": {
            "handle": 1,
            "in_hw": true,
            "actions": [ {
                    "order": 1,
                    "kind": "police",
                    "index": 2,
                    "control_action": {
                        "type": "drop"
                    },
                    "control_action": {
                        "type": "continue"
                    },
                    "overhead": 0,
                    "linklayer": "unspec",
                    "ref": 1,
                    "bind": 1,
                    "used_hw_stats": [ "delayed" ]
                } ]
        }

Signed-off-by: Roi Dayan <roid@nvidia.com>
Reviewed-by: Paul Blakey <paulb@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-11 02:28:36 +00:00
Eric Dumazet 52f136f640 tc: fq: add horizon attributes
Commit 39d010504e6b ("net_sched: sch_fq: add horizon attribute")
added kernel support for horizon attributes in linux-5.8

$ tc -s -d qd sh dev wlp2s0
qdisc fq 8006: root refcnt 2 limit 10000p flow_limit 100p buckets 1024 orphan_mask 1023 quantum 3028b initial_quantum 15140b low_rate_threshold 550Kbit refill_delay 40ms timer_slack 10us horizon 10s horizon_drop
 Sent 690924 bytes 3234 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  flows 112 (inactive 104 throttled 0)
  gc 0 highprio 0 throttled 2 latency 8.25us

$ tc qd change dev wlp2s0 root fq horizon 500ms horizon_cap

$ tc -s -d qd sh dev wlp2s0
qdisc fq 8006: root refcnt 2 limit 10000p flow_limit 100p buckets 1024 orphan_mask 1023 quantum 3028b initial_quantum 15140b low_rate_threshold 550Kbit refill_delay 40ms timer_slack 10us horizon 500ms horizon_cap
 Sent 831220 bytes 3844 pkt (dropped 0, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  flows 122 (inactive 120 throttled 0)
  gc 0 highprio 0 throttled 2 latency 8.25us

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-07 02:56:01 +00:00
Hangbin Liu 7ae2585b86 configure: convert LIBBPF environment variables to command-line options
Signed-off-by: Hangbin Liu <haliu@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-03 03:25:59 +00:00
Hangbin Liu a9c3d70d90 configure: add options ability
There are more and more global environment variables that land everywhere
in configure, which is making user hard to know which one does what.
Using command-line options would make it easier for users to learn or
remember the config options.

This patch converts the INCLUDE variable to command option first. Check
if the first variable has '-' to compile with the old INCLUDE path
setting method.

Signed-off-by: Hangbin Liu <haliu@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-06-03 03:25:11 +00:00
Roman Mashak 9d9b1a84a5 ss: update ss man page
'-b' option allows to request BPF filter opcodes, however
currently the kernel returns only classic BPF filter, so
reflect this in man page.

Signed-off-by: Roman Mashak <mrv@mojatatu.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-06-01 15:55:06 -07:00
Ariel Levkovich 825bd5dacb tc: f_flower: Add missing ct_state flags to usage description
Add ct_state flags rpl and inv to the commands usage
description

Signed-off-by: Ariel Levkovich <lariel@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-27 14:40:05 +00:00
Ariel Levkovich 7fda6c588a tc: f_flower: Add option to match on related ct state
Add support for matching on ct_state flag related.
The related state indicates a packet is associated with an existing
connection.

Example:
$ tc filter add dev ens1f0_0 ingress prio 1 chain 1 proto ip flower \
  ct_state -est-rel+trk \
  action mirred egress redirect dev ens1f0_1

$ tc filter add dev ens1f0_0 ingress prio 1 chain 1 proto ip flower \
  ct_state +rel+trk \
  action mirred egress redirect dev ens1f0_1

Signed-off-by: Ariel Levkovich <lariel@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-27 14:39:14 +00:00
Florian Westphal d3740fdc26 libgenl: make genl_add_mcast_grp set errno on error
genl_add_mcast_grp doesn't set errno in all cases.

On kernels that support mptcp but lack event support (all kernels <= 5.11)
MPTCP_PM_EV_GRP_NAME won't be found and ip will exit with

    "can't subscribe to mptcp events: Success"

Set errno to a meaningful value (ENOENT) when the group name isn't found
and also cover other spots where it returns nonzero with errno unset.

Fixes: ff619e4fd3 ("mptcp: add support for event monitoring")
Signed-off-by: Florian Westphal <fw@strlen.de>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-05-17 11:59:37 -07:00
Heiko Thiery c5b72cc56b lib/fs: fix issue when {name,open}_to_handle_at() is not implemented
With commit d5e6ee0dac the usage of functions name_to_handle_at() and
open_by_handle_at() are introduced. But these function are not available
e.g. in uclibc-ng < 1.0.35. To have a backward compatibility check for the
availability in the configure script and in case of absence do a direct
syscall.

Fixes: d5e6ee0dac ("ss: introduce cgroup2 cache and helper functions")
Cc: Dmitry Yakunin <zeil@yandex-team.ru>
Cc: Petr Vorel <petr.vorel@gmail.com>
Signed-off-by: Heiko Thiery <heiko.thiery@gmail.com>
Reviewed-by: Petr Vorel <petr.vorel@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-17 02:31:29 +00:00
David Ahern 62c88ed940 config.mk: Rerun configure when it is newer than config.mk
config.mk needs to be re-generated any time configure is changed.
Rename the existing make target and add a check that the config.mk
file needs to exist and must be newer than configure script.

Signed-off-by: David Ahern <dsahern@kernel.org>
Reviewed-by: Petr Vorel <petr.vorel@gmail.com>
Tested-by: Petr Vorel <petr.vorel@gmail.com>
2021-05-17 02:13:56 +00:00
Jakub Kicinski 49437375b6 ip: dynamically size columns when printing stats
This change makes ip -s -s output size the columns
automatically. I often find myself using json
output because the normal output is unreadable.
Even on a laptop after 2 days of uptime byte
and packet counters almost overflow their columns,
let alone a busy server.

For max readability switch to right align.

Before:

    RX: bytes  packets  errors  dropped missed  mcast
    8227918473 8617683  0       0       0       0
    RX errors: length   crc     frame   fifo    overrun
               0        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    691937917  4727223  0       0       0       0
    TX errors: aborted  fifo   window heartbeat transns
               0        0       0       0       10

After:

    RX:  bytes packets errors dropped  missed   mcast
    8228633710 8618408      0       0       0       0
    RX errors:  length    crc   frame    fifo overrun
                     0      0       0       0       0
    TX:  bytes packets errors dropped carrier collsns
     692006303 4727740      0       0       0       0
    TX errors: aborted   fifo  window heartbt transns
                     0      0       0       0      10

More importantly, with large values before:

    RX: bytes  packets  errors  dropped overrun mcast
    126570234447969 15016149200 0       0       0       0
    RX errors: length   crc     frame   fifo    missed
               0        0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    126570234447969 15016149200 0       0       0       0
    TX errors: aborted  fifo   window heartbeat transns
               0        0       0       0       10

Note that in this case we have full shift by a column,
e.g. the value under "dropped" is actually for "errors" etc.

After:

    RX:       bytes     packets errors dropped  missed   mcast
    126570234447969 15016149200      0       0       0       0
    RX errors:           length    crc   frame    fifo overrun
                              0      0       0       0       0
    TX:       bytes     packets errors dropped carrier collsns
    126570234447969 15016149200      0       0       0       0
    TX errors:          aborted   fifo  window heartbt transns
                              0      0       0       0      10

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:51:59 +00:00
Paolo Lungaroni 02ca3aabe9 seg6: add counters support for SRv6 Behaviors
We introduce the "count" optional attribute for supporting counters in SRv6
Behaviors as defined in [1], section 6. For each SRv6 Behavior instance,
counters defined in [1] are:

 - the total number of packets that have been correctly processed;
 - the total amount of traffic in bytes of all packets that have been
   correctly processed;

In addition, we introduce a new counter that counts the number of packets
that have NOT been properly processed (i.e. errors) by an SRv6 Behavior
instance.

Each SRv6 Behavior instance can be configured, at the time of its creation,
to make use of counters specifing the "count" attribute as follows:

 $ ip -6 route add 2001:db8::1 encap seg6local action End count dev eth0

per-behavior counters can be shown by adding "-s" to the iproute2 command
line, i.e.:

 $ ip -s -6 route show 2001:db8::1
 2001:db8::1 encap seg6local action End packets 0 bytes 0 errors 0 dev eth0

[1] https://www.rfc-editor.org/rfc/rfc8986.html#name-counters

v2:
 - add help and route.8 man page updates

Signed-off-by: Andrea Mayer <andrea.mayer@uniroma2.it>
Signed-off-by: Paolo Lungaroni <paolo.lungaroni@uniroma2.it>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:20:59 +00:00
Andrea Claudi e44786b269 tc: htb: improve burst error messages
When a wrong value is provided for "burst" or "cburst" parameters, the
resulting error message is unclear and can be misleading:

$ tc class add dev dummy0 parent 1: classid 1:1 htb rate 100KBps burst errtrigger
Illegal "buffer"

The message claims an illegal "buffer" is provided, but neither the
inline help nor the man page list "buffer" among the htb parameters, and
the only way to know that "burst", "maxburst" and "buffer" are synonyms
is to look into tc/q_htb.c.

This commit tries to improve this simply changing the error string to
the parameter name provided in the user-given command, clearly pointing
out where the wrong value is.

$ tc class add dev dummy0 parent 1: classid 1:1 htb rate 100KBps burst errtrigger
Illegal "burst"

$ tc class add dev dummy0 parent 1: classid 1:1 htb rate 100Kbps maxburst errtrigger
Illegal "maxburst"

Reported-by: Sebastian Mitterle <smitterl@redhat.com>
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:13:22 +00:00
Andrea Claudi 28ee49e515 tipc: bail out if key is abnormally long
tipc segfaults when called with an abnormally long key:

$ tipc node set key 0123456789abcdef0123456789abcdef0123456789abcdef
*** buffer overflow detected ***: terminated

Fix this returning an error if key length is longer than
TIPC_AEAD_KEYLEN_MAX.

Fixes: 24bee3bf97 ("tipc: add new commands to set TIPC AEAD key")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:08:47 +00:00
Andrea Claudi 93c267bfb4 tipc: bail out if algname is abnormally long
tipc segfaults when called with an abnormally long algname:

$ tipc node set key 0x1234 algname supercalifragilistichespiralidososupercalifragilistichespiralidoso
*** buffer overflow detected ***: terminated

Fix this returning an error if provided algname is longer than
TIPC_AEAD_ALG_NAME.

Fixes: 24bee3bf97 ("tipc: add new commands to set TIPC AEAD key")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:08:47 +00:00
Hoang Le 459f280813 tipc: call a sub-routine in separate socket
When receiving a result from first query to netlink, we may exec
a another query inside the callback. If calling this sub-routine
in the same socket, it will be discarded the result from previous
exection.
To avoid this we perform a nested query in separate socket.

Fixes: 2021028306 ("tipc: use the libmnl functions in lib/mnl_utils.c")
Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au>
Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-09 22:08:47 +00:00
Tyson Moore 0d95472a4b tc-cake: update docs to include LE diffserv
Linux kernel commit b8392808eb3fc28e ("sch_cake: add RFC 8622 LE PHB
support to CAKE diffserv handling") added packets with LE diffserv to
the Bulk priority tin. Update the documentation to reflect this change.

Signed-off-by: Tyson Moore <tyson@tyson.me>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:59:52 +00:00
Andrea Claudi 2d212aae55 dcb: fix memory leak
main() dinamically allocates dcb, but when dcb_help() is called it
returns without freeing it.

Fix this using a goto, as it is already done in the same function.

Fixes: 67033d1c1c ("Add skeleton of a new tool, dcb")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Reviewed-by: Petr Machata <me@pmachata.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:48:02 +00:00
Andrea Claudi cfd89a6f8b dcb: fix return value on dcb_cmd_app_show
dcb_cmd_app_show() is supposed to return EINVAL if an incorrect argument
is provided.

Fixes: 8e9bed1493 ("dcb: Add a subtool for the DCB APP object")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Reviewed-by: Petr Machata <me@pmachata.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:47:57 +00:00
Andrea Claudi 3296d4fe77 lib: bpf_legacy: avoid to pass invalid argument to close()
In function bpf_obj_open, if bpf_fetch_prog_arg() return an error, we
end up in the out: path with a negative value for fd, and pass it to
close.

Avoid this checking for fd to be positive.

Fixes: 32e93fb7f6 ("{f,m}_bpf: allow for sharing maps")
Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:43:54 +00:00
Andrea Claudi a2f1f66075 tc: q_ets: drop dead code from argument parsing
Checking for nbands to be at least 1 at this point is useless. Indeed:
- ets requires "bands", "quanta" or "strict" to be specified
- if "bands" is specified, nbands cannot be negative, see parse_nbands()
- if "strict" is specified, nstrict cannot be negative, see
  parse_nbands()
- if "quantum" is specified, nquanta cannot be negative, see
  parse_quantum()
- if "bands" is not specified, nbands is set to nstrict+nquanta
- the previous if statement takes care of the case when none of them are
  specified and nbands is 0, terminating execution.

Thus nbands cannot be < 1 at this point and this code cannot be executed.

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:42:44 +00:00
Jakub Kicinski 570d2cf0ec ip: align the name of the 'nohandler' stat
Before:

    RX: bytes  packets  errors  dropped missed  mcast
    8848233056 8548168  0       0       0       0
    RX errors: length   crc     frame   fifo    overrun   nohandler
               0        0       0       0       0       101
    TX: bytes  packets  errors  dropped carrier collsns compressed
    1142925945 4683483  0       0       0       0       101
    TX errors: aborted  fifo   window heartbeat transns
               0        0       0       0       14

After:

    RX: bytes  packets  errors  dropped missed  mcast
    8848297833 8548461  0       0       0       0
    RX errors: length   crc     frame   fifo    overrun nohandler
               0        0       0       0       0       101
    TX: bytes  packets  errors  dropped carrier collsns compressed
    1143049820 4683865  0       0       0       0       101
    TX errors: aborted  fifo   window heartbeat transns
               0        0       0       0       14

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:41:19 +00:00
David Ahern c3f852754f Update kernel headers
Update kernel headers to commit:
    8621436671f3 ("smc: disallow TCP_ULP in smc_setsockopt()")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-06 14:16:04 +00:00
David Ahern c79fcefaaf Merge branch 'rdma-copy-on-fork' into next
Gal Pressman  says:

====================

This is the userspace part for the new copy-on-fork attribute added to
the get sys netlink command.

The new attribute indicates that the kernel copies DMA pages on fork,
hence fork support through madvise and MADV_DONTFORK is not needed.

Kernel series was merged:
https://lore.kernel.org/linux-rdma/20210418121025.66849-1-galpress@amazon.com/

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-03 14:45:19 +00:00
Gal Pressman bce4247869 rdma: Add copy-on-fork to get sys command
The new attribute indicates that the kernel copies DMA pages on fork,
hence fork support through madvise and MADV_DONTFORK is not needed.

If the attribute is not reported (expected on older kernels),
copy-on-fork is disabled.

Example:
$ rdma sys
netns shared copy-on-fork on

Signed-off-by: Gal Pressman <galpress@amazon.com>
Acked-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-03 14:43:13 +00:00
Gal Pressman 212e2c1d0c rdma: update uapi headers
Update rdma_netlink.h file upto kernel commit
6cc9e215eb27 ("RDMA/nldev: Add copy-on-fork attribute to get sys command")

Signed-off-by: Gal Pressman <galpress@amazon.com>
Acked-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-05-03 14:43:06 +00:00
Jianguo Wu 7f1d58d1a1 mptcp: make sure flag signal is set when add addr with port
When add address with port, it is mean to send an ADD_ADDR to remote,
so it must have flag signal set.

Fixes: 42fbca91cd ("mptcp: add support for port based endpoint")
Signed-off-by: Jianguo Wu <wujianguo@chinatelecom.cn>
Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-30 14:30:24 +00:00
David Ahern e1e089d1f2 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:48:28 +00:00
Jethro Beekman d56dcd3549 ip: Add nodst option to macvlan type source
The default behavior for source MACVLAN is to duplicate packets to
appropriate type source devices, and then do the normal destination MACVLAN
flow. This patch adds an option to skip destination MACVLAN processing if
any matching source MACVLAN device has the option set.

This allows setting up a "catch all" device for source MACVLAN: create one
or more devices with type source nodst, and one device with e.g. type vepa,
and incoming traffic will be received on exactly one device.

Signed-off-by: Jethro Beekman <kernel@jbeekman.nl>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:45:59 +00:00
David Ahern e5f1505e53 Merge branch 'rdma-resource-tracking' into next
Leon Romanovsky  says:

====================

This is the user space part of already accepted to the kernel series
that extends RDMA netlink interface to return uverbs context and SRQ
information.

The accepted kernel series can be seen here:
https://lore.kernel.org/linux-rdma/20210422133459.GA2390260@nvidia.com/

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:37:32 +00:00
Neta Ostrovsky 9b272e138d rdma: Add SRQ resource tracking information
Sample output:

$ rdma res show srq
dev ibp8s0f0 srqn 0 type BASIC pdn 3 comm [ib_ipoib]
dev ibp8s0f0 srqn 4 type BASIC lqpn 125-128,130-140 pdn 9 pid 3581 comm ibv_srq_pingpon
dev ibp8s0f0 srqn 5 type BASIC lqpn 141-156 pdn 10 pid 3584 comm ibv_srq_pingpon
dev ibp8s0f0 srqn 6 type BASIC lqpn 157-172 pdn 11 pid 3590 comm ibv_srq_pingpon
dev ibp8s0f1 srqn 0 type BASIC pdn 3 comm [ib_ipoib]
dev ibp8s0f1 srqn 1 type BASIC lqpn 329-344 pdn 4 pid 3586 comm ibv_srq_pingpon

$ rdma res show srq lqpn 126-141
dev ibp8s0f0 srqn 4 type BASIC lqpn 126-128,130-140 pdn 9 pid 3581 comm ibv_srq_pingpon
dev ibp8s0f0 srqn 5 type BASIC lqpn 141 pdn 10 pid 3584 comm ibv_srq_pingpon

$ rdma res show srq lqpn 127
dev ibp8s0f0 srqn 4 type BASIC lqpn 127 pdn 9 pid 3581 comm ibv_srq_pingpon

Reviewed-by: Ido Kalir <idok@nvidia.com>
Reviewed-by: Mark Zhang <markz@mellanox.com>
Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:37:16 +00:00
Neta Ostrovsky 4278941285 rdma: Add context resource tracking information
Sample output:

$ rdma res show ctx
dev ibp8s0f0 ctxn 0 pid 980 comm ibv_rc_pingpong
dev ibp8s0f0 ctxn 1 pid 981 comm ibv_rc_pingpong
dev ibp8s0f0 ctxn 2 pid 992 comm ibv_rc_pingpong
dev ibp8s0f1 ctxn 0 pid 984 comm ibv_rc_pingpong
dev ibp8s0f1 ctxn 1 pid 987 comm ibv_rc_pingpong

$ rdma res show ctx dev ibp8s0f1
dev ibp8s0f1 ctxn 0 pid 984 comm ibv_rc_pingpong
dev ibp8s0f1 ctxn 1 pid 987 comm ibv_rc_pingpong

Reviewed-by: Mark Zhang <markz@mellanox.com>
Reviewed-by: Ido Kalir <idok@nvidia.com>
Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:36:59 +00:00
Neta Ostrovsky 4c61b5b9df rdma: Update uapi headers
Update rdma_netlink.h file upto kernel commit c6c11ad3ab9f
("RDMA/nldev: Add QP numbers to SRQ information")

Reviewed-by: Mark Zhang <markz@mellanox.com>
Signed-off-by: Neta Ostrovsky <netao@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:36:21 +00:00
David Ahern a5ea744ca2 Update kernel headers
Update kernel headers to commit:
    99ba0ea616aa ("sfc: adjust efx->xdp_tx_queue_count with the real number of initialized queues")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-28 15:35:30 +00:00
Stephen Hemminger 2363bc99f9 Merge git://git.kernel.org/pub/scm/network/iproute2/iproute2-next
Required manual fix of devlink/devlink.c

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
2021-04-27 19:39:39 -07:00
Nikolay Aleksandrov c72de3713d bridge: vlan: dump port only if there are any vlans
When I added support for new vlan rtm dumping, I made a mistake in the
output format when there are no vlans on the port. This patch fixes it by
not printing ports without vlan entries (similar to current situation).

Example (no vlans):
$ bridge -d vlan show
port              vlan-id

Fixes: e5f87c8341 ("bridge: vlan: add support for the new rtm dump call")
Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-26 02:32:46 +00:00
Tony Ambardar e705b19d48 ip: drop 2-char command assumption
The 'ip' utility hardcodes the assumption of being a 2-char command, where
any follow-on characters are passed as an argument:

  $ ./ip-full help
  Object "-full" is unknown, try "ip help".

This confusing behaviour isn't seen with 'tc' for example, and was added in
a 2005 commit without documentation. It was noticed during testing of 'ip'
variants built/packaged with different feature sets (e.g. w/o BPF support).

Mitigate the problem by redoing the command without the 2-char assumption
if the follow-on characters fail to parse as a valid command.

Fixes: 351efcde4e ("Update header files to 2.6.14")
Signed-off-by: Tony Ambardar <Tony.Ambardar@gmail.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-26 02:29:42 +00:00
Andrea Claudi 81bfd01a4c lib: move get_task_name() from rdma
The function get_task_name() is used to get the name of a process from
its pid, and its implementation is similar to ip/iptuntap.c:pid_name().

Move it to lib/fs.c to use a single implementation and make it easily
reusable.

Signed-off-by: Andrea Claudi <aclaudi@redhat.com>
Acked-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:22:16 +00:00
David Ahern 75a35d50a3 Merge branch 'bridge-vlan' into next
Nikolay Aleksandrov  says:

====================

From: Nikolay Aleksandrov <nikolay@nvidia.com>

This set extends the bridge vlan code to use the new vlan RTM calls
which allow to dump detailed per-port, per-vlan information and also to
manipulate the per-vlan options. It also allows to monitor any vlan
changes (add/del/option change). The rtm vlan dumps have an extensible
format which allows us to add new options and attributes easily, and
also to request the kernel to filter on different vlan information when
dumping. The new kernel dump code tries to use compressed vlan format as
much as possible (it includes netlink attributes for vlan start and
end) to reduce the number of generated messages and netlink traffic.
The iproute2 support is activated by using the "-d" flag when showing
vlan information, that will cause it to use the new rtm dump call and
get all the detailed information, if "-s" is also specified it will dump
per-vlan statistics as well. Obviously in that case the vlans cannot be
compressed. To change per-vlan options (currently only STP state is
supported) a new vlan command is added - "set". It can be used to set
options of bridge or port vlans and vlan ranges can be used, all of the
new vlan option code uses extack to show more understandable errors.
The set adds the first supported per-vlan option - STP state.
Man pages and usage information are updated accordingly.

Example:
 $ bridge -d vlan show
 port              vlan-id
 ens13             1 PVID Egress Untagged
                     state forwarding
 bridge            1 PVID Egress Untagged
                     state forwarding

 $ bridge vlan set vid 1 dev ens13 state blocking
 $ bridge -d vlan show
 port              vlan-id
 ens13             1 PVID Egress Untagged
                     state blocking
 bridge            1 PVID Egress Untagged
                     state forwarding

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:20:13 +00:00
Nikolay Aleksandrov c311404780 bridge: monitor: add support for vlan monitoring
Add support for vlan activity monitoring, we display vlan notifications on
vlan add/del/options change. The man page and help are also updated
accordingly.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:39 +00:00
Nikolay Aleksandrov e5f87c8341 bridge: vlan: add support for the new rtm dump call
Use the new bridge vlan rtm dump helper to dump all of the available
vlan information when -details (-d) is used with vlan show. It is also
capable of dumping vlan stats if -statistics (-s) is added.
Currently this is the only interface capable of dumping per-vlan
options. The vlan dump format is compatible with current vlan show, it
uses the same helpers to dump vlan information. The new addition is one
line which will contain the per-vlan options (similar to ip -d link show
for ports). Currently only the vlan STP state is printed.
The call uses compressed vlan format by default.

Example:
$ bridge -s -d vlan show
port              vlan-id
virbr1            1 PVID Egress Untagged
                    state forwarding

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:34 +00:00
Nikolay Aleksandrov 34c14bea22 libnetlink: add bridge vlan dump request helper
Add rtnl bridge vlan dump request helper which will be used to retrieve
bridge vlan information and options.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:29 +00:00
Nikolay Aleksandrov 04e2783d5e bridge: vlan: add option set command and state option
Add a new per-vlan option set command. It allows to manipulate vlan
options, those can be bridge-wide or per-port depending on what device
is specified. The first option that can be set is the vlan STP state,
it is identical to the bridge port STP state. The man page is also
updated accordingly.

Example:
 $ bridge vlan set vid 10 dev br0 state learning
or a range:
 $ bridge vlan set vid 10-20 dev swp1 state blocking

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:24 +00:00
Nikolay Aleksandrov f2f52fcabe bridge: add parse_stp_state helper
Add a helper which parses an STP state string to its numeric value.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:20 +00:00
Nikolay Aleksandrov f07516c3b0 bridge: rename and export print_portstate
Rename print_portstate to print_stp_state in preparation for use by vlan
code as well (per-vlan state), and export it. To be in line with the new
naming rename also port_states to stp_states as they'll be used for
vlans, too.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:13:09 +00:00
Florian Westphal ff619e4fd3 mptcp: add support for event monitoring
This adds iproute2 support for mptcp event monitoring, e.g. creation,
establishment, address announcements from the peer, subflow establishment
and so on.

While the kernel-generated events are primarily aimed at mptcpd (e.g. for
subflow management), this is also useful for debugging.

This adds print support for the existing events.

Sample output of 'ip mptcp monitor':
[       CREATED] token=83f3a692 remid=0 locid=0 saddr4=10.0.1.2 daddr4=10.0.1.1 sport=58710 dport=10011
[   ESTABLISHED] token=83f3a692 remid=0 locid=0 saddr4=10.0.1.2 daddr4=10.0.1.1 sport=58710 dport=10011
[SF_ESTABLISHED] token=83f3a692 remid=0 locid=1 saddr4=10.0.2.2 daddr4=10.0.1.1 sport=40195 dport=10011 backup=0
[        CLOSED] token=83f3a692

Signed-off-by: Florian Westphal <fw@strlen.de>
2021-04-22 05:10:25 +00:00
David Ahern 98040c2dc1 Update kernel headers
Update kernel headers to commit:
    5d869070569a ("net: phy: marvell: don't use empty switch default case")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-22 05:09:39 +00:00
Chunmei Xu 44b563269e ip-nexthop: support flush by id
since id is unique for nexthop, it is heavy to dump all nexthops.
use existing delete_nexthop to support flush by id

Signed-off-by: Chunmei Xu <xuchunmei@linux.alibaba.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Tested-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-08 15:38:58 +00:00
Hoang Le 2021028306 tipc: use the libmnl functions in lib/mnl_utils.c
To avoid code duplication, tipc should be converted to use the helper
functions for working with libmnl in lib/mnl_utils.c

Acked-by: Jon Maloy <jmaloy@redhat.com>
Signed-off-by: Hoang Le <hoang.h.le@dektech.com.au>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-04-03 01:10:54 +00:00
Baowen Zheng cf9ae1bd31 police: add support for packet-per-second rate limiting
Allow a policer action to enforce a rate-limit based on packets-per-second,
configurable using a packet-per-second rate and burst parameters.

e.g.
 # $TC actions add action police pkts_rate 1000 pkts_burst 200 index 1
 # $TC actions ls action police
 total acts 1

	action order 0:  police 0x1 rate 0bit burst 0b mtu 4096Mb pkts_rate 1000 pkts_burst 200
	ref 1 bind 0

Signed-off-by: Baowen Zheng <baowen.zheng@corigine.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Louis Peens <louis.peens@netronome.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-30 03:04:50 +00:00
Cooper Lees 16430e9afd Add Open/R to rt_protos
- Open Routing is using ID 99 for it's installed routes
- https://github.com/facebook/openr
- Kernel has accepted 99 in `rtnetlink.h`

Signed-of-by: Cooper Lees <me@cooperlees.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-30 03:04:09 +00:00
David Ahern 76bfc185f2 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-21 17:16:01 +00:00
Sabrina Dubroca 3c75135835 ip: xfrm: add support for tfcpad
This patch adds support for setting and displaying the Traffic Flow
Confidentiality attribute for an XFRM state, which allows padding ESP
packets to a specified length.

Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-21 17:15:07 +00:00
David Ahern fa505da84b Merge branch 'nexthop-resilient-hash' into next
Petr Machata  says:

====================

Support for resilient next-hop groups was recently accepted to Linux
kernel[1]. Resilient next-hop groups add a layer of indirection between the
SKB hash and the next hop. Thus the hash is used to reference a hash table
bucket, which is then used to reference a particular next hop. This allows
the system more flexibility when assigning SKB hash space to next hops.
Previously, each next hop had to be assigned a continuous range of SKB hash
space. With a hash table as an intermediate layer, it is possible to
reassign next hops with a hash table bucket granularity. In turn, this
mends issues with traffic flow redirection resulting from next hop removal
or adjustments in next-hop weights.

In this patch set, introduce support for resilient next-hop groups to
iproute2.

- Patch #1 brings include/uapi/linux/nexthop.h and /rtnetlink.h up to date.

- Patches #2 and #3 add new helpers that will be useful later.

- Patch #4 extends the ip/nexthop sub-tool to accept group type as a
  command line argument, and to dispatch based on the specified type.

- Patch #5 adds the support for resilient next-hop groups.

- Patch #6 adds the support for resilient next-hop group bucket interface.

To illustrate the usage, consider the following commands:

 # ip nexthop add id 1 via 192.0.2.2 dev dummy1
 # ip nexthop add id 2 via 192.0.2.3 dev dummy1
 # ip nexthop add id 10 group 1/2 type resilient \
	buckets 8 idle_timer 60 unbalanced_timer 300

The last command creates a resilient next-hop group. It will have 8
buckets, each bucket will be considered idle when no traffic hits it for at
least 60 seconds, and if the table remains out of balance for 300 seconds,
it will be forcefully brought into balance.

And this is how the next-hop group bucket interface looks:

 # ip nexthop bucket show id 10
 id 10 index 0 idle_time 5.59 nhid 1
 id 10 index 1 idle_time 5.59 nhid 1
 id 10 index 2 idle_time 8.74 nhid 2
 id 10 index 3 idle_time 8.74 nhid 2
 id 10 index 4 idle_time 8.74 nhid 1
 id 10 index 5 idle_time 8.74 nhid 1
 id 10 index 6 idle_time 8.74 nhid 1
 id 10 index 7 idle_time 8.74 nhid 1

[1] https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=2a0186a37700b0d5b8cc40be202a62af44f02fa2

====================

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:05:29 +00:00
Ido Schimmel 2be6d18b30 nexthop: Add support for nexthop buckets
Add ability to dump multiple nexthop buckets and get a specific one.
Example:

 # ip nexthop add id 10 group 1/2 type resilient buckets 8
 # ip nexthop
 id 1 via 192.0.2.2 dev dummy10 scope link
 id 2 via 192.0.2.19 dev dummy20 scope link
 id 10 group 1/2 type resilient buckets 8 idle_timer 120 unbalanced_timer 0 unbalanced_time 0
 # ip nexthop bucket
 id 10 index 0 idle_time 28.1 nhid 2
 id 10 index 1 idle_time 28.1 nhid 2
 id 10 index 2 idle_time 28.1 nhid 2
 id 10 index 3 idle_time 28.1 nhid 2
 id 10 index 4 idle_time 28.1 nhid 1
 id 10 index 5 idle_time 28.1 nhid 1
 id 10 index 6 idle_time 28.1 nhid 1
 id 10 index 7 idle_time 28.1 nhid 1
 # ip nexthop bucket show nhid 1
 id 10 index 4 idle_time 53.59 nhid 1
 id 10 index 5 idle_time 53.59 nhid 1
 id 10 index 6 idle_time 53.59 nhid 1
 id 10 index 7 idle_time 53.59 nhid 1
 # ip nexthop bucket get id 10 index 5
 id 10 index 5 idle_time 81 nhid 1
 # ip -j -p nexthop bucket get id 10 index 5
 [ {
         "id": 10,
         "bucket": {
             "index": 5,
             "idle_time": 104.89,
             "nhid": 1
         },
         "flags": [ ]
     } ]

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:01:25 +00:00
Ido Schimmel 9167671822 nexthop: Add support for resilient nexthop groups
Add ability to configure resilient nexthop groups and show their current
configuration. Example:

 # ip nexthop add id 10 group 1/2 type resilient buckets 8
 # ip nexthop show id 10
 id 10 group 1/2 type resilient buckets 8 idle_timer 120 unbalanced_timer 0
 # ip -j -p nexthop show id 10
 [ {
         "id": 10,
         "group": [ {
                 "id": 1
             },{
                 "id": 2
             } ],
         "type": "resilient",
         "resilient_args": {
             "buckets": 8,
             "idle_timer": 120,
             "unbalanced_timer": 0
         },
         "flags": [ ]
     } ]

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:01:18 +00:00
Ido Schimmel b82d6b81fa nexthop: Add ability to specify group type
Next patches are going to add a 'resilient' nexthop group type, so allow
users to specify the type using the 'type' argument. Currently, only
'mpath' type is supported.

These two commands are equivalent:

 # ip nexthop add id 10 group 1/2/3
 # ip nexthop add id 10 group 1/2/3 type mpath

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:00:49 +00:00
Petr Machata 28fb925d8b nexthop: Extract a helper to parse a NH ID
NH ID extraction is a common operation, and will become more common still
with the resilient NH groups support. Add a helper that does what it
usually done and returns the parsed NH ID.

Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:00:43 +00:00
Petr Machata e757f741e9 json_print: Add print_tv()
Add a helper to dump a timeval. Print by first converting to double and
then dispatching to print_color_float().

Signed-off-by: Petr Machata <petrm@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 15:00:08 +00:00
David Ahern a5b355c08c Update kernel headers
Update kernel headers to commit:
    38cb57602369 ("selftests: net: forwarding: Fix a typo")

Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-19 14:59:17 +00:00
David Ahern 27ca8989c1 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-15 15:08:01 +00:00
Parav Pandit c54e7bd605 devlink: Add error print when unknown values specified
When user specifies either unknown flavour or unknown state during
devlink port commands, return appropriate error message.

Signed-off-by: Parav Pandit <parav@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-03 04:00:16 +00:00
Parav Pandit 62ff25e51b devlink: Use generic socket helpers from library
User generic socket helpers from library for netlink generic socket
access.

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-03 04:00:10 +00:00
Parav Pandit e3a4067e52 utils: Introduce helper routines for generic socket recv
Introduce helper for generic socket receive helper and introduce helper
to build command with custom family and version.

Use API in subsequent devlink patch.

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-03 04:00:04 +00:00
Parav Pandit 03662000e4 devlink: Use library provided string processing APIs
User helper routines provided by library for counting slash and
splitting string on delimiter.

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-03 03:59:58 +00:00
Paolo Abeni 42fbca91cd mptcp: add support for port based endpoint
The feature is supported by the kernel since 5.11-net-next,
let's allow user-space to use it.

Just parse and dump an additional, per endpoint, u16 attribute

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-01 00:15:10 +00:00
David Ahern 455c9f5361 Merge branch 'main' into next
Signed-off-by: David Ahern <dsahern@kernel.org>
2021-03-01 00:07:57 +00:00
198 changed files with 9203 additions and 1853 deletions

View File

@ -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 @@ MAKEFLAGS += --no-print-directory
endif
PREFIX?=/usr
LIBDIR?=$(PREFIX)/lib
SBINDIR?=/sbin
CONFDIR?=/etc/iproute2
NETNS_RUN_DIR?=/var/run/netns
@ -40,9 +41,18 @@ DEFINES+=-DCONFDIR=\"$(CONFDIR)\" \
-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
@ -81,7 +91,9 @@ help:
@echo " V=[0|1] - set build verbosity level"
config.mk:
sh configure $(KERNEL_INCLUDE)
@if [ ! -f config.mk -o configure -nt config.mk ]; then \
sh configure $(KERNEL_INCLUDE); \
fi
install: all
install -m 0755 -d $(DESTDIR)$(SBINDIR)

View File

@ -10,6 +10,11 @@ void print_vlan_info(struct rtattr *tb, int ifindex);
int print_linkinfo(struct nlmsghdr *n, void *arg);
int print_mdb_mon(struct nlmsghdr *n, void *arg);
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,
bool global_only);
void br_print_router_port_stats(struct rtattr *pattr);
int do_fdb(int argc, char **argv);
int do_mdb(int argc, char **argv);

View File

@ -37,10 +37,10 @@ static void usage(void)
fprintf(stderr,
"Usage: bridge [ OPTIONS ] OBJECT { COMMAND | help }\n"
" bridge [ -force ] -batch filename\n"
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
" -c[ompressvlans] -color -p[retty] -j[son] }\n");
"where OBJECT := { link | fdb | mdb | vlan | monitor }\n"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] |\n"
" -o[neline] | -t[imestamp] | -n[etns] name |\n"
" -c[ompressvlans] -color -p[retty] -j[son] }\n");
exit(-1);
}
@ -149,9 +149,9 @@ main(int argc, char **argv)
NEXT_ARG();
if (netns_switch(argv[1]))
exit(-1);
} else if (matches_color(opt, &color)) {
} else if (matches(opt, "-compressvlans") == 0) {
++compress_vlans;
} else if (matches_color(opt, &color)) {
} else if (matches(opt, "-force") == 0) {
++force;
} else if (matches(opt, "-json") == 0) {

View File

@ -192,10 +192,13 @@ int print_fdb(struct nlmsghdr *n, void *arg)
"mac", "%s ", lladdr);
}
if (!filter_index && r->ndm_ifindex)
if (!filter_index && r->ndm_ifindex) {
print_string(PRINT_FP, NULL, "dev ", NULL);
print_color_string(PRINT_ANY, COLOR_IFNAME,
"ifname", "dev %s ",
"ifname", "%s ",
ll_index_to_name(r->ndm_ifindex));
}
if (tb[NDA_DST]) {
int family = AF_INET;
@ -208,9 +211,11 @@ int print_fdb(struct nlmsghdr *n, void *arg)
RTA_PAYLOAD(tb[NDA_DST]),
RTA_DATA(tb[NDA_DST]));
print_string(PRINT_FP, NULL, "dst ", NULL);
print_color_string(PRINT_ANY,
ifa_family_color(family),
"dst", "dst %s ", dst);
"dst", "%s ", dst);
}
if (vid)

View File

@ -19,7 +19,7 @@
static unsigned int filter_index;
static const char *port_states[] = {
static const char *stp_states[] = {
[BR_STATE_DISABLED] = "disabled",
[BR_STATE_LISTENING] = "listening",
[BR_STATE_LEARNING] = "learning",
@ -68,16 +68,31 @@ static void print_link_flags(FILE *fp, unsigned int flags, unsigned int mdown)
close_json_array(PRINT_ANY, "> ");
}
static void print_portstate(__u8 state)
void print_stp_state(__u8 state)
{
if (state <= BR_STATE_BLOCKING)
print_string(PRINT_ANY, "state",
"state %s ", port_states[state]);
"state %s ", stp_states[state]);
else
print_uint(PRINT_ANY, "state",
"state (%d) ", state);
}
int parse_stp_state(const char *arg)
{
size_t nstates = ARRAY_SIZE(stp_states);
int state;
for (state = 0; state < nstates; state++)
if (strcmp(stp_states[state], arg) == 0)
break;
if (state == nstates)
state = -1;
return state;
}
static void print_hwmode(__u16 mode)
{
if (mode >= ARRAY_SIZE(hw_mode))
@ -96,7 +111,7 @@ static void print_protinfo(FILE *fp, struct rtattr *attr)
parse_rtattr_nested(prtb, IFLA_BRPORT_MAX, attr);
if (prtb[IFLA_BRPORT_STATE])
print_portstate(rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
print_stp_state(rta_getattr_u8(prtb[IFLA_BRPORT_STATE]));
if (prtb[IFLA_BRPORT_PRIORITY])
print_uint(PRINT_ANY, "priority",
@ -161,7 +176,7 @@ static void print_protinfo(FILE *fp, struct rtattr *attr)
print_on_off(PRINT_ANY, "isolated", "isolated %s ",
rta_getattr_u8(prtb[IFLA_BRPORT_ISOLATED]));
} else
print_portstate(rta_getattr_u8(attr));
print_stp_state(rta_getattr_u8(attr));
}
@ -359,14 +374,11 @@ static int brlink_modify(int argc, char **argv)
} else if (strcmp(*argv, "state") == 0) {
NEXT_ARG();
char *endptr;
size_t nstates = ARRAY_SIZE(port_states);
state = strtol(*argv, &endptr, 10);
if (!(**argv != '\0' && *endptr == '\0')) {
for (state = 0; state < nstates; state++)
if (strcasecmp(port_states[state], *argv) == 0)
break;
if (state == nstates) {
state = parse_stp_state(*argv);
if (state == -1) {
fprintf(stderr,
"Error: invalid STP port state\n");
return -1;

View File

@ -16,9 +16,9 @@
#include <arpa/inet.h>
#include "libnetlink.h"
#include "utils.h"
#include "br_common.h"
#include "rt_names.h"
#include "utils.h"
#include "json_print.h"
#ifndef MDBA_RTA
@ -59,7 +59,7 @@ static const char *format_timer(__u32 ticks, int align)
return tbuf;
}
static void __print_router_port_stats(FILE *f, struct rtattr *pattr)
void br_print_router_port_stats(struct rtattr *pattr)
{
struct rtattr *tb[MDBA_ROUTER_PATTR_MAX + 1];
@ -101,13 +101,13 @@ static void br_print_router_ports(FILE *f, struct rtattr *attr,
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);

View File

@ -31,7 +31,7 @@ static int prefix_banner;
static void usage(void)
{
fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | all]\n");
fprintf(stderr, "Usage: bridge monitor [file | link | fdb | mdb | vlan | all]\n");
exit(-1);
}
@ -67,6 +67,12 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
print_nlmsg_timestamp(fp, n);
return 0;
case RTM_NEWVLAN:
case RTM_DELVLAN:
if (prefix_banner)
fprintf(fp, "[VLAN]");
return print_vlan_rtm(n, arg, true, false);
default:
return 0;
}
@ -79,6 +85,7 @@ int do_monitor(int argc, char **argv)
int llink = 0;
int lneigh = 0;
int lmdb = 0;
int lvlan = 0;
rtnl_close(&rth);
@ -95,8 +102,12 @@ int do_monitor(int argc, char **argv)
} else if (matches(*argv, "mdb") == 0) {
lmdb = 1;
groups = 0;
} else if (matches(*argv, "vlan") == 0) {
lvlan = 1;
groups = 0;
} else if (strcmp(*argv, "all") == 0) {
groups = ~RTMGRP_TC;
lvlan = 1;
prefix_banner = 1;
} else if (matches(*argv, "help") == 0) {
usage();
@ -134,6 +145,12 @@ int do_monitor(int argc, char **argv)
if (rtnl_open(&rth, groups) < 0)
exit(1);
if (lvlan && rtnl_add_nl_group(&rth, RTNLGRP_BRVLAN) < 0) {
fprintf(stderr, "Failed to add bridge vlan group to list\n");
exit(1);
}
ll_init_map(&rth);
if (rtnl_listen(&rth, accept_msg, stdout) < 0)

View File

@ -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"
@ -16,6 +17,7 @@
#include "utils.h"
static unsigned int filter_index, filter_vlan;
static int vlan_rtm_cur_ifidx = -1;
enum vlan_show_subject {
VLAN_SHOW_VLAN,
@ -33,8 +35,24 @@ static void usage(void)
"Usage: bridge vlan { add | del } vid VLAN_ID dev DEV [ tunnel_info id TUNNEL_ID ]\n"
" [ 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);
}
@ -241,6 +259,277 @@ static int vlan_modify(int cmd, int argc, char **argv)
return 0;
}
static int vlan_option_set(int argc, char **argv)
{
struct {
struct nlmsghdr n;
struct br_vlan_msg bvm;
char buf[1024];
} 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 bridge_vlan_info vinfo = {};
struct rtattr *afspec;
char *d = NULL;
short vid = -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();
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;
}
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);
if (!(**argv != '\0' && *endptr == '\0'))
state = parse_stp_state(*argv);
if (state == -1) {
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;
}
if (rtnl_talk(&rth, &req.n, NULL) < 0)
return -1;
return 0;
}
static int vlan_global_option_set(int argc, char **argv)
{
struct {
struct nlmsghdr n;
struct br_vlan_msg bvm;
char buf[1024];
} 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;
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;
return 0;
}
/* In order to use this function for both filtering and non-filtering cases
* we need to make it a tristate:
* return -1 - if filtering we've gone over so don't continue
@ -422,14 +711,8 @@ static void print_vlan_flags(__u16 flags)
close_json_array(PRINT_JSON, NULL);
}
static void print_one_vlan_stats(const struct bridge_vlan_xstats *vstats)
static void __print_one_vlan_stats(const struct bridge_vlan_xstats *vstats)
{
open_json_object(NULL);
print_hu(PRINT_ANY, "vid", "%hu", vstats->vid);
print_vlan_flags(vstats->flags);
print_nl();
print_string(PRINT_FP, NULL, "%-" __stringify(IFNAMSIZ) "s ", "");
print_lluint(PRINT_ANY, "rx_bytes", "RX: %llu bytes",
vstats->rx_bytes);
@ -441,6 +724,16 @@ static void print_one_vlan_stats(const struct bridge_vlan_xstats *vstats)
vstats->tx_bytes);
print_lluint(PRINT_ANY, "tx_packets", " %llu packets\n",
vstats->tx_packets);
}
static void print_one_vlan_stats(const struct bridge_vlan_xstats *vstats)
{
open_json_object(NULL);
print_hu(PRINT_ANY, "vid", "%hu", vstats->vid);
print_vlan_flags(vstats->flags);
print_nl();
__print_one_vlan_stats(vstats);
close_json_object();
}
@ -521,6 +814,288 @@ static int print_vlan_stats(struct nlmsghdr *n, void *arg)
return 0;
}
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 *vtb[BRIDGE_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(vtb[BRIDGE_VLANDB_GOPTS_ID]);
if (vtb[BRIDGE_VLANDB_GOPTS_RANGE])
vrange = rta_getattr_u16(vtb[BRIDGE_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 (vtb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING];
print_uint(PRINT_ANY, "mcast_snooping", "mcast_snooping %u ",
rta_getattr_u8(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER];
print_uint(PRINT_ANY, "mcast_querier", "mcast_querier %u ",
rta_getattr_u8(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION];
print_uint(PRINT_ANY, "mcast_igmp_version",
"mcast_igmp_version %u ", rta_getattr_u8(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION];
print_uint(PRINT_ANY, "mcast_mld_version",
"mcast_mld_version %u ", rta_getattr_u8(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT];
print_uint(PRINT_ANY, "mcast_last_member_count",
"mcast_last_member_count %u ",
rta_getattr_u32(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL];
print_lluint(PRINT_ANY, "mcast_last_member_interval",
"mcast_last_member_interval %llu ",
rta_getattr_u64(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT];
print_uint(PRINT_ANY, "mcast_startup_query_count",
"mcast_startup_query_count %u ",
rta_getattr_u32(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL];
print_lluint(PRINT_ANY, "mcast_startup_query_interval",
"mcast_startup_query_interval %llu ",
rta_getattr_u64(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL];
print_lluint(PRINT_ANY, "mcast_membership_interval",
"mcast_membership_interval %llu ",
rta_getattr_u64(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL];
print_lluint(PRINT_ANY, "mcast_querier_interval",
"mcast_querier_interval %llu ",
rta_getattr_u64(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL]) {
vattr = vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL];
print_lluint(PRINT_ANY, "mcast_query_interval",
"mcast_query_interval %llu ",
rta_getattr_u64(vattr));
}
if (vtb[BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL]) {
vattr = vtb[BRIDGE_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 (vtb[BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS]) {
vattr = RTA_DATA(vtb[BRIDGE_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 *vtb[BRIDGE_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(vtb[BRIDGE_VLANDB_ENTRY_INFO]);
memset(&vstats, 0, sizeof(vstats));
if (vtb[BRIDGE_VLANDB_ENTRY_RANGE])
vrange = rta_getattr_u16(vtb[BRIDGE_VLANDB_ENTRY_RANGE]);
else
vrange = vinfo->vid;
if (filter_vlan && (filter_vlan < vinfo->vid || filter_vlan > vrange))
return;
if (vtb[BRIDGE_VLANDB_ENTRY_STATE])
state = rta_getattr_u8(vtb[BRIDGE_VLANDB_ENTRY_STATE]);
if (vtb[BRIDGE_VLANDB_ENTRY_STATS]) {
struct rtattr *stb[BRIDGE_VLANDB_STATS_MAX+1];
struct rtattr *attr;
attr = vtb[BRIDGE_VLANDB_ENTRY_STATS];
parse_rtattr(stb, BRIDGE_VLANDB_STATS_MAX, RTA_DATA(attr),
RTA_PAYLOAD(attr));
if (stb[BRIDGE_VLANDB_STATS_RX_BYTES]) {
attr = stb[BRIDGE_VLANDB_STATS_RX_BYTES];
vstats.rx_bytes = rta_getattr_u64(attr);
}
if (stb[BRIDGE_VLANDB_STATS_RX_PACKETS]) {
attr = stb[BRIDGE_VLANDB_STATS_RX_PACKETS];
vstats.rx_packets = rta_getattr_u64(attr);
}
if (stb[BRIDGE_VLANDB_STATS_TX_PACKETS]) {
attr = stb[BRIDGE_VLANDB_STATS_TX_PACKETS];
vstats.tx_packets = rta_getattr_u64(attr);
}
if (stb[BRIDGE_VLANDB_STATS_TX_BYTES]) {
attr = stb[BRIDGE_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 (vtb[BRIDGE_VLANDB_ENTRY_MCAST_ROUTER]) {
vattr = vtb[BRIDGE_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 br_vlan_msg *bvm = NLMSG_DATA(n);
int len = n->nlmsg_len;
struct rtattr *a;
int rem;
if (n->nlmsg_type != RTM_NEWVLAN && n->nlmsg_type != RTM_DELVLAN &&
n->nlmsg_type != RTM_GETVLAN) {
fprintf(stderr, "Unknown vlan rtm message: %08x %08x %08x\n",
n->nlmsg_len, n->nlmsg_type, n->nlmsg_flags);
return 0;
}
len -= NLMSG_LENGTH(sizeof(*bvm));
if (len < 0) {
fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
return -1;
}
if (bvm->family != AF_BRIDGE)
return 0;
if (filter_index && filter_index != bvm->ifindex)
return 0;
if (n->nlmsg_type == RTM_DELVLAN)
print_bool(PRINT_ANY, "deleted", "Deleted ", true);
if (monitor)
vlan_rtm_cur_ifidx = -1;
if (vlan_rtm_cur_ifidx != -1 && vlan_rtm_cur_ifidx != bvm->ifindex) {
close_vlan_port();
vlan_rtm_cur_ifidx = -1;
}
rem = len;
for (a = BRVLAN_RTA(bvm); RTA_OK(a, rem); a = RTA_NEXT(a, rem)) {
unsigned short rta_type = a->rta_type & NLA_TYPE_MASK;
/* skip unknown attributes */
if (rta_type > BRIDGE_VLANDB_MAX ||
(global_only && rta_type != BRIDGE_VLANDB_GLOBAL_OPTIONS))
continue;
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;
}
}
return 0;
}
static int print_vlan_rtm_filter(struct nlmsghdr *n, void *arg)
{
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)
{
char *filter_dev = NULL;
@ -549,6 +1124,34 @@ static int vlan_show(int argc, char **argv, int subject)
new_json_obj(json);
/* if show_details is true then use the new bridge vlan dump format */
if (show_details && subject == VLAN_SHOW_VLAN) {
__u32 dump_flags = show_stats ? BRIDGE_VLANDB_DUMPF_STATS : 0;
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_filter, &subject);
if (ret < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
}
if (vlan_rtm_cur_ifidx != -1)
close_vlan_port();
goto out;
}
if (!show_stats) {
if (rtnl_linkdump_req_filter(&rth, PF_BRIDGE,
(compress_vlans ?
@ -602,6 +1205,62 @@ static int vlan_show(int argc, char **argv, int subject)
}
}
out:
delete_json_obj();
fflush(stdout);
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;
@ -651,6 +1310,24 @@ void print_vlan_info(struct rtattr *tb, int ifindex)
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);
@ -667,6 +1344,10 @@ int do_vlan(int argc, char **argv)
if (matches(*argv, "tunnelshow") == 0) {
return vlan_show(argc-1, argv+1, VLAN_SHOW_TUNNELINFO);
}
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 {

117
configure vendored
View File

@ -1,13 +1,10 @@
#!/bin/sh
# SPDX-License-Identifier: GPL-2.0
# This is not an autoconf generated configure
#
# Influential LIBBPF environment variables:
# LIBBPF_FORCE={on,off} on: require link against libbpf;
# off: disable libbpf probing
# LIBBPF_DIR Path to libbpf DESTDIR to use
INCLUDE=${1:-"$PWD/include"}
INCLUDE="$PWD/include"
PREFIX="/usr"
LIBDIR="\${prefix}/lib"
# Output file which is input to Makefile
CONFIG=config.mk
@ -153,6 +150,15 @@ EOF
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
@ -202,6 +208,31 @@ EOF
rm -f $TMPDIR/setnstest.c $TMPDIR/setnstest
}
check_name_to_handle_at()
{
cat >$TMPDIR/name_to_handle_at_test.c <<EOF
#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv)
{
struct file_handle *fhp;
int mount_id, flags, dirfd;
char *pathname;
name_to_handle_at(dirfd, pathname, fhp, &mount_id, flags);
return 0;
}
EOF
if $CC -I$INCLUDE -o $TMPDIR/name_to_handle_at_test $TMPDIR/name_to_handle_at_test.c >/dev/null 2>&1; then
echo "yes"
echo "CFLAGS += -DHAVE_HANDLE_AT" >>$CONFIG
else
echo "no"
fi
rm -f $TMPDIR/name_to_handle_at_test.c $TMPDIR/name_to_handle_at_test
}
check_ipset()
{
cat >$TMPDIR/ipsettest.c <<EOF
@ -461,6 +492,76 @@ endif
EOF
}
usage()
{
cat <<EOF
Usage: $0 [OPTIONS]
--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
}
# Compat with the old INCLUDE path setting method.
if [ $# -eq 1 ] && [ "$(echo $1 | cut -c 1)" != '-' ]; then
INCLUDE="$1"
else
while [ "$#" -gt 0 ]; do
case "$1" in
--include_dir)
shift
INCLUDE="$1" ;;
--include_dir=*)
INCLUDE="${1#*=}" ;;
--libdir)
shift
LIBDIR="$1" ;;
--libdir=*)
LIBDIR="${1#*=}" ;;
--libbpf_dir)
shift
LIBBPF_DIR="$1" ;;
--libbpf_dir=*)
LIBBPF_DIR="${1#*=}" ;;
--libbpf_force)
shift
LIBBPF_FORCE="$1" ;;
--libbpf_force=*)
LIBBPF_FORCE="${1#*=}" ;;
--prefix)
shift
PREFIX="$1" ;;
--prefix=*)
PREFIX="${1#*=}" ;;
-h | --help)
usage 0 ;;
--*)
;;
*)
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
@ -484,6 +585,7 @@ if ! grep -q TC_CONFIG_NO_XT $CONFIG; then
fi
echo
check_lib_dir
if ! grep -q TC_CONFIG_NO_XT $CONFIG; then
echo -n "iptables modules directory: "
check_ipt_lib_dir
@ -492,6 +594,9 @@ fi
echo -n "libc has setns: "
check_setns
echo -n "libc has name_to_handle_at: "
check_name_to_handle_at
echo -n "SELinux support: "
check_selinux

View File

@ -571,7 +571,8 @@ int main(int argc, char **argv)
break;
case 'h':
dcb_help();
return 0;
ret = EXIT_SUCCESS;
goto dcb_free;
default:
fprintf(stderr, "Unknown option.\n");
dcb_help();

View File

@ -667,7 +667,7 @@ static int dcb_cmd_app_show(struct dcb *dcb, const char *dev, int argc, char **a
out:
close_json_object();
dcb_app_table_fini(&tab);
return 0;
return ret;
}
static int dcb_cmd_app_flush(struct dcb *dcb, const char *dev, int argc, char **argv)

View File

@ -7,6 +7,7 @@ ifeq ($(HAVE_MNL),y)
DEVLINKOBJ = devlink.o mnlg.o
TARGETS += devlink
LDLIBS += -lm
endif

File diff suppressed because it is too large Load Diff

View File

@ -30,38 +30,11 @@ struct mnlg_socket {
unsigned int seq;
};
static struct nlmsghdr *__mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
uint16_t flags, uint32_t id,
uint8_t version)
{
struct genlmsghdr genl = {
.cmd = cmd,
.version = version,
};
struct nlmsghdr *nlh;
nlh = mnlu_msg_prepare(nlg->buf, id, flags, &genl, sizeof(genl));
nlg->seq = nlh->nlmsg_seq;
return nlh;
}
struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
uint16_t flags)
{
return __mnlg_msg_prepare(nlg, cmd, flags, nlg->id, nlg->version);
}
int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh)
int mnlg_socket_send(struct mnlu_gen_socket *nlg, const struct nlmsghdr *nlh)
{
return mnl_socket_sendto(nlg->nl, nlh, nlh->nlmsg_len);
}
int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data)
{
return mnlu_socket_recv_run(nlg->nl, nlg->seq, nlg->buf, MNL_SOCKET_BUFFER_SIZE,
data_cb, data);
}
struct group_info {
bool found;
uint32_t id;
@ -141,15 +114,17 @@ static int get_group_id_cb(const struct nlmsghdr *nlh, void *data)
return MNL_CB_OK;
}
int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name)
int mnlg_socket_group_add(struct mnlu_gen_socket *nlg, const char *group_name)
{
struct nlmsghdr *nlh;
struct group_info group_info;
int err;
nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
mnl_attr_put_u16(nlh, CTRL_ATTR_FAMILY_ID, nlg->id);
nlh = _mnlu_gen_socket_cmd_prepare(nlg, CTRL_CMD_GETFAMILY,
NLM_F_REQUEST | NLM_F_ACK,
GENL_ID_CTRL, 1);
mnl_attr_put_u16(nlh, CTRL_ATTR_FAMILY_ID, nlg->family);
err = mnlg_socket_send(nlg, nlh);
if (err < 0)
@ -157,7 +132,7 @@ int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name)
group_info.found = false;
group_info.name = group_name;
err = mnlg_socket_recv_run(nlg, get_group_id_cb, &group_info);
err = mnlu_gen_socket_recv_run(nlg, get_group_id_cb, &group_info);
if (err < 0)
return err;
@ -174,85 +149,7 @@ int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name)
return 0;
}
static int get_family_id_attr_cb(const struct nlattr *attr, void *data)
{
const struct nlattr **tb = data;
int type = mnl_attr_get_type(attr);
if (mnl_attr_type_valid(attr, CTRL_ATTR_MAX) < 0)
return MNL_CB_ERROR;
if (type == CTRL_ATTR_FAMILY_ID &&
mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
return MNL_CB_ERROR;
tb[type] = attr;
return MNL_CB_OK;
}
static int get_family_id_cb(const struct nlmsghdr *nlh, void *data)
{
uint32_t *p_id = data;
struct nlattr *tb[CTRL_ATTR_MAX + 1] = {};
struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
mnl_attr_parse(nlh, sizeof(*genl), get_family_id_attr_cb, tb);
if (!tb[CTRL_ATTR_FAMILY_ID])
return MNL_CB_ERROR;
*p_id = mnl_attr_get_u16(tb[CTRL_ATTR_FAMILY_ID]);
return MNL_CB_OK;
}
struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version)
{
struct mnlg_socket *nlg;
struct nlmsghdr *nlh;
int err;
nlg = malloc(sizeof(*nlg));
if (!nlg)
return NULL;
nlg->buf = malloc(MNL_SOCKET_BUFFER_SIZE);
if (!nlg->buf)
goto err_buf_alloc;
nlg->nl = mnlu_socket_open(NETLINK_GENERIC);
if (!nlg->nl)
goto err_socket_open;
nlh = __mnlg_msg_prepare(nlg, CTRL_CMD_GETFAMILY,
NLM_F_REQUEST | NLM_F_ACK, GENL_ID_CTRL, 1);
mnl_attr_put_strz(nlh, CTRL_ATTR_FAMILY_NAME, family_name);
err = mnlg_socket_send(nlg, nlh);
if (err < 0)
goto err_mnlg_socket_send;
err = mnlg_socket_recv_run(nlg, get_family_id_cb, &nlg->id);
if (err < 0)
goto err_mnlg_socket_recv_run;
nlg->version = version;
return nlg;
err_mnlg_socket_recv_run:
err_mnlg_socket_send:
mnl_socket_close(nlg->nl);
err_socket_open:
free(nlg->buf);
err_buf_alloc:
free(nlg);
return NULL;
}
void mnlg_socket_close(struct mnlg_socket *nlg)
{
mnl_socket_close(nlg->nl);
free(nlg->buf);
free(nlg);
}
int mnlg_socket_get_fd(struct mnlg_socket *nlg)
int mnlg_socket_get_fd(struct mnlu_gen_socket *nlg)
{
return mnl_socket_get_fd(nlg->nl);
}

View File

@ -14,15 +14,10 @@
#include <libmnl/libmnl.h>
struct mnlg_socket;
struct mnlu_gen_socket;
struct nlmsghdr *mnlg_msg_prepare(struct mnlg_socket *nlg, uint8_t cmd,
uint16_t flags);
int mnlg_socket_send(struct mnlg_socket *nlg, const struct nlmsghdr *nlh);
int mnlg_socket_recv_run(struct mnlg_socket *nlg, mnl_cb_t data_cb, void *data);
int mnlg_socket_group_add(struct mnlg_socket *nlg, const char *group_name);
struct mnlg_socket *mnlg_socket_open(const char *family_name, uint8_t version);
void mnlg_socket_close(struct mnlg_socket *nlg);
int mnlg_socket_get_fd(struct mnlg_socket *nlg);
int mnlg_socket_send(struct mnlu_gen_socket *nlg, const struct nlmsghdr *nlh);
int mnlg_socket_group_add(struct mnlu_gen_socket *nlg, const char *group_name);
int mnlg_socket_get_fd(struct mnlu_gen_socket *nlg);
#endif /* _MNLG_H_ */

View File

@ -10,7 +10,7 @@ Where:
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

@ -17,6 +17,7 @@
16 dhcp
18 keepalived
42 babel
99 openr
186 bgp
187 isis
188 ospf

View File

@ -81,6 +81,7 @@ _PRINT_FUNC(0xhex, unsigned long long)
_PRINT_FUNC(luint, unsigned long)
_PRINT_FUNC(lluint, unsigned long long)
_PRINT_FUNC(float, double)
_PRINT_FUNC(tv, const struct timeval *)
#undef _PRINT_FUNC
#define _PRINT_NAME_VALUE_FUNC(type_name, type, format_char) \

View File

@ -21,6 +21,7 @@ struct { \
}, \
}
int genl_add_mcast_grp(struct rtnl_handle *grth, __u16 genl_family, const char *group);
int genl_resolve_family(struct rtnl_handle *grth, const char *family);
int genl_init_handle(struct rtnl_handle *grth, const char *family,
int *genl_family);

View File

@ -69,6 +69,8 @@ int rtnl_neightbldump_req(struct rtnl_handle *rth, int family)
__attribute__((warn_unused_result));
int rtnl_mdbdump_req(struct rtnl_handle *rth, int family)
__attribute__((warn_unused_result));
int rtnl_brvlandump_req(struct rtnl_handle *rth, int family, __u32 dump_flags)
__attribute__((warn_unused_result));
int rtnl_netconfdump_req(struct rtnl_handle *rth, int family)
__attribute__((warn_unused_result));
@ -97,6 +99,9 @@ int rtnl_dump_request_n(struct rtnl_handle *rth, struct nlmsghdr *n)
int rtnl_nexthopdump_req(struct rtnl_handle *rth, int family,
req_filter_fn_t filter_fn)
__attribute__((warn_unused_result));
int rtnl_nexthop_bucket_dump_req(struct rtnl_handle *rth, int family,
req_filter_fn_t filter_fn)
__attribute__((warn_unused_result));
struct rtnl_ctrl_data {
int nsid;
@ -104,6 +109,27 @@ struct rtnl_ctrl_data {
typedef int (*rtnl_filter_t)(struct nlmsghdr *n, void *);
/**
* rtnl error handler called from
* rtnl_dump_done()
* rtnl_dump_error()
*
* Return value is a bitmask of the following values:
* RTNL_LET_NLERR
* error handled as usual
* RTNL_SUPPRESS_NLMSG_DONE_NLERR
* error in nlmsg_type == NLMSG_DONE will be suppressed
* RTNL_SUPPRESS_NLMSG_ERROR_NLERR
* error in nlmsg_type == NLMSG_ERROR will be suppressed
* and nlmsg will be skipped
* RTNL_SUPPRESS_NLERR - suppress error in both previous cases
*/
#define RTNL_LET_NLERR 0x01
#define RTNL_SUPPRESS_NLMSG_DONE_NLERR 0x02
#define RTNL_SUPPRESS_NLMSG_ERROR_NLERR 0x04
#define RTNL_SUPPRESS_NLERR 0x06
typedef int (*rtnl_err_hndlr_t)(struct nlmsghdr *n, void *);
typedef int (*rtnl_listen_filter_t)(struct rtnl_ctrl_data *,
struct nlmsghdr *n, void *);
@ -113,6 +139,8 @@ typedef int (*nl_ext_ack_fn_t)(const char *errmsg, uint32_t off,
struct rtnl_dump_filter_arg {
rtnl_filter_t filter;
void *arg1;
rtnl_err_hndlr_t errhndlr;
void *arg2;
__u16 nc_flags;
};
@ -121,6 +149,15 @@ int rtnl_dump_filter_nc(struct rtnl_handle *rth,
void *arg, __u16 nc_flags);
#define rtnl_dump_filter(rth, filter, arg) \
rtnl_dump_filter_nc(rth, filter, arg, 0)
int rtnl_dump_filter_errhndlr_nc(struct rtnl_handle *rth,
rtnl_filter_t filter,
void *arg1,
rtnl_err_hndlr_t errhndlr,
void *arg2,
__u16 nc_flags);
#define rtnl_dump_filter_errhndlr(rth, filter, farg, errhndlr, earg) \
rtnl_dump_filter_errhndlr_nc(rth, filter, farg, errhndlr, earg, 0)
int rtnl_talk(struct rtnl_handle *rtnl, struct nlmsghdr *n,
struct nlmsghdr **answer)
__attribute__((warn_unused_result));
@ -280,6 +317,11 @@ int rtnl_from_file(FILE *, rtnl_listen_filter_t handler,
((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct if_stats_msg))))
#endif
#ifndef BRVLAN_RTA
#define BRVLAN_RTA(r) \
((struct rtattr *)(((char *)(r)) + NLMSG_ALIGN(sizeof(struct br_vlan_msg))))
#endif
/* User defined nlmsg_type which is used mostly for logging netlink
* messages from dump file */
#define NLMSG_TSTAMP 15

View File

@ -13,6 +13,10 @@ struct mnlu_gen_socket {
int mnlu_gen_socket_open(struct mnlu_gen_socket *nlg, const char *family_name,
uint8_t version);
void mnlu_gen_socket_close(struct mnlu_gen_socket *nlg);
struct nlmsghdr *
_mnlu_gen_socket_cmd_prepare(struct mnlu_gen_socket *nlg,
uint8_t cmd, uint16_t flags,
uint32_t id, uint8_t version);
struct nlmsghdr *mnlu_gen_socket_cmd_prepare(struct mnlu_gen_socket *nlg,
uint8_t cmd, uint16_t flags);
int mnlu_gen_socket_sndrcv(struct mnlu_gen_socket *nlg, const struct nlmsghdr *nlh,
@ -23,5 +27,7 @@ struct nlmsghdr *mnlu_msg_prepare(void *buf, uint32_t nlmsg_type, uint16_t flags
void *extra_header, size_t extra_header_size);
int mnlu_socket_recv_run(struct mnl_socket *nl, unsigned int seq, void *buf, size_t buf_size,
mnl_cb_t cb, void *data);
int mnlu_gen_socket_recv_run(struct mnlu_gen_socket *nlg, mnl_cb_t cb,
void *data);
#endif /* __MNL_UTILS_H__ */

62
include/uapi/linux/amt.h Normal file
View File

@ -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_ */

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,7 @@ struct btf_type {
* "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 and DECL_TAG.
* "type" is a type_id referring to another type.
*/
union {
@ -52,28 +52,33 @@ struct btf_type {
};
};
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x0f)
#define BTF_INFO_KIND(info) (((info) >> 24) & 0x1f)
#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_MAX BTF_KIND_DATASEC
#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 */
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 */
NR_BTF_KINDS,
BTF_KIND_MAX = NR_BTF_KINDS - 1,
};
/* For some specific BTF_KIND, "struct btf_type" is immediately
* followed by extra data.
@ -169,4 +174,15 @@ struct btf_var_secinfo {
__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;
};
#endif /* __LINUX_BTF_H__ */

View File

@ -123,8 +123,8 @@ struct can_frame {
/*
* defined bits for canfd_frame.flags
*
* The use of struct canfd_frame implies the Extended Data Length (EDL) bit to
* be set in the CAN frame bitstream on the wire. The EDL bit switch turns
* The use of struct canfd_frame implies the FD Frame (FDF) bit to
* be set in the CAN frame bitstream on the wire. The FDF bit switch turns
* the CAN controllers bitstream processor into the CAN FD mode which creates
* two new options within the CAN FD frame specification:
*
@ -135,9 +135,18 @@ struct can_frame {
* controller only the CANFD_BRS bit is relevant for real CAN controllers when
* building a CAN FD frame for transmission. Setting the CANFD_ESI bit can make
* sense for virtual CAN interfaces to test applications with echoed frames.
*
* The struct can_frame and struct canfd_frame intentionally share the same
* layout to be able to write CAN frame content into a CAN FD frame structure.
* 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.
*/
#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */
#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */
#define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */
/**
* struct canfd_frame - CAN flexible data rate frame structure

View File

@ -101,6 +101,8 @@ struct can_ctrlmode {
#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,35 @@ enum {
IFLA_CAN_BITRATE_CONST,
IFLA_CAN_DATA_BITRATE_CONST,
IFLA_CAN_BITRATE_MAX,
__IFLA_CAN_MAX
IFLA_CAN_TDC,
/* 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
};
/* u16 termination range: 1..65535 Ohms */
#define CAN_TERMINATION_DISABLED 0

View File

@ -126,6 +126,11 @@ enum devlink_command {
DEVLINK_CMD_HEALTH_REPORTER_TEST,
DEVLINK_CMD_RATE_GET, /* can dump */
DEVLINK_CMD_RATE_SET,
DEVLINK_CMD_RATE_NEW,
DEVLINK_CMD_RATE_DEL,
/* add new commands above here */
__DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
@ -206,6 +211,11 @@ enum devlink_port_flavour {
*/
};
enum devlink_rate_type {
DEVLINK_RATE_TYPE_LEAF,
DEVLINK_RATE_TYPE_NODE,
};
enum devlink_param_cmode {
DEVLINK_PARAM_CMODE_RUNTIME,
DEVLINK_PARAM_CMODE_DRIVERINIT,
@ -534,6 +544,15 @@ enum devlink_attr {
DEVLINK_ATTR_RELOAD_ACTION_STATS, /* nested */
DEVLINK_ATTR_PORT_PCI_SF_NUMBER, /* u32 */
DEVLINK_ATTR_RATE_TYPE, /* u16 */
DEVLINK_ATTR_RATE_TX_SHARE, /* u64 */
DEVLINK_ATTR_RATE_TX_MAX, /* u64 */
DEVLINK_ATTR_RATE_NODE_NAME, /* string */
DEVLINK_ATTR_RATE_PARENT_NODE_NAME, /* string */
DEVLINK_ATTR_REGION_MAX_SNAPSHOTS, /* u32 */
/* add new attributes above here, update the policy in devlink.c */
__DEVLINK_ATTR_MAX,

View File

@ -140,6 +140,9 @@ struct icmp6hdr {
#define ICMPV6_UNK_OPTION 2
#define ICMPV6_HDR_INCOMP 3
/* Codes for EXT_ECHO (PROBE) */
#define ICMPV6_EXT_ECHO_REQUEST 160
#define ICMPV6_EXT_ECHO_REPLY 161
/*
* constants for (set|get)sockopt
*/

View File

@ -54,6 +54,7 @@
#define ARPHRD_X25 271 /* CCITT X.25 */
#define ARPHRD_HWX25 272 /* Boards with X.25 in firmware */
#define ARPHRD_CAN 280 /* Controller Area Network */
#define ARPHRD_MCTP 290
#define ARPHRD_PPP 512
#define ARPHRD_CISCO 513 /* Cisco HDLC */
#define ARPHRD_HDLC ARPHRD_CISCO

View File

@ -153,14 +153,3 @@ enum {
#define BOND_3AD_STAT_MAX (__BOND_3AD_STAT_MAX - 1)
#endif /* _LINUX_IF_BONDING_H */
/*
* Local variables:
* version-control: t
* kept-new-versions: 5
* c-indent-level: 8
* c-basic-offset: 8
* tab-width: 8
* End:
*/

View File

@ -479,16 +479,22 @@ enum {
/* flags used in BRIDGE_VLANDB_DUMP_FLAGS attribute to affect dumps */
#define BRIDGE_VLANDB_DUMPF_STATS (1 << 0) /* Include stats in the dump */
#define BRIDGE_VLANDB_DUMPF_GLOBAL (1 << 1) /* Dump global vlan options only */
/* Bridge vlan RTM attributes
* [BRIDGE_VLANDB_ENTRY] = {
* [BRIDGE_VLANDB_ENTRY_INFO]
* ...
* }
* [BRIDGE_VLANDB_GLOBAL_OPTIONS] = {
* [BRIDGE_VLANDB_GOPTS_ID]
* ...
* }
*/
enum {
BRIDGE_VLANDB_UNSPEC,
BRIDGE_VLANDB_ENTRY,
BRIDGE_VLANDB_GLOBAL_OPTIONS,
__BRIDGE_VLANDB_MAX,
};
#define BRIDGE_VLANDB_MAX (__BRIDGE_VLANDB_MAX - 1)
@ -500,6 +506,7 @@ enum {
BRIDGE_VLANDB_ENTRY_STATE,
BRIDGE_VLANDB_ENTRY_TUNNEL_INFO,
BRIDGE_VLANDB_ENTRY_STATS,
BRIDGE_VLANDB_ENTRY_MCAST_ROUTER,
__BRIDGE_VLANDB_ENTRY_MAX,
};
#define BRIDGE_VLANDB_ENTRY_MAX (__BRIDGE_VLANDB_ENTRY_MAX - 1)
@ -538,6 +545,29 @@ enum {
};
#define BRIDGE_VLANDB_STATS_MAX (__BRIDGE_VLANDB_STATS_MAX - 1)
enum {
BRIDGE_VLANDB_GOPTS_UNSPEC,
BRIDGE_VLANDB_GOPTS_ID,
BRIDGE_VLANDB_GOPTS_RANGE,
BRIDGE_VLANDB_GOPTS_MCAST_SNOOPING,
BRIDGE_VLANDB_GOPTS_MCAST_IGMP_VERSION,
BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION,
BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_CNT,
BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_CNT,
BRIDGE_VLANDB_GOPTS_MCAST_LAST_MEMBER_INTVL,
BRIDGE_VLANDB_GOPTS_PAD,
BRIDGE_VLANDB_GOPTS_MCAST_MEMBERSHIP_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_QUERY_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_QUERY_RESPONSE_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS,
BRIDGE_VLANDB_GOPTS_MCAST_QUERIER_STATE,
__BRIDGE_VLANDB_GOPTS_MAX
};
#define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
/* Bridge multicast database attributes
* [MDBA_MDB] = {
* [MDBA_MDB_ENTRY] = {
@ -627,6 +657,9 @@ enum {
MDBA_ROUTER_PATTR_UNSPEC,
MDBA_ROUTER_PATTR_TIMER,
MDBA_ROUTER_PATTR_TYPE,
MDBA_ROUTER_PATTR_INET_TIMER,
MDBA_ROUTER_PATTR_INET6_TIMER,
MDBA_ROUTER_PATTR_VID,
__MDBA_ROUTER_PATTR_MAX
};
#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1)
@ -718,12 +751,14 @@ struct br_mcast_stats {
/* bridge boolean options
* BR_BOOLOPT_NO_LL_LEARN - disable learning from link-local packets
* BR_BOOLOPT_MCAST_VLAN_SNOOPING - control vlan multicast snooping
*
* IMPORTANT: if adding a new option do not forget to handle
* it in br_boolopt_toggle/get and bridge sysfs
*/
enum br_boolopt_id {
BR_BOOLOPT_NO_LL_LEARN,
BR_BOOLOPT_MCAST_VLAN_SNOOPING,
BR_BOOLOPT_MAX
};
@ -736,4 +771,17 @@ struct br_boolopt_multi {
__u32 optval;
__u32 optmask;
};
enum {
BRIDGE_QUERIER_UNSPEC,
BRIDGE_QUERIER_IP_ADDRESS,
BRIDGE_QUERIER_IP_PORT,
BRIDGE_QUERIER_IP_OTHER_TIMER,
BRIDGE_QUERIER_PAD,
BRIDGE_QUERIER_IPV6_ADDRESS,
BRIDGE_QUERIER_IPV6_PORT,
BRIDGE_QUERIER_IPV6_OTHER_TIMER,
__BRIDGE_QUERIER_MAX
};
#define BRIDGE_QUERIER_MAX (__BRIDGE_QUERIER_MAX - 1)
#endif /* _LINUX_IF_BRIDGE_H */

View File

@ -86,6 +86,7 @@
* over Ethernet
*/
#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */
#define ETH_P_REALTEK 0x8899 /* Multiple proprietary protocols */
#define ETH_P_AOE 0x88A2 /* ATA over Ethernet */
#define ETH_P_8021AD 0x88A8 /* 802.1ad Service VLAN */
#define ETH_P_802_EX1 0x88B5 /* 802.1 Local Experimental 1. */
@ -116,7 +117,7 @@
#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 */
/*
@ -151,6 +152,9 @@
#define ETH_P_MAP 0x00F9 /* Qualcomm multiplexing and
* aggregation protocol
*/
#define ETH_P_MCTP 0x00FA /* Management component transport
* protocol packets
*/
/*
* This is an Ethernet frame header.

View File

@ -341,6 +341,13 @@ enum {
IFLA_ALT_IFNAME, /* Alternative ifname */
IFLA_PERM_ADDRESS,
IFLA_PROTO_DOWN_REASON,
/* device (sysfs) name as parent, used instead
* of IFLA_LINK where there's no parent netdev
*/
IFLA_PARENT_DEV_NAME,
IFLA_PARENT_DEV_BUS_NAME,
__IFLA_MAX
};
@ -408,6 +415,7 @@ enum {
IFLA_INET6_ICMP6STATS, /* statistics (icmpv6) */
IFLA_INET6_TOKEN, /* device token */
IFLA_INET6_ADDR_GEN_MODE, /* implicit address generator mode */
IFLA_INET6_RA_MTU, /* mtu carried in the RA message */
__IFLA_INET6_MAX
};
@ -470,6 +478,7 @@ enum {
IFLA_BR_MCAST_MLD_VERSION,
IFLA_BR_VLAN_STATS_PER_PORT,
IFLA_BR_MULTI_BOOLOPT,
IFLA_BR_MCAST_QUERIER_STATE,
__IFLA_BR_MAX,
};
@ -612,6 +621,7 @@ enum macvlan_macaddr_mode {
};
#define MACVLAN_FLAG_NOPROMISC 1
#define MACVLAN_FLAG_NODST 2 /* skip dst macvlan if matching src macvlan */
/* VRF section */
enum {
@ -845,6 +855,7 @@ enum {
IFLA_BOND_AD_ACTOR_SYSTEM,
IFLA_BOND_TLB_DYNAMIC_LB,
IFLA_BOND_PEER_NOTIF_DELAY,
IFLA_BOND_AD_LACP_ACTIVE,
__IFLA_BOND_MAX,
};
@ -1233,6 +1244,8 @@ enum {
#define RMNET_FLAGS_INGRESS_MAP_COMMANDS (1U << 1)
#define RMNET_FLAGS_INGRESS_MAP_CKSUMV4 (1U << 2)
#define RMNET_FLAGS_EGRESS_MAP_CKSUMV4 (1U << 3)
#define RMNET_FLAGS_INGRESS_MAP_CKSUMV5 (1U << 4)
#define RMNET_FLAGS_EGRESS_MAP_CKSUMV5 (1U << 5)
enum {
IFLA_RMNET_UNSPEC,
@ -1248,4 +1261,14 @@ struct ifla_rmnet_flags {
__u32 mask;
};
/* MCTP section */
enum {
IFLA_MCTP_UNSPEC,
IFLA_MCTP_NET,
__IFLA_MCTP_MAX,
};
#define IFLA_MCTP_MAX (__IFLA_MCTP_MAX - 1)
#endif /* _LINUX_IF_LINK_H */

View File

@ -188,11 +188,22 @@ struct ip_mreq_source {
};
struct ip_msfilter {
__be32 imsf_multiaddr;
__be32 imsf_interface;
__u32 imsf_fmode;
__u32 imsf_numsrc;
__be32 imsf_slist[1];
union {
struct {
__be32 imsf_multiaddr_aux;
__be32 imsf_interface_aux;
__u32 imsf_fmode_aux;
__u32 imsf_numsrc_aux;
__be32 imsf_slist[1];
};
struct {
__be32 imsf_multiaddr;
__be32 imsf_interface;
__u32 imsf_fmode;
__u32 imsf_numsrc;
__be32 imsf_slist_flex[];
};
};
};
#define IP_MSFILTER_SIZE(numsrc) \
@ -211,11 +222,22 @@ struct group_source_req {
};
struct group_filter {
__u32 gf_interface; /* interface index */
struct __kernel_sockaddr_storage gf_group; /* multicast address */
__u32 gf_fmode; /* filter mode */
__u32 gf_numsrc; /* number of sources */
struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */
union {
struct {
__u32 gf_interface_aux; /* interface index */
struct __kernel_sockaddr_storage gf_group_aux; /* multicast address */
__u32 gf_fmode_aux; /* filter mode */
__u32 gf_numsrc_aux; /* number of sources */
struct __kernel_sockaddr_storage gf_slist[1]; /* interface index */
};
struct {
__u32 gf_interface; /* interface index */
struct __kernel_sockaddr_storage gf_group; /* multicast address */
__u32 gf_fmode; /* filter mode */
__u32 gf_numsrc; /* number of sources */
struct __kernel_sockaddr_storage gf_slist_flex[]; /* interface index */
};
};
};
#define GROUP_FILTER_SIZE(numsrc) \
@ -289,6 +311,9 @@ struct sockaddr_in {
/* Address indicating an error return. */
#define INADDR_NONE ((unsigned long int) 0xffffffff)
/* Dummy address for src of ICMP replies if no real address is set (RFC7600). */
#define INADDR_DUMMY ((unsigned long int) 0xc0000008)
/* Network number for local host loopback. */
#define IN_LOOPBACKNET 127

View File

@ -145,6 +145,7 @@ struct in6_flowlabel_req {
#define IPV6_TLV_PADN 1
#define IPV6_TLV_ROUTERALERT 5
#define IPV6_TLV_CALIPSO 7 /* RFC 5570 */
#define IPV6_TLV_IOAM 49 /* TEMPORARY IANA allocation for IOAM */
#define IPV6_TLV_JUMBO 194
#define IPV6_TLV_HAO 201 /* home address option */

133
include/uapi/linux/ioam6.h Normal file
View File

@ -0,0 +1,133 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* IPv6 IOAM implementation
*
* Author:
* Justin Iurman <justin.iurman@uliege.be>
*/
#ifndef _LINUX_IOAM6_H
#define _LINUX_IOAM6_H
#include <asm/byteorder.h>
#include <linux/types.h>
#define IOAM6_U16_UNAVAILABLE U16_MAX
#define IOAM6_U32_UNAVAILABLE U32_MAX
#define IOAM6_U64_UNAVAILABLE U64_MAX
#define IOAM6_DEFAULT_ID (IOAM6_U32_UNAVAILABLE >> 8)
#define IOAM6_DEFAULT_ID_WIDE (IOAM6_U64_UNAVAILABLE >> 8)
#define IOAM6_DEFAULT_IF_ID IOAM6_U16_UNAVAILABLE
#define IOAM6_DEFAULT_IF_ID_WIDE IOAM6_U32_UNAVAILABLE
/*
* IPv6 IOAM Option Header
*/
struct ioam6_hdr {
__u8 opt_type;
__u8 opt_len;
__u8 :8; /* reserved */
#define IOAM6_TYPE_PREALLOC 0
__u8 type;
} __attribute__((packed));
/*
* IOAM Trace Header
*/
struct ioam6_trace_hdr {
__be16 namespace_id;
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 :1, /* unused */
:1, /* unused */
overflow:1,
nodelen:5;
__u8 remlen:7,
:1; /* unused */
union {
__be32 type_be32;
struct {
__u32 bit7:1,
bit6:1,
bit5:1,
bit4:1,
bit3:1,
bit2:1,
bit1:1,
bit0:1,
bit15:1, /* unused */
bit14:1, /* unused */
bit13:1, /* unused */
bit12:1, /* unused */
bit11:1,
bit10:1,
bit9:1,
bit8:1,
bit23:1, /* reserved */
bit22:1,
bit21:1, /* unused */
bit20:1, /* unused */
bit19:1, /* unused */
bit18:1, /* unused */
bit17:1, /* unused */
bit16:1, /* unused */
:8; /* reserved */
} type;
};
#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 nodelen:5,
overflow:1,
:1, /* unused */
:1; /* unused */
__u8 :1, /* unused */
remlen:7;
union {
__be32 type_be32;
struct {
__u32 bit0:1,
bit1:1,
bit2:1,
bit3:1,
bit4:1,
bit5:1,
bit6:1,
bit7:1,
bit8:1,
bit9:1,
bit10:1,
bit11:1,
bit12:1, /* unused */
bit13:1, /* unused */
bit14:1, /* unused */
bit15:1, /* unused */
bit16:1, /* unused */
bit17:1, /* unused */
bit18:1, /* unused */
bit19:1, /* unused */
bit20:1, /* unused */
bit21:1, /* unused */
bit22:1,
bit23:1, /* reserved */
:8; /* reserved */
} type;
};
#else
#error "Please fix <asm/byteorder.h>"
#endif
#define IOAM6_TRACE_DATA_SIZE_MAX 244
__u8 data[0];
} __attribute__((packed));
#endif /* _LINUX_IOAM6_H */

View File

@ -0,0 +1,52 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* IPv6 IOAM Generic Netlink API
*
* Author:
* Justin Iurman <justin.iurman@uliege.be>
*/
#ifndef _LINUX_IOAM6_GENL_H
#define _LINUX_IOAM6_GENL_H
#define IOAM6_GENL_NAME "IOAM6"
#define IOAM6_GENL_VERSION 0x1
enum {
IOAM6_ATTR_UNSPEC,
IOAM6_ATTR_NS_ID, /* u16 */
IOAM6_ATTR_NS_DATA, /* u32 */
IOAM6_ATTR_NS_DATA_WIDE,/* u64 */
#define IOAM6_MAX_SCHEMA_DATA_LEN (255 * 4)
IOAM6_ATTR_SC_ID, /* u32 */
IOAM6_ATTR_SC_DATA, /* Binary */
IOAM6_ATTR_SC_NONE, /* Flag */
IOAM6_ATTR_PAD,
__IOAM6_ATTR_MAX,
};
#define IOAM6_ATTR_MAX (__IOAM6_ATTR_MAX - 1)
enum {
IOAM6_CMD_UNSPEC,
IOAM6_CMD_ADD_NAMESPACE,
IOAM6_CMD_DEL_NAMESPACE,
IOAM6_CMD_DUMP_NAMESPACES,
IOAM6_CMD_ADD_SCHEMA,
IOAM6_CMD_DEL_SCHEMA,
IOAM6_CMD_DUMP_SCHEMAS,
IOAM6_CMD_NS_SET_SCHEMA,
__IOAM6_CMD_MAX,
};
#define IOAM6_CMD_MAX (__IOAM6_CMD_MAX - 1)
#endif /* _LINUX_IOAM6_GENL_H */

View File

@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
/*
* IPv6 IOAM Lightweight Tunnel API
*
* Author:
* Justin Iurman <justin.iurman@uliege.be>
*/
#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 */
__IOAM6_IPTUNNEL_MAX,
};
#define IOAM6_IPTUNNEL_MAX (__IOAM6_IPTUNNEL_MAX - 1)
#endif /* _LINUX_IOAM6_IPTUNNEL_H */

View File

@ -169,6 +169,7 @@ enum
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

@ -14,6 +14,7 @@ enum lwtunnel_encap_types {
LWTUNNEL_ENCAP_BPF,
LWTUNNEL_ENCAP_SEG6_LOCAL,
LWTUNNEL_ENCAP_RPL,
LWTUNNEL_ENCAP_IOAM6,
__LWTUNNEL_ENCAP_MAX,
};

View File

@ -97,5 +97,6 @@
#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

@ -4,6 +4,11 @@
#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 */
#include <sys/socket.h> /* for struct sockaddr */
#define MPTCP_SUBFLOW_FLAG_MCAP_REM _BITUL(0)
#define MPTCP_SUBFLOW_FLAG_MCAP_LOC _BITUL(1)
@ -73,6 +78,7 @@ enum {
#define MPTCP_PM_ADDR_FLAG_SIGNAL (1 << 0)
#define MPTCP_PM_ADDR_FLAG_SUBFLOW (1 << 1)
#define MPTCP_PM_ADDR_FLAG_BACKUP (1 << 2)
#define MPTCP_PM_ADDR_FLAG_FULLMESH (1 << 3)
enum {
MPTCP_PM_CMD_UNSPEC,
@ -105,6 +111,7 @@ struct mptcp_info {
__u64 mptcpi_rcv_nxt;
__u8 mptcpi_local_addr_used;
__u8 mptcpi_local_addr_max;
__u8 mptcpi_csum_enabled;
};
/*
@ -174,10 +181,49 @@ enum mptcp_event_attr {
MPTCP_ATTR_FLAGS, /* u16 */
MPTCP_ATTR_TIMEOUT, /* u32 */
MPTCP_ATTR_IF_IDX, /* s32 */
MPTCP_ATTR_RESET_REASON,/* u32 */
MPTCP_ATTR_RESET_FLAGS, /* u32 */
__MPTCP_ATTR_AFTER_LAST
};
#define MPTCP_ATTR_MAX (__MPTCP_ATTR_AFTER_LAST - 1)
/* MPTCP Reset reason codes, rfc8684 */
#define MPTCP_RST_EUNSPEC 0
#define MPTCP_RST_EMPTCP 1
#define MPTCP_RST_ERESOURCE 2
#define MPTCP_RST_EPROHIBIT 3
#define MPTCP_RST_EWQ2BIG 4
#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

@ -31,6 +31,7 @@ enum {
NDA_PROTOCOL, /* Originator of entry */
NDA_NH_ID,
NDA_FDB_EXT_ATTRS,
NDA_FLAGS_EXT,
__NDA_MAX
};
@ -40,14 +41,16 @@ enum {
* 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,9 +68,22 @@ enum {
#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 {

View File

@ -49,6 +49,7 @@ enum nf_inet_hooks {
enum nf_dev_hooks {
NF_NETDEV_INGRESS,
NF_NETDEV_EGRESS,
NF_NETDEV_NUMHOOKS
};

View File

@ -91,9 +91,10 @@ struct nlmsghdr {
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_DATA(nlh) ((void *)(((char *)nlh) + NLMSG_HDRLEN))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
(struct nlmsghdr *)(((char *)(nlh)) + \
NLMSG_ALIGN((nlh)->nlmsg_len)))
#define NLMSG_OK(nlh,len) ((len) >= (int)sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
(nlh)->nlmsg_len <= (len))

View File

@ -21,7 +21,10 @@ struct nexthop_grp {
};
enum {
NEXTHOP_GRP_TYPE_MPATH, /* default type if not specified */
NEXTHOP_GRP_TYPE_MPATH, /* hash-threshold nexthop group
* default type if not specified
*/
NEXTHOP_GRP_TYPE_RES, /* resilient nexthop group */
__NEXTHOP_GRP_TYPE_MAX,
};
@ -52,8 +55,50 @@ enum {
NHA_FDB, /* flag; nexthop belongs to a bridge fdb */
/* if NHA_FDB is added, OIF, BLACKHOLE, ENCAP cannot be set */
/* nested; resilient nexthop group attributes */
NHA_RES_GROUP,
/* nested; nexthop bucket attributes */
NHA_RES_BUCKET,
__NHA_MAX,
};
#define NHA_MAX (__NHA_MAX - 1)
enum {
NHA_RES_GROUP_UNSPEC,
/* Pad attribute for 64-bit alignment. */
NHA_RES_GROUP_PAD = NHA_RES_GROUP_UNSPEC,
/* u16; number of nexthop buckets in a resilient nexthop group */
NHA_RES_GROUP_BUCKETS,
/* clock_t as u32; nexthop bucket idle timer (per-group) */
NHA_RES_GROUP_IDLE_TIMER,
/* clock_t as u32; nexthop unbalanced timer */
NHA_RES_GROUP_UNBALANCED_TIMER,
/* clock_t as u64; nexthop unbalanced time */
NHA_RES_GROUP_UNBALANCED_TIME,
__NHA_RES_GROUP_MAX,
};
#define NHA_RES_GROUP_MAX (__NHA_RES_GROUP_MAX - 1)
enum {
NHA_RES_BUCKET_UNSPEC,
/* Pad attribute for 64-bit alignment. */
NHA_RES_BUCKET_PAD = NHA_RES_BUCKET_UNSPEC,
/* u16; nexthop bucket index */
NHA_RES_BUCKET_INDEX,
/* clock_t as u64; nexthop bucket idle time */
NHA_RES_BUCKET_IDLE_TIME,
/* u32; nexthop id assigned to the nexthop bucket */
NHA_RES_BUCKET_NH_ID,
__NHA_RES_BUCKET_MAX,
};
#define NHA_RES_BUCKET_MAX (__NHA_RES_BUCKET_MAX - 1)
#endif

View File

@ -22,6 +22,7 @@ enum {
__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.
*/
@ -190,6 +191,8 @@ enum {
TCA_POLICE_PAD,
TCA_POLICE_RATE64,
TCA_POLICE_PEAKRATE64,
TCA_POLICE_PKTRATE64,
TCA_POLICE_PKTBURST64,
__TCA_POLICE_MAX
#define TCA_POLICE_RESULT TCA_POLICE_RESULT
};

View File

@ -827,6 +827,8 @@ struct tc_codel_xstats {
/* FQ_CODEL */
#define FQ_CODEL_QUANTUM_MAX (1 << 20)
enum {
TCA_FQ_CODEL_UNSPEC,
TCA_FQ_CODEL_TARGET,
@ -838,6 +840,8 @@ enum {
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
};

View File

@ -178,6 +178,13 @@ enum {
RTM_GETVLAN,
#define RTM_GETVLAN RTM_GETVLAN
RTM_NEWNEXTHOPBUCKET = 116,
#define RTM_NEWNEXTHOPBUCKET RTM_NEWNEXTHOPBUCKET
RTM_DELNEXTHOPBUCKET,
#define RTM_DELNEXTHOPBUCKET RTM_DELNEXTHOPBUCKET
RTM_GETNEXTHOPBUCKET,
#define RTM_GETNEXTHOPBUCKET RTM_GETNEXTHOPBUCKET
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@ -283,6 +290,7 @@ enum {
#define RTPROT_MROUTED 17 /* Multicast daemon */
#define RTPROT_KEEPALIVED 18 /* Keepalived daemon */
#define RTPROT_BABEL 42 /* Babel daemon */
#define RTPROT_OPENR 99 /* Open Routing (Open/R) Routes */
#define RTPROT_BGP 186 /* BGP Routes */
#define RTPROT_ISIS 187 /* ISIS Routes */
#define RTPROT_OSPF 188 /* OSPF Routes */

View File

@ -141,6 +141,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_EXPOSE_POTENTIALLY_FAILED_STATE 131
#define SCTP_EXPOSE_PF_STATE SCTP_EXPOSE_POTENTIALLY_FAILED_STATE
#define SCTP_REMOTE_UDP_ENCAPS_PORT 132
#define SCTP_PLPMTUD_PROBE_INTERVAL 133
/* PR-SCTP policies */
#define SCTP_PR_SCTP_NONE 0x0000
@ -1207,4 +1208,11 @@ enum sctp_sched_type {
SCTP_SS_MAX = SCTP_SS_RR
};
/* Probe Interval socket option */
struct sctp_probeinterval {
sctp_assoc_t spi_assoc_id;
struct sockaddr_storage spi_address;
__u32 spi_interval;
};
#endif /* _SCTP_H */

View File

@ -27,6 +27,7 @@ enum {
SEG6_LOCAL_OIF,
SEG6_LOCAL_BPF,
SEG6_LOCAL_VRFTABLE,
SEG6_LOCAL_COUNTERS,
__SEG6_LOCAL_MAX,
};
#define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
@ -63,6 +64,8 @@ enum {
SEG6_LOCAL_ACTION_END_AM = 14,
/* custom BPF action */
SEG6_LOCAL_ACTION_END_BPF = 15,
/* decap and lookup of DA in v4 or v6 table */
SEG6_LOCAL_ACTION_END_DT46 = 16,
__SEG6_LOCAL_ACTION_MAX,
};
@ -78,4 +81,33 @@ enum {
#define SEG6_LOCAL_BPF_PROG_MAX (__SEG6_LOCAL_BPF_PROG_MAX - 1)
/* SRv6 Behavior counters are encoded as netlink attributes guaranteeing the
* correct alignment.
* Each counter is identified by a different attribute type (i.e.
* SEG6_LOCAL_CNT_PACKETS).
*
* - SEG6_LOCAL_CNT_PACKETS: identifies a counter that counts the number of
* packets that have been CORRECTLY processed by an SRv6 Behavior instance
* (i.e., packets that generate errors or are dropped are NOT counted).
*
* - SEG6_LOCAL_CNT_BYTES: identifies a counter that counts the total amount
* of traffic in bytes of all packets that have been CORRECTLY processed by
* an SRv6 Behavior instance (i.e., packets that generate errors or are
* dropped are NOT counted).
*
* - SEG6_LOCAL_CNT_ERRORS: identifies a counter that counts the number of
* packets that have NOT been properly processed by an SRv6 Behavior instance
* (i.e., packets that generate errors or are dropped).
*/
enum {
SEG6_LOCAL_CNT_UNSPEC,
SEG6_LOCAL_CNT_PAD, /* pad for 64 bits values */
SEG6_LOCAL_CNT_PACKETS,
SEG6_LOCAL_CNT_BYTES,
SEG6_LOCAL_CNT_ERRORS,
__SEG6_LOCAL_CNT_MAX,
};
#define SEG6_LOCAL_CNT_MAX (__SEG6_LOCAL_CNT_MAX - 1)
#endif

View File

@ -290,6 +290,8 @@ enum
LINUX_MIB_TCPDUPLICATEDATAREHASH, /* TCPDuplicateDataRehash */
LINUX_MIB_TCPDSACKRECVSEGS, /* TCPDSACKRecvSegs */
LINUX_MIB_TCPDSACKIGNOREDDUBIOUS, /* TCPDSACKIgnoredDubious */
LINUX_MIB_TCPMIGRATEREQSUCCESS, /* TCPMigrateReqSuccess */
LINUX_MIB_TCPMIGRATEREQFAILURE, /* TCPMigrateReqFailure */
__LINUX_MIB_MAX
};

View File

@ -26,4 +26,9 @@ struct __kernel_sockaddr_storage {
};
};
#define SOCK_SNDBUF_LOCK 1
#define SOCK_RCVBUF_LOCK 2
#define SOCK_BUF_LOCK_MASK (SOCK_SNDBUF_LOCK | SOCK_RCVBUF_LOCK)
#endif /* _LINUX_SOCKET_H */

View File

@ -4,3 +4,40 @@
#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[]; \
}

View File

@ -17,6 +17,7 @@
#define SKBMOD_F_SMAC 0x2
#define SKBMOD_F_ETYPE 0x4
#define SKBMOD_F_SWAPMAC 0x8
#define SKBMOD_F_ECN 0x10
struct tc_skbmod {
tc_gen;

View File

@ -84,6 +84,20 @@
#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_SET_RECORD_TYPE 1
#define TLS_GET_RECORD_TYPE 2
@ -124,6 +138,22 @@ struct tls12_crypto_info_chacha20_poly1305 {
unsigned char rec_seq[TLS_CIPHER_CHACHA20_POLY1305_REC_SEQ_SIZE];
};
struct tls12_crypto_info_sm4_gcm {
struct tls_crypto_info info;
unsigned char iv[TLS_CIPHER_SM4_GCM_IV_SIZE];
unsigned char key[TLS_CIPHER_SM4_GCM_KEY_SIZE];
unsigned char salt[TLS_CIPHER_SM4_GCM_SALT_SIZE];
unsigned char rec_seq[TLS_CIPHER_SM4_GCM_REC_SEQ_SIZE];
};
struct tls12_crypto_info_sm4_ccm {
struct tls_crypto_info info;
unsigned char iv[TLS_CIPHER_SM4_CCM_IV_SIZE];
unsigned char key[TLS_CIPHER_SM4_CCM_KEY_SIZE];
unsigned char salt[TLS_CIPHER_SM4_CCM_SALT_SIZE];
unsigned char rec_seq[TLS_CIPHER_SM4_CCM_REC_SEQ_SIZE];
};
enum {
TLS_INFO_UNSPEC,
TLS_INFO_VERSION,

View File

@ -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

@ -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 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 */
#endif /* _LINUX_VIRTIO_IDS_H */

16
include/uapi/linux/wwan.h Normal file
View File

@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
* Copyright (C) 2021 Intel Corporation.
*/
#ifndef _WWAN_H_
#define _WWAN_H_
enum {
IFLA_WWAN_UNSPEC,
IFLA_WWAN_LINK_ID, /* u32 */
__IFLA_WWAN_MAX
};
#define IFLA_WWAN_MAX (__IFLA_WWAN_MAX - 1)
#endif /* _WWAN_H_ */

View File

@ -215,6 +215,11 @@ enum {
XFRM_MSG_MAPPING,
#define XFRM_MSG_MAPPING XFRM_MSG_MAPPING
XFRM_MSG_SETDEFAULT,
#define XFRM_MSG_SETDEFAULT XFRM_MSG_SETDEFAULT
XFRM_MSG_GETDEFAULT,
#define XFRM_MSG_GETDEFAULT XFRM_MSG_GETDEFAULT
__XFRM_MSG_MAX
};
#define XFRM_MSG_MAX (__XFRM_MSG_MAX - 1)
@ -508,6 +513,15 @@ struct xfrm_user_offload {
#define XFRM_OFFLOAD_IPV6 1
#define XFRM_OFFLOAD_INBOUND 2
struct xfrm_userpolicy_default {
#define XFRM_USERPOLICY_UNSPEC 0
#define XFRM_USERPOLICY_BLOCK 1
#define XFRM_USERPOLICY_ACCEPT 2
__u8 in;
__u8 fwd;
__u8 out;
};
/* backwards compatibility for userspace */
#define XFRMGRP_ACQUIRE 1
#define XFRMGRP_EXPIRE 2

View File

@ -8,6 +8,7 @@
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
#include <stdint.h>
#ifdef HAVE_LIBBSD
#include <bsd/string.h>
@ -50,6 +51,9 @@ void incomplete_command(void) __attribute__((noreturn));
#define NEXT_ARG_FWD() do { argv++; argc--; } while(0)
#define PREV_ARG() do { argv--; argc++; } while(0)
/* Upper limit for batch mode */
#define MAX_ARGS 512
#define TIME_UNITS_PER_SEC 1000000
#define NSEC_PER_USEC 1000
#define NSEC_PER_MSEC 1000000
@ -105,17 +109,6 @@ static inline bool is_addrtype_inet_not_multi(const inet_prefix *p)
return (p->flags & ADDRTYPE_INET_MULTI) == ADDRTYPE_INET;
}
#define DN_MAXADDL 20
#ifndef AF_DECnet
#define AF_DECnet 12
#endif
struct dn_naddr
{
unsigned short a_len;
unsigned char a_addr[DN_MAXADDL];
};
#ifndef AF_MPLS
# define AF_MPLS 28
#endif
@ -205,9 +198,15 @@ bool matches(const char *prefix, const char *string);
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);
@ -264,7 +263,7 @@ 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[]);
#define BIT(nr) (1UL << (nr))
#define BIT(nr) (UINT64_C(1) << (nr))
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
@ -308,6 +307,7 @@ char *find_cgroup2_mount(bool do_mount);
__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_rtnl_link_stats_rta(struct rtnl_link_stats64 *stats64,
struct rtattr *tb[]);

View File

@ -1 +1 @@
static const char version[] = "5.12.0";
static const char version[] = "5.15.0";

View File

@ -11,14 +11,15 @@ IPOBJ=ip.o ipaddress.o ipaddrlabel.o iproute.o iprule.o ipnetns.o \
iplink_bridge.o iplink_bridge_slave.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
ipnexthop.o ipmptcp.o iplink_bareudp.o iplink_wwan.o ipioam6.o \
iplink_amt.o
RTMONOBJ=rtmon.o
include ../config.mk
ALLOBJ=$(IPOBJ) $(RTMONOBJ)
SCRIPTS=ifcfg rtpr routel routef
SCRIPTS=routel
TARGETS=ip rtmon
all: $(TARGETS) $(SCRIPTS)

150
ip/ifcfg
View File

@ -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

25
ip/ip.c
View File

@ -64,15 +64,15 @@ static void usage(void)
fprintf(stderr,
"Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n"
" ip [ -force ] -batch filename\n"
"where OBJECT := { address | addrlabel | fou | help | ila | 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"
" OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n"
" -h[uman-readable] | -iec | -j[son] | -p[retty] |\n"
" -f[amily] { inet | inet6 | mpls | bridge | link } |\n"
" -4 | -6 | -I | -D | -M | -B | -0 |\n"
" -4 | -6 | -M | -B | -0 |\n"
" -l[oops] { maximum-addr-flush-attempts } | -br[ief] |\n"
" -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |\n"
" -rc[vbuf] [size] | -n[etns] name | -N[umeric] | -a[ll] |\n"
@ -121,11 +121,12 @@ static const struct cmd {
{ "sr", do_seg6 },
{ "nexthop", do_ipnh },
{ "mptcp", do_mptcp },
{ "ioam", do_ioam6 },
{ "help", do_help },
{ 0 }
};
static int do_cmd(const char *argv0, int argc, char **argv)
static int do_cmd(const char *argv0, int argc, char **argv, bool final)
{
const struct cmd *c;
@ -134,7 +135,8 @@ static int do_cmd(const char *argv0, int argc, char **argv)
return -(c->func(argc-1, argv+1));
}
fprintf(stderr, "Object \"%s\" is unknown, try \"ip help\".\n", argv0);
if (final)
fprintf(stderr, "Object \"%s\" is unknown, try \"ip help\".\n", argv0);
return EXIT_FAILURE;
}
@ -143,7 +145,7 @@ static int ip_batch_cmd(int argc, char *argv[], void *data)
const int *orig_family = data;
preferred_family = *orig_family;
return do_cmd(argv[0], argc, argv);
return do_cmd(argv[0], argc, argv, true);
}
static int batch(const char *name)
@ -222,8 +224,6 @@ int main(int argc, char **argv)
preferred_family = AF_INET6;
} else if (strcmp(opt, "-0") == 0) {
preferred_family = AF_PACKET;
} else if (strcmp(opt, "-D") == 0) {
preferred_family = AF_DECnet;
} else if (strcmp(opt, "-M") == 0) {
preferred_family = AF_MPLS;
} else if (strcmp(opt, "-B") == 0) {
@ -313,11 +313,14 @@ int main(int argc, char **argv)
rtnl_set_strict_dump(&rth);
if (strlen(basename) > 2)
return do_cmd(basename+2, argc, argv);
if (strlen(basename) > 2) {
int ret = do_cmd(basename+2, argc, argv, false);
if (ret != EXIT_FAILURE)
return ret;
}
if (argc > 1)
return do_cmd(argv[1], argc-1, argv+1);
return do_cmd(argv[1], argc-1, argv+1, true);
rtnl_close(&rth);
usage();

View File

@ -53,7 +53,7 @@ int print_prefix(struct nlmsghdr *n, void *arg);
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);
@ -89,6 +89,7 @@ int netns_identify_pid(const char *pidstr, char *name, int len);
int do_seg6(int argc, char **argv);
int do_ipnh(int argc, char **argv);
int do_mptcp(int argc, char **argv);
int do_ioam6(int argc, char **argv);
int iplink_get(char *name, __u32 filt_mask);
int iplink_ifla_xstats(int argc, char **argv);
@ -166,7 +167,8 @@ int name_is_vrf(const char *name);
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);
#endif /* _IP_COMMON_H_ */

View File

@ -10,6 +10,7 @@
*
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -59,6 +60,7 @@ static void usage(void)
" 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"
@ -544,6 +546,29 @@ static void print_vfinfo(FILE *fp, struct ifinfomsg *ifi, struct rtattr *vfinfo)
print_vf_stats64(fp, vf[IFLA_VF_STATS]);
}
static void size_columns(unsigned int cols[], unsigned int n, ...)
{
unsigned int i, len;
uint64_t val, powi;
va_list args;
va_start(args, n);
for (i = 0; i < n; i++) {
val = va_arg(args, unsigned long long);
if (human_readable)
continue;
for (len = 1, powi = 10; powi < val; len++, powi *= 10)
/* nothing */;
if (len > cols[i])
cols[i] = len;
}
va_end(args);
}
void print_num(FILE *fp, unsigned int width, uint64_t count)
{
const char *prefix = "kMGTPE";
@ -554,7 +579,7 @@ void print_num(FILE *fp, unsigned int width, uint64_t count)
char buf[64];
if (!human_readable || count < base) {
fprintf(fp, "%-*"PRIu64" ", width, count);
fprintf(fp, "%*"PRIu64" ", width, count);
return;
}
@ -581,7 +606,7 @@ void print_num(FILE *fp, unsigned int width, uint64_t count)
snprintf(buf, sizeof(buf), "%.*f%c%s", precision,
(double) count / powi, *prefix, use_iec ? "i" : "");
fprintf(fp, "%-*s ", width, buf);
fprintf(fp, "%*s ", width, buf);
}
static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
@ -659,6 +684,15 @@ static void __print_link_stats(FILE *fp, struct rtattr *tb[])
{
const struct rtattr *carrier_changes = tb[IFLA_CARRIER_CHANGES];
struct rtnl_link_stats64 _s, *s = &_s;
unsigned int cols[] = {
strlen("*X errors:"),
strlen("packets"),
strlen("errors"),
strlen("dropped"),
strlen("heartbt"),
strlen("overrun"),
strlen("compressed"),
};
int ret;
ret = get_rtnl_link_stats_rta(s, tb);
@ -739,65 +773,98 @@ static void __print_link_stats(FILE *fp, struct rtattr *tb[])
close_json_object();
close_json_object();
} else {
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);
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);
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)
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);
/* RX stats */
fprintf(fp, " RX: bytes packets errors dropped missed mcast %s%s",
s->rx_compressed ? "compressed" : "", _SL_);
fprintf(fp, " RX: %*s %*s %*s %*s %*s %*s %*s%s",
cols[0] - 4, "bytes", cols[1], "packets",
cols[2], "errors", cols[3], "dropped",
cols[4], "missed", cols[5], "mcast",
cols[6], s->rx_compressed ? "compressed" : "", _SL_);
fprintf(fp, " ");
print_num(fp, 10, s->rx_bytes);
print_num(fp, 8, s->rx_packets);
print_num(fp, 7, s->rx_errors);
print_num(fp, 7, s->rx_dropped);
print_num(fp, 7, s->rx_missed_errors);
print_num(fp, 7, s->multicast);
print_num(fp, cols[0], s->rx_bytes);
print_num(fp, cols[1], s->rx_packets);
print_num(fp, cols[2], s->rx_errors);
print_num(fp, cols[3], s->rx_dropped);
print_num(fp, cols[4], s->rx_missed_errors);
print_num(fp, cols[5], s->multicast);
if (s->rx_compressed)
print_num(fp, 7, s->rx_compressed);
print_num(fp, cols[6], s->rx_compressed);
/* RX error stats */
if (show_stats > 1) {
fprintf(fp, "%s", _SL_);
fprintf(fp, " RX errors: length crc frame fifo overrun%s%s",
s->rx_nohandler ? " nohandler" : "", _SL_);
fprintf(fp, " ");
print_num(fp, 8, s->rx_length_errors);
print_num(fp, 7, s->rx_crc_errors);
print_num(fp, 7, s->rx_frame_errors);
print_num(fp, 7, s->rx_fifo_errors);
print_num(fp, 7, s->rx_over_errors);
fprintf(fp, " RX errors:%*s %*s %*s %*s %*s %*s %*s%s",
cols[0] - 10, "", cols[1], "length",
cols[2], "crc", cols[3], "frame",
cols[4], "fifo", cols[5], "overrun",
cols[6], s->rx_nohandler ? "nohandler" : "",
_SL_);
fprintf(fp, "%*s", cols[0] + 5, "");
print_num(fp, cols[1], s->rx_length_errors);
print_num(fp, cols[2], s->rx_crc_errors);
print_num(fp, cols[3], s->rx_frame_errors);
print_num(fp, cols[4], s->rx_fifo_errors);
print_num(fp, cols[5], s->rx_over_errors);
if (s->rx_nohandler)
print_num(fp, 7, s->rx_nohandler);
print_num(fp, cols[6], s->rx_nohandler);
}
fprintf(fp, "%s", _SL_);
/* TX stats */
fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
s->tx_compressed ? "compressed" : "", _SL_);
fprintf(fp, " TX: %*s %*s %*s %*s %*s %*s %*s%s",
cols[0] - 4, "bytes", cols[1], "packets",
cols[2], "errors", cols[3], "dropped",
cols[4], "carrier", cols[5], "collsns",
cols[6], s->tx_compressed ? "compressed" : "", _SL_);
fprintf(fp, " ");
print_num(fp, 10, s->tx_bytes);
print_num(fp, 8, s->tx_packets);
print_num(fp, 7, s->tx_errors);
print_num(fp, 7, s->tx_dropped);
print_num(fp, 7, s->tx_carrier_errors);
print_num(fp, 7, s->collisions);
print_num(fp, cols[0], s->tx_bytes);
print_num(fp, cols[1], s->tx_packets);
print_num(fp, cols[2], s->tx_errors);
print_num(fp, cols[3], s->tx_dropped);
print_num(fp, cols[4], s->tx_carrier_errors);
print_num(fp, cols[5], s->collisions);
if (s->tx_compressed)
print_num(fp, 7, s->tx_compressed);
print_num(fp, cols[6], s->tx_compressed);
/* TX error stats */
if (show_stats > 1) {
fprintf(fp, "%s", _SL_);
fprintf(fp, " TX errors: aborted fifo window heartbeat");
if (carrier_changes)
fprintf(fp, " transns");
fprintf(fp, "%s", _SL_);
fprintf(fp, " TX errors:%*s %*s %*s %*s %*s %*s%s",
cols[0] - 10, "", cols[1], "aborted",
cols[2], "fifo", cols[3], "window",
cols[4], "heartbt",
cols[5], carrier_changes ? "transns" : "",
_SL_);
fprintf(fp, " ");
print_num(fp, 8, s->tx_aborted_errors);
print_num(fp, 7, s->tx_fifo_errors);
print_num(fp, 7, s->tx_window_errors);
print_num(fp, 7, s->tx_heartbeat_errors);
fprintf(fp, "%*s", cols[0] + 5, "");
print_num(fp, cols[1], s->tx_aborted_errors);
print_num(fp, cols[2], s->tx_fifo_errors);
print_num(fp, cols[3], s->tx_window_errors);
print_num(fp, cols[4], s->tx_heartbeat_errors);
if (carrier_changes)
print_num(fp, 7,
print_num(fp, cols[5],
rta_getattr_u32(carrier_changes));
}
}
@ -1176,6 +1243,20 @@ int print_linkinfo(struct nlmsghdr *n, void *arg)
RTA_PAYLOAD(tb[IFLA_PHYS_SWITCH_ID]),
b1, sizeof(b1)));
}
if (tb[IFLA_PARENT_DEV_BUS_NAME]) {
print_string(PRINT_ANY,
"parentbus",
"parentbus %s ",
rta_getattr_str(tb[IFLA_PARENT_DEV_BUS_NAME]));
}
if (tb[IFLA_PARENT_DEV_NAME]) {
print_string(PRINT_ANY,
"parentdev",
"parentdev %s ",
rta_getattr_str(tb[IFLA_PARENT_DEV_NAME]));
}
}
if ((do_link || show_details) && tb[IFLA_IFALIAS]) {
@ -2043,6 +2124,8 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
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;

333
ip/ipioam6.c Normal file
View File

@ -0,0 +1,333 @@
// SPDX-License-Identifier: GPL-2.0
/*
* ioam6.c "ip ioam"
*
* Author: Justin Iurman <justin.iurman@uliege.be>
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#include <linux/genetlink.h>
#include <linux/ioam6_genl.h>
#include "utils.h"
#include "ip_common.h"
#include "libgenl.h"
#include "json_print.h"
static void usage(void)
{
fprintf(stderr,
"Usage: ip ioam { COMMAND | help }\n"
" ip ioam namespace show\n"
" ip ioam namespace add ID [ data DATA32 ] [ wide DATA64 ]\n"
" ip ioam namespace del ID\n"
" ip ioam schema show\n"
" ip ioam schema add ID DATA\n"
" ip ioam schema del ID\n"
" ip ioam namespace set ID schema { ID | none }\n");
exit(-1);
}
static struct rtnl_handle grth = { .fd = -1 };
static int genl_family = -1;
#define IOAM6_REQUEST(_req, _bufsiz, _cmd, _flags) \
GENL_REQUEST(_req, _bufsiz, genl_family, 0, \
IOAM6_GENL_VERSION, _cmd, _flags)
static struct {
unsigned int cmd;
__u32 sc_id;
__u32 ns_data;
__u64 ns_data_wide;
__u16 ns_id;
bool has_ns_data;
bool has_ns_data_wide;
bool sc_none;
__u8 sc_data[IOAM6_MAX_SCHEMA_DATA_LEN];
} opts;
static void print_namespace(struct rtattr *attrs[])
{
print_uint(PRINT_ANY, "namespace", "namespace %u",
rta_getattr_u16(attrs[IOAM6_ATTR_NS_ID]));
if (attrs[IOAM6_ATTR_SC_ID])
print_uint(PRINT_ANY, "schema", " [schema %u]",
rta_getattr_u32(attrs[IOAM6_ATTR_SC_ID]));
if (attrs[IOAM6_ATTR_NS_DATA])
print_hex(PRINT_ANY, "data", ", data %#010x",
rta_getattr_u32(attrs[IOAM6_ATTR_NS_DATA]));
if (attrs[IOAM6_ATTR_NS_DATA_WIDE])
print_0xhex(PRINT_ANY, "wide", ", wide %#018lx",
rta_getattr_u64(attrs[IOAM6_ATTR_NS_DATA_WIDE]));
print_nl();
}
static void print_schema(struct rtattr *attrs[])
{
__u8 data[IOAM6_MAX_SCHEMA_DATA_LEN];
int len, i = 0;
print_uint(PRINT_ANY, "schema", "schema %u",
rta_getattr_u32(attrs[IOAM6_ATTR_SC_ID]));
if (attrs[IOAM6_ATTR_NS_ID])
print_uint(PRINT_ANY, "namespace", " [namespace %u]",
rta_getattr_u16(attrs[IOAM6_ATTR_NS_ID]));
len = RTA_PAYLOAD(attrs[IOAM6_ATTR_SC_DATA]);
memcpy(data, RTA_DATA(attrs[IOAM6_ATTR_SC_DATA]), len);
print_null(PRINT_ANY, "data", ", data:", NULL);
while (i < len) {
print_hhu(PRINT_ANY, "", " %02x", data[i]);
i++;
}
print_nl();
}
static int process_msg(struct nlmsghdr *n, void *arg)
{
struct rtattr *attrs[IOAM6_ATTR_MAX + 1];
struct genlmsghdr *ghdr;
int len = n->nlmsg_len;
if (n->nlmsg_type != genl_family)
return -1;
len -= NLMSG_LENGTH(GENL_HDRLEN);
if (len < 0)
return -1;
ghdr = NLMSG_DATA(n);
parse_rtattr(attrs, IOAM6_ATTR_MAX, (void *)ghdr + GENL_HDRLEN, len);
open_json_object(NULL);
switch (ghdr->cmd) {
case IOAM6_CMD_DUMP_NAMESPACES:
print_namespace(attrs);
break;
case IOAM6_CMD_DUMP_SCHEMAS:
print_schema(attrs);
break;
}
close_json_object();
return 0;
}
static int ioam6_do_cmd(void)
{
IOAM6_REQUEST(req, 1056, opts.cmd, NLM_F_REQUEST);
int dump = 0;
if (genl_init_handle(&grth, IOAM6_GENL_NAME, &genl_family))
exit(1);
req.n.nlmsg_type = genl_family;
switch (opts.cmd) {
case IOAM6_CMD_ADD_NAMESPACE:
addattr16(&req.n, sizeof(req), IOAM6_ATTR_NS_ID, opts.ns_id);
if (opts.has_ns_data)
addattr32(&req.n, sizeof(req), IOAM6_ATTR_NS_DATA,
opts.ns_data);
if (opts.has_ns_data_wide)
addattr64(&req.n, sizeof(req), IOAM6_ATTR_NS_DATA_WIDE,
opts.ns_data_wide);
break;
case IOAM6_CMD_DEL_NAMESPACE:
addattr16(&req.n, sizeof(req), IOAM6_ATTR_NS_ID, opts.ns_id);
break;
case IOAM6_CMD_DUMP_NAMESPACES:
case IOAM6_CMD_DUMP_SCHEMAS:
dump = 1;
break;
case IOAM6_CMD_ADD_SCHEMA:
addattr32(&req.n, sizeof(req), IOAM6_ATTR_SC_ID, opts.sc_id);
addattr_l(&req.n, sizeof(req), IOAM6_ATTR_SC_DATA, opts.sc_data,
strlen((const char *)opts.sc_data));
break;
case IOAM6_CMD_DEL_SCHEMA:
addattr32(&req.n, sizeof(req), IOAM6_ATTR_SC_ID, opts.sc_id);
break;
case IOAM6_CMD_NS_SET_SCHEMA:
addattr16(&req.n, sizeof(req), IOAM6_ATTR_NS_ID, opts.ns_id);
if (opts.sc_none)
addattr(&req.n, sizeof(req), IOAM6_ATTR_SC_NONE);
else
addattr32(&req.n, sizeof(req), IOAM6_ATTR_SC_ID,
opts.sc_id);
break;
}
if (!dump) {
if (rtnl_talk(&grth, &req.n, NULL) < 0)
return -1;
} else {
req.n.nlmsg_flags |= NLM_F_DUMP;
req.n.nlmsg_seq = grth.dump = ++grth.seq;
if (rtnl_send(&grth, &req, req.n.nlmsg_len) < 0) {
perror("Failed to send dump request");
exit(1);
}
new_json_obj(json);
if (rtnl_dump_filter(&grth, process_msg, stdout) < 0) {
fprintf(stderr, "Dump terminated\n");
exit(1);
}
delete_json_obj();
fflush(stdout);
}
return 0;
}
int do_ioam6(int argc, char **argv)
{
bool maybe_wide = false;
if (argc < 1 || strcmp(*argv, "help") == 0)
usage();
memset(&opts, 0, sizeof(opts));
if (strcmp(*argv, "namespace") == 0) {
NEXT_ARG();
if (strcmp(*argv, "show") == 0) {
opts.cmd = IOAM6_CMD_DUMP_NAMESPACES;
} else if (strcmp(*argv, "add") == 0) {
NEXT_ARG();
if (get_u16(&opts.ns_id, *argv, 0))
invarg("Invalid namespace ID", *argv);
if (NEXT_ARG_OK()) {
NEXT_ARG_FWD();
if (strcmp(*argv, "data") == 0) {
NEXT_ARG();
if (get_u32(&opts.ns_data, *argv, 0))
invarg("Invalid data", *argv);
maybe_wide = true;
opts.has_ns_data = true;
} else if (strcmp(*argv, "wide") == 0) {
NEXT_ARG();
if (get_u64(&opts.ns_data_wide, *argv, 16))
invarg("Invalid wide data", *argv);
opts.has_ns_data_wide = true;
} else {
invarg("Invalid argument", *argv);
}
}
if (NEXT_ARG_OK()) {
NEXT_ARG_FWD();
if (!maybe_wide || strcmp(*argv, "wide") != 0)
invarg("Unexpected argument", *argv);
NEXT_ARG();
if (get_u64(&opts.ns_data_wide, *argv, 16))
invarg("Invalid wide data", *argv);
opts.has_ns_data_wide = true;
}
opts.cmd = IOAM6_CMD_ADD_NAMESPACE;
} else if (strcmp(*argv, "del") == 0) {
NEXT_ARG();
if (get_u16(&opts.ns_id, *argv, 0))
invarg("Invalid namespace ID", *argv);
opts.cmd = IOAM6_CMD_DEL_NAMESPACE;
} else if (strcmp(*argv, "set") == 0) {
NEXT_ARG();
if (get_u16(&opts.ns_id, *argv, 0))
invarg("Invalid namespace ID", *argv);
NEXT_ARG();
if (strcmp(*argv, "schema") != 0)
invarg("Unknown", *argv);
NEXT_ARG();
if (strcmp(*argv, "none") == 0) {
opts.sc_none = true;
} else {
if (get_u32(&opts.sc_id, *argv, 0))
invarg("Invalid schema ID", *argv);
opts.sc_none = false;
}
opts.cmd = IOAM6_CMD_NS_SET_SCHEMA;
} else {
invarg("Unknown", *argv);
}
} else if (strcmp(*argv, "schema") == 0) {
NEXT_ARG();
if (strcmp(*argv, "show") == 0) {
opts.cmd = IOAM6_CMD_DUMP_SCHEMAS;
} else if (strcmp(*argv, "add") == 0) {
NEXT_ARG();
if (get_u32(&opts.sc_id, *argv, 0))
invarg("Invalid schema ID", *argv);
NEXT_ARG();
if (strlen(*argv) > IOAM6_MAX_SCHEMA_DATA_LEN)
invarg("Schema DATA too big", *argv);
memcpy(opts.sc_data, *argv, strlen(*argv));
opts.cmd = IOAM6_CMD_ADD_SCHEMA;
} else if (strcmp(*argv, "del") == 0) {
NEXT_ARG();
if (get_u32(&opts.sc_id, *argv, 0))
invarg("Invalid schema ID", *argv);
opts.cmd = IOAM6_CMD_DEL_SCHEMA;
} else {
invarg("Unknown", *argv);
}
} else {
invarg("Unknown", *argv);
}
return ioam6_do_cmd();
}

View File

@ -50,20 +50,21 @@ void iplink_types_usage(void)
{
/* Remember to add new entry here if new type is added. */
fprintf(stderr,
"TYPE := { bareudp | bond | bond_slave | bridge | bridge_slave |\n"
"TYPE := { amt | bareudp | bond | bond_slave | bridge | bridge_slave |\n"
" dummy | erspan | geneve | gre | gretap | 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 | xfrm }\n");
" vcan | veth | vlan | vrf | vti | vxcan | vxlan | wwan |\n"
" xfrm }\n");
}
void iplink_usage(void)
{
if (iplink_have_newlink()) {
fprintf(stderr,
"Usage: ip link add [link DEV] [ name ] NAME\n"
"Usage: ip link add [link DEV | parentdev NAME] [ name ] NAME\n"
" [ txqueuelen PACKETS ]\n"
" [ address LLADDR ]\n"
" [ broadcast LLADDR ]\n"
@ -119,6 +120,7 @@ void iplink_usage(void)
" [ gso_max_size BYTES ] | [ gso_max_segs PACKETS ]\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"
@ -577,6 +579,7 @@ static int iplink_parse_vf(int vf, int *argcp, char ***argvp,
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;
@ -682,6 +685,7 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
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;
@ -938,6 +942,10 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
*argv);
addattr32(&req->n, sizeof(*req),
IFLA_GSO_MAX_SEGS, max_segs);
} else if (strcmp(*argv, "parentdev") == 0) {
NEXT_ARG();
addattr_l(&req->n, sizeof(*req), IFLA_PARENT_DEV_NAME,
*argv, strlen(*argv) + 1);
} else {
if (matches(*argv, "help") == 0)
usage();
@ -975,9 +983,11 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
}
}
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);
}
@ -1014,6 +1024,9 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req, char **type)
/* 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,

200
ip/iplink_amt.c Normal file
View File

@ -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 (tb[IFLA_AMT_MODE])
print_string(PRINT_ANY, "mode", "%s ",
modename[rta_getattr_u32(tb[IFLA_AMT_MODE])]);
if (tb[IFLA_AMT_GATEWAY_PORT])
print_uint(PRINT_ANY, "gateway_port", "gateway_port %u ",
rta_getattr_be16(tb[IFLA_AMT_GATEWAY_PORT]));
if (tb[IFLA_AMT_RELAY_PORT])
print_uint(PRINT_ANY, "relay_port", "relay_port %u ",
rta_getattr_be16(tb[IFLA_AMT_RELAY_PORT]));
if (tb[IFLA_AMT_LOCAL_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_LOCAL_IP]);
print_string(PRINT_ANY, "local", "local %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_REMOTE_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_REMOTE_IP]);
print_string(PRINT_ANY, "remote", "remote %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_DISCOVERY_IP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_AMT_DISCOVERY_IP]);
print_string(PRINT_ANY, "discovery", "discovery %s ",
format_host(AF_INET, 4, &addr));
}
if (tb[IFLA_AMT_LINK]) {
unsigned int link = rta_getattr_u32(tb[IFLA_AMT_LINK]);
print_string(PRINT_ANY, "link", "dev %s ",
ll_index_to_name(link));
}
if (tb[IFLA_AMT_MAX_TUNNELS])
print_uint(PRINT_ANY, "max_tunnels", "max_tunnels %u ",
rta_getattr_u32(tb[IFLA_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

@ -41,6 +41,9 @@ static const char *arp_validate_tbl[] = {
"active",
"backup",
"all",
"filter",
"filter_active",
"filter_backup",
NULL,
};
@ -74,6 +77,12 @@ static const char *xmit_hash_policy_tbl[] = {
NULL,
};
static const char *lacp_active_tbl[] = {
"off",
"on",
NULL,
};
static const char *lacp_rate_tbl[] = {
"slow",
"fast",
@ -139,17 +148,19 @@ static void print_explain(FILE *f)
" [ packets_per_slave PACKETS_PER_SLAVE ]\n"
" [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n"
" [ lacp_rate LACP_RATE ]\n"
" [ lacp_active LACP_ACTIVE]\n"
" [ ad_select AD_SELECT ]\n"
" [ ad_user_port_key PORTKEY ]\n"
" [ ad_actor_sys_prio SYSPRIO ]\n"
" [ ad_actor_system LLADDR ]\n"
"\n"
"BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n"
"ARP_VALIDATE := none|active|backup|all\n"
"ARP_VALIDATE := none|active|backup|all|filter|filter_active|filter_backup\n"
"ARP_ALL_TARGETS := any|all\n"
"PRIMARY_RESELECT := always|better|failure\n"
"FAIL_OVER_MAC := none|active|follow\n"
"XMIT_HASH_POLICY := layer2|layer2+3|layer3+4|encap2+3|encap3+4|vlan+srcmac\n"
"LACP_ACTIVE := off|on\n"
"LACP_RATE := slow|fast\n"
"AD_SELECT := stable|bandwidth|count\n"
);
@ -165,7 +176,7 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
{
__u8 mode, use_carrier, primary_reselect, fail_over_mac;
__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
__u8 lacp_rate, ad_select, tlb_dynamic_lb;
__u8 lacp_active, lacp_rate, ad_select, tlb_dynamic_lb;
__u16 ad_user_port_key, ad_actor_sys_prio;
__u32 miimon, updelay, downdelay, peer_notify_delay, arp_interval, arp_validate;
__u32 arp_all_targets, resend_igmp, min_links, lp_interval;
@ -323,6 +334,13 @@ static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
lacp_rate = get_index(lacp_rate_tbl, *argv);
addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
} else if (strcmp(*argv, "lacp_active") == 0) {
NEXT_ARG();
if (get_index(lacp_active_tbl, *argv) < 0)
invarg("invalid lacp_active", *argv);
lacp_active = get_index(lacp_active_tbl, *argv);
addattr8(n, 1024, IFLA_BOND_AD_LACP_ACTIVE, lacp_active);
} else if (matches(*argv, "ad_select") == 0) {
NEXT_ARG();
if (get_index(ad_select_tbl, *argv) < 0)
@ -561,6 +579,15 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
"packets_per_slave %u ",
rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
if (tb[IFLA_BOND_AD_LACP_ACTIVE]) {
const char *lacp_active = get_name(lacp_active_tbl,
rta_getattr_u8(tb[IFLA_BOND_AD_LACP_ACTIVE]));
print_string(PRINT_ANY,
"ad_lacp_active",
"lacp_active %s ",
lacp_active);
}
if (tb[IFLA_BOND_AD_LACP_RATE]) {
const char *lacp_rate = get_name(lacp_rate_tbl,
rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));

View File

@ -43,6 +43,7 @@ static void print_explain(FILE *f)
" [ 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 +84,7 @@ void br_dump_bridge_id(const struct ifla_bridge_id *id, char *buf, size_t len)
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) {
@ -200,6 +202,18 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
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 +393,9 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
argc--, argv++;
}
if (bm.optmask)
addattr_l(n, 1024, IFLA_BR_MULTI_BOOLOPT,
&bm, sizeof(bm));
return 0;
}
@ -559,6 +576,18 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
"mcast_snooping %u ",
rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
if (tb[IFLA_BR_MULTI_BOOLOPT]) {
__u32 mcvl_bit = 1 << BR_BOOLOPT_MCAST_VLAN_SNOOPING;
struct br_boolopt_multi *bm;
bm = RTA_DATA(tb[IFLA_BR_MULTI_BOOLOPT]);
if (bm->optmask & mcvl_bit)
print_uint(PRINT_ANY,
"mcast_vlan_snooping",
"mcast_vlan_snooping %u ",
!!(bm->optval & mcvl_bit));
}
if (tb[IFLA_BR_MCAST_ROUTER])
print_uint(PRINT_ANY,
"mcast_router",

View File

@ -28,6 +28,7 @@ static void print_usage(FILE *f)
"\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 @@ static void print_usage(FILE *f)
"\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 @@ static void set_ctrlmode(char *name, char *arg,
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 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
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 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
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 @@ static int can_parse_opt(struct link_util *lu, int argc, char **argv,
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,11 +324,75 @@ static const char *can_state_names[CAN_STATE_MAX] = {
[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)
{
open_json_object(attr);
print_int(PRINT_JSON, "min", NULL, min);
print_int(PRINT_JSON, "max", NULL, max);
print_nl();
print_string(PRINT_FP, NULL, "%s", "\t ");
}
static void can_print_timing_min_max(const char *json_attr, const char *fp_attr,
int min, int 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 *tb[IFLA_CAN_TDC_MAX + 1];
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
if (tb[IFLA_CAN_TDC_TDCV] || tb[IFLA_CAN_TDC_TDCO] ||
tb[IFLA_CAN_TDC_TDCF]) {
open_json_object("tdc");
can_print_nl_indent();
if (tb[IFLA_CAN_TDC_TDCV]) {
__u32 *tdcv = RTA_DATA(tb[IFLA_CAN_TDC_TDCV]);
print_uint(PRINT_ANY, "tdcv", " tdcv %u", *tdcv);
}
if (tb[IFLA_CAN_TDC_TDCO]) {
__u32 *tdco = RTA_DATA(tb[IFLA_CAN_TDC_TDCO]);
print_uint(PRINT_ANY, "tdco", " tdco %u", *tdco);
}
if (tb[IFLA_CAN_TDC_TDCF]) {
__u32 *tdcf = RTA_DATA(tb[IFLA_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 *tb[IFLA_CAN_TDC_MAX + 1];
parse_rtattr_nested(tb, IFLA_CAN_TDC_MAX, tdc_attr);
open_json_object("tdc");
can_print_nl_indent();
if (tb[IFLA_CAN_TDC_TDCV_MIN] && tb[IFLA_CAN_TDC_TDCV_MAX]) {
__u32 *tdcv_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MIN]);
__u32 *tdcv_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCV_MAX]);
can_print_timing_min_max("tdcv", " tdcv", *tdcv_min, *tdcv_max);
}
if (tb[IFLA_CAN_TDC_TDCO_MIN] && tb[IFLA_CAN_TDC_TDCO_MAX]) {
__u32 *tdco_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MIN]);
__u32 *tdco_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCO_MAX]);
can_print_timing_min_max("tdco", " tdco", *tdco_min, *tdco_max);
}
if (tb[IFLA_CAN_TDC_TDCF_MIN] && tb[IFLA_CAN_TDC_TDCF_MAX]) {
__u32 *tdcf_min = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MIN]);
__u32 *tdcf_max = RTA_DATA(tb[IFLA_CAN_TDC_TDCF_MAX]);
can_print_timing_min_max("tdcf", " tdcf", *tdcf_min, *tdcf_max);
}
close_json_object();
}
@ -282,8 +404,7 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_CAN_CTRLMODE]) {
struct can_ctrlmode *cm = RTA_DATA(tb[IFLA_CAN_CTRLMODE]);
if (cm->flags)
print_ctrlmode(f, cm->flags);
print_ctrlmode(PRINT_ANY, cm->flags, "ctrlmode");
}
if (tb[IFLA_CAN_STATE]) {
@ -297,56 +418,39 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
struct can_berr_counter *bc =
RTA_DATA(tb[IFLA_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 (tb[IFLA_CAN_RESTART_MS]) {
__u32 *restart_ms = RTA_DATA(tb[IFLA_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 (tb[IFLA_CAN_BITTIMING] && !tb[IFLA_CAN_BITRATE_CONST]) {
struct can_bittiming *bt = RTA_DATA(tb[IFLA_CAN_BITTIMING]);
char sp[6];
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);
}
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 +458,18 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
struct can_bittiming_const *btc =
RTA_DATA(tb[IFLA_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 (tb[IFLA_CAN_BITRATE_CONST]) {
@ -391,64 +485,52 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
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_const[i]);
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_const[i]);
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_const[i]);
print_uint(PRINT_ANY, NULL,
i < bitrate_cnt - 1 ? "%8u, " : "%8u",
bitrate_const[i]);
}
close_json_array(PRINT_JSON, " ]");
}
/* data bittiming is irrelevant if fixed bitrate is defined */
if (tb[IFLA_CAN_DATA_BITTIMING] && !tb[IFLA_CAN_DATA_BITRATE_CONST]) {
struct can_bittiming *dbt =
RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
char dsp[6];
if (is_json_context()) {
json_writer_t *jw;
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);
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);
}
if (tb[IFLA_CAN_TDC])
can_print_tdc_opt(f, tb[IFLA_CAN_TDC]);
close_json_object();
}
/* data bittiming const is irrelevant if fixed bitrate is defined */
@ -457,29 +539,22 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
struct can_bittiming_const *dbtc =
RTA_DATA(tb[IFLA_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);
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);
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);
}
if (tb[IFLA_CAN_TDC])
can_print_tdc_const_opt(f, tb[IFLA_CAN_TDC]);
close_json_object();
}
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
@ -497,30 +572,23 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
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_const[i]);
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_const[i]);
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_const[i]);
print_uint(PRINT_ANY, NULL,
i < dbitrate_cnt - 1 ? "%8u, " : "%8u",
dbitrate_const[i]);
}
close_json_array(PRINT_JSON, " ]");
}
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
@ -530,29 +598,21 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
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_const[i]);
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_const[i]);
fprintf(f, "%hu ]", trm_const[i]);
}
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_const[i]);
close_json_array(PRINT_JSON, " ]");
}
if (tb[IFLA_CAN_CLOCK]) {
struct can_clock *clock = RTA_DATA(tb[IFLA_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 +625,23 @@ static void can_print_xstats(struct link_util *lu,
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

@ -243,7 +243,6 @@ static int geneve_parse_opt(struct link_util *lu, int argc, char **argv,
static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 vni;
__u8 ttl = 0;
__u8 tos = 0;
@ -252,15 +251,12 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GENEVE_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (!tb[IFLA_GENEVE_ID] ||
RTA_PAYLOAD(tb[IFLA_GENEVE_ID]) < sizeof(__u32))
return;
vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]);
print_uint(PRINT_ANY, "id", "id %u ", vni);
if (tb[IFLA_GENEVE_ID] &&
RTA_PAYLOAD(tb[IFLA_GENEVE_ID]) >= sizeof(__u32)) {
print_uint(PRINT_ANY, "id", "id %u ", rta_getattr_u32(tb[IFLA_GENEVE_ID]));
}
if (tb[IFLA_GENEVE_REMOTE]) {
__be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]);

View File

@ -33,7 +33,7 @@ static void print_explain(struct link_util *lu, FILE *f)
"Usage: ... %s mode MODE [flag MODE_FLAG] MODE_OPTS [bcqueuelen BC_QUEUE_LEN]\n"
"\n"
"MODE: private | vepa | bridge | passthru | source\n"
"MODE_FLAG: null | nopromisc\n"
"MODE_FLAG: null | nopromisc | nodst\n"
"MODE_OPTS: for mode \"source\":\n"
"\tmacaddr { { add | del } <macaddr> | set [ <macaddr> [ <macaddr> ... ] ] | flush }\n"
"BC_QUEUE_LEN: Length of the rx queue for broadcast/multicast: [0-4294967295]\n",
@ -58,7 +58,7 @@ static int mode_arg(const char *arg)
static int flag_arg(const char *arg)
{
fprintf(stderr,
"Error: argument of \"flag\" must be \"nopromisc\" or \"null\", not \"%s\"\n",
"Error: argument of \"flag\" must be \"nopromisc\", \"nodst\" or \"null\", not \"%s\"\n",
arg);
return -1;
}
@ -102,6 +102,8 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
if (strcmp(*argv, "nopromisc") == 0)
flags |= MACVLAN_FLAG_NOPROMISC;
else if (strcmp(*argv, "nodst") == 0)
flags |= MACVLAN_FLAG_NODST;
else if (strcmp(*argv, "null") == 0)
flags |= 0;
else
@ -159,6 +161,9 @@ static int macvlan_parse_opt(struct link_util *lu, int argc, char **argv,
} else if (matches(*argv, "nopromisc") == 0) {
flags |= MACVLAN_FLAG_NOPROMISC;
has_flags = 1;
} else if (matches(*argv, "nodst") == 0) {
flags |= MACVLAN_FLAG_NODST;
has_flags = 1;
} else if (matches(*argv, "bcqueuelen") == 0) {
__u32 bc_queue_len;
NEXT_ARG();
@ -229,6 +234,9 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
if (flags & MACVLAN_FLAG_NOPROMISC)
print_bool(PRINT_ANY, "nopromisc", "nopromisc ", true);
if (flags & MACVLAN_FLAG_NODST)
print_bool(PRINT_ANY, "nodst", "nodst ", true);
if (tb[IFLA_MACVLAN_BC_QUEUE_LEN] &&
RTA_PAYLOAD(tb[IFLA_MACVLAN_BC_QUEUE_LEN]) >= sizeof(__u32)) {
__u32 bc_queue_len = rta_getattr_u32(tb[IFLA_MACVLAN_BC_QUEUE_LEN]);

View File

@ -408,7 +408,6 @@ static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv,
static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
__u32 vni;
__u8 ttl = 0;
__u8 tos = 0;
__u32 maxaddr;
@ -419,15 +418,12 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_VXLAN_COLLECT_METADATA] &&
rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA])) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (!tb[IFLA_VXLAN_ID] ||
RTA_PAYLOAD(tb[IFLA_VXLAN_ID]) < sizeof(__u32))
return;
vni = rta_getattr_u32(tb[IFLA_VXLAN_ID]);
print_uint(PRINT_ANY, "id", "id %u ", vni);
if (tb[IFLA_VXLAN_ID] &&
RTA_PAYLOAD(tb[IFLA_VXLAN_ID]) >= sizeof(__u32)) {
print_uint(PRINT_ANY, "id", "id %u ", rta_getattr_u32(tb[IFLA_VXLAN_ID]));
}
if (tb[IFLA_VXLAN_GROUP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);

72
ip/iplink_wwan.c Normal file
View File

@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <stdio.h>
#include <linux/netlink.h>
#include <linux/wwan.h>
#include "utils.h"
#include "ip_common.h"
static void print_explain(FILE *f)
{
fprintf(f,
"Usage: ... wwan linkid LINKID\n"
"\n"
"Where: LINKID := 0-4294967295\n"
);
}
static void explain(void)
{
print_explain(stderr);
}
static int wwan_parse_opt(struct link_util *lu, int argc, char **argv,
struct nlmsghdr *n)
{
while (argc > 0) {
if (matches(*argv, "linkid") == 0) {
__u32 linkid;
NEXT_ARG();
if (get_u32(&linkid, *argv, 0))
invarg("linkid", *argv);
addattr32(n, 1024, IFLA_WWAN_LINK_ID, linkid);
} else if (matches(*argv, "help") == 0) {
explain();
return -1;
} else {
fprintf(stderr, "wwan: unknown command \"%s\"?\n",
*argv);
explain();
return -1;
}
argc--, argv++;
}
return 0;
}
static void wwan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
return;
if (tb[IFLA_WWAN_LINK_ID])
print_uint(PRINT_ANY, "linkid", "linkid %u ",
rta_getattr_u32(tb[IFLA_WWAN_LINK_ID]));
}
static void wwan_print_help(struct link_util *lu, int argc, char **argv,
FILE *f)
{
print_explain(f);
}
struct link_util wwan_link_util = {
.id = "wwan",
.maxattr = IFLA_WWAN_MAX,
.parse_opt = wwan_parse_opt,
.print_opt = wwan_print_opt,
.print_help = wwan_print_help,
};

View File

@ -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;
@ -88,7 +89,13 @@ static int accept_msg(struct rtnl_ctrl_data *ctrl,
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:
case RTM_DELNEXTHOPBUCKET:
print_headers(fp, "[NEXTHOPBUCKET]", ctrl);
print_nexthop_bucket(n, arg);
return 0;
case RTM_NEWLINK:

View File

@ -1,28 +1,35 @@
// 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"
" [ FLAG-LIST ]\n"
" [ port NR ] [ FLAG-LIST ]\n"
" ip mptcp endpoint delete id ID\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");
@ -97,6 +104,7 @@ static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n,
bool id_set = false;
__u32 index = 0;
__u32 flags = 0;
__u16 port = 0;
__u8 id = 0;
ll_init_map(&rth);
@ -123,6 +131,10 @@ static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n,
if (!index)
invarg("device does not exist\n", ifname);
} else if (matches(*argv, "port") == 0) {
NEXT_ARG();
if (get_u16(&port, *argv, 0))
invarg("expected port", *argv);
} else if (get_addr(&address, *argv, AF_UNSPEC) == 0) {
addr_set = true;
} else {
@ -137,6 +149,9 @@ static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n,
if (!id_set && !adding)
missarg("ID");
if (port && !(flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
invarg("flags must have signal when using port", "port");
attr_addr = addattr_nest(n, MPTCP_BUFLEN,
MPTCP_PM_ATTR_ADDR | NLA_F_NESTED);
if (id_set)
@ -145,6 +160,8 @@ static int mptcp_parse_opt(int argc, char **argv, struct nlmsghdr *n,
addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_FLAGS, flags);
if (index)
addattr32(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_IF_IDX, index);
if (port)
addattr16(n, MPTCP_BUFLEN, MPTCP_PM_ADDR_ATTR_PORT, port);
if (addr_set) {
int type;
@ -181,8 +198,8 @@ static int print_mptcp_addrinfo(struct rtattr *addrinfo)
__u8 family = AF_UNSPEC, addr_attr_type;
const char *ifname;
unsigned int flags;
__u16 id, port;
int index;
__u16 id;
parse_rtattr_nested(tb, MPTCP_PM_ADDR_ATTR_MAX, addrinfo);
@ -196,6 +213,11 @@ static int print_mptcp_addrinfo(struct rtattr *addrinfo)
print_string(PRINT_ANY, "address", "%s ",
format_host_rta(family, tb[addr_attr_type]));
}
if (tb[MPTCP_PM_ADDR_ATTR_PORT]) {
port = rta_getattr_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]);
if (port)
print_uint(PRINT_ANY, "port", "port %u ", port);
}
if (tb[MPTCP_PM_ADDR_ATTR_ID]) {
id = rta_getattr_u8(tb[MPTCP_PM_ADDR_ATTR_ID]);
print_uint(PRINT_ANY, "id", "id %u ", id);
@ -262,7 +284,7 @@ static int mptcp_addr_dump(void)
return -2;
}
close_json_object();
delete_json_obj();
fflush(stdout);
return 0;
}
@ -283,7 +305,11 @@ static int mptcp_addr_show(int argc, char **argv)
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();
fflush(stdout);
return ret;
}
static int mptcp_addr_flush(int argc, char **argv)
@ -385,6 +411,110 @@ static int mptcp_limit_get_set(int argc, char **argv, int cmd)
return 0;
}
static const char * const event_to_str[] = {
[MPTCP_EVENT_CREATED] = "CREATED",
[MPTCP_EVENT_ESTABLISHED] = "ESTABLISHED",
[MPTCP_EVENT_CLOSED] = "CLOSED",
[MPTCP_EVENT_ANNOUNCED] = "ANNOUNCED",
[MPTCP_EVENT_REMOVED] = "REMOVED",
[MPTCP_EVENT_SUB_ESTABLISHED] = "SF_ESTABLISHED",
[MPTCP_EVENT_SUB_CLOSED] = "SF_CLOSED",
[MPTCP_EVENT_SUB_PRIORITY] = "SF_PRIO",
};
static void print_addr(const char *key, int af, struct rtattr *value)
{
void *data = RTA_DATA(value);
char str[INET6_ADDRSTRLEN];
if (inet_ntop(af, data, str, sizeof(str)))
printf(" %s=%s", key, str);
}
static int mptcp_monitor_msg(struct rtnl_ctrl_data *ctrl,
struct nlmsghdr *n, void *arg)
{
const struct genlmsghdr *ghdr = NLMSG_DATA(n);
struct rtattr *tb[MPTCP_ATTR_MAX + 1];
int len = n->nlmsg_len;
len -= NLMSG_LENGTH(GENL_HDRLEN);
if (len < 0)
return -1;
if (n->nlmsg_type != genl_family)
return 0;
if (timestamp)
print_timestamp(stdout);
if (ghdr->cmd >= ARRAY_SIZE(event_to_str)) {
printf("[UNKNOWN %u]\n", ghdr->cmd);
goto out;
}
if (event_to_str[ghdr->cmd] == NULL) {
printf("[UNKNOWN %u]\n", ghdr->cmd);
goto out;
}
printf("[%14s]", event_to_str[ghdr->cmd]);
parse_rtattr(tb, MPTCP_ATTR_MAX, (void *) ghdr + GENL_HDRLEN, len);
printf(" token=%08x", rta_getattr_u32(tb[MPTCP_ATTR_TOKEN]));
if (tb[MPTCP_ATTR_REM_ID])
printf(" remid=%u", rta_getattr_u8(tb[MPTCP_ATTR_REM_ID]));
if (tb[MPTCP_ATTR_LOC_ID])
printf(" locid=%u", rta_getattr_u8(tb[MPTCP_ATTR_LOC_ID]));
if (tb[MPTCP_ATTR_SADDR4])
print_addr("saddr4", AF_INET, tb[MPTCP_ATTR_SADDR4]);
if (tb[MPTCP_ATTR_DADDR4])
print_addr("daddr4", AF_INET, tb[MPTCP_ATTR_DADDR4]);
if (tb[MPTCP_ATTR_SADDR6])
print_addr("saddr6", AF_INET6, tb[MPTCP_ATTR_SADDR6]);
if (tb[MPTCP_ATTR_DADDR6])
print_addr("daddr6", AF_INET6, tb[MPTCP_ATTR_DADDR6]);
if (tb[MPTCP_ATTR_SPORT])
printf(" sport=%u", rta_getattr_be16(tb[MPTCP_ATTR_SPORT]));
if (tb[MPTCP_ATTR_DPORT])
printf(" dport=%u", rta_getattr_be16(tb[MPTCP_ATTR_DPORT]));
if (tb[MPTCP_ATTR_BACKUP])
printf(" backup=%d", rta_getattr_u8(tb[MPTCP_ATTR_BACKUP]));
if (tb[MPTCP_ATTR_ERROR])
printf(" error=%d", rta_getattr_u8(tb[MPTCP_ATTR_ERROR]));
if (tb[MPTCP_ATTR_FLAGS])
printf(" flags=%x", rta_getattr_u16(tb[MPTCP_ATTR_FLAGS]));
if (tb[MPTCP_ATTR_TIMEOUT])
printf(" timeout=%u", rta_getattr_u32(tb[MPTCP_ATTR_TIMEOUT]));
if (tb[MPTCP_ATTR_IF_IDX])
printf(" ifindex=%d", rta_getattr_s32(tb[MPTCP_ATTR_IF_IDX]));
if (tb[MPTCP_ATTR_RESET_REASON])
printf(" reset_reason=%u", rta_getattr_u32(tb[MPTCP_ATTR_RESET_REASON]));
if (tb[MPTCP_ATTR_RESET_FLAGS])
printf(" reset_flags=0x%x", rta_getattr_u32(tb[MPTCP_ATTR_RESET_FLAGS]));
puts("");
out:
fflush(stdout);
return 0;
}
static int mptcp_monitor(void)
{
if (genl_add_mcast_grp(&genl_rth, genl_family, MPTCP_PM_EV_GRP_NAME) < 0) {
perror("can't subscribe to mptcp events");
return 1;
}
if (rtnl_listen(&genl_rth, mptcp_monitor_msg, stdout) < 0)
return 2;
return 0;
}
int do_mptcp(int argc, char **argv)
{
if (argc == 0)
@ -429,6 +559,14 @@ int do_mptcp(int argc, char **argv)
MPTCP_PM_CMD_GET_LIMITS);
}
if (matches(*argv, "monitor") == 0) {
NEXT_ARG_FWD();
if (argc == 0)
return mptcp_monitor();
goto unknown;
}
unknown:
fprintf(stderr, "Command \"%s\" is unknown, try \"ip mptcp help\".\n",
*argv);

View File

@ -37,8 +37,8 @@ static void usage(void)
{
fprintf(stderr,
"Usage: ip mroute show [ [ to ] PREFIX ] [ from PREFIX ] [ iif DEVICE ]\n"
" [ table TABLE_ID ]\n"
"TABLE_ID := [ local | main | default | all | NUMBER ]\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

View File

@ -50,11 +50,12 @@ static void usage(void)
{
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"
" { ADDR [ lladdr LLADDR ] [ nud STATE ] proxy ADDR }\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"
" [ vrf NAME ] [ nomaster ]\n"
" ip neigh get { ADDR | proxy ADDR } dev DEV\n"
"\n"
"STATE := { delay | failed | incomplete | noarp | none |\n"
@ -115,6 +116,7 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
.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;
@ -148,6 +150,11 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
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) {
@ -183,7 +190,10 @@ static int ipneigh_modify(int cmd, int flags, int argc, char **argv)
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 llabuf[20];
int l;
@ -235,7 +245,7 @@ static void print_neigh_state(unsigned int nud)
#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);
@ -251,6 +261,51 @@ static void print_neigh_state(unsigned int nud)
close_json_array(PRINT_JSON, NULL);
}
static int print_neigh_brief(FILE *fp, struct ndmsg *r, struct rtattr *tb[])
{
if (tb[NDA_DST]) {
const char *dst;
int family = r->ndm_family;
if (family == AF_BRIDGE) {
if (RTA_PAYLOAD(tb[NDA_DST]) == sizeof(struct in6_addr))
family = AF_INET6;
else
family = AF_INET;
}
dst = format_host_rta(family, tb[NDA_DST]);
print_color_string(PRINT_ANY, ifa_family_color(family),
"dst", "%-39s ", dst);
}
if (!filter.index && r->ndm_ifindex) {
print_color_string(PRINT_ANY, COLOR_IFNAME,
"dev", "%-16s ",
ll_index_to_name(r->ndm_ifindex));
}
if (tb[NDA_LLADDR]) {
const char *lladdr;
SPRINT_BUF(b1);
lladdr = ll_addr_n2a(RTA_DATA(tb[NDA_LLADDR]),
RTA_PAYLOAD(tb[NDA_LLADDR]),
ll_index_to_type(r->ndm_ifindex),
b1, sizeof(b1));
print_color_string(PRINT_ANY, COLOR_MAC,
"lladdr", "%s", lladdr);
}
print_string(PRINT_FP, NULL, "%s", "\n");
close_json_object();
fflush(fp);
return 0;
}
int print_neigh(struct nlmsghdr *n, void *arg)
{
FILE *fp = (FILE *)arg;
@ -258,6 +313,7 @@ int print_neigh(struct nlmsghdr *n, void *arg)
int len = n->nlmsg_len;
struct rtattr *tb[NDA_MAX+1];
static int logit = 1;
__u32 ext_flags = 0;
__u8 protocol = 0;
if (n->nlmsg_type != RTM_NEWNEIGH && n->nlmsg_type != RTM_DELNEIGH &&
@ -283,8 +339,7 @@ int print_neigh(struct nlmsghdr *n, void *arg)
if (!(filter.state&r->ndm_state) &&
!(r->ndm_flags & NTF_PROXY) &&
!(r->ndm_flags & NTF_EXT_LEARNED) &&
(r->ndm_state || !(filter.state&0x100)) &&
(r->ndm_family != AF_DECnet))
(r->ndm_state || !(filter.state&0x100)))
return 0;
if (filter.master && !(n->nlmsg_flags & NLM_F_DUMP_FILTERED)) {
@ -302,6 +357,8 @@ int print_neigh(struct nlmsghdr *n, void *arg)
if (tb[NDA_PROTOCOL])
protocol = rta_getattr_u8(tb[NDA_PROTOCOL]);
if (tb[NDA_FLAGS_EXT])
ext_flags = rta_getattr_u32(tb[NDA_FLAGS_EXT]);
if (filter.protocol && filter.protocol != protocol)
return 0;
@ -337,6 +394,9 @@ int print_neigh(struct nlmsghdr *n, void *arg)
else if (n->nlmsg_type == RTM_GETNEIGH)
print_null(PRINT_ANY, "miss", "%s ", "miss");
if (brief)
return print_neigh_brief(fp, r, tb);
if (tb[NDA_DST]) {
const char *dst;
int family = r->ndm_family;
@ -376,27 +436,26 @@ int print_neigh(struct nlmsghdr *n, void *arg)
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 (tb[NDA_CACHEINFO])
print_cacheinfo(RTA_DATA(tb[NDA_CACHEINFO]));
if (tb[NDA_PROBES])
print_uint(PRINT_ANY, "probes", " probes %u",
print_uint(PRINT_ANY, "probes", "probes %u ",
rta_getattr_u32(tb[NDA_PROBES]));
}
@ -406,13 +465,13 @@ int print_neigh(struct nlmsghdr *n, void *arg)
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)));
}
print_string(PRINT_FP, NULL, "\n", "");
close_json_object();
fflush(stdout);
fflush(fp);
return 0;
}
@ -488,6 +547,8 @@ static int do_show_or_flush(int argc, char **argv, int flush)
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) {

File diff suppressed because it is too large Load Diff

View File

@ -47,15 +47,15 @@ static void usage(void)
{
fprintf(stderr,
"Usage: ip ntable change name NAME [ dev DEV ]\n"
" [ thresh1 VAL ] [ thresh2 VAL ] [ thresh3 VAL ] [ gc_int MSEC ]\n"
" [ PARMS ]\n"
" [ thresh1 VAL ] [ thresh2 VAL ] [ thresh3 VAL ] [ gc_int MSEC ]\n"
" [ PARMS ]\n"
"Usage: ip ntable show [ dev DEV ] [ name NAME ]\n"
"PARMS := [ base_reachable MSEC ] [ retrans MSEC ] [ gc_stale MSEC ]\n"
" [ delay_probe MSEC ] [ queue LEN ]\n"
" [ app_probes VAL ] [ ucast_probes VAL ] [ mcast_probes VAL ]\n"
" [ anycast_delay MSEC ] [ proxy_delay MSEC ] [ proxy_queue LEN ]\n"
" [ locktime MSEC ]\n"
" [ delay_probe MSEC ] [ queue LEN ]\n"
" [ app_probes VAL ] [ ucast_probes VAL ] [ mcast_probes VAL ]\n"
" [ anycast_delay MSEC ] [ proxy_delay MSEC ] [ proxy_queue LEN ]\n"
" [ locktime MSEC ]\n"
);
exit(-1);

View File

@ -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
@ -82,7 +83,7 @@ static void usage(void)
" [ ttl-propagate { enabled | disabled } ]\n"
"INFO_SPEC := { NH | nhid ID } OPTIONS FLAGS [ nexthop NH ]...\n"
"NH := [ encap ENCAPTYPE ENCAPHDR ] [ via [ FAMILY ] ADDRESS ]\n"
" [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"
" [ dev STRING ] [ weight NUMBER ] NHFLAGS\n"
"FAMILY := [ inet | inet6 | mpls | bridge | link ]\n"
"OPTIONS := FLAGS [ mtu NUMBER ] [ advmss NUMBER ] [ as [ to ] ADDRESS ]\n"
" [ rtt TIME ] [ rttvar TIME ] [ reordering NUMBER ]\n"
@ -101,10 +102,18 @@ static void usage(void)
"TIME := NUMBER[s|ms]\n"
"BOOL := [1|0]\n"
"FEATURES := ecn\n"
"ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl ]\n"
"ENCAPHDR := [ MPLSLABEL | SEG6HDR ]\n"
"ENCAPTYPE := [ mpls | ip | ip6 | seg6 | seg6local | rpl | ioam6 ]\n"
"ENCAPHDR := [ MPLSLABEL | SEG6HDR | SEG6LOCAL | IOAM6HDR ]\n"
"SEG6HDR := [ mode SEGMODE ] segs ADDR1,ADDRi,ADDRn [hmac HMACKEYID] [cleanup]\n"
"SEGMODE := [ encap | inline ]\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"
" table TABLEID | vrftable TABLEID | endpoint PROGNAME }\n"
"IOAM6HDR := trace prealloc type IOAM6_TRACE_TYPE ns IOAM6_NAMESPACE size IOAM6_TRACE_SIZE\n"
"ROUTE_GET_FLAGS := [ fibmatch ]\n");
exit(-1);
}
@ -402,13 +411,13 @@ static void print_rt_pref(FILE *fp, unsigned int pref)
}
}
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);
}
@ -539,13 +548,11 @@ static void print_rta_newdst(FILE *fp, const struct rtmsg *r,
}
}
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),
@ -553,6 +560,13 @@ void print_rta_gateway(FILE *fp, unsigned char family, const struct rtattr *rta)
}
}
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;
@ -854,7 +868,7 @@ int print_route(struct nlmsghdr *n, void *arg)
print_rta_via(fp, tb[RTA_VIA]);
if (tb[RTA_OIF] && filter.oifmask != -1)
print_rta_if(fp, tb[RTA_OIF], "dev");
print_rta_ifidx(fp, rta_getattr_u32(tb[RTA_OIF]), "dev");
if (table && (table != RT_TABLE_MAIN || show_details > 0) && !filter.tb)
print_string(PRINT_ANY,
@ -938,7 +952,7 @@ int print_route(struct nlmsghdr *n, void *arg)
print_rta_metrics(fp, tb[RTA_METRICS]);
if (tb[RTA_IIF] && filter.iifmask != -1)
print_rta_if(fp, tb[RTA_IIF], "iif");
print_rta_ifidx(fp, rta_getattr_u32(tb[RTA_IIF]), "iif");
if (tb[RTA_PREF])
print_rt_pref(fp, rta_getattr_u8(tb[RTA_PREF]));
@ -955,6 +969,10 @@ int print_route(struct nlmsghdr *n, void *arg)
propagate ? "enabled" : "disabled");
}
if (tb[RTA_NH_ID] && show_details)
print_cache_nexthop_id(fp, "\n\tnh_info ", "nh_info",
rta_getattr_u32(tb[RTA_NH_ID]));
if (tb[RTA_MULTIPATH])
print_rta_multipath(fp, r, tb[RTA_MULTIPATH]);
@ -1727,6 +1745,18 @@ static int iproute_flush(int family, rtnl_filter_t filter_fn)
}
}
static int save_route_errhndlr(struct nlmsghdr *n, void *arg)
{
int err = -*(int *)NLMSG_DATA(n);
if (n->nlmsg_type == NLMSG_DONE &&
filter.tb == RT_TABLE_MAIN &&
err == ENOENT)
return RTNL_SUPPRESS_NLMSG_DONE_NLERR;
return RTNL_LET_NLERR;
}
static int iproute_list_flush_or_save(int argc, char **argv, int action)
{
int dump_family = preferred_family;
@ -1939,7 +1969,8 @@ static int iproute_list_flush_or_save(int argc, char **argv, int action)
new_json_obj(json);
if (rtnl_dump_filter(&rth, filter_fn, stdout) < 0) {
if (rtnl_dump_filter_errhndlr(&rth, filter_fn, stdout,
save_route_errhndlr, NULL) < 0) {
fprintf(stderr, "Dump terminated\n");
return -2;
}

View File

@ -34,6 +34,8 @@
#include <linux/seg6_hmac.h>
#include <linux/seg6_local.h>
#include <linux/if_tunnel.h>
#include <linux/ioam6.h>
#include <linux/ioam6_iptunnel.h>
static const char *format_encap_type(int type)
{
@ -54,6 +56,8 @@ static const char *format_encap_type(int type)
return "seg6local";
case LWTUNNEL_ENCAP_RPL:
return "rpl";
case LWTUNNEL_ENCAP_IOAM6:
return "ioam6";
default:
return "unknown";
}
@ -90,6 +94,8 @@ static int read_encap_type(const char *name)
return LWTUNNEL_ENCAP_SEG6_LOCAL;
else if (strcmp(name, "rpl") == 0)
return LWTUNNEL_ENCAP_RPL;
else if (strcmp(name, "ioam6") == 0)
return LWTUNNEL_ENCAP_IOAM6;
else if (strcmp(name, "help") == 0)
encap_type_usage();
@ -204,6 +210,63 @@ static void print_encap_rpl(FILE *fp, struct rtattr *encap)
print_rpl_srh(fp, srh);
}
static const char *ioam6_mode_types[IOAM6_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_types[mode])
return "<unknown>";
return ioam6_mode_types[mode];
}
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_types[i] && !strcmp(mode, ioam6_mode_types[i]))
return i;
}
return 0;
}
static void print_encap_ioam6(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[IOAM6_IPTUNNEL_MAX + 1];
struct ioam6_trace_hdr *trace;
__u8 mode;
parse_rtattr_nested(tb, IOAM6_IPTUNNEL_MAX, encap);
if (!tb[IOAM6_IPTUNNEL_MODE] || !tb[IOAM6_IPTUNNEL_TRACE])
return;
mode = rta_getattr_u8(tb[IOAM6_IPTUNNEL_MODE]);
if (!tb[IOAM6_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, tb[IOAM6_IPTUNNEL_DST]));
trace = RTA_DATA(tb[IOAM6_IPTUNNEL_TRACE]);
print_null(PRINT_ANY, "trace", "trace ", NULL);
print_null(PRINT_ANY, "prealloc", "prealloc ", NULL);
print_hex(PRINT_ANY, "type", "type %#08x ", ntohl(trace->type_be32) >> 8);
print_uint(PRINT_ANY, "ns", "ns %u ", ntohs(trace->namespace_id));
print_uint(PRINT_ANY, "size", "size %u ", trace->remlen * 4);
}
static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
[SEG6_LOCAL_ACTION_END] = "End",
[SEG6_LOCAL_ACTION_END_X] = "End.X",
@ -220,6 +283,7 @@ static const char *seg6_action_names[SEG6_LOCAL_ACTION_MAX + 1] = {
[SEG6_LOCAL_ACTION_END_AS] = "End.AS",
[SEG6_LOCAL_ACTION_END_AM] = "End.AM",
[SEG6_LOCAL_ACTION_END_BPF] = "End.BPF",
[SEG6_LOCAL_ACTION_END_DT46] = "End.DT46",
};
static const char *format_action_type(int action)
@ -266,6 +330,42 @@ static void print_encap_bpf_prog(FILE *fp, struct rtattr *encap,
}
}
static void print_seg6_local_counters(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[SEG6_LOCAL_CNT_MAX + 1];
__u64 packets = 0, bytes = 0, errors = 0;
parse_rtattr_nested(tb, SEG6_LOCAL_CNT_MAX, encap);
if (tb[SEG6_LOCAL_CNT_PACKETS])
packets = rta_getattr_u64(tb[SEG6_LOCAL_CNT_PACKETS]);
if (tb[SEG6_LOCAL_CNT_BYTES])
bytes = rta_getattr_u64(tb[SEG6_LOCAL_CNT_BYTES]);
if (tb[SEG6_LOCAL_CNT_ERRORS])
errors = rta_getattr_u64(tb[SEG6_LOCAL_CNT_ERRORS]);
if (is_json_context()) {
open_json_object("stats64");
print_u64(PRINT_JSON, "packets", NULL, packets);
print_u64(PRINT_JSON, "bytes", NULL, bytes);
print_u64(PRINT_JSON, "errors", NULL, errors);
close_json_object();
} else {
print_string(PRINT_FP, NULL, "%s ", "packets");
print_num(fp, 1, packets);
print_string(PRINT_FP, NULL, "%s ", "bytes");
print_num(fp, 1, bytes);
print_string(PRINT_FP, NULL, "%s ", "errors");
print_num(fp, 1, errors);
}
}
static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
{
struct rtattr *tb[SEG6_LOCAL_MAX + 1];
@ -325,6 +425,9 @@ static void print_encap_seg6local(FILE *fp, struct rtattr *encap)
if (tb[SEG6_LOCAL_BPF])
print_encap_bpf_prog(fp, tb[SEG6_LOCAL_BPF], "endpoint");
if (tb[SEG6_LOCAL_COUNTERS] && show_stats)
print_seg6_local_counters(fp, tb[SEG6_LOCAL_COUNTERS]);
}
static void print_encap_mpls(FILE *fp, struct rtattr *encap)
@ -617,6 +720,9 @@ void lwt_print_encap(FILE *fp, struct rtattr *encap_type,
case LWTUNNEL_ENCAP_RPL:
print_encap_rpl(fp, encap);
break;
case LWTUNNEL_ENCAP_IOAM6:
print_encap_ioam6(fp, encap);
break;
}
}
@ -813,6 +919,122 @@ out:
return ret;
}
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;
__u32 trace_type = 0;
inet_prefix addr;
__u8 mode;
if (strcmp(*argv, "mode") != 0) {
mode = IOAM6_IPTUNNEL_MODE_INLINE;
} else {
NEXT_ARG();
mode = read_ioam6mode_type(*argv);
if (!mode)
invarg("Invalid mode", *argv);
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") != 0)
missarg("prealloc");
while (NEXT_ARG_OK()) {
NEXT_ARG_FWD();
if (strcmp(*argv, "type") == 0) {
NEXT_ARG();
if (trace_type)
duparg2("type", *argv);
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 (get_u16(&trace_ns, *argv, 0))
invarg("Invalid namespace ID", *argv);
} else if (strcmp(*argv, "size") == 0) {
NEXT_ARG();
if (trace_size)
duparg2("size", *argv);
if (get_u16(&trace_size, *argv, 0) || !trace_size)
invarg("Invalid trace size", *argv);
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 (!trace_type)
missarg("type");
if (!ns_found)
missarg("ns");
if (!trace_size)
missarg("size");
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_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;
}
*argcp = argc + 1;
*argvp = argv - 1;
free(trace);
return 0;
}
struct lwt_x {
struct rtattr *rta;
size_t len;
@ -862,13 +1084,39 @@ static int lwt_parse_bpf(struct rtattr *rta, size_t len,
return 0;
}
/* for the moment, counters are always initialized to zero by the kernel; so we
* do not expect to parse any argument here.
*/
static int seg6local_fill_counters(struct rtattr *rta, size_t len, int attr)
{
struct rtattr *nest;
int ret;
nest = rta_nest(rta, len, attr);
ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_PACKETS, 0);
if (ret < 0)
return ret;
ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_BYTES, 0);
if (ret < 0)
return ret;
ret = rta_addattr64(rta, len, SEG6_LOCAL_CNT_ERRORS, 0);
if (ret < 0)
return ret;
rta_nest_end(rta, nest);
return 0;
}
static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
char ***argvp)
{
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;
int action_ok = 0, srh_ok = 0, bpf_ok = 0;
struct ipv6_sr_hdr *srh;
char **argv = *argvp;
int argc = *argcp;
@ -932,6 +1180,11 @@ static int parse_encap_seg6local(struct rtattr *rta, size_t len, int *argcp,
if (!oif)
exit(nodev(*argv));
ret = rta_addattr32(rta, len, SEG6_LOCAL_OIF, oif);
} else if (strcmp(*argv, "count") == 0) {
if (counters_ok++)
duparg2("count", *argv);
ret = seg6local_fill_counters(rta, len,
SEG6_LOCAL_COUNTERS);
} else if (strcmp(*argv, "srh") == 0) {
NEXT_ARG();
if (srh_ok++)
@ -1673,6 +1926,9 @@ int lwt_parse_encap(struct rtattr *rta, size_t len, int *argcp, char ***argvp,
case LWTUNNEL_ENCAP_RPL:
ret = parse_encap_rpl(rta, len, &argc, &argv);
break;
case LWTUNNEL_ENCAP_IOAM6:
ret = parse_encap_ioam6(rta, len, &argc, &argv);
break;
default:
fprintf(stderr, "Error: unsupported encap type\n");
break;

View File

@ -34,10 +34,10 @@ static void usage(void)
{
fprintf(stderr,
"Usage: ip sr { COMMAND | help }\n"
" ip sr hmac show\n"
" ip sr hmac set KEYID ALGO\n"
" ip sr tunsrc show\n"
" ip sr tunsrc set ADDRESS\n"
" ip sr hmac show\n"
" ip sr hmac set KEYID ALGO\n"
" ip sr tunsrc show\n"
" ip sr tunsrc set ADDRESS\n"
"where ALGO := { sha1 | sha256 }\n");
exit(-1);
}

View File

@ -34,18 +34,18 @@ static void usage(void)
{
fprintf(stderr,
"Usage: ip tunnel { add | change | del | show | prl | 6rd } [ NAME ]\n"
" [ mode { gre | ipip | isatap | sit | vti } ]\n"
" [ remote ADDR ] [ local ADDR ]\n"
" [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"
" [ prl-default ADDR ] [ prl-nodefault ADDR ] [ prl-delete ADDR ]\n"
" [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n"
" [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n"
" [ mode { gre | ipip | isatap | sit | vti } ]\n"
" [ remote ADDR ] [ local ADDR ]\n"
" [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"
" [ prl-default ADDR ] [ prl-nodefault ADDR ] [ prl-delete ADDR ]\n"
" [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]\n"
" [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n"
"\n"
"Where: NAME := STRING\n"
" ADDR := { IP_ADDRESS | any }\n"
" TOS := { STRING | 00..ff | inherit | inherit/STRING | inherit/00..ff }\n"
" TTL := { 1..255 | inherit }\n"
" KEY := { DOTTED_QUAD | NUMBER }\n");
"Where: NAME := STRING\n"
" ADDR := { IP_ADDRESS | any }\n"
" TOS := { STRING | 00..ff | inherit | inherit/STRING | inherit/00..ff }\n"
" TTL := { 1..255 | inherit }\n"
" KEY := { DOTTED_QUAD | NUMBER }\n");
exit(-1);
}

View File

@ -42,11 +42,11 @@ static void usage(void)
{
fprintf(stderr,
"Usage: ip tuntap { add | del | show | list | lst | help } [ dev PHYS_DEV ]\n"
" [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"
" [ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ] [ name NAME ]\n"
" [ mode { tun | tap } ] [ user USER ] [ group GROUP ]\n"
" [ one_queue ] [ pi ] [ vnet_hdr ] [ multi_queue ] [ name NAME ]\n"
"\n"
"Where: USER := { STRING | NUMBER }\n"
" GROUP := { STRING | NUMBER }\n");
"Where: USER := { STRING | NUMBER }\n"
" GROUP := { STRING | NUMBER }\n");
exit(-1);
}
@ -243,6 +243,9 @@ static void print_flags(long flags)
if (flags & IFF_ONE_QUEUE)
print_string(PRINT_ANY, NULL, " %s", "one_queue");
if (flags & IFF_MULTI_QUEUE)
print_string(PRINT_ANY, NULL, " %s", "multi_queue");
if (flags & IFF_VNET_HDR)
print_string(PRINT_ANY, NULL, " %s", "vnet_hdr");
@ -253,42 +256,14 @@ static void print_flags(long flags)
print_string(PRINT_ANY, NULL, " %s", "filter");
flags &= ~(IFF_TUN | IFF_TAP | IFF_NO_PI | IFF_ONE_QUEUE |
IFF_VNET_HDR | IFF_PERSIST | IFF_NOFILTER);
IFF_MULTI_QUEUE | IFF_VNET_HDR | IFF_PERSIST |
IFF_NOFILTER);
if (flags)
print_0xhex(PRINT_ANY, NULL, "%#llx", flags);
print_0xhex(PRINT_ANY, NULL, " %#llx", flags);
close_json_array(PRINT_JSON, NULL);
}
static char *pid_name(pid_t pid)
{
char *comm;
FILE *f;
int err;
err = asprintf(&comm, "/proc/%d/comm", pid);
if (err < 0)
return NULL;
f = fopen(comm, "r");
free(comm);
if (!f) {
perror("fopen");
return NULL;
}
if (fscanf(f, "%ms\n", &comm) != 1) {
perror("fscanf");
comm = NULL;
}
if (fclose(f))
perror("fclose");
return comm;
}
static void show_processes(const char *name)
{
glob_t globbuf = { };
@ -346,7 +321,7 @@ static void show_processes(const char *name)
} else if (err == 2 &&
!strcmp("iff", key) &&
!strcmp(name, value)) {
char *pname = pid_name(pid);
char *pname = get_task_name(pid);
print_string(PRINT_ANY, "name",
"%s", pname ? : "<NULL>");

View File

@ -907,6 +907,14 @@ void xfrm_xfrma_print(struct rtattr *tb[], __u16 family,
fprintf(fp, "if_id %#x", if_id);
fprintf(fp, "%s", _SL_);
}
if (tb[XFRMA_TFCPAD]) {
__u32 tfcpad = rta_getattr_u32(tb[XFRMA_TFCPAD]);
if (prefix)
fputs(prefix, fp);
fprintf(fp, "tfcpad %u", tfcpad);
fprintf(fp, "%s", _SL_);
}
}
static int xfrm_selector_iszero(struct xfrm_selector *s)

View File

@ -442,7 +442,6 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GRE_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
tnl_print_endpoint("remote", tb[IFLA_GRE_REMOTE], AF_INET);

View File

@ -461,7 +461,6 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_GRE_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (tb[IFLA_GRE_FLAGS])

View File

@ -344,7 +344,6 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
if (tb[IFLA_IPTUN_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (tb[IFLA_IPTUN_FLAGS])

View File

@ -368,7 +368,6 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
if (tb[IFLA_IPTUN_COLLECT_METADATA]) {
print_bool(PRINT_ANY, "external", "external ", true);
return;
}
if (tb[IFLA_IPTUN_PROTO]) {

53
ip/nh_common.h Normal file
View File

@ -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 _buf[RTA_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

@ -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

124
ip/routel
View File

@ -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."""
test "X-h" = "X$1" && echo "Usage: $0 [tablenr [raw ip args...]]" && exit 64
import sys
import json
import getopt
import subprocess
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);
}
'
def usage():
'''Print usage and exit'''
print("Usage: {} [tablenr [raw ip args...]]".format(sys.argv[0]))
sys.exit(64)
def main():
'''Process the arguments'''
family = 'inet'
try:
opts, args = getopt.getopt(sys.argv[1:], "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)))
for record in tbl:
fields = [record[k] if k in record else '' for k in keys]
print(fmt.format(*fields))
if __name__ == "__main__":
main()

View File

@ -65,7 +65,7 @@ static void usage(void)
fprintf(stderr,
"Usage: rtmon [ OPTIONS ] file FILE [ all | LISTofOBJECTS ]\n"
"OPTIONS := { -f[amily] { inet | inet6 | link | help } |\n"
" -4 | -6 | -0 | -V[ersion] }\n"
" -4 | -6 | -0 | -V[ersion] }\n"
"LISTofOBJECTS := [ link ] [ address ] [ route ]\n");
exit(-1);
}

View File

@ -1,5 +0,0 @@
#! /bin/sh
# SPDX-License-Identifier: GPL-2.0
exec tr "[\\\\]" "[
]"

View File

@ -132,6 +132,7 @@ void xfrm_state_info_print(struct xfrm_usersa_info *xsinfo,
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

@ -323,6 +323,9 @@ static int xfrm_accept_msg(struct rtnl_ctrl_data *ctrl,
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;
}

Some files were not shown because too many files have changed in this diff Show More