* [PATCH 06/27] ip: iplink.c: open/close json object for ip -brief -json link show dev DEV
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ip/iplink.c b/ip/iplink.c
index 5aff2fde..19bda1b9 100644
--- a/ip/iplink.c
+++ b/ip/iplink.c
@@ -1041,10 +1041,12 @@ int iplink_get(unsigned int flags, char *name, __u32 filt_mask)
if (rtnl_talk(&rth, &req.n, &answer.n, sizeof(answer)) < 0)
return -2;
+ open_json_object(NULL);
if (brief)
print_linkinfo_brief(NULL, &answer.n, stdout, NULL);
else
print_linkinfo(NULL, &answer.n, stdout);
+ close_json_object();
return 0;
}
--
2.13.3
^ permalink raw reply related
* [PATCH 05/27] ip: ipaddress.c: add support for json output
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
This patch converts all output (mostly fprintfs) to the new ip_print api
which handle both regular and json output.
Initialize a json_writer and open an array object if -json was specified.
Note that the JSON attribute naming follows the NETLINK_ATTRIBUTE naming.
In many places throughout the code, IP, matches integer values with
hardcoded strings tables, such as link mode, link operstate or link
family.
In JSON context, this will result in a named string field. In the
very unlikely event that the requested index is out of bound, IP
displays the raw integer value. For JSON context this result in
having a different integer field example bellow:
if (mode >= ARRAY_SIZE(link_modes))
print_int(PRINT_ANY, "linkmode_index", "mode %d ", mode);
else
print_string(PRINT_ANY, "linkmode", "mode %s ",
link_modes[mode]);
The "_index" suffix is open to discussion and it is something that I came
up with. The bottom line is that you can't have a string field that may
become an int field in specific cases. Programs written in strongly type
languages (like C) might break if they are expecting a string value and
got an integer instead. We don't want to confuse anybody or make the code
even more complicated handling these specifics cases.
Hence the extra "_index" field that is easy to check for and deal with.
JSON schema, followed by live example:
Live config used:
$ ip link add dev vxlan42 type vxlan id 42
$ ip link add dev bond0 type bond
$ ip link add name swp1.50 link swp1 type vlan id 50
$ ip link add dev br0 type bridge
$ ip link set dev vxlan42 master br0
$ ip link set dev bond0 master br0
$ ip link set dev swp1.50 master br0
$ ip link set dev br0 up
$ ip -d link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode
DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 promiscuity 0
addrgenmode eui64
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast
state UP mode DEFAULT group default qlen 1000
link/ether 08:00:27:db:31:88 brd ff:ff:ff:ff:ff:ff promiscuity 0
addrgenmode eui64
3: swp1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode
DEFAULT group default qlen 1000
link/ether 08:00:27:5b:b1:75 brd ff:ff:ff:ff:ff:ff promiscuity 0
addrgenmode eui64
10: vxlan42: <BROADCAST,MULTICAST> mtu 1500 qdisc noop master br0 state
DOWN mode DEFAULT group default
link/ether 4a:d9:91:42:a2:d2 brd ff:ff:ff:ff:ff:ff promiscuity 1
vxlan id 42 srcport 0 0 dstport 8472 ageing 300
bridge_slave state disabled priority 8 cost 100 hairpin off guard off
root_block off fastleave off learning on flood on port_id 0x8001 port_no
0x1 designated_port 32769 designated_cost 0 designated_bridge
8000.8:0:27:5b:b1:75 designated_root 8000.8:0:27:5b:b1:75 hold_timer
0.00 message_age_timer 0.00 forward_delay_timer 0.00
topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off
mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off
addrgenmode eui64
11: bond0: <BROADCAST,MULTICAST,MASTER> mtu 1500 qdisc noop master br0
state DOWN mode DEFAULT group default
link/ether e2:aa:7b:17:c5:14 brd ff:ff:ff:ff:ff:ff promiscuity 1
bond mode 802.3ad miimon 100 updelay 0 downdelay 0 use_carrier 1
arp_interval 0 arp_validate none arp_all_targets any primary_reselect
always fail_over_mac none xmit_hash_policy layer3+4 resend_igmp 1
num_grat_arp 1 all_slaves_active 0 min_links 1 lp_interval 1
packets_per_slave 1 lacp_rate fast ad_select stable ad_actor_sys_prio
65535 ad_user_port_key 0 ad_actor_system 00:00:00:00:00:00
bridge_slave state disabled priority 8 cost 100 hairpin off guard off
root_block off fastleave off learning on flood on port_id 0x8002 port_no
0x2 designated_port 32770 designated_cost 0 designated_bridge
8000.8:0:27:5b:b1:75 designated_root 8000.8:0:27:5b:b1:75 hold_timer
0.00 message_age_timer 0.00 forward_delay_timer 0.00
topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off
mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off
addrgenmode eui64
12: swp1.50@swp1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop master
br0 state DOWN mode DEFAULT group default
link/ether 08:00:27:5b:b1:75 brd ff:ff:ff:ff:ff:ff promiscuity 1
vlan protocol 802.1Q id 50 <REORDER_HDR>
bridge_slave state disabled priority 8 cost 100 hairpin off guard off
root_block off fastleave off learning on flood on port_id 0x8003 port_no
0x3 designated_port 32771 designated_cost 0 designated_bridge
8000.8:0:27:5b:b1:75 designated_root 8000.8:0:27:5b:b1:75 hold_timer
0.00 message_age_timer 0.00 forward_delay_timer 0.00
topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off
mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off
addrgenmode eui64
13: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state
DOWN mode DEFAULT group default
link/ether 08:00:27:5b:b1:75 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time
30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q
bridge_id 8000.8:0:27:5b:b1:75 designated_root 8000.8:0:27:5b:b1:75
root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0
hello_timer 0.00 tcn_timer 0.00 topology_change_timer 0.00
gc_timer 244.44 vlan_default_pvid 1 vlan_stats_enabled 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 4096
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 3125
mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_version 1
nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 addrgenmode
eui64
// Schema for: ip -brief link show
[
{
"deleted": {
"type": "bool",
"attr": "RTM_DELLINK"
},
"link": {
"type": "string",
"attr": "IFLA_LINK"
},
"ifname": {
"type": "string",
"attr": "IFNAME"
},
"operstate": {
"type": "string",
"attr": "IFLA_OPERSTATE",
"mutually_exclusive": {
"operstate_index": {
"type": "uint",
"comment": "if state >= ARRAY_SIZE(oper_states)"
}
}
},
"address": {
"type": "string",
"attr": "IFLA_ADDRESS"
},
"flags": {
"type": "array",
"attr": "IFF_LOOPBACK, IFF_BROADCAST...IFF_*"
},
"addr_info": {
"type": "array",
"array": [
{
"deleted": {
"type": "bool",
"attr": "RTM_DELADDR"
},
"family": {
"type": "string",
"attr": "ifa->ifa_family",
"mutually_exclusive": {
"family_index": {
"type": "uint",
"comment": "if family is not known"
}
}
},
"local": {
"type": "string",
"attr": "IFA_LOCAL"
},
"address": {
"type": "string",
"attr": "IFLA_LOCAL && IFA_ADDRESS"
},
"prefixlen": {
"type": "int",
"attr": "IFLA_LOCAL"
}
}
]
}
}
]
$ ip -json -brief link show
[{
"ifname": "lo",
"operstate": "UNKNOWN",
"address": "00:00:00:00:00:00",
"flags": ["LOOPBACK","UP","LOWER_UP"]
},{
"ifname": "eth0",
"operstate": "UP",
"address": "08:00:27:db:31:88",
"flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"]
},{
"ifname": "swp1",
"operstate": "DOWN",
"address": "08:00:27:5b:b1:75",
"flags": ["BROADCAST","MULTICAST"]
},{
"ifname": "vxlan42",
"operstate": "DOWN",
"address": "4a:d9:91:42:a2:d2",
"flags": ["BROADCAST","MULTICAST"]
},{
"ifname": "bond0",
"operstate": "DOWN",
"address": "e2:aa:7b:17:c5:14",
"flags": ["BROADCAST","MULTICAST","MASTER"]
},{
"link": "swp1",
"ifname": "swp1.50",
"operstate": "DOWN",
"address": "08:00:27:5b:b1:75",
"flags": ["BROADCAST","MULTICAST","M-DOWN"]
},{
"ifname": "br0",
"operstate": "DOWN",
"address": "08:00:27:5b:b1:75",
"flags": ["NO-CARRIER","BROADCAST","MULTICAST","UP"]
}
]
Schema for normal plus -details: ip -json -details link show
[
{
"deleted": {
"type": "bool",
"attr": "RTM_DELLINK"
},
"ifindex": {
"type": "int"
},
"ifname": {
"type": "string",
"attr": "IFLA_IFNAME"
},
"link": {
"type": "string",
"attr": "IFLA_LINK",
"mutually_exclusive": {
"link_index": {
"type": "int",
"comment": "if IFLA_LINK_NETNSID exists"
}
}
},
"flags": {
"type": "array",
"attr": "IFF_LOOPBACK, IFF_BROADCAST...IFF_*"
},
"mtu": {
"type": "int",
"attr": "IFLA_MTU"
},
"xdp": {
"type": "object",
"attr": "IFLA_XDP",
"object": {
"mode": {
"type": "utin",
"attr": "IFLA_XDP_ATTACHED"
},
"prog_id": {
"type": "uint",
"attr": "IFLA_XDP_PROG_ID"
}
}
},
"qdisc": {
"type": "string",
"attr": "IFLA_QDISC"
},
"master": {
"type": "string",
"attr": "IFLA_MASTER"
},
"operstate": {
"type": "string",
"attr": "IFLA_OPERSTATE",
"mutually_exclusive": {
"operstate_index": {
"type": "uint",
"comment": "if state >= ARRAY_SIZE(oper_states)"
}
}
},
"linkmode": {
"type": "string",
"attr": "IFLA_LINKMODE",
"mutually_exclusive": {
"linkmode_index": {
"type": "uint",
"comment": "if mode >= ARRAY_SIZE(link_modes)"
}
}
},
"group": {
"type": "string",
"attr": "IFLA_GROUP"
},
"txqlen": {
"type": "int",
"attr": "IFLA_TXQLEN"
},
"event": {
"type": "string",
"attr": "IFLA_EVENT",
"mutually_exclusive": {
"event_index": {
"type": "uint",
"attr": "IFLA_OPERSTATE",
"comment": "if event >= ARRAY_SIZE(link_events)"
}
}
},
"link_type": {
"type": "string",
"attr": "ifi_type"
},
"address": {
"type": "string",
"attr": "IFLA_ADDRESS"
},
"link_pointtopoint": {
"type": "bool",
"attr": "IFF_POINTOPOINT"
},
"broadcast": {
"type": "string",
"attr": "IFLA_BROADCAST"
},
"link_netnsid": {
"type": "int",
"attr": "IFLA_LINK_NETNSID"
},
"proto_down": {
"type": "bool",
"attr": "IFLA_PROTO_DOWN"
},
//
// if -details
//
"promiscuity": {
"type": "uint",
"attr": "IFLA_PROMISCUITY"
},
"linkinfo": {
"type": "dict",
"attr": "IFLA_LINKINFO",
"dict": {
"info_kind": {
"type": "string",
"attr": "IFLA_INFO_KIND"
},
"info_data": {
"type": "dict",
"attr": "IFLA_INFO_DATA",
"dict": {}
},
"info_xstats": {
"type": "dict",
"attr": "IFLA_INFO_XSTATS",
"dict": {}
},
"info_slave_data": {
"type": "dict",
"attr": "IFLA_INFO_SLAVE_DATA",
"dict": {}
}
}
},
"inet6_addr_gen_mode": {
"type": "string",
"attr": "IFLA_INET6_ADDR_GEN_MODE"
},
"num_tx_queues": {
"type": "uint",
"attr": "IFLA_NUM_TX_QUEUES"
},
"num_rx_queues": {
"type": "uint",
"attr": "IFLA_NUM_RX_QUEUES"
},
"gso_max_size": {
"type": "uint",
"attr": "IFLA_GSO_MAX_SIZE"
},
"gso_max_segs": {
"type": "uint",
"attr": "IFLA_GSO_MAX_SEGS"
},
"phys_port_name": {
"type": "string",
"attr": "IFLA_PHYS_PORT_NAME"
},
"phys_port_id": {
"type": "string",
"attr": "IFLA_PHYS_PORT_ID"
},
"phys_switch_id": {
"type": "string",
"attr": "IFLA_PHYS_SWITCH_ID"
},
"ifalias": {
"type": "string",
"attr": "IFLA_IFALIAS"
},
"stats": {
"type": "dict",
"attr": "IFLA_STATS",
"dict": {
"rx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint"
},
"packets": {
"type": "uint"
},
"errors": {
"type": "uint"
},
"dropped": {
"type": "uint"
},
"over_errors": {
"type": "uint"
},
"multicast": {
"type": "uint"
},
"compressed": {
"type": "uint"
},
"length_errors": {
"type": "uint"
},
"crc_errors": {
"type": "uint"
},
"frame_errors": {
"type": "uint"
},
"fifo_errors": {
"type": "uint"
},
"missed_errors": {
"type": "uint"
},
"nohandler": {
"type": "uint"
}
}
},
"tx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint"
},
"packets": {
"type": "uint"
},
"errors": {
"type": "uint"
},
"dropped": {
"type": "uint"
},
"carrier_errors": {
"type": "uint"
},
"collisions": {
"type": "uint"
},
"compressed": {
"type": "uint"
},
"aborted_errors": {
"type": "uint"
},
"fifo_errors": {
"type": "uint"
},
"window_errors": {
"type": "uint"
},
"heartbeat_errors": {
"type": "uint"
},
"carrier_changes": {
"type": "uint"
}
}
}
}
},
"stats64": {
"type": "dict",
"attr": "IFLA_STATS64",
"dict": {
"rx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint"
},
"packets": {
"type": "uint"
},
"errors": {
"type": "uint"
},
"dropped": {
"type": "uint"
},
"over_errors": {
"type": "uint"
},
"multicast": {
"type": "uint"
},
"compressed": {
"type": "uint"
},
"length_errors": {
"type": "uint"
},
"crc_errors": {
"type": "uint"
},
"frame_errors": {
"type": "uint"
},
"fifo_errors": {
"type": "uint"
},
"missed_errors": {
"type": "uint"
},
"nohandler": {
"type": "uint"
}
}
},
"tx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint"
},
"packets": {
"type": "uint"
},
"errors": {
"type": "uint"
},
"dropped": {
"type": "uint"
},
"carrier_errors": {
"type": "uint"
},
"collisions": {
"type": "uint"
},
"compressed": {
"type": "uint"
},
"aborted_errors": {
"type": "uint"
},
"fifo_errors": {
"type": "uint"
},
"window_errors": {
"type": "uint"
},
"heartbeat_errors": {
"type": "uint"
},
"carrier_changes": {
"type": "uint"
}
}
}
}
},
"vfinfo_list": {
"type": "array",
"attr": "IFLA_VFINFO_LIST",
"array": [
{
"vf": {
"type": "int"
},
"mac": {
"type": "string"
},
"vlan_list": {
"type": "array",
"attr": "IFLA_VF_VLAN_LIST",
"array": [
{
"vlan": {
"type": "int"
},
"qos": {
"type": "int"
},
"protocol": {
"type": "string"
}
}
]
},
"vlan": {
"type": "int",
"attr": "!IFLA_VF_VLAN_LIST && IFLA_VF_VLAN"
},
"qos": {
"type": "int",
"attr": "!IFLA_VF_VLAN_LIST && IFLA_VF_VLAN"
},
"tx_rate": {
"type": "int"
},
"rate": {
"type": "dict",
"attr": "IFLA_VF_RATE",
"dict": {
"max_tx": {
"type": "int"
},
"min_tx": {
"type": "int"
}
}
},
"spoofchk": {
"type": "bool",
"attr": "IFLA_VF_SPOOFCHK"
},
"link_state": {
"type": "string",
"attr": "IFLA_VF_LINK_STATE"
},
"trust": {
"type": "bool",
"attr": "IFLA_VF_TRUST"
},
"query_rss_en": {
"type": "bool",
"attr": "IFLA_VF_RSS_QUERY_EN"
},
"stats": {
"type": "dict",
"attr": "IFLA_VF_STATS",
"dict": {
"rx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint",
"attr": "IFLA_VF_STATS_RX_BYTES"
},
"packets": {
"type": "uint",
"attr": "IFLA_VF_STATS_RX_PACKETS"
},
"multicast": {
"type": "uint",
"attr": "IFLA_VF_STATS_MULTICAST"
},
"broadcast": {
"type": "uint",
"attr": "IFLA_VF_STATS_BROADCAST"
}
}
},
"tx": {
"type": "dict",
"dict": {
"bytes": {
"type": "uint",
"attr": "IFLA_VF_STATS_TX_BYTES"
},
"packets": {
"type": "uint",
"attr": "IFLA_VF_STATS_TX_PACKETS"
}
}
}
}
}
}
]
}
}
]
Example with the config previously given:
Note that here, linkinfo attributes are not populated.
The schemas are provided in each link type patches.
$ ip -details -json link show
[{
"ifindex": 1,
"ifname": "lo",
"flags": ["LOOPBACK","UP","LOWER_UP"],
"mtu": 65536,
"qdisc": "noqueue",
"operstate": "UNKNOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "loopback",
"address": "00:00:00:00:00:00",
"broadcast": "00:00:00:00:00:00",
"promiscuity": 0,
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 2,
"ifname": "eth0",
"flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "pfifo_fast",
"operstate": "UP",
"linkmode": "DEFAULT",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "08:00:27:db:31:88",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 3,
"ifname": "swp1",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "08:00:27:5b:b1:75",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 10,
"ifname": "vxlan42",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1500,
"qdisc": "noop",
"master": "br0",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "4a:d9:91:42:a2:d2",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 1,
"linkinfo": {
"info_kind": "vxlan",
"info_data": {},
"info_slave_kind": "bridge",
"info_slave_data": {}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "bond0",
"flags": ["BROADCAST","MULTICAST","MASTER"],
"mtu": 1500,
"qdisc": "noop",
"master": "br0",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "e2:aa:7b:17:c5:14",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 1,
"linkinfo": {
"info_kind": "bond",
"info_data": {},
"info_slave_kind": "bridge",
"info_slave_data": {},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 16,
"num_rx_queues": 16,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 12,
"ifname": "swp1.50",
"link": "swp1",
"flags": ["BROADCAST","MULTICAST","M-DOWN"],
"mtu": 1500,
"qdisc": "noop",
"master": "br0",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "08:00:27:5b:b1:75",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 1,
"linkinfo": {
"info_kind": "vlan",
"info_data": {},
"info_slave_kind": "bridge",
"info_slave_data": {},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 13,
"ifname": "br0",
"flags": ["NO-CARRIER","BROADCAST","MULTICAST","UP"],
"mtu": 1500,
"qdisc": "noqueue",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "08:00:27:5b:b1:75",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "bridge",
"info_data": {},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/ipaddress.c | 1089 +++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 766 insertions(+), 323 deletions(-)
diff --git a/ip/ipaddress.c b/ip/ipaddress.c
index cf8ef818..293d958c 100644
--- a/ip/ipaddress.c
+++ b/ip/ipaddress.c
@@ -30,6 +30,7 @@
#include <linux/sockios.h>
#include <linux/net_namespace.h>
+#include "utils.h"
#include "rt_names.h"
#include "utils.h"
#include "ll_map.h"
@@ -84,13 +85,14 @@ static void usage(void)
static void print_link_flags(FILE *fp, unsigned int flags, unsigned int mdown)
{
- fprintf(fp, "<");
+ open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
if (flags & IFF_UP && !(flags & IFF_RUNNING))
- fprintf(fp, "NO-CARRIER%s", flags ? "," : "");
+ print_string(PRINT_ANY, NULL,
+ flags ? "%s," : "%s", "NO-CARRIER");
flags &= ~IFF_RUNNING;
-#define _PF(f) if (flags&IFF_##f) { \
- flags &= ~IFF_##f ; \
- fprintf(fp, #f "%s", flags ? "," : ""); }
+#define _PF(f) if (flags&IFF_##f) { \
+ flags &= ~IFF_##f ; \
+ print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); }
_PF(LOOPBACK);
_PF(BROADCAST);
_PF(POINTOPOINT);
@@ -111,10 +113,10 @@ static void print_link_flags(FILE *fp, unsigned int flags, unsigned int mdown)
_PF(ECHO);
#undef _PF
if (flags)
- fprintf(fp, "%x", flags);
+ print_hex(PRINT_ANY, NULL, "%x", flags);
if (mdown)
- fprintf(fp, ",M-DOWN");
- fprintf(fp, "> ");
+ print_string(PRINT_ANY, NULL, ",%s", "M-DOWN");
+ close_json_array(PRINT_ANY, "> ");
}
static const char *oper_states[] = {
@@ -125,14 +127,26 @@ static const char *oper_states[] = {
static void print_operstate(FILE *f, __u8 state)
{
if (state >= ARRAY_SIZE(oper_states)) {
- fprintf(f, "state %#x ", state);
+ if (is_json_context())
+ print_uint(PRINT_JSON, "operstate_index", NULL, state);
+ else
+ print_0xhex(PRINT_FP, NULL, "state %#x", state);
} else if (brief) {
- color_fprintf(f, oper_state_color(state),
- "%-14s ", oper_states[state]);
+ print_color_string(PRINT_ANY,
+ oper_state_color(state),
+ "operstate",
+ "%-14s ",
+ oper_states[state]);
} else {
- fprintf(f, "state ");
- color_fprintf(f, oper_state_color(state),
- "%s ", oper_states[state]);
+ if (is_json_context())
+ print_string(PRINT_JSON,
+ "operstate",
+ NULL, oper_states[state]);
+ else {
+ fprintf(f, "state ");
+ color_fprintf(f, oper_state_color(state),
+ "%s ", oper_states[state]);
+ }
}
}
@@ -169,7 +183,7 @@ static void print_queuelen(FILE *f, struct rtattr *tb[IFLA_MAX + 1])
qlen = ifr.ifr_qlen;
}
if (qlen)
- fprintf(f, "qlen %d", qlen);
+ print_int(PRINT_ANY, "txqlen", "qlen %d", qlen);
}
static const char *link_modes[] = {
@@ -181,9 +195,15 @@ static void print_linkmode(FILE *f, struct rtattr *tb)
unsigned int mode = rta_getattr_u8(tb);
if (mode >= ARRAY_SIZE(link_modes))
- fprintf(f, "mode %d ", mode);
+ print_int(PRINT_ANY,
+ "linkmode_index",
+ "mode %d ",
+ mode);
else
- fprintf(f, "mode %s ", link_modes[mode]);
+ print_string(PRINT_ANY,
+ "linkmode",
+ "mode %s "
+ , link_modes[mode]);
}
static char *parse_link_kind(struct rtattr *tb, bool slave)
@@ -215,13 +235,14 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
char slave[32];
parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb);
+ open_json_object("linkinfo");
if (linkinfo[IFLA_INFO_KIND]) {
const char *kind
= rta_getattr_str(linkinfo[IFLA_INFO_KIND]);
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " %s ", kind);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ print_string(PRINT_ANY, "info_kind", " %s ", kind);
lu = get_link_kind(kind);
if (lu && lu->print_opt) {
@@ -232,11 +253,16 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
linkinfo[IFLA_INFO_DATA]);
data = attr;
}
+ open_json_object("info_data");
lu->print_opt(lu, fp, data);
+ close_json_object();
if (linkinfo[IFLA_INFO_XSTATS] && show_stats &&
- lu->print_xstats)
+ lu->print_xstats) {
+ open_json_object("info_xstats");
lu->print_xstats(lu, fp, linkinfo[IFLA_INFO_XSTATS]);
+ close_json_object();
+ }
}
}
@@ -244,8 +270,12 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
const char *slave_kind
= rta_getattr_str(linkinfo[IFLA_INFO_SLAVE_KIND]);
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " %s_slave ", slave_kind);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ print_string(PRINT_ANY,
+ "info_slave_kind",
+ " %s_slave ",
+ slave_kind);
+
snprintf(slave, sizeof(slave), "%s_slave", slave_kind);
slave_lu = get_link_kind(slave);
@@ -257,9 +287,12 @@ static void print_linktype(FILE *fp, struct rtattr *tb)
linkinfo[IFLA_INFO_SLAVE_DATA]);
data = attr;
}
+ open_json_object("info_slave_data");
slave_lu->print_opt(slave_lu, fp, data);
+ close_json_object();
}
}
+ close_json_object();
}
static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
@@ -275,22 +308,39 @@ static void print_af_spec(FILE *fp, struct rtattr *af_spec_attr)
if (tb[IFLA_INET6_ADDR_GEN_MODE]) {
__u8 mode = rta_getattr_u8(tb[IFLA_INET6_ADDR_GEN_MODE]);
+ SPRINT_BUF(b1);
switch (mode) {
case IN6_ADDR_GEN_MODE_EUI64:
- fprintf(fp, "addrgenmode eui64 ");
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "eui64");
break;
case IN6_ADDR_GEN_MODE_NONE:
- fprintf(fp, "addrgenmode none ");
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "none");
break;
case IN6_ADDR_GEN_MODE_STABLE_PRIVACY:
- fprintf(fp, "addrgenmode stable_secret ");
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "stable_secret");
break;
case IN6_ADDR_GEN_MODE_RANDOM:
- fprintf(fp, "addrgenmode random ");
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ "random");
break;
default:
- fprintf(fp, "addrgenmode %#.2hhx ", mode);
+ snprintf(b1, sizeof(b1), "%#.2hhx", mode);
+ print_string(PRINT_ANY,
+ "inet6_addr_gen_mode",
+ "addrgenmode %s ",
+ b1);
break;
}
}
@@ -316,83 +366,135 @@ static void print_vfinfo(FILE *fp, struct rtattr *vfinfo)
vf_mac = RTA_DATA(vf[IFLA_VF_MAC]);
vf_tx_rate = RTA_DATA(vf[IFLA_VF_TX_RATE]);
- fprintf(fp, "%s vf %d MAC %s", _SL_, vf_mac->vf,
- ll_addr_n2a((unsigned char *)&vf_mac->mac,
- ETH_ALEN, 0, b1, sizeof(b1)));
+ print_string(PRINT_FP, NULL, "%s ", _SL_);
+ print_int(PRINT_ANY, "vf", "vf %d ", vf_mac->vf);
+ print_string(PRINT_ANY, "mac", "MAC %s",
+ ll_addr_n2a((unsigned char *) &vf_mac->mac,
+ ETH_ALEN, 0, b1, sizeof(b1)));
+
if (vf[IFLA_VF_VLAN_LIST]) {
struct rtattr *i, *vfvlanlist = vf[IFLA_VF_VLAN_LIST];
int rem = RTA_PAYLOAD(vfvlanlist);
+ open_json_array(PRINT_JSON, "vlan_list");
for (i = RTA_DATA(vfvlanlist);
- RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
- struct ifla_vf_vlan_info *vf_vlan_info =
- RTA_DATA(i);
+ RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
+ struct ifla_vf_vlan_info *vf_vlan_info = RTA_DATA(i);
SPRINT_BUF(b2);
+ open_json_object(NULL);
if (vf_vlan_info->vlan)
- fprintf(fp, ", vlan %d", vf_vlan_info->vlan);
+ print_int(PRINT_ANY,
+ "vlan",
+ ", vlan %d",
+ vf_vlan_info->vlan);
if (vf_vlan_info->qos)
- fprintf(fp, ", qos %d", vf_vlan_info->qos);
+ print_int(PRINT_ANY,
+ "qos",
+ ", qos %d",
+ vf_vlan_info->qos);
if (vf_vlan_info->vlan_proto &&
vf_vlan_info->vlan_proto != htons(ETH_P_8021Q))
- fprintf(fp, ", vlan protocol %s",
- ll_proto_n2a(vf_vlan_info->vlan_proto,
+ print_string(PRINT_ANY,
+ "protocol",
+ ", vlan protocol %s",
+ ll_proto_n2a(
+ vf_vlan_info->vlan_proto,
b2, sizeof(b2)));
-
+ close_json_object();
}
+ close_json_array(PRINT_JSON, NULL);
} else {
struct ifla_vf_vlan *vf_vlan = RTA_DATA(vf[IFLA_VF_VLAN]);
if (vf_vlan->vlan)
- fprintf(fp, ", vlan %d", vf_vlan->vlan);
+ print_int(PRINT_ANY,
+ "vlan",
+ ", vlan %d",
+ vf_vlan->vlan);
if (vf_vlan->qos)
- fprintf(fp, ", qos %d", vf_vlan->qos);
+ print_int(PRINT_ANY, "qos", ", qos %d", vf_vlan->qos);
}
+
if (vf_tx_rate->rate)
- fprintf(fp, ", tx rate %d (Mbps)", vf_tx_rate->rate);
+ print_int(PRINT_ANY,
+ "tx_rate",
+ ", tx rate %d (Mbps)",
+ vf_tx_rate->rate);
if (vf[IFLA_VF_RATE]) {
struct ifla_vf_rate *vf_rate = RTA_DATA(vf[IFLA_VF_RATE]);
-
- if (vf_rate->max_tx_rate)
- fprintf(fp, ", max_tx_rate %dMbps", vf_rate->max_tx_rate);
- if (vf_rate->min_tx_rate)
- fprintf(fp, ", min_tx_rate %dMbps", vf_rate->min_tx_rate);
+ int max_tx = vf_rate->max_tx_rate;
+ int min_tx = vf_rate->min_tx_rate;
+
+ if (is_json_context()) {
+ open_json_object("rate");
+ print_int(PRINT_JSON, "max_tx", NULL, max_tx);
+ print_int(PRINT_ANY, "min_tx", NULL, min_tx);
+ close_json_object();
+ } else {
+ if (max_tx)
+ fprintf(fp, ", max_tx_rate %dMbps", max_tx);
+ if (min_tx)
+ fprintf(fp, ", min_tx_rate %dMbps", min_tx);
+ }
}
+
if (vf[IFLA_VF_SPOOFCHK]) {
struct ifla_vf_spoofchk *vf_spoofchk =
RTA_DATA(vf[IFLA_VF_SPOOFCHK]);
if (vf_spoofchk->setting != -1)
- fprintf(fp, ", spoof checking %s",
- vf_spoofchk->setting ? "on" : "off");
+ print_bool(PRINT_ANY,
+ "spoofchk",
+ vf_spoofchk->setting ?
+ ", spoof checking on" : ", spoof checking off",
+ vf_spoofchk->setting);
}
+
if (vf[IFLA_VF_LINK_STATE]) {
struct ifla_vf_link_state *vf_linkstate =
RTA_DATA(vf[IFLA_VF_LINK_STATE]);
if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_AUTO)
- fprintf(fp, ", link-state auto");
+ print_string(PRINT_ANY,
+ "link_state",
+ ", link-state %s",
+ "auto");
else if (vf_linkstate->link_state == IFLA_VF_LINK_STATE_ENABLE)
- fprintf(fp, ", link-state enable");
+ print_string(PRINT_ANY,
+ "link_state",
+ ", link-state %s",
+ "enable");
else
- fprintf(fp, ", link-state disable");
+ print_string(PRINT_ANY,
+ "link_state",
+ ", link-state %s",
+ "disable");
}
+
if (vf[IFLA_VF_TRUST]) {
struct ifla_vf_trust *vf_trust = RTA_DATA(vf[IFLA_VF_TRUST]);
if (vf_trust->setting != -1)
- fprintf(fp, ", trust %s",
- vf_trust->setting ? "on" : "off");
+ print_bool(PRINT_ANY,
+ "trust",
+ vf_trust->setting ? ", trust on" : ", trust off",
+ vf_trust->setting);
}
+
if (vf[IFLA_VF_RSS_QUERY_EN]) {
struct ifla_vf_rss_query_en *rss_query =
RTA_DATA(vf[IFLA_VF_RSS_QUERY_EN]);
if (rss_query->setting != -1)
- fprintf(fp, ", query_rss %s",
- rss_query->setting ? "on" : "off");
+ print_bool(PRINT_ANY,
+ "query_rss_en",
+ rss_query->setting ? ", query_rss on"
+ : ", query_rss off",
+ rss_query->setting);
}
+
if (vf[IFLA_VF_STATS] && show_stats)
print_vf_stats64(fp, vf[IFLA_VF_STATS]);
}
@@ -432,7 +534,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" : "");
+ (double) count / powi, *prefix, use_iec ? "i" : "");
fprintf(fp, "%-*s ", width, buf);
}
@@ -448,155 +550,337 @@ static void print_vf_stats64(FILE *fp, struct rtattr *vfstats)
parse_rtattr_nested(vf, IFLA_VF_MAX, vfstats);
- /* RX stats */
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " RX: bytes packets mcast bcast %s", _SL_);
- fprintf(fp, " ");
+ if (is_json_context()) {
+ open_json_object("stats");
+
+ /* RX stats */
+ open_json_object("rx");
+ print_uint(PRINT_JSON, "bytes", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_RX_BYTES]));
+ print_uint(PRINT_JSON, "packets", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_RX_PACKETS]));
+ print_uint(PRINT_JSON, "multicast", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_MULTICAST]));
+ print_uint(PRINT_JSON, "broadcast", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_BROADCAST]));
+ close_json_object();
+
+ /* TX stats */
+ open_json_object("tx");
+ print_uint(PRINT_JSON, "tx_bytes", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_TX_BYTES]));
+ print_uint(PRINT_JSON, "tx_packets", NULL,
+ rta_getattr_u64(vf[IFLA_VF_STATS_TX_PACKETS]));
+ close_json_object();
+ close_json_object();
+ } else {
+ /* RX stats */
+ fprintf(fp, "%s", _SL_);
+ fprintf(fp, " RX: bytes packets mcast bcast %s", _SL_);
+ fprintf(fp, " ");
- print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_RX_BYTES]));
- print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_RX_PACKETS]));
- print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_MULTICAST]));
- print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_BROADCAST]));
+ print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_RX_BYTES]));
+ print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_RX_PACKETS]));
+ print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_MULTICAST]));
+ print_num(fp, 7, rta_getattr_u64(vf[IFLA_VF_STATS_BROADCAST]));
- /* TX stats */
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " TX: bytes packets %s", _SL_);
- fprintf(fp, " ");
+ /* TX stats */
+ fprintf(fp, "%s", _SL_);
+ fprintf(fp, " TX: bytes packets %s", _SL_);
+ fprintf(fp, " ");
- print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_TX_BYTES]));
- print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_TX_PACKETS]));
+ print_num(fp, 10, rta_getattr_u64(vf[IFLA_VF_STATS_TX_BYTES]));
+ print_num(fp, 8, rta_getattr_u64(vf[IFLA_VF_STATS_TX_PACKETS]));
+ }
}
static void print_link_stats64(FILE *fp, const struct rtnl_link_stats64 *s,
const struct rtattr *carrier_changes)
{
- /* RX stats */
- fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
- 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_over_errors);
- print_num(fp, 7, s->multicast);
- if (s->rx_compressed)
- print_num(fp, 7, s->rx_compressed);
-
- /* RX error stats */
- if (show_stats > 1) {
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " RX errors: length crc frame fifo missed%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_missed_errors);
- if (s->rx_nohandler)
- print_num(fp, 7, s->rx_nohandler);
+ if (is_json_context()) {
+ open_json_object("stats644");
+
+ /* RX stats */
+ open_json_object("rx");
+ print_uint(PRINT_JSON, "bytes", NULL, s->rx_bytes);
+ print_uint(PRINT_JSON, "packets", NULL, s->rx_packets);
+ print_uint(PRINT_JSON, "errors", NULL, s->rx_errors);
+ print_uint(PRINT_JSON, "dropped", NULL, s->rx_dropped);
+ print_uint(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
+ print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
+ if (s->rx_compressed)
+ print_uint(PRINT_JSON,
+ "compressed",
+ NULL, s->rx_compressed);
+
+ /* RX error stats */
+ if (show_stats > 1) {
+ print_uint(PRINT_JSON,
+ "length_errors",
+ NULL, s->rx_length_errors);
+ print_uint(PRINT_JSON,
+ "crc_errors",
+ NULL, s->rx_crc_errors);
+ print_uint(PRINT_JSON,
+ "frame_errors",
+ NULL, s->rx_frame_errors);
+ print_uint(PRINT_JSON,
+ "fifo_errors",
+ NULL, s->rx_fifo_errors);
+ print_uint(PRINT_JSON,
+ "missed_errors",
+ NULL, s->rx_missed_errors);
+ if (s->rx_nohandler)
+ print_uint(PRINT_JSON,
+ "nohandler", NULL, s->rx_nohandler);
+ }
+ close_json_object();
+
+ /* TX stats */
+ open_json_object("tx");
+ print_uint(PRINT_JSON, "bytes", NULL, s->tx_bytes);
+ print_uint(PRINT_JSON, "packets", NULL, s->tx_packets);
+ print_uint(PRINT_JSON, "errors", NULL, s->tx_errors);
+ print_uint(PRINT_JSON, "dropped", NULL, s->tx_dropped);
+ print_uint(PRINT_JSON,
+ "carrier_errors",
+ NULL, s->tx_carrier_errors);
+ print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
+ if (s->tx_compressed)
+ print_uint(PRINT_JSON,
+ "compressed",
+ NULL, s->tx_compressed);
+
+ /* TX error stats */
+ if (show_stats > 1) {
+ print_uint(PRINT_JSON,
+ "aborted_errors",
+ NULL, s->tx_aborted_errors);
+ print_uint(PRINT_JSON,
+ "fifo_errors",
+ NULL, s->tx_fifo_errors);
+ print_uint(PRINT_JSON,
+ "window_errors",
+ NULL, s->tx_window_errors);
+ print_uint(PRINT_JSON,
+ "heartbeat_errors",
+ NULL, s->tx_heartbeat_errors);
+ if (carrier_changes)
+ print_uint(PRINT_JSON, "carrier_changes", NULL,
+ rta_getattr_u32(carrier_changes));
+ }
+ close_json_object();
+ close_json_object();
- }
- fprintf(fp, "%s", _SL_);
+ } else {
+ /* RX stats */
+ fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
+ 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_over_errors);
+ print_num(fp, 7, s->multicast);
+ if (s->rx_compressed)
+ print_num(fp, 7, s->rx_compressed);
+
+ /* RX error stats */
+ if (show_stats > 1) {
+ fprintf(fp, "%s", _SL_);
+ fprintf(fp, " RX errors: length crc frame fifo missed%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_missed_errors);
+ if (s->rx_nohandler)
+ print_num(fp, 7, s->rx_nohandler);
- /* TX stats */
- fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
- 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);
- if (s->tx_compressed)
- print_num(fp, 7, 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, " ");
- 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);
- if (carrier_changes)
- print_num(fp, 7, rta_getattr_u32(carrier_changes));
+ /* TX stats */
+ fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
+ 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);
+ if (s->tx_compressed)
+ print_num(fp, 7, 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, " ");
+ 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);
+ if (carrier_changes)
+ print_num(fp, 7, rta_getattr_u32(carrier_changes));
+ }
}
}
static void print_link_stats32(FILE *fp, const struct rtnl_link_stats *s,
const struct rtattr *carrier_changes)
{
- /* RX stats */
- fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
- 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_over_errors);
- print_num(fp, 7, s->multicast);
- if (s->rx_compressed)
- print_num(fp, 7, s->rx_compressed);
-
- /* RX error stats */
- if (show_stats > 1) {
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " RX errors: length crc frame fifo missed%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_missed_errors);
- if (s->rx_nohandler)
- print_num(fp, 7, s->rx_nohandler);
- }
- fprintf(fp, "%s", _SL_);
+ if (is_json_context()) {
+ open_json_object("stats");
+
+ /* RX stats */
+ open_json_object("rx");
+ print_uint(PRINT_JSON, "bytes", NULL, s->rx_bytes);
+ print_uint(PRINT_JSON, "packets", NULL, s->rx_packets);
+ print_uint(PRINT_JSON, "errors", NULL, s->rx_errors);
+ print_uint(PRINT_JSON, "dropped", NULL, s->rx_dropped);
+ print_uint(PRINT_JSON, "over_errors", NULL, s->rx_over_errors);
+ print_uint(PRINT_JSON, "multicast", NULL, s->multicast);
+ if (s->rx_compressed)
+ print_int(PRINT_JSON,
+ "compressed",
+ NULL, s->rx_compressed);
+
+ /* RX error stats */
+ if (show_stats > 1) {
+ print_uint(PRINT_JSON,
+ "length_errors",
+ NULL, s->rx_length_errors);
+ print_uint(PRINT_JSON,
+ "crc_errors",
+ NULL, s->rx_crc_errors);
+ print_uint(PRINT_JSON,
+ "frame_errors",
+ NULL, s->rx_frame_errors);
+ print_uint(PRINT_JSON,
+ "fifo_errors",
+ NULL, s->rx_fifo_errors);
+ print_uint(PRINT_JSON,
+ "missed_errors",
+ NULL, s->rx_missed_errors);
+ if (s->rx_nohandler)
+ print_int(PRINT_JSON,
+ "nohandler",
+ NULL, s->rx_nohandler);
+ }
+ close_json_object();
+
+ /* TX stats */
+ open_json_object("tx");
+ print_uint(PRINT_JSON, "bytes", NULL, s->tx_bytes);
+ print_uint(PRINT_JSON, "packets", NULL, s->tx_packets);
+ print_uint(PRINT_JSON, "errors", NULL, s->tx_errors);
+ print_uint(PRINT_JSON, "dropped", NULL, s->tx_dropped);
+ print_uint(PRINT_JSON,
+ "carrier_errors",
+ NULL, s->tx_carrier_errors);
+ print_uint(PRINT_JSON, "collisions", NULL, s->collisions);
+ if (s->tx_compressed)
+ print_int(PRINT_JSON,
+ "compressed",
+ NULL, s->tx_compressed);
+
+ /* TX error stats */
+ if (show_stats > 1) {
+ print_uint(PRINT_JSON,
+ "aborted_errors",
+ NULL, s->tx_aborted_errors);
+ print_uint(PRINT_JSON,
+ "fifo_errors",
+ NULL, s->tx_fifo_errors);
+ print_uint(PRINT_JSON,
+ "window_errors",
+ NULL, s->tx_window_errors);
+ print_uint(PRINT_JSON,
+ "heartbeat_errors",
+ NULL, s->tx_heartbeat_errors);
+ if (carrier_changes)
+ print_uint(PRINT_JSON,
+ "carrier_changes",
+ NULL,
+ rta_getattr_u32(carrier_changes));
+ }
- /* TX stats */
- fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
- 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);
- if (s->tx_compressed)
- print_num(fp, 7, 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");
+ close_json_object();
+ close_json_object();
+ } else {
+ /* RX stats */
+ fprintf(fp, " RX: bytes packets errors dropped overrun mcast %s%s",
+ 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_over_errors);
+ print_num(fp, 7, s->multicast);
+ if (s->rx_compressed)
+ print_num(fp, 7, s->rx_compressed);
+
+ /* RX error stats */
+ if (show_stats > 1) {
+ fprintf(fp, "%s", _SL_);
+ fprintf(fp, " RX errors: length crc frame fifo missed%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_missed_errors);
+ if (s->rx_nohandler)
+ print_num(fp, 7, s->rx_nohandler);
+ }
fprintf(fp, "%s", _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);
- if (carrier_changes)
- print_num(fp, 7, rta_getattr_u32(carrier_changes));
+ /* TX stats */
+ fprintf(fp, " TX: bytes packets errors dropped carrier collsns %s%s",
+ 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);
+ if (s->tx_compressed)
+ print_num(fp, 7, 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, " ");
+ 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);
+ if (carrier_changes)
+ print_num(fp, 7, rta_getattr_u32(carrier_changes));
+ }
}
}
@@ -694,44 +978,50 @@ int print_linkinfo_brief(const struct sockaddr_nl *who,
return -1;
if (n->nlmsg_type == RTM_DELLINK)
- fprintf(fp, "Deleted ");
+ print_bool(PRINT_ANY, "deleted", "Deleted ", true);
if (tb[IFLA_LINK]) {
SPRINT_BUF(b1);
int iflink = rta_getattr_u32(tb[IFLA_LINK]);
- if (iflink == 0)
+ if (iflink == 0) {
snprintf(buf, sizeof(buf), "%s@NONE", name);
- else {
- snprintf(buf, sizeof(buf),
- "%s@%s", name, ll_idx_n2a(iflink, b1));
+ print_null(PRINT_JSON, "link", NULL, NULL);
+ } else {
+ const char *link = ll_idx_n2a(iflink, b1);
+
+ print_string(PRINT_JSON, "link", NULL, link);
+ snprintf(buf, sizeof(buf), "%s@%s", name, link);
m_flag = ll_index_to_flags(iflink);
m_flag = !(m_flag & IFF_UP);
}
} else
snprintf(buf, sizeof(buf), "%s", name);
- fprintf(fp, "%-16s ", buf);
+ print_string(PRINT_FP, NULL, "%-16s ", buf);
+ print_string(PRINT_JSON, "ifname", NULL, name);
if (tb[IFLA_OPERSTATE])
print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE]));
if (pfilter->family == AF_PACKET) {
SPRINT_BUF(b1);
+
if (tb[IFLA_ADDRESS]) {
- color_fprintf(fp, COLOR_MAC, "%s ",
- ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
- RTA_PAYLOAD(tb[IFLA_ADDRESS]),
- ifi->ifi_type,
- b1, sizeof(b1)));
+ print_color_string(PRINT_ANY, COLOR_MAC,
+ "address", "%s ",
+ ll_addr_n2a(
+ RTA_DATA(tb[IFLA_ADDRESS]),
+ RTA_PAYLOAD(tb[IFLA_ADDRESS]),
+ ifi->ifi_type,
+ b1, sizeof(b1)));
}
}
- if (pfilter->family == AF_PACKET)
+ if (pfilter->family == AF_PACKET) {
print_link_flags(fp, ifi->ifi_flags, m_flag);
-
- if (pfilter->family == AF_PACKET)
- fprintf(fp, "\n");
+ print_string(PRINT_FP, NULL, "%s", "\n");
+ }
fflush(fp);
return 0;
}
@@ -749,10 +1039,12 @@ static const char *link_events[] = {
static void print_link_event(FILE *f, __u32 event)
{
if (event >= ARRAY_SIZE(link_events))
- fprintf(f, "event %d ", event);
+ print_int(PRINT_ANY, "event", "event %d ", event);
else {
if (event)
- fprintf(f, "event %s ", link_events[event]);
+ print_string(PRINT_ANY,
+ "event", "event %s ",
+ link_events[event]);
}
}
@@ -808,41 +1100,63 @@ int print_linkinfo(const struct sockaddr_nl *who,
return -1;
if (n->nlmsg_type == RTM_DELLINK)
- fprintf(fp, "Deleted ");
-
- fprintf(fp, "%d: ", ifi->ifi_index);
- color_fprintf(fp, COLOR_IFNAME, "%s",
- tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>");
+ print_bool(PRINT_ANY, "deleted", "Deleted ", true);
+
+ print_int(PRINT_ANY, "ifindex", "%d: ", ifi->ifi_index);
+ if (tb[IFLA_IFNAME]) {
+ print_color_string(PRINT_ANY,
+ COLOR_IFNAME,
+ "ifname", "%s",
+ rta_getattr_str(tb[IFLA_IFNAME]));
+ } else {
+ print_null(PRINT_JSON, "ifname", NULL, NULL);
+ print_color_null(PRINT_FP, COLOR_IFNAME,
+ "ifname", "%s", "<nil>");
+ }
if (tb[IFLA_LINK]) {
- SPRINT_BUF(b1);
int iflink = rta_getattr_u32(tb[IFLA_LINK]);
if (iflink == 0)
- fprintf(fp, "@NONE: ");
+ print_null(PRINT_ANY, "link", "@%s: ", "NONE");
else {
if (tb[IFLA_LINK_NETNSID])
- fprintf(fp, "@if%d: ", iflink);
+ print_int(PRINT_ANY,
+ "link_index", "@if%d: ", iflink);
else {
- fprintf(fp, "@%s: ", ll_idx_n2a(iflink, b1));
+ SPRINT_BUF(b1);
+
+ print_string(PRINT_ANY,
+ "link",
+ "@%s: ",
+ ll_idx_n2a(iflink, b1));
m_flag = ll_index_to_flags(iflink);
m_flag = !(m_flag & IFF_UP);
}
}
} else {
- fprintf(fp, ": ");
+ print_string(PRINT_FP, NULL, ": ", NULL);
}
print_link_flags(fp, ifi->ifi_flags, m_flag);
if (tb[IFLA_MTU])
- fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU]));
+ print_int(PRINT_ANY,
+ "mtu", "mtu %u ",
+ rta_getattr_u32(tb[IFLA_MTU]));
if (tb[IFLA_XDP])
xdp_dump(fp, tb[IFLA_XDP]);
if (tb[IFLA_QDISC])
- fprintf(fp, "qdisc %s ", rta_getattr_str(tb[IFLA_QDISC]));
+ print_string(PRINT_ANY,
+ "qdisc",
+ "qdisc %s ",
+ rta_getattr_str(tb[IFLA_QDISC]));
if (tb[IFLA_MASTER]) {
SPRINT_BUF(b1);
- fprintf(fp, "master %s ", ll_idx_n2a(rta_getattr_u32(tb[IFLA_MASTER]), b1));
+
+ print_string(PRINT_ANY,
+ "master",
+ "master %s ",
+ ll_idx_n2a(rta_getattr_u32(tb[IFLA_MASTER]), b1));
}
if (tb[IFLA_OPERSTATE])
@@ -855,7 +1169,10 @@ int print_linkinfo(const struct sockaddr_nl *who,
SPRINT_BUF(b1);
int group = rta_getattr_u32(tb[IFLA_GROUP]);
- fprintf(fp, "group %s ", rtnl_group_n2a(group, b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "group",
+ "group %s ",
+ rtnl_group_n2a(group, b1, sizeof(b1)));
}
if (filter.showqueue)
@@ -866,47 +1183,68 @@ int print_linkinfo(const struct sockaddr_nl *who,
if (!filter.family || filter.family == AF_PACKET || show_details) {
SPRINT_BUF(b1);
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " link/%s ", ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ print_string(PRINT_ANY,
+ "link_type",
+ " link/%s ",
+ ll_type_n2a(ifi->ifi_type, b1, sizeof(b1)));
if (tb[IFLA_ADDRESS]) {
- color_fprintf(fp, COLOR_MAC, "%s",
- ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
- RTA_PAYLOAD(tb[IFLA_ADDRESS]),
- ifi->ifi_type,
- b1, sizeof(b1)));
+ print_color_string(PRINT_ANY,
+ COLOR_MAC,
+ "address",
+ "%s",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_ADDRESS]),
+ RTA_PAYLOAD(tb[IFLA_ADDRESS]),
+ ifi->ifi_type,
+ b1, sizeof(b1)));
}
if (tb[IFLA_BROADCAST]) {
- if (ifi->ifi_flags&IFF_POINTOPOINT)
- fprintf(fp, " peer ");
- else
- fprintf(fp, " brd ");
- color_fprintf(fp, COLOR_MAC, "%s",
- ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
- RTA_PAYLOAD(tb[IFLA_BROADCAST]),
- ifi->ifi_type,
- b1, sizeof(b1)));
+ if (ifi->ifi_flags&IFF_POINTOPOINT) {
+ print_string(PRINT_FP, NULL, " peer ", NULL);
+ print_bool(PRINT_JSON,
+ "link_pointtopoint", NULL, true);
+ } else {
+ print_string(PRINT_FP, NULL, " brd ", NULL);
+ }
+ print_color_string(PRINT_ANY,
+ COLOR_MAC,
+ "broadcast",
+ "%s",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_BROADCAST]),
+ RTA_PAYLOAD(tb[IFLA_BROADCAST]),
+ ifi->ifi_type,
+ b1, sizeof(b1)));
}
}
if (tb[IFLA_LINK_NETNSID]) {
int id = rta_getattr_u32(tb[IFLA_LINK_NETNSID]);
- if (id >= 0)
- fprintf(fp, " link-netnsid %d", id);
- else
- fprintf(fp, " link-netnsid unknown");
+ if (is_json_context()) {
+ print_int(PRINT_JSON, "link_netnsid", NULL, id);
+ } else {
+ if (id >= 0)
+ print_int(PRINT_FP, NULL,
+ " link-netnsid %d", id);
+ else
+ print_string(PRINT_FP, NULL,
+ " link-netnsid %s", "unknown");
+ }
}
if (tb[IFLA_PROTO_DOWN]) {
if (rta_getattr_u8(tb[IFLA_PROTO_DOWN]))
- fprintf(fp, " protodown on ");
+ print_bool(PRINT_ANY,
+ "proto_down", " protodown on ", true);
}
if (show_details) {
if (tb[IFLA_PROMISCUITY])
- fprintf(fp, " promiscuity %u ",
- rta_getattr_u32(tb[IFLA_PROMISCUITY]));
+ print_uint(PRINT_ANY,
+ "promiscuity",
+ " promiscuity %u ",
+ rta_getattr_u32(tb[IFLA_PROMISCUITY]));
if (tb[IFLA_LINKINFO])
print_linktype(fp, tb[IFLA_LINKINFO]);
@@ -915,50 +1253,68 @@ int print_linkinfo(const struct sockaddr_nl *who,
print_af_spec(fp, tb[IFLA_AF_SPEC]);
if (tb[IFLA_NUM_TX_QUEUES])
- fprintf(fp, "numtxqueues %u ",
- rta_getattr_u32(tb[IFLA_NUM_TX_QUEUES]));
+ print_uint(PRINT_ANY,
+ "num_tx_queues",
+ "numtxqueues %u ",
+ rta_getattr_u32(tb[IFLA_NUM_TX_QUEUES]));
if (tb[IFLA_NUM_RX_QUEUES])
- fprintf(fp, "numrxqueues %u ",
- rta_getattr_u32(tb[IFLA_NUM_RX_QUEUES]));
+ print_uint(PRINT_ANY,
+ "num_rx_queues",
+ "numrxqueues %u ",
+ rta_getattr_u32(tb[IFLA_NUM_RX_QUEUES]));
if (tb[IFLA_GSO_MAX_SIZE])
- fprintf(fp, "gso_max_size %u ",
- rta_getattr_u32(tb[IFLA_GSO_MAX_SIZE]));
+ print_uint(PRINT_ANY,
+ "gso_max_size",
+ "gso_max_size %u ",
+ rta_getattr_u32(tb[IFLA_GSO_MAX_SIZE]));
if (tb[IFLA_GSO_MAX_SEGS])
- fprintf(fp, "gso_max_segs %u ",
- rta_getattr_u32(tb[IFLA_GSO_MAX_SEGS]));
+ print_uint(PRINT_ANY,
+ "gso_max_segs",
+ "gso_max_segs %u ",
+ rta_getattr_u32(tb[IFLA_GSO_MAX_SEGS]));
if (tb[IFLA_PHYS_PORT_NAME])
- fprintf(fp, "portname %s ",
- rta_getattr_str(tb[IFLA_PHYS_PORT_NAME]));
+ print_string(PRINT_ANY,
+ "phys_port_name",
+ "portname %s ",
+ rta_getattr_str(tb[IFLA_PHYS_PORT_NAME]));
if (tb[IFLA_PHYS_PORT_ID]) {
SPRINT_BUF(b1);
- fprintf(fp, "portid %s ",
- hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_PORT_ID]),
- RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]),
- b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "phys_port_id",
+ "portid %s ",
+ hexstring_n2a(
+ RTA_DATA(tb[IFLA_PHYS_PORT_ID]),
+ RTA_PAYLOAD(tb[IFLA_PHYS_PORT_ID]),
+ b1, sizeof(b1)));
}
if (tb[IFLA_PHYS_SWITCH_ID]) {
SPRINT_BUF(b1);
- fprintf(fp, "switchid %s ",
- hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_SWITCH_ID]),
- RTA_PAYLOAD(tb[IFLA_PHYS_SWITCH_ID]),
- b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "phys_switch_id",
+ "switchid %s ",
+ hexstring_n2a(RTA_DATA(tb[IFLA_PHYS_SWITCH_ID]),
+ RTA_PAYLOAD(tb[IFLA_PHYS_SWITCH_ID]),
+ b1, sizeof(b1)));
}
}
if ((do_link || show_details) && tb[IFLA_IFALIAS]) {
- fprintf(fp, "%s alias %s", _SL_,
- rta_getattr_str(tb[IFLA_IFALIAS]));
+ print_string(PRINT_FP, NULL, "%s ", _SL_);
+ print_string(PRINT_ANY,
+ "ifalias",
+ "alias %s",
+ rta_getattr_str(tb[IFLA_IFALIAS]));
}
if (do_link && show_stats) {
- fprintf(fp, "%s", _SL_);
+ print_string(PRINT_FP, NULL, "%s", _SL_);
__print_link_stats(fp, tb);
}
@@ -966,11 +1322,16 @@ int print_linkinfo(const struct sockaddr_nl *who,
struct rtattr *i, *vflist = tb[IFLA_VFINFO_LIST];
int rem = RTA_PAYLOAD(vflist);
- for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem))
+ open_json_array(PRINT_JSON, "vfinfo_list");
+ for (i = RTA_DATA(vflist); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
+ open_json_object(NULL);
print_vfinfo(fp, i);
+ close_json_object();
+ }
+ close_json_array(PRINT_JSON, NULL);
}
- fprintf(fp, "\n");
+ print_string(PRINT_FP, NULL, "\n", NULL);
fflush(fp);
return 1;
}
@@ -1095,123 +1456,190 @@ int print_addrinfo(const struct sockaddr_nl *who, struct nlmsghdr *n,
}
if (n->nlmsg_type == RTM_DELADDR)
- fprintf(fp, "Deleted ");
+ print_bool(PRINT_ANY, "deleted", "Deleted ", true);
if (!brief) {
- if (filter.oneline || filter.flushb)
- fprintf(fp, "%u: %s", ifa->ifa_index, ll_index_to_name(ifa->ifa_index));
- if (ifa->ifa_family == AF_INET)
- fprintf(fp, " inet ");
- else if (ifa->ifa_family == AF_INET6)
- fprintf(fp, " inet6 ");
- else if (ifa->ifa_family == AF_DECnet)
- fprintf(fp, " dnet ");
- else if (ifa->ifa_family == AF_IPX)
- fprintf(fp, " ipx ");
+ if (filter.oneline || filter.flushb) {
+ const char *dev = ll_index_to_name(ifa->ifa_index);
+
+ if (is_json_context()) {
+ print_int(PRINT_JSON,
+ "index", NULL, ifa->ifa_index);
+ print_string(PRINT_JSON, "dev", NULL, dev);
+ } else {
+ fprintf(fp, "%u: %s", ifa->ifa_index, dev);
+ }
+ }
+
+ int family = ifa->ifa_family;
+
+ if (family == AF_INET)
+ print_string(PRINT_ANY, "family", " %s ", "inet");
+ else if (family == AF_INET6)
+ print_string(PRINT_ANY, "family", " %s ", "inet6");
+ else if (family == AF_DECnet)
+ print_string(PRINT_ANY, "family", " %s ", "dnet");
+ else if (family == AF_IPX)
+ print_string(PRINT_ANY, "family", " %s ", "ipx");
else
- fprintf(fp, " family %d ", ifa->ifa_family);
+ print_int(PRINT_ANY,
+ "family_index",
+ " family %d ", family);
}
if (rta_tb[IFA_LOCAL]) {
- color_fprintf(fp, ifa_family_color(ifa->ifa_family), "%s",
- format_host_rta(ifa->ifa_family,
- rta_tb[IFA_LOCAL]));
+ print_color_string(PRINT_ANY,
+ ifa_family_color(ifa->ifa_family),
+ "local",
+ "%s",
+ format_host_rta(ifa->ifa_family,
+ rta_tb[IFA_LOCAL]));
if (rta_tb[IFA_ADDRESS] &&
memcmp(RTA_DATA(rta_tb[IFA_ADDRESS]),
RTA_DATA(rta_tb[IFA_LOCAL]),
ifa->ifa_family == AF_INET ? 4 : 16)) {
- fprintf(fp, " peer ");
- color_fprintf(fp, ifa_family_color(ifa->ifa_family),
- "%s", format_host_rta(ifa->ifa_family,
- rta_tb[IFA_ADDRESS]));
+ print_string(PRINT_FP, NULL, "%s ", "peer");
+ print_color_string(PRINT_ANY,
+ ifa_family_color(ifa->ifa_family),
+ "address",
+ "%s",
+ format_host_rta(ifa->ifa_family,
+ rta_tb[IFA_ADDRESS]));
}
- fprintf(fp, "/%d ", ifa->ifa_prefixlen);
+ print_int(PRINT_ANY, "prefixlen", "/%d", ifa->ifa_prefixlen);
}
if (brief)
goto brief_exit;
- if (rta_tb[IFA_BROADCAST]) {
- fprintf(fp, "brd ");
- color_fprintf(fp, ifa_family_color(ifa->ifa_family), "%s ",
- format_host_rta(ifa->ifa_family,
- rta_tb[IFA_BROADCAST]));
- }
- if (rta_tb[IFA_ANYCAST]) {
- fprintf(fp, "any ");
- color_fprintf(fp, ifa_family_color(ifa->ifa_family), "%s ",
- format_host_rta(ifa->ifa_family,
- rta_tb[IFA_ANYCAST]));
- }
- fprintf(fp, "scope %s ", rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
+ if (rta_tb[IFA_BROADCAST])
+ print_color_string(PRINT_ANY,
+ ifa_family_color(ifa->ifa_family),
+ "broadcast",
+ "brd %s ",
+ format_host_rta(ifa->ifa_family,
+ rta_tb[IFA_BROADCAST]));
+
+ if (rta_tb[IFA_ANYCAST])
+ print_color_string(PRINT_ANY,
+ ifa_family_color(ifa->ifa_family),
+ "anycast",
+ "any %s ",
+ format_host_rta(ifa->ifa_family,
+ rta_tb[IFA_ANYCAST]));
+
+ print_string(PRINT_ANY,
+ "scope",
+ "scope %s ",
+ rtnl_rtscope_n2a(ifa->ifa_scope, b1, sizeof(b1)));
+
if (ifa_flags & IFA_F_SECONDARY) {
ifa_flags &= ~IFA_F_SECONDARY;
if (ifa->ifa_family == AF_INET6)
- fprintf(fp, "temporary ");
+ print_bool(PRINT_ANY, "temporary", "temporary ", true);
else
- fprintf(fp, "secondary ");
+ print_bool(PRINT_ANY, "secondary", "secondary ", true);
}
+
if (ifa_flags & IFA_F_TENTATIVE) {
ifa_flags &= ~IFA_F_TENTATIVE;
- fprintf(fp, "tentative ");
+ print_bool(PRINT_ANY, "tentative", "tentative ", true);
}
+
if (ifa_flags & IFA_F_DEPRECATED) {
ifa_flags &= ~IFA_F_DEPRECATED;
deprecated = 1;
- fprintf(fp, "deprecated ");
+ print_bool(PRINT_ANY, "deprecated", "deprecated ", true);
}
+
if (ifa_flags & IFA_F_HOMEADDRESS) {
ifa_flags &= ~IFA_F_HOMEADDRESS;
- fprintf(fp, "home ");
+ print_bool(PRINT_ANY, "homeaddress", "home ", true);
}
+
if (ifa_flags & IFA_F_NODAD) {
ifa_flags &= ~IFA_F_NODAD;
- fprintf(fp, "nodad ");
+ print_bool(PRINT_ANY, "nodad", "nodad ", true);
}
+
if (ifa_flags & IFA_F_MANAGETEMPADDR) {
ifa_flags &= ~IFA_F_MANAGETEMPADDR;
- fprintf(fp, "mngtmpaddr ");
+ print_bool(PRINT_ANY, "managetempaddr", "mngtmpaddr ", true);
}
+
if (ifa_flags & IFA_F_NOPREFIXROUTE) {
ifa_flags &= ~IFA_F_NOPREFIXROUTE;
- fprintf(fp, "noprefixroute ");
+ print_bool(PRINT_ANY, "noprefixroute", "noprefixroute ", true);
}
+
if (ifa_flags & IFA_F_MCAUTOJOIN) {
ifa_flags &= ~IFA_F_MCAUTOJOIN;
- fprintf(fp, "autojoin ");
+ print_bool(PRINT_ANY, "mcautojoin", "autojoin ", true);
}
+
if (!(ifa_flags & IFA_F_PERMANENT))
- fprintf(fp, "dynamic ");
+ print_bool(PRINT_ANY, "permanent", "dynamic ", true);
else
ifa_flags &= ~IFA_F_PERMANENT;
+
if (ifa_flags & IFA_F_DADFAILED) {
ifa_flags &= ~IFA_F_DADFAILED;
- fprintf(fp, "dadfailed ");
+ print_bool(PRINT_ANY, "dadfailed", "dadfailed ", true);
}
- if (ifa_flags)
- fprintf(fp, "flags %02x ", ifa_flags);
+
+ if (ifa_flags) {
+ if (is_json_context()) {
+ SPRINT_BUF(flags);
+
+ snprintf(flags, sizeof(flags), "%02x", ifa_flags);
+ print_string(PRINT_JSON, "flags", NULL, flags);
+ } else {
+ fprintf(fp, "flags %02x ", ifa_flags);
+ }
+ }
+
if (rta_tb[IFA_LABEL])
- fprintf(fp, "%s", rta_getattr_str(rta_tb[IFA_LABEL]));
+ print_string(PRINT_ANY,
+ "label",
+ "%s",
+ rta_getattr_str(rta_tb[IFA_LABEL]));
+
if (rta_tb[IFA_CACHEINFO]) {
struct ifa_cacheinfo *ci = RTA_DATA(rta_tb[IFA_CACHEINFO]);
- fprintf(fp, "%s", _SL_);
- fprintf(fp, " valid_lft ");
- if (ci->ifa_valid == INFINITY_LIFE_TIME)
- fprintf(fp, "forever");
- else
- fprintf(fp, "%usec", ci->ifa_valid);
- fprintf(fp, " preferred_lft ");
- if (ci->ifa_prefered == INFINITY_LIFE_TIME)
- fprintf(fp, "forever");
- else {
+ print_string(PRINT_FP, NULL, "%s", _SL_);
+ print_string(PRINT_FP, NULL, " valid_lft ", NULL);
+
+ if (ci->ifa_valid == INFINITY_LIFE_TIME) {
+ print_uint(PRINT_JSON,
+ "valid_life_time",
+ NULL, INFINITY_LIFE_TIME);
+ print_string(PRINT_FP, NULL, "%s", "forever");
+ } else {
+ print_uint(PRINT_ANY,
+ "valid_life_time", "%usec", ci->ifa_valid);
+ }
+
+ print_string(PRINT_FP, NULL, " preferred_lft ", NULL);
+ if (ci->ifa_prefered == INFINITY_LIFE_TIME) {
+ print_uint(PRINT_JSON,
+ "preferred_life_time",
+ NULL, INFINITY_LIFE_TIME);
+ print_string(PRINT_FP, NULL, "%s", "forever");
+ } else {
if (deprecated)
- fprintf(fp, "%dsec", ci->ifa_prefered);
+ print_int(PRINT_ANY,
+ "preferred_life_time",
+ "%dsec",
+ ci->ifa_prefered);
else
- fprintf(fp, "%usec", ci->ifa_prefered);
+ print_uint(PRINT_ANY,
+ "preferred_life_time",
+ "%usec",
+ ci->ifa_prefered);
}
}
- fprintf(fp, "\n");
+ print_string(PRINT_FP, NULL, "%s", "\n");
brief_exit:
fflush(fp);
return 0;
@@ -1220,6 +1648,7 @@ brief_exit:
static int print_selected_addrinfo(struct ifinfomsg *ifi,
struct nlmsg_list *ainfo, FILE *fp)
{
+ open_json_array(PRINT_JSON, "addr_info");
for ( ; ainfo ; ainfo = ainfo->next) {
struct nlmsghdr *n = &ainfo->h;
struct ifaddrmsg *ifa = NLMSG_DATA(n);
@@ -1237,10 +1666,14 @@ static int print_selected_addrinfo(struct ifinfomsg *ifi,
if (filter.up && !(ifi->ifi_flags&IFF_UP))
continue;
+ open_json_object(NULL);
print_addrinfo(NULL, n, fp);
+ close_json_object();
}
+ close_json_array(PRINT_JSON, NULL);
+
if (brief) {
- fprintf(fp, "\n");
+ print_string(PRINT_FP, NULL, "%s", "\n");
fflush(fp);
}
return 0;
@@ -1731,6 +2164,12 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
}
/*
+ * Initialize a json_writer and open an array object
+ * if -json was specified.
+ */
+ new_json_obj(json, stdout);
+
+ /*
* If only filter_dev present and none of the other
* link filters are present, use RTM_GETLINK to get
* the link device
@@ -1738,8 +2177,10 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (filter_dev && filter.group == -1 && do_link == 1) {
if (iplink_get(0, filter_dev, RTEXT_FILTER_VF) < 0) {
perror("Cannot send link get request");
+ delete_json_obj();
exit(1);
}
+ delete_json_obj();
exit(0);
}
@@ -1761,6 +2202,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
int res = 0;
struct ifinfomsg *ifi = NLMSG_DATA(&l->h);
+ open_json_object(NULL);
if (brief) {
if (print_linkinfo_brief(NULL, &l->h,
stdout, NULL) == 0)
@@ -1776,6 +2218,7 @@ static int ipaddr_list_flush_or_save(int argc, char **argv, int action)
if (res > 0 && !do_link && show_stats)
print_link_stats(stdout, &l->h);
}
+ close_json_object();
}
fflush(stdout);
@@ -1783,7 +2226,7 @@ out:
if (ainfo)
free_nlmsg_chain(ainfo);
free_nlmsg_chain(&linfo);
-
+ delete_json_obj();
return 0;
}
--
2.13.3
^ permalink raw reply related
* [PATCH 07/27] ip: iplink_bond.c: add json output support
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema and live example:
bond: IFLA_INFO_DATA
{
"mode": {
"type": "string",
"attr": "IFLA_BOND_MODE"
},
"active_slave": {
"type": "string",
"attr": "IFLA_BOND_ACTIVE_SLAVE",
"mutually_exclusive": {
"active_slave_index": {
"type": "int",
"comment": "if active slave doesn't have a valid ifname"
}
}
},
"miimon": {
"type": "uint",
"attr": "IFLA_BOND_MIIMON"
},
"updelay": {
"type": "uint",
"attr": "IFLA_BOND_UPDELAY"
},
"downdelay": {
"type": "uint",
"attr": "IFLA_BOND_DOWNDELAY"
},
"use_carrier": {
"type": "uint",
"attr": "IFLA_BOND_USE_CARRIER"
},
"arp_interval": {
"type": "uint",
"attr": "IFLA_BOND_ARP_INTERVAL"
},
"arp_ip_target": {
"type": "array",
"attr": "IFLA_BOND_ARP_IP_TARGET",
"array": [
{
"type": "string"
}
]
},
"arp_validate": {
"type": "string",
"attr": "IFLA_BOND_ARP_VALIDATE"
},
"arp_all_targets": {
"type": "string",
"attr": "IFLA_BOND_ARP_ALL_TARGETS"
},
"primary": {
"type": "string",
"attr": "IFLA_BOND_PRIMARY",
"mutually_exclusive": {
"primary_index": {
"type": "int",
"comment": "if primary doesn't have a valid ifname"
}
}
},
"primary_reselect": {
"type": "string",
"attr": "IFLA_BOND_PRIMARY_RESELECT"
},
"fail_over_mac": {
"type": "string",
"attr": "IFLA_BOND_FAIL_OVER_MAC"
},
"xmit_hash_policy": {
"type": "string",
"attr": "IFLA_BOND_XMIT_HASH_POLICY"
},
"resend_igmp": {
"type": "uint",
"attr": "IFLA_BOND_RESEND_IGMP"
},
"num_peer_notif": {
"type": "uint",
"attr": "IFLA_BOND_NUM_PEER_NOTIF"
},
"all_slaves_active": {
"type": "uint",
"attr": "IFLA_BOND_ALL_SLAVES_ACTIVE"
},
"min_links": {
"type": "uint",
"attr": "IFLA_BOND_MIN_LINKS"
},
"lp_interval": {
"type": "uint",
"attr": "IFLA_BOND_LP_INTERVAL"
},
"packets_per_slave": {
"type": "uint",
"attr": "IFLA_BOND_PACKETS_PER_SLAVE"
},
"ad_lacp_rate": {
"type": "string",
"attr": "IFLA_BOND_AD_LACP_RATE"
},
"ad_select": {
"type": "string",
"attr": "IFLA_BOND_AD_SELECT"
},
"ad_info": {
"type": "dict",
"attr": "IFLA_BOND_AD_INFO",
"dict": {
"aggregator": {
"type": "int",
"attr": "IFLA_BOND_AD_INFO_AGGREGATOR"
},
"num_ports": {
"type": "int",
"attr": "IFLA_BOND_AD_INFO_NUM_PORTS"
},
"actor_key": {
"type": "int",
"attr": "IFLA_BOND_AD_INFO_ACTOR_KEY"
},
"partner_key": {
"type": "int",
"attr": "IFLA_BOND_AD_INFO_PARTNER_KEY"
},
"partner_mac": {
"type": "string",
"attr": "IFLA_BOND_AD_INFO_PARTNER_MAC"
}
}
},
"ad_actor_sys_prio": {
"type": "uint",
"attr": "IFLA_BOND_AD_ACTOR_SYS_PRIO"
},
"ad_user_port_key": {
"type": "uint",
"attr": "IFLA_BOND_AD_USER_PORT_KEY"
},
"ad_actor_system": {
"type": "string",
"attr": "IFLA_BOND_AD_ACTOR_SYSTEM"
},
"tlb_dynamic_lb": {
"type": "uint",
"attr": "IFLA_BOND_TLB_DYNAMIC_LB"
}
}
$ ip link add dev bond42 type bond
$ ip link set dev swp5 master bond42
$ ip link set dev bond42 up
$ ip link set dev swp5 up
$ ip -details -json link show
[{
"ifindex": 7,
"ifname": "swp5",
"flags": ["BROADCAST","MULTICAST","SLAVE","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "pfifo_fast",
"master": "bond42",
"operstate": "UP",
"linkmode": "DEFAULT",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "08:00:27:5c:03:c6",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_slave_kind": "bond",
"info_slave_data": {
"state": "BACKUP",
"mii_status": "UP",
"link_failure_count": 0,
"perm_hwaddr": "08:00:27:5c:03:c6",
"queue_id": 0,
"ad_aggregator_id": 1,
"ad_actor_oper_port_state": 79,
"ad_partner_oper_port_state": 1
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 14,
"ifname": "bond42",
"flags": ["NO-CARRIER","BROADCAST","MULTICAST","MASTER","UP"],
"mtu": 1500,
"qdisc": "noqueue",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "08:00:27:5c:03:c6",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "bond",
"info_data": {
"mode": "802.3ad",
"miimon": 100,
"updelay": 0,
"downdelay": 0,
"use_carrier": 1,
"arp_interval": 0,
"arp_validate": null,
"arp_all_targets": "any",
"primary_reselect": "always",
"fail_over_mac": "none",
"xmit_hash_policy": "layer3+4",
"resend_igmp": 1,
"num_peer_notif": 1,
"all_slaves_active": 0,
"min_links": 1,
"lp_interval": 1,
"packets_per_slave": 1,
"ad_lacp_rate": "fast",
"ad_select": "stable",
"ad_info": {
"aggregator": 1,
"num_ports": 1,
"actor_key": 0,
"partner_key": 1,
"partner_mac": "00:00:00:00:00:00"
},
"ad_actor_sys_prio": 65535,
"ad_user_port_key": 0,
"ad_actor_system": "00:00:00:00:00:00"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 16,
"num_rx_queues": 16,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_bond.c | 231 ++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 160 insertions(+), 71 deletions(-)
diff --git a/ip/iplink_bond.c b/ip/iplink_bond.c
index 772b05fd..2b5cf4f6 100644
--- a/ip/iplink_bond.c
+++ b/ip/iplink_bond.c
@@ -376,8 +376,8 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_BOND_MODE]) {
const char *mode = get_name(mode_tbl,
- rta_getattr_u8(tb[IFLA_BOND_MODE]));
- fprintf(f, "mode %s ", mode);
+ rta_getattr_u8(tb[IFLA_BOND_MODE]));
+ print_string(PRINT_ANY, "mode", "mode %s ", mode);
}
if (tb[IFLA_BOND_ACTIVE_SLAVE] &&
@@ -386,61 +386,97 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
const char *n = if_indextoname(ifindex, buf);
if (n)
- fprintf(f, "active_slave %s ", n);
+ print_string(PRINT_ANY,
+ "active_slave",
+ "active_slave %s ",
+ n);
else
- fprintf(f, "active_slave %u ", ifindex);
+ print_uint(PRINT_ANY,
+ "active_slave_index",
+ "active_slave %u ",
+ ifindex);
}
if (tb[IFLA_BOND_MIIMON])
- fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
+ print_uint(PRINT_ANY,
+ "miimon",
+ "miimon %u ",
+ rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
if (tb[IFLA_BOND_UPDELAY])
- fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
+ print_uint(PRINT_ANY,
+ "updelay",
+ "updelay %u ",
+ rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
if (tb[IFLA_BOND_DOWNDELAY])
- fprintf(f, "downdelay %u ",
- rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
+ print_uint(PRINT_ANY,
+ "downdelay",
+ "downdelay %u ",
+ rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
if (tb[IFLA_BOND_USE_CARRIER])
- fprintf(f, "use_carrier %u ",
- rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
+ print_uint(PRINT_ANY,
+ "use_carrier",
+ "use_carrier %u ",
+ rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
if (tb[IFLA_BOND_ARP_INTERVAL])
- fprintf(f, "arp_interval %u ",
- rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
+ print_uint(PRINT_ANY,
+ "arp_interval",
+ "arp_interval %u ",
+ rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
if (tb[IFLA_BOND_ARP_IP_TARGET]) {
struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
int i;
parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
- tb[IFLA_BOND_ARP_IP_TARGET]);
+ tb[IFLA_BOND_ARP_IP_TARGET]);
- if (iptb[0])
- fprintf(f, "arp_ip_target ");
+ if (iptb[0]) {
+ open_json_array(PRINT_JSON, "arp_ip_target");
+ print_string(PRINT_FP, NULL, "arp_ip_target ", NULL);
+ }
for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
if (iptb[i])
- fprintf(f, "%s",
- rt_addr_n2a_rta(AF_INET, iptb[i]));
- if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1])
+ print_string(PRINT_ANY,
+ NULL,
+ "%s",
+ rt_addr_n2a_rta(AF_INET, iptb[i]));
+ if (!is_json_context()
+ && i < BOND_MAX_ARP_TARGETS-1
+ && iptb[i+1])
fprintf(f, ",");
}
- if (iptb[0])
- fprintf(f, " ");
+ if (iptb[0]) {
+ print_string(PRINT_FP, NULL, " ", NULL);
+ close_json_array(PRINT_JSON, NULL);
+ }
}
if (tb[IFLA_BOND_ARP_VALIDATE]) {
- const char *arp_validate = get_name(arp_validate_tbl,
- rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]));
- fprintf(f, "arp_validate %s ", arp_validate);
+ __u32 arp_v = rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]);
+ const char *arp_validate = get_name(arp_validate_tbl, arp_v);
+
+ if (!arp_v && is_json_context())
+ print_null(PRINT_JSON, "arp_validate", NULL, NULL);
+ else
+ print_string(PRINT_ANY,
+ "arp_validate",
+ "arp_validate %s ",
+ arp_validate);
}
if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
const char *arp_all_targets = get_name(arp_all_targets_tbl,
- rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
- fprintf(f, "arp_all_targets %s ", arp_all_targets);
+ rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
+ print_string(PRINT_ANY,
+ "arp_all_targets",
+ "arp_all_targets %s ",
+ arp_all_targets);
}
if (tb[IFLA_BOND_PRIMARY] &&
@@ -449,123 +485,176 @@ static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
const char *n = if_indextoname(ifindex, buf);
if (n)
- fprintf(f, "primary %s ", n);
+ print_string(PRINT_ANY, "primary", "primary %s ", n);
else
- fprintf(f, "primary %u ", ifindex);
+ print_uint(PRINT_ANY,
+ "primary_index",
+ "primary %u ",
+ ifindex);
}
if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
const char *primary_reselect = get_name(primary_reselect_tbl,
- rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
- fprintf(f, "primary_reselect %s ", primary_reselect);
+ rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
+ print_string(PRINT_ANY,
+ "primary_reselect",
+ "primary_reselect %s ",
+ primary_reselect);
}
if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
const char *fail_over_mac = get_name(fail_over_mac_tbl,
- rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
- fprintf(f, "fail_over_mac %s ", fail_over_mac);
+ rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
+ print_string(PRINT_ANY,
+ "fail_over_mac",
+ "fail_over_mac %s ",
+ fail_over_mac);
}
if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
- rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
- fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy);
+ rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
+ print_string(PRINT_ANY,
+ "xmit_hash_policy",
+ "xmit_hash_policy %s ",
+ xmit_hash_policy);
}
if (tb[IFLA_BOND_RESEND_IGMP])
- fprintf(f, "resend_igmp %u ",
- rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
+ print_uint(PRINT_ANY,
+ "resend_igmp",
+ "resend_igmp %u ",
+ rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
if (tb[IFLA_BOND_NUM_PEER_NOTIF])
- fprintf(f, "num_grat_arp %u ",
- rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
+ print_uint(PRINT_ANY,
+ "num_peer_notif",
+ "num_grat_arp %u ",
+ rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
- fprintf(f, "all_slaves_active %u ",
- rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
+ print_uint(PRINT_ANY,
+ "all_slaves_active",
+ "all_slaves_active %u ",
+ rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
if (tb[IFLA_BOND_MIN_LINKS])
- fprintf(f, "min_links %u ",
- rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
+ print_uint(PRINT_ANY,
+ "min_links",
+ "min_links %u ",
+ rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
if (tb[IFLA_BOND_LP_INTERVAL])
- fprintf(f, "lp_interval %u ",
- rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
+ print_uint(PRINT_ANY,
+ "lp_interval",
+ "lp_interval %u ",
+ rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
- fprintf(f, "packets_per_slave %u ",
- rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
+ print_uint(PRINT_ANY,
+ "packets_per_slave",
+ "packets_per_slave %u ",
+ rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
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]));
- fprintf(f, "lacp_rate %s ", lacp_rate);
+ rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
+ print_string(PRINT_ANY,
+ "ad_lacp_rate",
+ "lacp_rate %s ",
+ lacp_rate);
}
if (tb[IFLA_BOND_AD_SELECT]) {
const char *ad_select = get_name(ad_select_tbl,
- rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
- fprintf(f, "ad_select %s ", ad_select);
+ rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
+ print_string(PRINT_ANY,
+ "ad_select",
+ "ad_select %s ",
+ ad_select);
}
if (tb[IFLA_BOND_AD_INFO]) {
struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
- tb[IFLA_BOND_AD_INFO]);
+ tb[IFLA_BOND_AD_INFO]);
+
+ open_json_object("ad_info");
if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
- fprintf(f, "ad_aggregator %d ",
- rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
+ print_int(PRINT_ANY,
+ "aggregator",
+ "ad_aggregator %d ",
+ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
- fprintf(f, "ad_num_ports %d ",
- rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
+ print_int(PRINT_ANY,
+ "num_ports",
+ "ad_num_ports %d ",
+ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
- fprintf(f, "ad_actor_key %d ",
- rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
+ print_int(PRINT_ANY,
+ "actor_key",
+ "ad_actor_key %d ",
+ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
- fprintf(f, "ad_partner_key %d ",
- rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
+ print_int(PRINT_ANY,
+ "partner_key",
+ "ad_partner_key %d ",
+ rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
unsigned char *p =
RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
SPRINT_BUF(b);
- fprintf(f, "ad_partner_mac %s ",
- ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
+ print_string(PRINT_ANY,
+ "partner_mac",
+ "ad_partner_mac %s ",
+ ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
}
+
+ close_json_object();
}
if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
- fprintf(f, "ad_actor_sys_prio %u ",
- rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
+ print_uint(PRINT_ANY,
+ "ad_actor_sys_prio",
+ "ad_actor_sys_prio %u ",
+ rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
}
if (tb[IFLA_BOND_AD_USER_PORT_KEY]) {
- fprintf(f, "ad_user_port_key %u ",
- rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
+ print_uint(PRINT_ANY,
+ "ad_user_port_key",
+ "ad_user_port_key %u ",
+ rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
}
if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) {
/* We assume the l2 address is an Ethernet MAC address */
SPRINT_BUF(b1);
- fprintf(f, "ad_actor_system %s ",
- ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
- RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
- 1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
+
+ print_string(PRINT_ANY,
+ "ad_actor_system",
+ "ad_actor_system %s ",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
+ RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
+ 1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
}
if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
- fprintf(f, "tlb_dynamic_lb %u ",
- rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
+ print_uint(PRINT_ANY,
+ "tlb_dynamic_lb",
+ "tlb_dynamic_lb %u ",
+ rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
}
}
static void bond_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_explain(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 08/27] ip: iplink_bond_slave.c: add json output support (info_slave_data)
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema and live example:
bond_slave: IFLA_INFO_SLAVE_DATA
{
"state": {
"type": "string",
"attr": "IFLA_BOND_SLAVE_STATE",
"mutually_exclusive": {
"state_index": {
"type": "int",
"comment": "if (state >= ARRAY_SIZE(slave_states))"
}
}
},
"mii_status": {
"type": "string",
"attr": "IFLA_BOND_SLAVE_MII_STATUS",
"mutually_exclusive": {
"mii_status_index": {
"type": "int",
"comment": "if (status >= ARRAY_SIZE(slave_mii_status))"
}
}
},
"link_failure_count": {
"type": "int",
"attr": "IFLA_BOND_SLAVE_LINK_FAILURE_COUNT"
},
"perm_hwaddr": {
"type": "string",
"attr": "IFLA_BOND_SLAVE_PERM_HWADDR"
},
"queue_id": {
"type": "int",
"attr": "IFLA_BOND_SLAVE_QUEUE_ID"
},
"ad_aggregator_id": {
"type": "int",
"attr": "IFLA_BOND_SLAVE_AD_AGGREGATOR_ID"
},
"ad_actor_oper_port_state": {
"type": "int",
"attr": "IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE"
},
"ad_partner_oper_port_state": {
"type": "int",
"attr": "IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE"
}
}
$ ip link add dev bond42 type bond
$ ip link set dev swp5 master bond42
$ ip link set dev bond42 up
$ ip link set dev swp5 up
$ ip -details -json link show
[{
"ifindex": 7,
"ifname": "swp5",
"flags": ["BROADCAST","MULTICAST","SLAVE","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "pfifo_fast",
"master": "bond42",
"operstate": "UP",
"linkmode": "DEFAULT",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "08:00:27:5c:03:c6",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_slave_kind": "bond",
"info_slave_data": {
"state": "BACKUP",
"mii_status": "UP",
"link_failure_count": 0,
"perm_hwaddr": "08:00:27:5c:03:c6",
"queue_id": 0,
"ad_aggregator_id": 1,
"ad_actor_oper_port_state": 79,
"ad_partner_oper_port_state": 1
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 14,
"ifname": "bond42",
"flags": ["NO-CARRIER","BROADCAST","MULTICAST","MASTER","UP"],
"mtu": 1500,
"qdisc": "noqueue",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "08:00:27:5c:03:c6",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "bond",
"info_data": {
"mode": "802.3ad",
"miimon": 100,
"updelay": 0,
"downdelay": 0,
"use_carrier": 1,
"arp_interval": 0,
"arp_validate": null,
"arp_all_targets": "any",
"primary_reselect": "always",
"fail_over_mac": "none",
"xmit_hash_policy": "layer3+4",
"resend_igmp": 1,
"num_peer_notif": 1,
"all_slaves_active": 0,
"min_links": 1,
"lp_interval": 1,
"packets_per_slave": 1,
"ad_lacp_rate": "fast",
"ad_select": "stable",
"ad_info": {
"aggregator": 1,
"num_ports": 1,
"actor_key": 0,
"partner_key": 1,
"partner_mac": "00:00:00:00:00:00"
},
"ad_actor_sys_prio": 65535,
"ad_user_port_key": 0,
"ad_actor_system": "00:00:00:00:00:00"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 16,
"num_rx_queues": 16,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_bond_slave.c | 57 ++++++++++++++++++++++++++++++++++----------------
1 file changed, 39 insertions(+), 18 deletions(-)
diff --git a/ip/iplink_bond_slave.c b/ip/iplink_bond_slave.c
index 877e2d9e..67219c67 100644
--- a/ip/iplink_bond_slave.c
+++ b/ip/iplink_bond_slave.c
@@ -37,9 +37,12 @@ static void print_slave_state(FILE *f, struct rtattr *tb)
unsigned int state = rta_getattr_u8(tb);
if (state >= ARRAY_SIZE(slave_states))
- fprintf(f, "state %d ", state);
+ print_int(PRINT_ANY, "state_index", "state %d ", state);
else
- fprintf(f, "state %s ", slave_states[state]);
+ print_string(PRINT_ANY,
+ "state",
+ "state %s ",
+ slave_states[state]);
}
static const char *slave_mii_status[] = {
@@ -54,9 +57,15 @@ static void print_slave_mii_status(FILE *f, struct rtattr *tb)
unsigned int status = rta_getattr_u8(tb);
if (status >= ARRAY_SIZE(slave_mii_status))
- fprintf(f, "mii_status %d ", status);
+ print_int(PRINT_ANY,
+ "mii_status_index",
+ "mii_status %d ",
+ status);
else
- fprintf(f, "mii_status %s ", slave_mii_status[status]);
+ print_string(PRINT_ANY,
+ "mii_status",
+ "mii_status %s ",
+ slave_mii_status[status]);
}
static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
@@ -72,30 +81,42 @@ static void bond_slave_print_opt(struct link_util *lu, FILE *f, struct rtattr *t
print_slave_mii_status(f, tb[IFLA_BOND_SLAVE_MII_STATUS]);
if (tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT])
- fprintf(f, "link_failure_count %d ",
- rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
+ print_int(PRINT_ANY,
+ "link_failure_count",
+ "link_failure_count %d ",
+ rta_getattr_u32(tb[IFLA_BOND_SLAVE_LINK_FAILURE_COUNT]));
if (tb[IFLA_BOND_SLAVE_PERM_HWADDR])
- fprintf(f, "perm_hwaddr %s ",
- ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
- RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
- 0, b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "perm_hwaddr",
+ "perm_hwaddr %s ",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
+ RTA_PAYLOAD(tb[IFLA_BOND_SLAVE_PERM_HWADDR]),
+ 0, b1, sizeof(b1)));
if (tb[IFLA_BOND_SLAVE_QUEUE_ID])
- fprintf(f, "queue_id %d ",
- rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
+ print_int(PRINT_ANY,
+ "queue_id",
+ "queue_id %d ",
+ rta_getattr_u16(tb[IFLA_BOND_SLAVE_QUEUE_ID]));
if (tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID])
- fprintf(f, "ad_aggregator_id %d ",
- rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
+ print_int(PRINT_ANY,
+ "ad_aggregator_id",
+ "ad_aggregator_id %d ",
+ rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_AGGREGATOR_ID]));
if (tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE])
- fprintf(f, "ad_actor_oper_port_state %d ",
- rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
+ print_int(PRINT_ANY,
+ "ad_actor_oper_port_state",
+ "ad_actor_oper_port_state %d ",
+ rta_getattr_u8(tb[IFLA_BOND_SLAVE_AD_ACTOR_OPER_PORT_STATE]));
if (tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE])
- fprintf(f, "ad_partner_oper_port_state %d ",
- rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
+ print_int(PRINT_ANY,
+ "ad_partner_oper_port_state",
+ "ad_partner_oper_port_state %d ",
+ rta_getattr_u16(tb[IFLA_BOND_SLAVE_AD_PARTNER_OPER_PORT_STATE]));
}
static int bond_slave_parse_opt(struct link_util *lu, int argc, char **argv,
--
2.13.3
^ permalink raw reply related
* [PATCH 09/27] ip: iplink_hsr.c: add json output support
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
hsr: IFLA_INFO_DATA
{
"slave1": {
"type": "string",
"attr": "IFLA_HSR_SLAVE1"
},
"slave2": {
"type": "string",
"attr": "IFLA_HSR_SLAVE2"
},
"seq_nr": {
"type": "int",
"attr": "IFLA_HSR_SEQ_NR"
},
"supervision_addr": {
"type": "int",
"attr": "IFLA_HSR_SUPERVISION_ADDR"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_hsr.c | 36 +++++++++++++++++++++---------------
1 file changed, 21 insertions(+), 15 deletions(-)
diff --git a/ip/iplink_hsr.c b/ip/iplink_hsr.c
index 696b2c91..c673ccf7 100644
--- a/ip/iplink_hsr.c
+++ b/ip/iplink_hsr.c
@@ -110,30 +110,36 @@ static void hsr_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]) < ETH_ALEN)
return;
- fprintf(f, "slave1 ");
if (tb[IFLA_HSR_SLAVE1])
- fprintf(f, "%s ",
- ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
+ print_string(PRINT_ANY,
+ "slave1",
+ "slave1 %s ",
+ ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE1])));
else
- fprintf(f, "<none> ");
+ print_null(PRINT_ANY, "slave1", "slave1 %s ", "<none>");
- fprintf(f, "slave2 ");
if (tb[IFLA_HSR_SLAVE2])
- fprintf(f, "%s ",
- ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
+ print_string(PRINT_ANY,
+ "slave2",
+ "slave2 %s ",
+ ll_index_to_name(rta_getattr_u32(tb[IFLA_HSR_SLAVE2])));
else
- fprintf(f, "<none> ");
+ print_null(PRINT_ANY, "slave2", "slave2 %s ", "<none>");
if (tb[IFLA_HSR_SEQ_NR])
- fprintf(f, "sequence %d ",
- rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
+ print_int(PRINT_ANY,
+ "seq_nr",
+ "sequence %d ",
+ rta_getattr_u16(tb[IFLA_HSR_SEQ_NR]));
if (tb[IFLA_HSR_SUPERVISION_ADDR])
- fprintf(f, "supervision %s ",
- ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
- RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
- ARPHRD_VOID,
- b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "supervision_addr",
+ "supervision %s ",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_HSR_SUPERVISION_ADDR]),
+ RTA_PAYLOAD(tb[IFLA_HSR_SUPERVISION_ADDR]),
+ ARPHRD_VOID,
+ b1, sizeof(b1)));
}
static void hsr_print_help(struct link_util *lu, int argc, char **argv,
--
2.13.3
^ permalink raw reply related
* [PATCH 10/27] ip: iplink_bridge.c: add json output support
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema and live example:
bridge: IFLA_INFO_DATA
{
"forward_delay": {
"type": "uint",
"attr": "IFLA_BR_FORWARD_DELAY"
},
"hello_time": {
"type": "uint",
"attr": "IFLA_BR_HELLO_TIME"
},
"max_age": {
"type": "uint",
"attr": "IFLA_BR_MAX_AGE"
},
"ageing_time": {
"type": "uint",
"attr": "IFLA_BR_AGEING_TIME"
},
"stp_state": {
"type": "uint",
"attr": "IFLA_BR_STP_STATE"
},
"priority": {
"type": "uint",
"attr": "IFLA_BR_PRIORITY"
},
"vlan_filtering": {
"type": "uint",
"attr": "IFLA_BR_VLAN_FILTERING"
},
"vlan_protocol": {
"type": "string",
"attr": "IFLA_BR_VLAN_PROTOCOL"
},
"bridge_id": {
"type": "string",
"attr": "IFLA_BR_BRIDGE_ID"
},
"root_id": {
"type": "string",
"attr": "IFLA_BR_ROOT_ID"
},
"root_port": {
"type": "uint",
"attr": "IFLA_BR_ROOT_PORT"
},
"root_path_cost": {
"type": "uint",
"attr": "IFLA_BR_ROOT_PATH_COST"
},
"topology_change": {
"type": "uint",
"attr": "IFLA_BR_TOPOLOGY_CHANGE"
},
"topology_change_detected": {
"type": "uint",
"attr": "IFLA_BR_TOPOLOGY_CHANGE_DETECTED"
},
"hello_timer": {
"type": "float",
"attr": "IFLA_BR_HELLO_TIMER"
},
"tcn_timer": {
"type": "float",
"attr": "IFLA_BR_TCN_TIMER"
},
"topology_change_timer": {
"type": "float",
"attr": "IFLA_BR_TOPOLOGY_CHANGE_TIMER"
},
"gc_timer": {
"type": "float",
"attr": "IFLA_BR_GC_TIMER"
},
"vlan_default_pvid": {
"type": "uint",
"attr": "IFLA_BR_VLAN_DEFAULT_PVID"
},
"vlan_stats_enabled": {
"type": "uint",
"attr": "IFLA_BR_VLAN_STATS_ENABLED"
},
"group_fwd_mask": {
"type": "string",
"attr": "IFLA_BR_GROUP_FWD_MASK"
},
"group_addr": {
"type": "string",
"attr": "IFLA_BR_GROUP_ADDR"
},
"mcast_snooping": {
"type": "uint",
"attr": "IFLA_BR_MCAST_SNOOPING"
},
"mcast_router": {
"type": "uint",
"attr": "IFLA_BR_MCAST_ROUTER"
},
"mcast_query_use_ifaddr": {
"type": "uint",
"attr": "IFLA_BR_MCAST_QUERY_USE_IFADDR"
},
"mcast_querier": {
"type": "uint",
"attr": "IFLA_BR_MCAST_QUERIER"
},
"mcast_hash_elasticity": {
"type": "uint",
"attr": "IFLA_BR_MCAST_HASH_ELASTICITY"
},
"mcast_hash_max": {
"type": "uint",
"attr": "IFLA_BR_MCAST_HASH_MAX"
},
"mcast_last_member_cnt": {
"type": "uint",
"attr": "IFLA_BR_MCAST_LAST_MEMBER_CNT"
},
"mcast_startup_query_cnt": {
"type": "uint",
"attr": "IFLA_BR_MCAST_STARTUP_QUERY_CNT"
},
"mcast_last_member_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_LAST_MEMBER_INTVL"
},
"mcast_membership_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_MEMBERSHIP_INTVL"
},
"mcast_querier_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_QUERIER_INTVL"
},
"mcast_query_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_QUERY_INTVL"
},
"mcast_query_response_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_QUERY_RESPONSE_INTVL"
},
"mcast_startup_query_intvl": {
"type": "lluint",
"attr": "IFLA_BR_MCAST_STARTUP_QUERY_INTVL"
},
"mcast_stats_enabled": {
"type": "uint",
"attr": "IFLA_BR_MCAST_STATS_ENABLED"
},
"mcast_igmp_version": {
"type": "uint",
"attr": "IFLA_BR_MCAST_IGMP_VERSION"
},
"mcast_mld_version": {
"type": "uint",
"attr": "IFLA_BR_MCAST_MLD_VERSION"
},
"nf_call_iptables": {
"type": "uint",
"attr": "IFLA_BR_NF_CALL_IPTABLES"
},
"nf_call_ip6tables": {
"type": "uint",
"attr": "IFLA_BR_NF_CALL_IP6TABLES"
},
"nf_call_arptables": {
"type": "uint",
"attr": "IFLA_BR_NF_CALL_ARPTABLES"
}
}
$ ip link add dev br42 type bridge
$ ip link add dev bond42 type bond
$ ip link set dev bond42 master br42
$ ip link set dev bond42 up
$ ip link set dev br42 up
$ ip -details link show
15: br42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state
UP mode DEFAULT group default
link/ether 22:8f:91:bb:9f:09 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time
30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q
bridge_id 8000.22:8f:91:bb:9f:9 designated_root 8000.22:8f:91:bb:9f:9
root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0
hello_timer 0.00 tcn_timer 0.00 topology_change_timer 0.00
gc_timer 199.11 vlan_default_pvid 1 vlan_stats_enabled 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 4096
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 3125
mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_version 1
nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 addrgenmode
eui64
16: bond42: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc
noqueue master br42 state UNKNOWN mode DEFAULT group default
link/ether 22:8f:91:bb:9f:09 brd ff:ff:ff:ff:ff:ff promiscuity 1
bond mode 802.3ad miimon 100 updelay 0 downdelay 0 use_carrier 1
arp_interval 0 arp_validate none arp_all_targets any primary_reselect
always fail_over_mac none xmit_hash_policy layer3+4 resend_igmp 1
num_grat_arp 1 all_slaves_active 0 min_links 1 lp_interval 1
packets_per_slave 1 lacp_rate fast ad_select stable ad_actor_sys_prio
65535 ad_user_port_key 0 ad_actor_system 00:00:00:00:00:00
bridge_slave state forwarding priority 8 cost 100 hairpin off guard
off root_block off fastleave off learning on flood on port_id 0x8001
port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge
8000.22:8f:91:bb:9f:9 designated_root 8000.22:8f:91:bb:9f:9 hold_timer
0.00 message_age_timer 0.00 forward_delay_timer 0.00
topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off
mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off
addrgenmode eui64
$ ip -details -json link show
[{
"ifindex": 15,
"ifname": "br42",
"flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "noqueue",
"operstate": "UP",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "22:8f:91:bb:9f:09",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "bridge",
"info_data": {
"forward_delay": 1500,
"hello_time": 200,
"max_age": 2000,
"ageing_time": 30000,
"stp_state": 0,
"priority": 32768,
"vlan_filtering": 0,
"vlan_protocol": "802.1Q",
"bridge_id": "8000.22:8f:91:bb:9f:9",
"root_id": "8000.22:8f:91:bb:9f:9",
"root_port": 0,
"root_path_cost": 0,
"topology_change": 0,
"topology_change_detected": 0,
"hello_timer": 0.00,
"tcn_timer": 0.00,
"topology_change_timer": 0.00,
"gc_timer": 298.27,
"vlan_default_pvid": 1,
"vlan_stats_enabled": 0,
"group_fwd_mask": "0",
"group_addr": "01:80:c2:00:00:00",
"mcast_snooping": 1,
"mcast_router": 1,
"mcast_query_use_ifaddr": 0,
"mcast_querier": 0,
"mcast_hash_elasticity": 4096,
"mcast_hash_max": 4096,
"mcast_last_member_cnt": 2,
"mcast_startup_query_cnt": 2,
"mcast_last_member_intvl": 100,
"mcast_membership_intvl": 26000,
"mcast_querier_intvl": 25500,
"mcast_query_intvl": 12500,
"mcast_query_response_intvl": 1000,
"mcast_startup_query_intvl": 3125,
"mcast_stats_enabled": 0,
"mcast_igmp_version": 2,
"mcast_mld_version": 1,
"nf_call_iptables": 0,
"nf_call_ip6tables": 0,
"nf_call_arptables": 0
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 16,
"ifname": "bond42",
"flags": ["BROADCAST","MULTICAST","MASTER","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "noqueue",
"master": "br42",
"operstate": "UNKNOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "22:8f:91:bb:9f:09",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 1,
"linkinfo": {
"info_kind": "bond",
"info_data": {
"mode": "802.3ad",
"miimon": 100,
"updelay": 0,
"downdelay": 0,
"use_carrier": 1,
"arp_interval": 0,
"arp_validate": null,
"arp_all_targets": "any",
"primary_reselect": "always",
"fail_over_mac": "none",
"xmit_hash_policy": "layer3+4",
"resend_igmp": 1,
"num_peer_notif": 1,
"all_slaves_active": 0,
"min_links": 1,
"lp_interval": 1,
"packets_per_slave": 1,
"ad_lacp_rate": "fast",
"ad_select": "stable",
"ad_actor_sys_prio": 65535,
"ad_user_port_key": 0,
"ad_actor_system": "00:00:00:00:00:00"
},
"info_slave_kind": "bridge",
"info_slave_data": {
"state": "forwarding",
"priority": 8,
"cost": 100,
"hairpin": false,
"guard": false,
"root_block": false,
"fastleave": false,
"learning": true,
"flood": true,
"id": "0x8001",
"no": "0x1",
"designated_port": 32769,
"designated_cost": 0,
"bridge_id": "8000.22:8f:91:bb:9f:9",
"root_id": "8000.22:8f:91:bb:9f:9",
"hold_timer": 0.00,
"message_age_timer": 0.00,
"forward_delay_timer": 11.97,
"topology_change_ack": 0,
"config_pending": 0,
"proxy_arp": false,
"proxy_arp_wifi": false,
"multicast_router": 1,
"mcast_flood": true
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 16,
"num_rx_queues": 16,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_bridge.c | 291 +++++++++++++++++++++++++++++++++--------------------
1 file changed, 184 insertions(+), 107 deletions(-)
diff --git a/ip/iplink_bridge.c b/ip/iplink_bridge.c
index cccdec1c..f355a73d 100644
--- a/ip/iplink_bridge.c
+++ b/ip/iplink_bridge.c
@@ -373,45 +373,81 @@ static int bridge_parse_opt(struct link_util *lu, int argc, char **argv,
return 0;
}
+static void _bridge_print_timer(FILE *f,
+ const char *attr,
+ struct rtattr *timer)
+{
+ struct timeval tv;
+
+ __jiffies_to_tv(&tv, rta_getattr_u64(timer));
+ if (is_json_context()) {
+ json_writer_t *jw = get_json_writer();
+
+ jsonw_name(jw, attr);
+ jsonw_printf(jw, "%i.%.2i",
+ (int)tv.tv_sec,
+ (int)tv.tv_usec / 10000);
+ } else {
+ fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec,
+ (int)tv.tv_usec / 10000);
+ }
+}
+
static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
return;
if (tb[IFLA_BR_FORWARD_DELAY])
- fprintf(f, "forward_delay %u ",
- rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
+ print_uint(PRINT_ANY,
+ "forward_delay",
+ "forward_delay %u ",
+ rta_getattr_u32(tb[IFLA_BR_FORWARD_DELAY]));
if (tb[IFLA_BR_HELLO_TIME])
- fprintf(f, "hello_time %u ",
- rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
+ print_uint(PRINT_ANY,
+ "hello_time",
+ "hello_time %u ",
+ rta_getattr_u32(tb[IFLA_BR_HELLO_TIME]));
if (tb[IFLA_BR_MAX_AGE])
- fprintf(f, "max_age %u ",
- rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
+ print_uint(PRINT_ANY,
+ "max_age",
+ "max_age %u ",
+ rta_getattr_u32(tb[IFLA_BR_MAX_AGE]));
if (tb[IFLA_BR_AGEING_TIME])
- fprintf(f, "ageing_time %u ",
- rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
+ print_uint(PRINT_ANY,
+ "ageing_time",
+ "ageing_time %u ",
+ rta_getattr_u32(tb[IFLA_BR_AGEING_TIME]));
if (tb[IFLA_BR_STP_STATE])
- fprintf(f, "stp_state %u ",
- rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
+ print_uint(PRINT_ANY,
+ "stp_state",
+ "stp_state %u ",
+ rta_getattr_u32(tb[IFLA_BR_STP_STATE]));
if (tb[IFLA_BR_PRIORITY])
- fprintf(f, "priority %u ",
- rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
+ print_uint(PRINT_ANY,
+ "priority",
+ "priority %u ",
+ rta_getattr_u16(tb[IFLA_BR_PRIORITY]));
if (tb[IFLA_BR_VLAN_FILTERING])
- fprintf(f, "vlan_filtering %u ",
- rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
+ print_uint(PRINT_ANY,
+ "vlan_filtering",
+ "vlan_filtering %u ",
+ rta_getattr_u8(tb[IFLA_BR_VLAN_FILTERING]));
if (tb[IFLA_BR_VLAN_PROTOCOL]) {
SPRINT_BUF(b1);
- fprintf(f, "vlan_protocol %s ",
- ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
- b1, sizeof(b1)));
+ print_string(PRINT_ANY,
+ "vlan_protocol",
+ "vlan_protocol %s ",
+ ll_proto_n2a(rta_getattr_u16(tb[IFLA_BR_VLAN_PROTOCOL]),
+ b1, sizeof(b1)));
}
if (tb[IFLA_BR_BRIDGE_ID]) {
@@ -419,7 +455,10 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), bridge_id,
sizeof(bridge_id));
- fprintf(f, "bridge_id %s ", bridge_id);
+ print_string(PRINT_ANY,
+ "bridge_id",
+ "bridge_id %s ",
+ bridge_id);
}
if (tb[IFLA_BR_ROOT_ID]) {
@@ -427,159 +466,197 @@ static void bridge_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
br_dump_bridge_id(RTA_DATA(tb[IFLA_BR_BRIDGE_ID]), root_id,
sizeof(root_id));
- fprintf(f, "designated_root %s ", root_id);
+ print_string(PRINT_ANY,
+ "root_id",
+ "designated_root %s ",
+ root_id);
}
if (tb[IFLA_BR_ROOT_PORT])
- fprintf(f, "root_port %u ",
- rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
+ print_uint(PRINT_ANY,
+ "root_port",
+ "root_port %u ",
+ rta_getattr_u16(tb[IFLA_BR_ROOT_PORT]));
if (tb[IFLA_BR_ROOT_PATH_COST])
- fprintf(f, "root_path_cost %u ",
- rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
+ print_uint(PRINT_ANY,
+ "root_path_cost",
+ "root_path_cost %u ",
+ rta_getattr_u32(tb[IFLA_BR_ROOT_PATH_COST]));
if (tb[IFLA_BR_TOPOLOGY_CHANGE])
- fprintf(f, "topology_change %u ",
- rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
+ print_uint(PRINT_ANY,
+ "topology_change",
+ "topology_change %u ",
+ rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE]));
if (tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED])
- fprintf(f, "topology_change_detected %u ",
- rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
-
- if (tb[IFLA_BR_HELLO_TIMER]) {
- struct timeval tv;
-
- __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_HELLO_TIMER]));
- fprintf(f, "hello_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
-
- if (tb[IFLA_BR_TCN_TIMER]) {
- struct timeval tv;
-
- __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_TCN_TIMER]));
- fprintf(f, "tcn_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
+ print_uint(PRINT_ANY,
+ "topology_change_detected",
+ "topology_change_detected %u ",
+ rta_getattr_u8(tb[IFLA_BR_TOPOLOGY_CHANGE_DETECTED]));
- if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]) {
- unsigned long jiffies;
- struct timeval tv;
+ if (tb[IFLA_BR_HELLO_TIMER])
+ _bridge_print_timer(f, "hello_timer", tb[IFLA_BR_HELLO_TIMER]);
- jiffies = rta_getattr_u64(tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
- __jiffies_to_tv(&tv, jiffies);
- fprintf(f, "topology_change_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
+ if (tb[IFLA_BR_TCN_TIMER])
+ _bridge_print_timer(f, "tcn_timer", tb[IFLA_BR_TCN_TIMER]);
- if (tb[IFLA_BR_GC_TIMER]) {
- struct timeval tv;
+ if (tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER])
+ _bridge_print_timer(f, "topology_change_timer",
+ tb[IFLA_BR_TOPOLOGY_CHANGE_TIMER]);
- __jiffies_to_tv(&tv, rta_getattr_u64(tb[IFLA_BR_GC_TIMER]));
- fprintf(f, "gc_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
+ if (tb[IFLA_BR_GC_TIMER])
+ _bridge_print_timer(f, "gc_timer", tb[IFLA_BR_GC_TIMER]);
if (tb[IFLA_BR_VLAN_DEFAULT_PVID])
- fprintf(f, "vlan_default_pvid %u ",
- rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
+ print_uint(PRINT_ANY,
+ "vlan_default_pvid",
+ "vlan_default_pvid %u ",
+ rta_getattr_u16(tb[IFLA_BR_VLAN_DEFAULT_PVID]));
if (tb[IFLA_BR_VLAN_STATS_ENABLED])
- fprintf(f, "vlan_stats_enabled %u ",
- rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
+ print_uint(PRINT_ANY,
+ "vlan_stats_enabled",
+ "vlan_stats_enabled %u ",
+ rta_getattr_u8(tb[IFLA_BR_VLAN_STATS_ENABLED]));
if (tb[IFLA_BR_GROUP_FWD_MASK])
- fprintf(f, "group_fwd_mask %#x ",
- rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
+ print_0xhex(PRINT_ANY,
+ "group_fwd_mask",
+ "group_fwd_mask %#x ",
+ rta_getattr_u16(tb[IFLA_BR_GROUP_FWD_MASK]));
if (tb[IFLA_BR_GROUP_ADDR]) {
SPRINT_BUF(mac);
- fprintf(f, "group_address %s ",
- ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
- RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
- 1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
+ print_string(PRINT_ANY,
+ "group_addr",
+ "group_address %s ",
+ ll_addr_n2a(RTA_DATA(tb[IFLA_BR_GROUP_ADDR]),
+ RTA_PAYLOAD(tb[IFLA_BR_GROUP_ADDR]),
+ 1 /*ARPHDR_ETHER*/, mac, sizeof(mac)));
}
if (tb[IFLA_BR_MCAST_SNOOPING])
- fprintf(f, "mcast_snooping %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
+ print_uint(PRINT_ANY,
+ "mcast_snooping",
+ "mcast_snooping %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_SNOOPING]));
if (tb[IFLA_BR_MCAST_ROUTER])
- fprintf(f, "mcast_router %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
+ print_uint(PRINT_ANY,
+ "mcast_router",
+ "mcast_router %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_ROUTER]));
if (tb[IFLA_BR_MCAST_QUERY_USE_IFADDR])
- fprintf(f, "mcast_query_use_ifaddr %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
+ print_uint(PRINT_ANY,
+ "mcast_query_use_ifaddr",
+ "mcast_query_use_ifaddr %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_QUERY_USE_IFADDR]));
if (tb[IFLA_BR_MCAST_QUERIER])
- fprintf(f, "mcast_querier %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
+ print_uint(PRINT_ANY,
+ "mcast_querier",
+ "mcast_querier %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_QUERIER]));
if (tb[IFLA_BR_MCAST_HASH_ELASTICITY])
- fprintf(f, "mcast_hash_elasticity %u ",
- rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
+ print_uint(PRINT_ANY,
+ "mcast_hash_elasticity",
+ "mcast_hash_elasticity %u ",
+ rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_ELASTICITY]));
if (tb[IFLA_BR_MCAST_HASH_MAX])
- fprintf(f, "mcast_hash_max %u ",
- rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
+ print_uint(PRINT_ANY,
+ "mcast_hash_max",
+ "mcast_hash_max %u ",
+ rta_getattr_u32(tb[IFLA_BR_MCAST_HASH_MAX]));
if (tb[IFLA_BR_MCAST_LAST_MEMBER_CNT])
- fprintf(f, "mcast_last_member_count %u ",
- rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
+ print_uint(PRINT_ANY,
+ "mcast_last_member_cnt",
+ "mcast_last_member_count %u ",
+ rta_getattr_u32(tb[IFLA_BR_MCAST_LAST_MEMBER_CNT]));
if (tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT])
- fprintf(f, "mcast_startup_query_count %u ",
- rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
+ print_uint(PRINT_ANY,
+ "mcast_startup_query_cnt",
+ "mcast_startup_query_count %u ",
+ rta_getattr_u32(tb[IFLA_BR_MCAST_STARTUP_QUERY_CNT]));
if (tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL])
- fprintf(f, "mcast_last_member_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_last_member_intvl",
+ "mcast_last_member_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_LAST_MEMBER_INTVL]));
if (tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL])
- fprintf(f, "mcast_membership_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_membership_intvl",
+ "mcast_membership_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_MEMBERSHIP_INTVL]));
if (tb[IFLA_BR_MCAST_QUERIER_INTVL])
- fprintf(f, "mcast_querier_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_querier_intvl",
+ "mcast_querier_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_QUERIER_INTVL]));
if (tb[IFLA_BR_MCAST_QUERY_INTVL])
- fprintf(f, "mcast_query_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_query_intvl",
+ "mcast_query_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_INTVL]));
if (tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL])
- fprintf(f, "mcast_query_response_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_query_response_intvl",
+ "mcast_query_response_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_QUERY_RESPONSE_INTVL]));
if (tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL])
- fprintf(f, "mcast_startup_query_interval %llu ",
- rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
+ print_lluint(PRINT_ANY,
+ "mcast_startup_query_intvl",
+ "mcast_startup_query_interval %llu ",
+ rta_getattr_u64(tb[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]));
if (tb[IFLA_BR_MCAST_STATS_ENABLED])
- fprintf(f, "mcast_stats_enabled %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
+ print_uint(PRINT_ANY,
+ "mcast_stats_enabled",
+ "mcast_stats_enabled %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_STATS_ENABLED]));
if (tb[IFLA_BR_MCAST_IGMP_VERSION])
- fprintf(f, "mcast_igmp_version %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
+ print_uint(PRINT_ANY,
+ "mcast_igmp_version",
+ "mcast_igmp_version %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_IGMP_VERSION]));
if (tb[IFLA_BR_MCAST_MLD_VERSION])
- fprintf(f, "mcast_mld_version %u ",
- rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
+ print_uint(PRINT_ANY,
+ "mcast_mld_version",
+ "mcast_mld_version %u ",
+ rta_getattr_u8(tb[IFLA_BR_MCAST_MLD_VERSION]));
if (tb[IFLA_BR_NF_CALL_IPTABLES])
- fprintf(f, "nf_call_iptables %u ",
- rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
+ print_uint(PRINT_ANY,
+ "nf_call_iptables",
+ "nf_call_iptables %u ",
+ rta_getattr_u8(tb[IFLA_BR_NF_CALL_IPTABLES]));
if (tb[IFLA_BR_NF_CALL_IP6TABLES])
- fprintf(f, "nf_call_ip6tables %u ",
- rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
+ print_uint(PRINT_ANY,
+ "nf_call_ip6tables",
+ "nf_call_ip6tables %u ",
+ rta_getattr_u8(tb[IFLA_BR_NF_CALL_IP6TABLES]));
if (tb[IFLA_BR_NF_CALL_ARPTABLES])
- fprintf(f, "nf_call_arptables %u ",
- rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
+ print_uint(PRINT_ANY,
+ "nf_call_arptables",
+ "nf_call_arptables %u ",
+ rta_getattr_u8(tb[IFLA_BR_NF_CALL_ARPTABLES]));
}
static void bridge_print_help(struct link_util *lu, int argc, char **argv,
--
2.13.3
^ permalink raw reply related
* [PATCH 11/27] ip: iplink_bridge_slave.c: add json output support
From: Julien Fortin @ 2017-08-03 15:54 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
bridge_slave: IFLA_INFO_SLAVE_DATA
{
"state": {
"type": "string",
"attr": "IFLA_BRPORT_STATE",
"mutually_exclusive": {
"state_index": {
"type": "uint",
"comment": "if (state > BR_STATE_BLOCKING)"
}
}
},
"priority": {
"type": "int",
"attr": "IFLA_BRPORT_PRIORITY"
},
"cost": {
"type": "int",
"attr": "IFLA_BRPORT_COST"
},
"mode": {
"type": "bool",
"attr": "IFLA_BRPORT_MODE"
},
"guard": {
"type": "bool",
"attr": "IFLA_BRPORT_GUARD"
},
"protect": {
"type": "bool",
"attr": "IFLA_BRPORT_PROTECT"
},
"fast_leave": {
"type": "bool",
"attr": "IFLA_BRPORT_FAST_LEAVE"
},
"learning": {
"type": "bool",
"attr": "IFLA_BRPORT_LEARNING"
},
"unicast_flood": {
"type": "bool",
"attr": "IFLA_BRPORT_UNICAST_FLOOD"
},
"id": {
"type": "string",
"attr": "IFLA_BRPORT_ID"
},
"no": {
"type": "string",
"attr": "IFLA_BRPORT_NO"
},
"designated_port": {
"type": "uint",
"attr": "IFLA_BRPORT_DESIGNATED_PORT"
},
"designated_cost": {
"type": "uint",
"attr": "IFLA_BRPORT_DESIGNATED_COST"
},
"bridge_id": {
"type": "string",
"attr": "IFLA_BRPORT_BRIDGE_ID"
},
"root_id": {
"type": "string",
"attr": "IFLA_BRPORT_ROOT_ID"
},
"hold_timer": {
"type": "float",
"attr": "IFLA_BRPORT_HOLD_TIMER"
},
"message_age_timer": {
"type": "float",
"attr": "IFLA_BRPORT_MESSAGE_AGE_TIMER"
},
"forward_delay_timer": {
"type": "float",
"attr": "IFLA_BRPORT_FORWARD_DELAY_TIMER"
},
"topology_change_ack": {
"type": "uint",
"attr": "IFLA_BRPORT_TOPOLOGY_CHANGE_ACK"
},
"config_pending": {
"type": "uint",
"attr": "IFLA_BRPORT_CONFIG_PENDING"
},
"proxyarp": {
"type": "bool",
"attr": "IFLA_BRPORT_PROXYARP"
},
"proxyarp_wifi": {
"type": "bool",
"attr": "IFLA_BRPORT_PROXYARP_WIFI"
},
"multicast_router": {
"type": "uint",
"attr": "IFLA_BRPORT_MULTICAST_ROUTER"
},
"mcast_flood": {
"type": "bool",
"attr": "IFLA_BRPORT_MCAST_FLOOD"
}
}
$ ip link add dev br42 type bridge
$ ip link add dev bond42 type bond
$ ip link set dev bond42 master br42
$ ip link set dev bond42 up
$ ip link set dev br42 up
$ ip -details link show
$ ip -details link show
15: br42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state
UP mode DEFAULT group default
link/ether 22:8f:91:bb:9f:09 brd ff:ff:ff:ff:ff:ff promiscuity 0
bridge forward_delay 1500 hello_time 200 max_age 2000 ageing_time
30000 stp_state 0 priority 32768 vlan_filtering 0 vlan_protocol 802.1Q
bridge_id 8000.22:8f:91:bb:9f:9 designated_root 8000.22:8f:91:bb:9f:9
root_port 0 root_path_cost 0 topology_change 0 topology_change_detected 0
hello_timer 0.00 tcn_timer 0.00 topology_change_timer 0.00
gc_timer 199.11 vlan_default_pvid 1 vlan_stats_enabled 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 4096
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 3125
mcast_stats_enabled 0 mcast_igmp_version 2 mcast_mld_version 1
nf_call_iptables 0 nf_call_ip6tables 0 nf_call_arptables 0 addrgenmode
eui64
16: bond42: <BROADCAST,MULTICAST,MASTER,UP,LOWER_UP> mtu 1500 qdisc
noqueue master br42 state UNKNOWN mode DEFAULT group default
link/ether 22:8f:91:bb:9f:09 brd ff:ff:ff:ff:ff:ff promiscuity 1
bond mode 802.3ad miimon 100 updelay 0 downdelay 0 use_carrier 1
arp_interval 0 arp_validate none arp_all_targets any primary_reselect
always fail_over_mac none xmit_hash_policy layer3+4 resend_igmp 1
num_grat_arp 1 all_slaves_active 0 min_links 1 lp_interval 1
packets_per_slave 1 lacp_rate fast ad_select stable ad_actor_sys_prio
65535 ad_user_port_key 0 ad_actor_system 00:00:00:00:00:00
bridge_slave state forwarding priority 8 cost 100 hairpin off guard
off root_block off fastleave off learning on flood on port_id 0x8001
port_no 0x1 designated_port 32769 designated_cost 0 designated_bridge
8000.22:8f:91:bb:9f:9 designated_root 8000.22:8f:91:bb:9f:9 hold_timer
0.00 message_age_timer 0.00 forward_delay_timer 0.00
topology_change_ack 0 config_pending 0 proxy_arp off proxy_arp_wifi off
mcast_router 1 mcast_fast_leave off mcast_flood on neigh_suppress off
addrgenmode eui64
$ ip -details -json link show
[{
"ifindex": 15,
"ifname": "br42",
"flags": ["BROADCAST","MULTICAST","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "noqueue",
"operstate": "UP",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "22:8f:91:bb:9f:09",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "bridge",
"info_data": {
"forward_delay": 1500,
"hello_time": 200,
"max_age": 2000,
"ageing_time": 30000,
"stp_state": 0,
"priority": 32768,
"vlan_filtering": 0,
"vlan_protocol": "802.1Q",
"bridge_id": "8000.22:8f:91:bb:9f:9",
"root_id": "8000.22:8f:91:bb:9f:9",
"root_port": 0,
"root_path_cost": 0,
"topology_change": 0,
"topology_change_detected": 0,
"hello_timer": 0.00,
"tcn_timer": 0.00,
"topology_change_timer": 0.00,
"gc_timer": 298.27,
"vlan_default_pvid": 1,
"vlan_stats_enabled": 0,
"group_fwd_mask": "0",
"group_addr": "01:80:c2:00:00:00",
"mcast_snooping": 1,
"mcast_router": 1,
"mcast_query_use_ifaddr": 0,
"mcast_querier": 0,
"mcast_hash_elasticity": 4096,
"mcast_hash_max": 4096,
"mcast_last_member_cnt": 2,
"mcast_startup_query_cnt": 2,
"mcast_last_member_intvl": 100,
"mcast_membership_intvl": 26000,
"mcast_querier_intvl": 25500,
"mcast_query_intvl": 12500,
"mcast_query_response_intvl": 1000,
"mcast_startup_query_intvl": 3125,
"mcast_stats_enabled": 0,
"mcast_igmp_version": 2,
"mcast_mld_version": 1,
"nf_call_iptables": 0,
"nf_call_ip6tables": 0,
"nf_call_arptables": 0
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 16,
"ifname": "bond42",
"flags": ["BROADCAST","MULTICAST","MASTER","UP","LOWER_UP"],
"mtu": 1500,
"qdisc": "noqueue",
"master": "br42",
"operstate": "UNKNOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "22:8f:91:bb:9f:09",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 1,
"linkinfo": {
"info_kind": "bond",
"info_data": {
"mode": "802.3ad",
"miimon": 100,
"updelay": 0,
"downdelay": 0,
"use_carrier": 1,
"arp_interval": 0,
"arp_validate": null,
"arp_all_targets": "any",
"primary_reselect": "always",
"fail_over_mac": "none",
"xmit_hash_policy": "layer3+4",
"resend_igmp": 1,
"num_peer_notif": 1,
"all_slaves_active": 0,
"min_links": 1,
"lp_interval": 1,
"packets_per_slave": 1,
"ad_lacp_rate": "fast",
"ad_select": "stable",
"ad_actor_sys_prio": 65535,
"ad_user_port_key": 0,
"ad_actor_system": "00:00:00:00:00:00"
},
"info_slave_kind": "bridge",
"info_slave_data": {
"state": "forwarding",
"priority": 8,
"cost": 100,
"hairpin": false,
"guard": false,
"root_block": false,
"fastleave": false,
"learning": true,
"flood": true,
"id": "0x8001",
"no": "0x1",
"designated_port": 32769,
"designated_cost": 0,
"bridge_id": "8000.22:8f:91:bb:9f:9",
"root_id": "8000.22:8f:91:bb:9f:9",
"hold_timer": 0.00,
"message_age_timer": 0.00,
"forward_delay_timer": 11.97,
"topology_change_ack": 0,
"config_pending": 0,
"proxy_arp": false,
"proxy_arp_wifi": false,
"multicast_router": 1,
"mcast_flood": true
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 16,
"num_rx_queues": 16,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_bridge_slave.c | 185 +++++++++++++++++++++++++++++------------------
1 file changed, 114 insertions(+), 71 deletions(-)
diff --git a/ip/iplink_bridge_slave.c b/ip/iplink_bridge_slave.c
index 3e883328..80272b09 100644
--- a/ip/iplink_bridge_slave.c
+++ b/ip/iplink_bridge_slave.c
@@ -56,14 +56,52 @@ static const char *port_states[] = {
static void print_portstate(FILE *f, __u8 state)
{
if (state <= BR_STATE_BLOCKING)
- fprintf(f, "state %s ", port_states[state]);
+ print_string(PRINT_ANY,
+ "state",
+ "state %s ",
+ port_states[state]);
else
- fprintf(f, "state (%d) ", state);
+ print_int(PRINT_ANY, "state_index", "state (%d) ", state);
}
-static void print_onoff(FILE *f, char *flag, __u8 val)
+static void _print_onoff(FILE *f, char *json_flag, char *flag, __u8 val)
{
- fprintf(f, "%s %s ", flag, val ? "on" : "off");
+ if (is_json_context())
+ print_bool(PRINT_JSON, flag, NULL, val);
+ else
+ fprintf(f, "%s %s ", flag, val ? "on" : "off");
+}
+
+static void _print_hex(FILE *f,
+ const char *json_attr,
+ const char *attr,
+ __u16 val)
+{
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%x", val);
+ print_string(PRINT_JSON, json_attr, NULL, b1);
+ } else {
+ fprintf(f, "%s 0x%x ", attr, val);
+ }
+}
+
+static void _print_timer(FILE *f, const char *attr, struct rtattr *timer)
+{
+ struct timeval tv;
+
+ __jiffies_to_tv(&tv, rta_getattr_u64(timer));
+ if (is_json_context()) {
+ json_writer_t *jw = get_json_writer();
+
+ jsonw_name(jw, attr);
+ jsonw_printf(jw, "%i.%.2i",
+ (int)tv.tv_sec, (int)tv.tv_usec / 10000);
+ } else {
+ fprintf(f, "%s %4i.%.2i ", attr, (int)tv.tv_sec,
+ (int)tv.tv_usec / 10000);
+ }
}
static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
@@ -76,59 +114,70 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
print_portstate(f, rta_getattr_u8(tb[IFLA_BRPORT_STATE]));
if (tb[IFLA_BRPORT_PRIORITY])
- fprintf(f, "priority %d ",
- rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
+ print_int(PRINT_ANY,
+ "priority",
+ "priority %d ",
+ rta_getattr_u16(tb[IFLA_BRPORT_PRIORITY]));
if (tb[IFLA_BRPORT_COST])
- fprintf(f, "cost %d ",
- rta_getattr_u32(tb[IFLA_BRPORT_COST]));
+ print_int(PRINT_ANY,
+ "cost",
+ "cost %d ",
+ rta_getattr_u32(tb[IFLA_BRPORT_COST]));
if (tb[IFLA_BRPORT_MODE])
- print_onoff(f, "hairpin",
- rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
+ _print_onoff(f, "mode", "hairpin",
+ rta_getattr_u8(tb[IFLA_BRPORT_MODE]));
if (tb[IFLA_BRPORT_GUARD])
- print_onoff(f, "guard",
- rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
+ _print_onoff(f, "guard", "guard",
+ rta_getattr_u8(tb[IFLA_BRPORT_GUARD]));
if (tb[IFLA_BRPORT_PROTECT])
- print_onoff(f, "root_block",
- rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
+ _print_onoff(f, "protect", "root_block",
+ rta_getattr_u8(tb[IFLA_BRPORT_PROTECT]));
if (tb[IFLA_BRPORT_FAST_LEAVE])
- print_onoff(f, "fastleave",
- rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
+ _print_onoff(f, "fast_leave", "fastleave",
+ rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
if (tb[IFLA_BRPORT_LEARNING])
- print_onoff(f, "learning",
- rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
+ _print_onoff(f, "learning", "learning",
+ rta_getattr_u8(tb[IFLA_BRPORT_LEARNING]));
if (tb[IFLA_BRPORT_UNICAST_FLOOD])
- print_onoff(f, "flood",
- rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
+ _print_onoff(f, "unicast_flood", "flood",
+ rta_getattr_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]));
if (tb[IFLA_BRPORT_ID])
- fprintf(f, "port_id 0x%x ",
- rta_getattr_u16(tb[IFLA_BRPORT_ID]));
+ _print_hex(f, "id", "port_id",
+ rta_getattr_u16(tb[IFLA_BRPORT_ID]));
if (tb[IFLA_BRPORT_NO])
- fprintf(f, "port_no 0x%x ",
- rta_getattr_u16(tb[IFLA_BRPORT_NO]));
+ _print_hex(f, "no", "port_no",
+ rta_getattr_u16(tb[IFLA_BRPORT_NO]));
if (tb[IFLA_BRPORT_DESIGNATED_PORT])
- fprintf(f, "designated_port %u ",
- rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_PORT]));
+ print_uint(PRINT_ANY,
+ "designated_port",
+ "designated_port %u ",
+ rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_PORT]));
if (tb[IFLA_BRPORT_DESIGNATED_COST])
- fprintf(f, "designated_cost %u ",
- rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_COST]));
+ print_uint(PRINT_ANY,
+ "designated_cost",
+ "designated_cost %u ",
+ rta_getattr_u16(tb[IFLA_BRPORT_DESIGNATED_COST]));
if (tb[IFLA_BRPORT_BRIDGE_ID]) {
char bridge_id[32];
br_dump_bridge_id(RTA_DATA(tb[IFLA_BRPORT_BRIDGE_ID]),
bridge_id, sizeof(bridge_id));
- fprintf(f, "designated_bridge %s ", bridge_id);
+ print_string(PRINT_ANY,
+ "bridge_id",
+ "designated_bridge %s ",
+ bridge_id);
}
if (tb[IFLA_BRPORT_ROOT_ID]) {
@@ -136,65 +185,59 @@ static void bridge_slave_print_opt(struct link_util *lu, FILE *f,
br_dump_bridge_id(RTA_DATA(tb[IFLA_BRPORT_ROOT_ID]),
root_id, sizeof(root_id));
- fprintf(f, "designated_root %s ", root_id);
- }
-
- if (tb[IFLA_BRPORT_HOLD_TIMER]) {
- struct timeval tv;
- __u64 htimer;
-
- htimer = rta_getattr_u64(tb[IFLA_BRPORT_HOLD_TIMER]);
- __jiffies_to_tv(&tv, htimer);
- fprintf(f, "hold_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
+ print_string(PRINT_ANY,
+ "root_id",
+ "designated_root %s ", root_id);
}
- if (tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]) {
- struct timeval tv;
- __u64 agetimer;
+ if (tb[IFLA_BRPORT_HOLD_TIMER])
+ _print_timer(f, "hold_timer", tb[IFLA_BRPORT_HOLD_TIMER]);
- agetimer = rta_getattr_u64(tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]);
- __jiffies_to_tv(&tv, agetimer);
- fprintf(f, "message_age_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
-
- if (tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]) {
- struct timeval tv;
- __u64 fwdtimer;
+ if (tb[IFLA_BRPORT_MESSAGE_AGE_TIMER])
+ _print_timer(f, "message_age_timer",
+ tb[IFLA_BRPORT_MESSAGE_AGE_TIMER]);
- fwdtimer = rta_getattr_u64(tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]);
- __jiffies_to_tv(&tv, fwdtimer);
- fprintf(f, "forward_delay_timer %4i.%.2i ", (int)tv.tv_sec,
- (int)tv.tv_usec/10000);
- }
+ if (tb[IFLA_BRPORT_FORWARD_DELAY_TIMER])
+ _print_timer(f, "forward_delay_timer",
+ tb[IFLA_BRPORT_FORWARD_DELAY_TIMER]);
if (tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK])
- fprintf(f, "topology_change_ack %u ",
- rta_getattr_u8(tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]));
+ print_uint(PRINT_ANY,
+ "topology_change_ack",
+ "topology_change_ack %u ",
+ rta_getattr_u8(tb[IFLA_BRPORT_TOPOLOGY_CHANGE_ACK]));
if (tb[IFLA_BRPORT_CONFIG_PENDING])
- fprintf(f, "config_pending %u ",
- rta_getattr_u8(tb[IFLA_BRPORT_CONFIG_PENDING]));
+ print_uint(PRINT_ANY,
+ "config_pending",
+ "config_pending %u ",
+ rta_getattr_u8(tb[IFLA_BRPORT_CONFIG_PENDING]));
+
if (tb[IFLA_BRPORT_PROXYARP])
- print_onoff(f, "proxy_arp",
- rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP]));
+ _print_onoff(f, "proxyarp", "proxy_arp",
+ rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP]));
if (tb[IFLA_BRPORT_PROXYARP_WIFI])
- print_onoff(f, "proxy_arp_wifi",
- rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP_WIFI]));
+ _print_onoff(f, "proxyarp_wifi", "proxy_arp_wifi",
+ rta_getattr_u8(tb[IFLA_BRPORT_PROXYARP_WIFI]));
if (tb[IFLA_BRPORT_MULTICAST_ROUTER])
- fprintf(f, "mcast_router %u ",
- rta_getattr_u8(tb[IFLA_BRPORT_MULTICAST_ROUTER]));
+ print_uint(PRINT_ANY,
+ "multicast_router",
+ "mcast_router %u ",
+ rta_getattr_u8(tb[IFLA_BRPORT_MULTICAST_ROUTER]));
if (tb[IFLA_BRPORT_FAST_LEAVE])
- print_onoff(f, "mcast_fast_leave",
- rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]));
+ // not printing any json here because
+ // we already printed fast_leave before
+ print_string(PRINT_FP,
+ NULL,
+ "mcast_fast_leave %s ",
+ rta_getattr_u8(tb[IFLA_BRPORT_FAST_LEAVE]) ? "on" : "off");
if (tb[IFLA_BRPORT_MCAST_FLOOD])
- print_onoff(f, "mcast_flood",
- rta_getattr_u8(tb[IFLA_BRPORT_MCAST_FLOOD]));
+ _print_onoff(f, "mcast_flood", "mcast_flood",
+ rta_getattr_u8(tb[IFLA_BRPORT_MCAST_FLOOD]));
}
static void bridge_slave_parse_on_off(char *arg_name, char *arg_val,
--
2.13.3
^ permalink raw reply related
* [PATCH 12/27] ip: iplink_can.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema: IFLA_INFO_DATA
{
"ctrlmode": {
"type": "array",
"attr": "IFLA_CAN_CTRLMODE",
"array": [
{
"type": "string"
}
]
},
"state": {
"type": "string",
"attr": "IFLA_CAN_STATE"
},
"berr_counter": {
"type": "dict",
"attr": "IFLA_CAN_BERR_COUNTER",
"dict": {
"tx": {
"type": "int"
},
"rx": {
"type": "int"
}
}
},
"restart_ms": {
"type": "int",
"attr": "IFLA_CAN_RESTART_MS"
},
"bittiming": {
"type": "dict",
"attr": "IFLA_CAN_BITTIMING",
"dict": {
"bitrate": {
"type": "int"
},
"sample_point": {
"type": "float"
},
"tq": {
"type": "int"
},
"prop_seg": {
"type": "int"
},
"phase_seg1": {
"type": "int"
},
"phase_seg2": {
"type": "int"
},
"sjw": {
"type": "int"
}
}
},
"bittiming_const": {
"type": "dict",
"attr": "IFLA_CAN_BITTIMING_CONST",
"dict": {
"name": {
"type": "string"
},
"tseg1": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"tseg2": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"sjw": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"brp": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"brp_inc": {
"type": "int"
}
}
},
"bittiming_bitrate": {
"type": "uint",
"attr": "IFLA_CAN_BITTIMING"
},
"bitrate_const": {
"type": "array",
"attr": "IFLA_CAN_BITRATE_CONST",
"array": [
{
"type": "uint"
}
]
},
"data_bittiming": {
"type": "dict",
"attr": "IFLA_CAN_DATA_BITTIMING",
"dict": {
"bitrate": {
"type": "int"
},
"sample_point": {
"type": "float"
},
"tq": {
"type": "int"
},
"prop_seg": {
"type": "int"
},
"phase_seg1": {
"type": "int"
},
"phase_seg2": {
"type": "int"
},
"sjw": {
"type": "int"
}
}
},
"data_bittiming_const": {
"type": "dict",
"attr": "IFLA_CAN_DATA_BITTIMING_CONST",
"dict": {
"name": {
"type": "string"
},
"tseg1": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"tseg2": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"sjw": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"brp": {
"type": "dict",
"dict": {
"min": {
"type": "int"
},
"max": {
"type": "int"
}
}
},
"brp_inc": {
"type": "int"
}
}
},
"data_bittiming_bitrate": {
"type": "uint",
"attr": "IFLA_CAN_DATA_BITTIMING"
},
"data_bitrate_const": {
"type": "array",
"attr": "IFLA_CAN_DATA_BITRATE_CONST",
"array": [
{
"type": "uint"
}
]
},
"termination": {
"type": "unsigned short",
"attr": "IFLA_CAN_TERMINATION"
},
"termination_const": {
"type": "array",
"attr": "IFLA_CAN_TERMINATION_CONST",
"array": [
{
"type": "unsigned short"
}
]
},
"clock": {
"type": "int",
"attr": "IFLA_CAN_CLOCK"
}
}
IFLA_INFO_XSTATS
{
"restarts": {
"type": "int"
},
"bus_error": {
"type": "int"
},
"arbitration_lost": {
"type": "int"
},
"error_warning": {
"type": "int"
},
"error_passive": {
"type": "int"
},
"bus_off": {
"type": "int"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_can.c | 276 ++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 208 insertions(+), 68 deletions(-)
diff --git a/ip/iplink_can.c b/ip/iplink_can.c
index 5df56b2b..760fa592 100644
--- a/ip/iplink_can.c
+++ b/ip/iplink_can.c
@@ -89,11 +89,11 @@ static void set_ctrlmode(char *name, char *arg,
static void print_ctrlmode(FILE *f, __u32 cm)
{
- fprintf(f, "<");
-#define _PF(cmflag, cmname) \
- if (cm & cmflag) { \
- cm &= ~cmflag; \
- fprintf(f, "%s%s", cmname, cm ? "," : ""); \
+ 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); \
}
_PF(CAN_CTRLMODE_LOOPBACK, "LOOPBACK");
_PF(CAN_CTRLMODE_LISTENONLY, "LISTEN-ONLY");
@@ -105,8 +105,8 @@ static void print_ctrlmode(FILE *f, __u32 cm)
_PF(CAN_CTRLMODE_PRESUME_ACK, "PRESUME-ACK");
#undef _PF
if (cm)
- fprintf(f, "%x", cm);
- fprintf(f, "> ");
+ print_hex(PRINT_ANY, NULL, "%x", cm);
+ close_json_array(PRINT_ANY, "> ");
}
static int can_parse_opt(struct link_util *lu, int argc, char **argv,
@@ -260,6 +260,14 @@ static const char *can_state_names[] = {
[CAN_STATE_SLEEPING] = "SLEEPING"
};
+static void can_print_json_timing_min_max(const char *attr, int min, int max)
+{
+ open_json_object(attr);
+ print_int(PRINT_JSON, "min", NULL, min);
+ print_int(PRINT_JSON, "max", NULL, max);
+ close_json_object();
+}
+
static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
{
if (!tb)
@@ -275,32 +283,64 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_CAN_STATE]) {
uint32_t state = rta_getattr_u32(tb[IFLA_CAN_STATE]);
- fprintf(f, "state %s ", state <= CAN_STATE_MAX ?
- can_state_names[state] : "UNKNOWN");
+ if (state <= CAN_STATE_MAX)
+ print_string(PRINT_ANY, "state", "state %s ",
+ can_state_names[state]);
+ else
+ print_null(PRINT_ANY, "state", "state UNKNOWN", NULL);
}
if (tb[IFLA_CAN_BERR_COUNTER]) {
struct can_berr_counter *bc =
RTA_DATA(tb[IFLA_CAN_BERR_COUNTER]);
- fprintf(f, "(berr-counter tx %d rx %d) ", bc->txerr, bc->rxerr);
+ 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);
+ }
}
if (tb[IFLA_CAN_RESTART_MS]) {
__u32 *restart_ms = RTA_DATA(tb[IFLA_CAN_RESTART_MS]);
- fprintf(f, "restart-ms %d ", *restart_ms);
+ print_int(PRINT_ANY,
+ "restart_ms",
+ "restart-ms %d ",
+ *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]);
- 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);
+ if (is_json_context()) {
+ open_json_object("bittiming");
+ print_int(PRINT_ANY, "bitrate", NULL, bt->bitrate);
+ jsonw_float_field_fmt(get_json_writer(),
+ "sample_point", "%.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);
+ }
}
/* bittiming const is irrelevant if fixed bitrate is defined */
@@ -308,17 +348,34 @@ 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]);
- 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);
+ 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);
+ }
}
if (tb[IFLA_CAN_BITRATE_CONST]) {
__u32 *bitrate_const = RTA_DATA(tb[IFLA_CAN_BITRATE_CONST]);
int bitrate_cnt = RTA_PAYLOAD(tb[IFLA_CAN_BITRATE_CONST]) /
- sizeof(*bitrate_const);
+ sizeof(*bitrate_const);
int i;
__u32 bitrate = 0;
@@ -328,33 +385,62 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
bitrate = bt->bitrate;
}
- fprintf(f, "\n bitrate %u", bitrate);
- fprintf(f, "\n [");
+ 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]);
+ }
- 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]);
+ fprintf(f, "%8u ]", bitrate_const[i]);
}
-
- if (!(i % 6) && i)
- fprintf(f, "\n ");
- fprintf(f, "%8u ]", bitrate_const[i]);
}
/* 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]);
-
- 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);
+ RTA_DATA(tb[IFLA_CAN_DATA_BITTIMING]);
+
+ if (is_json_context()) {
+ open_json_object("data_bittiming");
+ print_int(PRINT_JSON, "bitrate", NULL, dbt->bitrate);
+ jsonw_float_field_fmt(get_json_writer(),
+ "sample_point",
+ "%.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);
+ }
}
/* data bittiming const is irrelevant if fixed bitrate is defined */
@@ -363,11 +449,29 @@ 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]);
- 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 (is_json_context()) {
+ open_json_object("data_bittiming_const");
+ print_string(PRINT_JSON, "name", NULL, dbtc->name);
+ can_print_json_timing_min_max("tseg1",
+ dbtc->tseg1_min,
+ dbtc->tseg1_max);
+ can_print_json_timing_min_max("tseg2",
+ dbtc->tseg2_min,
+ dbtc->tseg2_max);
+ can_print_json_timing_min_max("sjw", 1, dbtc->sjw_max);
+ can_print_json_timing_min_max("brp",
+ dbtc->brp_min,
+ dbtc->brp_max);
+
+ print_int(PRINT_JSON, "brp_inc", NULL, dbtc->brp_inc);
+ close_json_object();
+ } else {
+ fprintf(f, "\n %s: dtseg1 %d..%d dtseg2 %d..%d "
+ "dsjw 1..%d dbrp %d..%d dbrp-inc %d",
+ dbtc->name, dbtc->tseg1_min, dbtc->tseg1_max,
+ dbtc->tseg2_min, dbtc->tseg2_max, dbtc->sjw_max,
+ dbtc->brp_min, dbtc->brp_max, dbtc->brp_inc);
+ }
}
if (tb[IFLA_CAN_DATA_BITRATE_CONST]) {
@@ -385,41 +489,62 @@ static void can_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
dbitrate = dbt->bitrate;
}
- fprintf(f, "\n dbitrate %u", dbitrate);
- fprintf(f, "\n [");
+ 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]);
+ }
- 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]);
+ fprintf(f, "%8u ]", dbitrate_const[i]);
}
-
- if (!(i % 6) && i)
- fprintf(f, "\n ");
- fprintf(f, "%8u ]", dbitrate_const[i]);
}
if (tb[IFLA_CAN_TERMINATION_CONST] && tb[IFLA_CAN_TERMINATION]) {
__u16 *trm = RTA_DATA(tb[IFLA_CAN_TERMINATION]);
__u16 *trm_const = RTA_DATA(tb[IFLA_CAN_TERMINATION_CONST]);
int trm_cnt = RTA_PAYLOAD(tb[IFLA_CAN_TERMINATION_CONST]) /
- sizeof(*trm_const);
+ sizeof(*trm_const);
int i;
- fprintf(f, "\n termination %hu [ ", *trm);
+ 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]);
+ for (i = 0; i < trm_cnt - 1; ++i)
+ fprintf(f, "%hu, ", trm_const[i]);
- fprintf(f, "%hu ]", trm_const[i]);
+ fprintf(f, "%hu ]", trm_const[i]);
+ }
}
if (tb[IFLA_CAN_CLOCK]) {
struct can_clock *clock = RTA_DATA(tb[IFLA_CAN_CLOCK]);
- fprintf(f, "\n clock %d", clock->freq);
+ print_int(PRINT_ANY,
+ "clock",
+ "\n clock %d",
+ clock->freq);
}
}
@@ -431,17 +556,32 @@ static void can_print_xstats(struct link_util *lu,
if (xstats && RTA_PAYLOAD(xstats) == sizeof(*stats)) {
stats = RTA_DATA(xstats);
- 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);
+
+ 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);
+ }
}
}
static void can_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_usage(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 13/27] ip: iplink_geneve.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"id": {
"type": "uint",
"attr": "IFLA_GENEVE_ID"
},
"remote": {
"type": "string",
"attr": "IFLA_GENEVE_REMOTE"
},
"remote6": {
"type": "string",
"attr": "IFLA_GENEVE_REMOTE6"
},
"ttl": {
"type": "int",
"attr": "IFLA_GENEVE_TTL"
},
"tos": {
"type": "string",
"attr": "IFLA_GENEVE_TOS"
},
"label": {
"type": "string",
"attr": "IFLA_GENEVE_LABEL"
},
"port": {
"type": "uint",
"attr": "IFLA_GENEVE_PORT"
},
"collect_metadata": {
"type": "bool",
"attr": "IFLA_GENEVE_COLLECT_METADATA"
},
"udp_csum": {
"type": "bool",
"attr": "IFLA_GENEVE_UDP_CSUM"
},
"udp_zero_csum6_tx": {
"type": "bool",
"attr": "IFLA_GENEVE_UDP_ZERO_CSUM6_TX"
},
"udp_zero_csum6_rx": {
"type": "bool",
"attr": "IFLA_GENEVE_UDP_ZERO_CSUM6_RX"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_geneve.c | 86 +++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 63 insertions(+), 23 deletions(-)
diff --git a/ip/iplink_geneve.c b/ip/iplink_geneve.c
index 594a3e59..f0f1d1c7 100644
--- a/ip/iplink_geneve.c
+++ b/ip/iplink_geneve.c
@@ -237,22 +237,28 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return;
vni = rta_getattr_u32(tb[IFLA_GENEVE_ID]);
- fprintf(f, "id %u ", vni);
+ print_uint(PRINT_ANY, "id", "id %u ", vni);
if (tb[IFLA_GENEVE_REMOTE]) {
__be32 addr = rta_getattr_u32(tb[IFLA_GENEVE_REMOTE]);
if (addr)
- fprintf(f, "remote %s ",
- format_host(AF_INET, 4, &addr));
+ print_string(PRINT_ANY,
+ "remote",
+ "remote %s ",
+ format_host(AF_INET, 4, &addr));
} else if (tb[IFLA_GENEVE_REMOTE6]) {
struct in6_addr addr;
memcpy(&addr, RTA_DATA(tb[IFLA_GENEVE_REMOTE6]), sizeof(struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
if (!IN6_IS_ADDR_MULTICAST(&addr))
- fprintf(f, "remote %s ",
- format_host(AF_INET6, sizeof(struct in6_addr), &addr));
+ print_string(PRINT_ANY,
+ "remote6",
+ "remote %s ",
+ format_host(AF_INET6,
+ sizeof(struct in6_addr),
+ &addr));
}
}
@@ -260,47 +266,81 @@ static void geneve_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
__u8 ttl = rta_getattr_u8(tb[IFLA_GENEVE_TTL]);
if (ttl)
- fprintf(f, "ttl %d ", ttl);
+ print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
}
if (tb[IFLA_GENEVE_TOS] &&
(tos = rta_getattr_u8(tb[IFLA_GENEVE_TOS]))) {
- if (tos == 1)
- fprintf(f, "tos inherit ");
- else
- fprintf(f, "tos %#x ", tos);
+ if (is_json_context()) {
+ print_0xhex(PRINT_JSON, "tos", "%#x", tos);
+ } else {
+ if (tos == 1) {
+ print_string(PRINT_FP,
+ "tos",
+ "tos %s ",
+ "inherit");
+ } else {
+ fprintf(f, "tos %#x ", tos);
+ }
+ }
}
if (tb[IFLA_GENEVE_LABEL]) {
__u32 label = rta_getattr_u32(tb[IFLA_GENEVE_LABEL]);
if (label)
- fprintf(f, "flowlabel %#x ", ntohl(label));
+ print_0xhex(PRINT_ANY,
+ "label",
+ "flowlabel %#x ",
+ ntohl(label));
}
if (tb[IFLA_GENEVE_PORT])
- fprintf(f, "dstport %u ",
- rta_getattr_be16(tb[IFLA_GENEVE_PORT]));
+ print_uint(PRINT_ANY,
+ "port",
+ "dstport %u ",
+ rta_getattr_be16(tb[IFLA_GENEVE_PORT]));
if (tb[IFLA_GENEVE_COLLECT_METADATA])
- fputs("external ", f);
+ print_bool(PRINT_ANY, "collect_metadata", "external ", true);
if (tb[IFLA_GENEVE_UDP_CSUM]) {
- if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]))
- fputs("no", f);
- fputs("udpcsum ", f);
+ if (is_json_context()) {
+ print_bool(PRINT_JSON,
+ "udp_csum",
+ NULL,
+ rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]));
+ } else {
+ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_CSUM]))
+ fputs("no", f);
+ fputs("udpcsum ", f);
+ }
}
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]) {
- if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
- fputs("no", f);
- fputs("udp6zerocsumtx ", f);
+ if (is_json_context()) {
+ print_bool(PRINT_JSON,
+ "udp_zero_csum6_tx",
+ NULL,
+ rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]));
+ } else {
+ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_TX]))
+ fputs("no", f);
+ fputs("udp6zerocsumtx ", f);
+ }
}
if (tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]) {
- if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
- fputs("no", f);
- fputs("udp6zerocsumrx ", f);
+ if (is_json_context()) {
+ print_bool(PRINT_JSON,
+ "udp_zero_csum6_rx",
+ NULL,
+ rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]));
+ } else {
+ if (!rta_getattr_u8(tb[IFLA_GENEVE_UDP_ZERO_CSUM6_RX]))
+ fputs("no", f);
+ fputs("udp6zerocsumrx ", f);
+ }
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH 14/27] ip: iplink_ipoib.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"key": {
"type": "string",
"attr": "IFLA_IPOIB_PKEY"
},
"mode": {
"type": "string",
"attr": "IFLA_IPOIB_PKEY"
},
"umcast": {
"type": "string",
"attr": "IFLA_IPOIB_UMCAST"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_ipoib.c | 30 +++++++++++++++++++++++++-----
1 file changed, 25 insertions(+), 5 deletions(-)
diff --git a/ip/iplink_ipoib.c b/ip/iplink_ipoib.c
index 86dc65ca..e69bda0e 100644
--- a/ip/iplink_ipoib.c
+++ b/ip/iplink_ipoib.c
@@ -91,23 +91,43 @@ static void ipoib_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
RTA_PAYLOAD(tb[IFLA_IPOIB_PKEY]) < sizeof(__u16))
return;
- fprintf(f, "pkey %#.4x ", rta_getattr_u16(tb[IFLA_IPOIB_PKEY]));
+ __u16 pkey = rta_getattr_u16(tb[IFLA_IPOIB_PKEY]);
+
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "%#.4x", pkey);
+ print_string(PRINT_JSON, "key", NULL, b1);
+ } else {
+ fprintf(f, "pkey %#.4x ", pkey);
+ }
if (!tb[IFLA_IPOIB_MODE] ||
RTA_PAYLOAD(tb[IFLA_IPOIB_MODE]) < sizeof(__u16))
return;
mode = rta_getattr_u16(tb[IFLA_IPOIB_MODE]);
- fprintf(f, "mode %s ",
+
+ const char *mode_str =
mode == IPOIB_MODE_DATAGRAM ? "datagram" :
- mode == IPOIB_MODE_CONNECTED ? "connected" :
- "unknown");
+ mode == IPOIB_MODE_CONNECTED ? "connected" : "unknown";
+
+ print_string(PRINT_ANY, "mode", "mode %s ", mode_str);
if (!tb[IFLA_IPOIB_UMCAST] ||
RTA_PAYLOAD(tb[IFLA_IPOIB_UMCAST]) < sizeof(__u16))
return;
- fprintf(f, "umcast %.4x ", rta_getattr_u16(tb[IFLA_IPOIB_UMCAST]));
+ __u16 umcast = rta_getattr_u16(tb[IFLA_IPOIB_UMCAST]);
+
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "%.4x", umcast);
+ print_string(PRINT_JSON, "umcast", NULL, b1);
+ } else {
+ fprintf(f, "umcast %.4x ", umcast);
+ }
}
static void ipoib_print_help(struct link_util *lu, int argc, char **argv,
--
2.13.3
^ permalink raw reply related
* [PATCH 15/27] ip: iplink_ipvlan.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"mode": {
"type": "string",
"attr": "IFLA_IPVLAN_MODE"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_ipvlan.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/ip/iplink_ipvlan.c b/ip/iplink_ipvlan.c
index f7735f3a..9f48309e 100644
--- a/ip/iplink_ipvlan.c
+++ b/ip/iplink_ipvlan.c
@@ -68,11 +68,11 @@ static void ipvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_IPVLAN_MODE]) {
if (RTA_PAYLOAD(tb[IFLA_IPVLAN_MODE]) == sizeof(__u16)) {
__u16 mode = rta_getattr_u16(tb[IFLA_IPVLAN_MODE]);
-
- fprintf(f, " mode %s ",
- mode == IPVLAN_MODE_L2 ? "l2" :
+ const char *mode_str = mode == IPVLAN_MODE_L2 ? "l2" :
mode == IPVLAN_MODE_L3 ? "l3" :
- mode == IPVLAN_MODE_L3S ? "l3s" : "unknown");
+ mode == IPVLAN_MODE_L3S ? "l3s" : "unknown";
+
+ print_string(PRINT_ANY, "mode", " mode %s ", mode_str);
}
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH 16/27] ip: iplink_vrf.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"table": {
"type": "uint",
"attr": "IFLA_VRF_TABLE"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_vrf.c | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/ip/iplink_vrf.c b/ip/iplink_vrf.c
index 917630e8..f13b1d24 100644
--- a/ip/iplink_vrf.c
+++ b/ip/iplink_vrf.c
@@ -62,7 +62,10 @@ static void vrf_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return;
if (tb[IFLA_VRF_TABLE])
- fprintf(f, "table %u ", rta_getattr_u32(tb[IFLA_VRF_TABLE]));
+ print_uint(PRINT_ANY,
+ "table",
+ "table %u ",
+ rta_getattr_u32(tb[IFLA_VRF_TABLE]));
}
static void vrf_slave_print_opt(struct link_util *lu, FILE *f,
@@ -72,13 +75,15 @@ static void vrf_slave_print_opt(struct link_util *lu, FILE *f,
return;
if (tb[IFLA_VRF_PORT_TABLE]) {
- fprintf(f, "table %u ",
- rta_getattr_u32(tb[IFLA_VRF_PORT_TABLE]));
+ print_uint(PRINT_ANY,
+ "table",
+ "table %u ",
+ rta_getattr_u32(tb[IFLA_VRF_PORT_TABLE]));
}
}
static void vrf_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
vrf_explain(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 17/27] ip: iplink_vxlan.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"id": {
"type": "uint",
"attr": "IFLA_VXLAN_ID"
},
"group": {
"type": "string",
"attr": "IFLA_VXLAN_GROUP"
},
"remote": {
"type": "string",
"attr": "IFLA_VXLAN_GROUP"
},
"group6": {
"type": "string",
"attr": "IFLA_VXLAN_GROUP6"
},
"remote6": {
"type": "string",
"attr": "IFLA_VXLAN_GROUP6"
},
"local": {
"type": "string",
"attr": "IFLA_VXLAN_LOCAL"
},
"local6": {
"type": "string",
"attr": "IFLA_VXLAN_LOCAL6"
},
"link": {
"type": "string",
"attr": "IFLA_VXLAN_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
"comment": "if not ifname for ifindex"
}
}
},
"port_range": {
"type": "dict",
"attr": "IFLA_VXLAN_PORT_RANGE",
"dict": {
"low": {
"type": "uint"
},
"high": {
"type": "uint"
}
}
},
"port": {
"type": "uint",
"attr": "IFLA_VXLAN_PORT"
},
"learning": {
"type": "bool",
"attr": "IFLA_VXLAN_LEARNING"
},
"proxy": {
"type": "bool",
"attr": "IFLA_VXLAN_PROXY"
},
"rsc": {
"type": "bool",
"attr": "IFLA_VXLAN_RSC"
},
"l2miss": {
"type": "bool",
"attr": "IFLA_VXLAN_L2MISS"
},
"l3miss": {
"type": "bool",
"attr": "IFLA_VXLAN_L3MISS"
},
"tos": {
"type": "string",
"attr": "IFLA_VXLAN_TOS"
},
"ttl": {
"type": "int",
"attr": "IFLA_VXLAN_TTL"
},
"label": {
"type": "string",
"attr": "IFLA_VXLAN_LABEL"
},
"ageing": {
"type": "uint",
"attr": "IFLA_VXLAN_AGEING"
},
"limit": {
"type": "uint",
"attr": "IFLA_VXLAN_LIMIT"
},
"udp_csum": {
"type": "bool",
"attr": "IFLA_VXLAN_UDP_CSUM"
},
"udp_zero_csum6_tx": {
"type": "bool",
"attr": "IFLA_VXLAN_UDP_ZERO_CSUM6_TX"
},
"udp_zero_csum6_rx": {
"type": "bool",
"attr": "IFLA_VXLAN_UDP_ZERO_CSUM6_RX"
},
"remcsum_tx": {
"type": "bool",
"attr": "IFLA_VXLAN_REMCSUM_TX"
},
"remcsum_rx": {
"type": "bool",
"attr": "IFLA_VXLAN_REMCSUM_RX"
},
"collect_metadata": {
"type": "bool",
"attr": "IFLA_VXLAN_COLLECT_METADATA"
},
"gbp": {
"type": "bool",
"attr": "IFLA_VXLAN_GBP"
},
"gpe": {
"type": "bool",
"attr": "IFLA_VXLAN_GPE"
}
}
$ ip link add name vxlan42 type vxlan id 42 dev eth0 remote 203.0.113.6
local 192.0.2.1 dstport 4789
$ ip link add name vxlan43 type vxlan id 43 dev eth0 group 239.0.0.1
dstport 4789
$ ip -details -json link show
[{
"ifindex": 17,
"ifname": "vxlan42",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1450,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "b2:92:0e:1a:c6:42",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vxlan",
"info_data": {
"id": 42,
"remote": "203.0.113.6",
"local": "192.0.2.1",
"link": "eth0",
"port_range": {
"low": 0,
"high": 0
},
"port": 4789,
"learning": true,
"ttl": 0,
"ageing": 300,
"udp_csum": false,
"udp_zero_csum6_tx": false,
"udp_zero_csum6_rx": false
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 18,
"ifname": "vxlan43",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1450,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "c6:51:4d:7f:f9:2f",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vxlan",
"info_data": {
"id": 43,
"group": "239.0.0.1",
"link": "eth0",
"port_range": {
"low": 0,
"high": 0
},
"port": 4789,
"learning": true,
"ttl": 0,
"ageing": 300,
"udp_csum": false,
"udp_zero_csum6_tx": false,
"udp_zero_csum6_rx": false
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_vxlan.c | 161 +++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 112 insertions(+), 49 deletions(-)
diff --git a/ip/iplink_vxlan.c b/ip/iplink_vxlan.c
index 2bd619d4..a0530dda 100644
--- a/ip/iplink_vxlan.c
+++ b/ip/iplink_vxlan.c
@@ -406,18 +406,22 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return;
vni = rta_getattr_u32(tb[IFLA_VXLAN_ID]);
- fprintf(f, "id %u ", vni);
+ print_uint(PRINT_ANY, "id", "id %u ", vni);
if (tb[IFLA_VXLAN_GROUP]) {
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_GROUP]);
if (addr) {
if (IN_MULTICAST(ntohl(addr)))
- fprintf(f, "group %s ",
- format_host(AF_INET, 4, &addr));
+ print_string(PRINT_ANY,
+ "group",
+ "group %s ",
+ format_host(AF_INET, 4, &addr));
else
- fprintf(f, "remote %s ",
- format_host(AF_INET, 4, &addr));
+ print_string(PRINT_ANY,
+ "remote",
+ "remote %s ",
+ format_host(AF_INET, 4, &addr));
}
} else if (tb[IFLA_VXLAN_GROUP6]) {
struct in6_addr addr;
@@ -425,11 +429,19 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_GROUP6]), sizeof(struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&addr)) {
if (IN6_IS_ADDR_MULTICAST(&addr))
- fprintf(f, "group %s ",
- format_host(AF_INET6, sizeof(struct in6_addr), &addr));
+ print_string(PRINT_ANY,
+ "group6",
+ "group %s ",
+ format_host(AF_INET6,
+ sizeof(struct in6_addr),
+ &addr));
else
- fprintf(f, "remote %s ",
- format_host(AF_INET6, sizeof(struct in6_addr), &addr));
+ print_string(PRINT_ANY,
+ "remote6",
+ "remote %s ",
+ format_host(AF_INET6,
+ sizeof(struct in6_addr),
+ &addr));
}
}
@@ -437,15 +449,21 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
__be32 addr = rta_getattr_u32(tb[IFLA_VXLAN_LOCAL]);
if (addr)
- fprintf(f, "local %s ",
- format_host(AF_INET, 4, &addr));
+ print_string(PRINT_ANY,
+ "local",
+ "local %s ",
+ format_host(AF_INET, 4, &addr));
} else if (tb[IFLA_VXLAN_LOCAL6]) {
struct in6_addr addr;
memcpy(&addr, RTA_DATA(tb[IFLA_VXLAN_LOCAL6]), sizeof(struct in6_addr));
if (!IN6_IS_ADDR_UNSPECIFIED(&addr))
- fprintf(f, "local %s ",
- format_host(AF_INET6, sizeof(struct in6_addr), &addr));
+ print_string(PRINT_ANY,
+ "local6",
+ "local %s ",
+ format_host(AF_INET6,
+ sizeof(struct in6_addr),
+ &addr));
}
if (tb[IFLA_VXLAN_LINK] &&
@@ -453,110 +471,155 @@ static void vxlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
if (tb[IFLA_VXLAN_PORT_RANGE]) {
const struct ifla_vxlan_port_range *r
= RTA_DATA(tb[IFLA_VXLAN_PORT_RANGE]);
- fprintf(f, "srcport %u %u ", ntohs(r->low), ntohs(r->high));
+ if (is_json_context()) {
+ open_json_object("port_range");
+ print_uint(PRINT_JSON, "low", NULL, ntohs(r->low));
+ print_uint(PRINT_JSON, "high", NULL, ntohs(r->high));
+ close_json_object();
+ } else {
+ fprintf(f, "srcport %u %u ",
+ ntohs(r->low), ntohs(r->high));
+ }
}
if (tb[IFLA_VXLAN_PORT])
- fprintf(f, "dstport %u ",
- rta_getattr_be16(tb[IFLA_VXLAN_PORT]));
+ print_uint(PRINT_ANY,
+ "port",
+ "dstport %u ",
+ rta_getattr_be16(tb[IFLA_VXLAN_PORT]));
- if (tb[IFLA_VXLAN_LEARNING] &&
- !rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]))
- fputs("nolearning ", f);
+ if (tb[IFLA_VXLAN_LEARNING]) {
+ __u8 learning = rta_getattr_u8(tb[IFLA_VXLAN_LEARNING]);
+
+ print_bool(PRINT_JSON, "learning", NULL, learning);
+ if (!learning)
+ print_bool(PRINT_FP, NULL, "nolearning ", true);
+ }
if (tb[IFLA_VXLAN_PROXY] && rta_getattr_u8(tb[IFLA_VXLAN_PROXY]))
- fputs("proxy ", f);
+ print_bool(PRINT_ANY, "proxy", "proxy ", true);
if (tb[IFLA_VXLAN_RSC] && rta_getattr_u8(tb[IFLA_VXLAN_RSC]))
- fputs("rsc ", f);
+ print_bool(PRINT_ANY, "rsc", "rsc ", true);
if (tb[IFLA_VXLAN_L2MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L2MISS]))
- fputs("l2miss ", f);
+ print_bool(PRINT_ANY, "l2miss", "l2miss ", true);
if (tb[IFLA_VXLAN_L3MISS] && rta_getattr_u8(tb[IFLA_VXLAN_L3MISS]))
- fputs("l3miss ", f);
+ print_bool(PRINT_ANY, "l3miss", "l3miss ", true);
if (tb[IFLA_VXLAN_TOS] &&
(tos = rta_getattr_u8(tb[IFLA_VXLAN_TOS]))) {
- if (tos == 1)
- fprintf(f, "tos inherit ");
- else
- fprintf(f, "tos %#x ", tos);
+ if (is_json_context()) {
+ print_0xhex(PRINT_JSON, "tos", "%#x", tos);
+ } else {
+ if (tos == 1)
+ fprintf(f, "tos %s ", "inherit");
+ else
+ fprintf(f, "tos %#x ", tos);
+ }
}
if (tb[IFLA_VXLAN_TTL]) {
__u8 ttl = rta_getattr_u8(tb[IFLA_VXLAN_TTL]);
if (ttl)
- fprintf(f, "ttl %d ", ttl);
+ print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
+ else
+ print_int(PRINT_JSON, "ttl", NULL, ttl);
}
if (tb[IFLA_VXLAN_LABEL]) {
__u32 label = rta_getattr_u32(tb[IFLA_VXLAN_LABEL]);
if (label)
- fprintf(f, "flowlabel %#x ", ntohl(label));
+ print_0xhex(PRINT_ANY,
+ "label",
+ "flowlabel %#x ",
+ ntohl(label));
}
if (tb[IFLA_VXLAN_AGEING]) {
__u32 age = rta_getattr_u32(tb[IFLA_VXLAN_AGEING]);
if (age == 0)
- fprintf(f, "ageing none ");
+ print_uint(PRINT_ANY, "ageing", "ageing none ", 0);
else
- fprintf(f, "ageing %u ", age);
+ print_uint(PRINT_ANY, "ageing", "ageing %u ", age);
}
if (tb[IFLA_VXLAN_LIMIT] &&
((maxaddr = rta_getattr_u32(tb[IFLA_VXLAN_LIMIT])) != 0))
- fprintf(f, "maxaddr %u ", maxaddr);
+ print_uint(PRINT_ANY, "limit", "maxaddr %u ", maxaddr);
if (tb[IFLA_VXLAN_UDP_CSUM]) {
- if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]))
- fputs("no", f);
- fputs("udpcsum ", f);
+ __u8 udp_csum = rta_getattr_u8(tb[IFLA_VXLAN_UDP_CSUM]);
+
+ if (is_json_context()) {
+ print_bool(PRINT_ANY, "udp_csum", NULL, udp_csum);
+ } else {
+ if (!udp_csum)
+ fputs("no", f);
+ fputs("udpcsum ", f);
+ }
}
if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]) {
- if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]))
- fputs("no", f);
- fputs("udp6zerocsumtx ", f);
+ __u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_TX]);
+
+ if (is_json_context()) {
+ print_bool(PRINT_ANY,
+ "udp_zero_csum6_tx", NULL, csum6);
+ } else {
+ if (!csum6)
+ fputs("no", f);
+ fputs("udp6zerocsumtx ", f);
+ }
}
if (tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]) {
- if (!rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]))
- fputs("no", f);
- fputs("udp6zerocsumrx ", f);
+ __u8 csum6 = rta_getattr_u8(tb[IFLA_VXLAN_UDP_ZERO_CSUM6_RX]);
+
+ if (is_json_context()) {
+ print_bool(PRINT_ANY,
+ "udp_zero_csum6_rx",
+ NULL,
+ csum6);
+ } else {
+ if (!csum6)
+ fputs("no", f);
+ fputs("udp6zerocsumrx ", f);
+ }
}
if (tb[IFLA_VXLAN_REMCSUM_TX] &&
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_TX]))
- fputs("remcsumtx ", f);
+ print_bool(PRINT_ANY, "remcsum_tx", "remcsumtx ", true);
if (tb[IFLA_VXLAN_REMCSUM_RX] &&
rta_getattr_u8(tb[IFLA_VXLAN_REMCSUM_RX]))
- fputs("remcsumrx ", f);
+ print_bool(PRINT_ANY, "remcsum_rx", "remcsumrx ", true);
if (tb[IFLA_VXLAN_COLLECT_METADATA] &&
rta_getattr_u8(tb[IFLA_VXLAN_COLLECT_METADATA]))
- fputs("external ", f);
+ print_bool(PRINT_ANY, "collect_metadata", "external ", true);
if (tb[IFLA_VXLAN_GBP])
- fputs("gbp ", f);
+ print_bool(PRINT_ANY, "gbp", "gbp ", true);
if (tb[IFLA_VXLAN_GPE])
- fputs("gpe ", f);
+ print_bool(PRINT_ANY, "gpe", "gpe ", true);
}
static void vxlan_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_explain(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 18/27] ip: iplink_xdp.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"attached": {
"type": "uint",
"attr": "IFLA_XDP_ATTACHED"
},
"prog_id": {
"type": "uint",
"attr": "IFLA_XDP_PROG_ID"
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_xdp.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/ip/iplink_xdp.c b/ip/iplink_xdp.c
index 9ae9ee5d..3a61076e 100644
--- a/ip/iplink_xdp.c
+++ b/ip/iplink_xdp.c
@@ -16,6 +16,7 @@
#include "xdp.h"
#include "bpf_util.h"
+#include "ip_common.h"
extern int force;
@@ -92,20 +93,24 @@ void xdp_dump(FILE *fp, struct rtattr *xdp)
return;
mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]);
- if (mode == XDP_ATTACHED_NONE)
- return;
- else if (mode == XDP_ATTACHED_DRV)
- fprintf(fp, "xdp");
- else if (mode == XDP_ATTACHED_SKB)
- fprintf(fp, "xdpgeneric");
- else if (mode == XDP_ATTACHED_HW)
- fprintf(fp, "xdpoffload");
- else
- fprintf(fp, "xdp[%u]", mode);
+ if (is_json_context()) {
+ print_uint(PRINT_JSON, "attached", NULL, mode);
+ } else {
+ if (mode == XDP_ATTACHED_NONE)
+ return;
+ else if (mode == XDP_ATTACHED_DRV)
+ fprintf(fp, "xdp");
+ else if (mode == XDP_ATTACHED_SKB)
+ fprintf(fp, "xdpgeneric");
+ else if (mode == XDP_ATTACHED_HW)
+ fprintf(fp, "xdpoffload");
+ else
+ fprintf(fp, "xdp[%u]", mode);
+ }
if (tb[IFLA_XDP_PROG_ID])
- fprintf(fp, "/id:%u",
- rta_getattr_u32(tb[IFLA_XDP_PROG_ID]));
+ print_uint(PRINT_ANY, "prog_id", "/id:%u",
+ rta_getattr_u32(tb[IFLA_XDP_PROG_ID]));
- fprintf(fp, " ");
+ print_string(PRINT_FP, NULL, "%c", " ");
}
--
2.13.3
^ permalink raw reply related
* [PATCH 19/27] ip: ipmacsec.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"sci": {
"type": "string",
"attr": "IFLA_MACSEC_SCI"
},
"protect": {
"type": "string",
"attr": "IFLA_MACSEC_PROTECT"
},
"cipher_suite": {
"type": "string",
"attr": "IFLA_MACSEC_CIPHER_SUITE"
},
"icv_len": {
"type": "uint",
"attr": "IFLA_MACSEC_ICV_LEN"
},
"encoding_sa": {
"type": "uint",
"attr": "IFLA_MACSEC_ENCODING_SA"
},
"validation": {
"type": "string",
"attr": "IFLA_MACSEC_VALIDATION"
},
"encrypt": {
"type": "string",
"attr": "IFLA_MACSEC_ENCRYPT"
},
"inc_sci": {
"type": "string",
"attr": "IFLA_MACSEC_INC_SCI"
},
"es": {
"type": "string",
"attr": "IFLA_MACSEC_ES"
},
"scb": {
"type": "string",
"attr": "IFLA_MACSEC_SCB"
},
"replay_protect": {
"type": "string",
"attr": "IFLA_MACSEC_REPLAY_PROTECT"
},
"window": {
"type": "int",
"attr": ""
}
}
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/ipmacsec.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 66 insertions(+), 18 deletions(-)
diff --git a/ip/ipmacsec.c b/ip/ipmacsec.c
index aa89a00f..ecc371a5 100644
--- a/ip/ipmacsec.c
+++ b/ip/ipmacsec.c
@@ -561,9 +561,14 @@ static int validate_secy_dump(struct rtattr **attrs)
static void print_flag(FILE *f, struct rtattr *attrs[], const char *desc,
int field)
{
- if (attrs[field])
- fprintf(f, "%s %s ", desc,
- values_on_off[!!rta_getattr_u8(attrs[field])]);
+ if (attrs[field]) {
+ const char *v = values_on_off[!!rta_getattr_u8(attrs[field])];
+
+ if (is_json_context())
+ print_string(PRINT_JSON, desc, NULL, v);
+ else
+ fprintf(f, "%s %s ", desc, v);
+ }
}
#define DEFAULT_CIPHER_NAME "GCM-AES-128"
@@ -1017,8 +1022,16 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return;
if (tb[IFLA_MACSEC_SCI]) {
- fprintf(f, "sci %016llx ",
- ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "%016llx",
+ ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
+ print_string(PRINT_JSON, "sci", NULL, b1);
+ } else {
+ fprintf(f, "sci %016llx ",
+ ntohll(rta_getattr_u64(tb[IFLA_MACSEC_SCI])));
+ }
}
print_flag(f, tb, "protect", IFLA_MACSEC_PROTECT);
@@ -1026,35 +1039,70 @@ static void macsec_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (tb[IFLA_MACSEC_CIPHER_SUITE]) {
__u64 csid = rta_getattr_u64(tb[IFLA_MACSEC_CIPHER_SUITE]);
- fprintf(f, "cipher %s ", cs_id_to_name(csid));
+ print_string(PRINT_ANY,
+ "cipher_suite",
+ "cipher %s ",
+ cs_id_to_name(csid));
}
if (tb[IFLA_MACSEC_ICV_LEN]) {
- fprintf(f, "icvlen %hhu ",
- rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
+ if (is_json_context()) {
+ char b2[4];
+
+ snprintf(b2, sizeof(b2), "%hhu",
+ rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
+ print_uint(PRINT_JSON, "icv_len", NULL, atoi(b2));
+ } else {
+ fprintf(f, "icvlen %hhu ",
+ rta_getattr_u8(tb[IFLA_MACSEC_ICV_LEN]));
+ }
}
if (tb[IFLA_MACSEC_ENCODING_SA]) {
- fprintf(f, "encodingsa %hhu ",
- rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
+ if (is_json_context()) {
+ char b2[4];
+
+ snprintf(b2, sizeof(b2), "%hhu",
+ rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
+ print_uint(PRINT_JSON, "encoding_sa", NULL, atoi(b2));
+ } else {
+ fprintf(f, "encodingsa %hhu ",
+ rta_getattr_u8(tb[IFLA_MACSEC_ENCODING_SA]));
+ }
}
if (tb[IFLA_MACSEC_VALIDATION]) {
__u8 val = rta_getattr_u8(tb[IFLA_MACSEC_VALIDATION]);
- fprintf(f, "validate %s ", VALIDATE_STR[val]);
+ print_string(PRINT_ANY,
+ "validation",
+ "validate %s ",
+ VALIDATE_STR[val]);
+ }
+
+ const char *inc_sci, *es, *replay;
+
+ if (is_json_context()) {
+ inc_sci = "inc_sci";
+ replay = "replay_protect";
+ es = "es";
+ } else {
+ inc_sci = "send_sci";
+ es = "end_station";
+ replay = "replay";
}
print_flag(f, tb, "encrypt", IFLA_MACSEC_ENCRYPT);
- print_flag(f, tb, "send_sci", IFLA_MACSEC_INC_SCI);
- print_flag(f, tb, "end_station", IFLA_MACSEC_ES);
+ print_flag(f, tb, inc_sci, IFLA_MACSEC_INC_SCI);
+ print_flag(f, tb, es, IFLA_MACSEC_ES);
print_flag(f, tb, "scb", IFLA_MACSEC_SCB);
+ print_flag(f, tb, replay, IFLA_MACSEC_REPLAY_PROTECT);
- print_flag(f, tb, "replay", IFLA_MACSEC_REPLAY_PROTECT);
- if (tb[IFLA_MACSEC_WINDOW]) {
- fprintf(f, "window %d ",
- rta_getattr_u32(tb[IFLA_MACSEC_WINDOW]));
- }
+ if (tb[IFLA_MACSEC_WINDOW])
+ print_int(PRINT_ANY,
+ "window",
+ "window %d ",
+ rta_getattr_u32(tb[IFLA_MACSEC_WINDOW]));
}
static bool check_txsc_flags(bool es, bool scb, bool sci)
--
2.13.3
^ permalink raw reply related
* [PATCH 20/27] ip: link_gre.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"external": {
"type": "bool",
"comment": "!tb[IFLA_GRE_COLLECT_METADATA]"
},
"remote": {
"type": "string",
"attr": "IFLA_GRE_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_GRE_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_GRE_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ttl": {
"type": "int",
"attr": "IFLA_GRE_TTL"
},
"tos": {
"type": "string",
"attr": "IFLA_GRE_TOS"
},
"pmtudisc": {
"type": "bool",
"attr": "IFLA_GRE_PMTUDISC"
},
"ikey": {
"type": "string",
"attr": "IFLA_GRE_IKEY"
},
"okey": {
"type": "string",
"attr": "IFLA_GRE_OKEY"
},
"iseq": {
"type": "bool",
"attr": "IFLA_GRE_IFLAGS & GRE_SEQ"
},
"oseq": {
"type": "bool",
"attr": "IFLA_GRE_OFLAGS & GRE_SEQ"
},
"icsum": {
"type": "bool",
"attr": "IFLA_GRE_IFLAGS & GRE_CSUM"
},
"ocsum": {
"type": "bool",
"attr": "IFLA_GRE_OFLAGS & GRE_CSUM"
},
"ignore_df": {
"type": "bool",
"attr": "IFLA_GRE_IGNORE_DF"
},
"encap": {
"type": "dict",
"attr": "IFLA_GRE_ENCAP_TYPE != TUNNEL_ENCAP_NONE",
"dict": {
"type": {
"type": "string",
"attr": "IFLA_GRE_ENCAP_TYPE"
},
"sport": {
"type": "uint",
"attr": "IFLA_GRE_ENCAP_SPORT"
},
"dport": {
"type": "uint",
"attr": "IFLA_GRE_ENCAP_DPORT"
},
"csum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM"
},
"csum6": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM6"
},
"remcsum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_REMCSUM"
}
}
}
}
$ ip link show
$ ip tunnel add tun42 mode gre local 192.0.2.42 remote 203.0.113.42 key 42
$ ip link show
10: gre0@NONE: <NOARP> mtu 1476 qdisc noop state DOWN mode DEFAULT group
default
link/gre 0.0.0.0 brd 0.0.0.0
11: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN
mode DEFAULT group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
12: tun42@NONE: <POINTOPOINT,NOARP> mtu 1472 qdisc noop state DOWN mode
DEFAULT group default
link/gre 192.0.2.42 peer 203.0.113.42
$ ip -details -json link show
[{
"ifindex": 10,
"ifname": "gre0",
"link": null,
"flags": ["NOARP"],
"mtu": 1476,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre",
"address": "0.0.0.0",
"broadcast": "0.0.0.0",
"promiscuity": 0,
"linkinfo": {
"info_kind": "gre",
"info_data": {
"remote": "any",
"local": "any",
"ttl": 0,
"pmtudisc": false
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "gretap0",
"link": null,
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1462,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"txqlen": 1000,
"link_type": "ether",
"address": "00:00:00:00:00:00",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "gretap",
"info_data": {
"remote": "any",
"local": "any",
"ttl": 0,
"pmtudisc": false
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 12,
"ifname": "tun42",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1472,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre",
"address": "192.0.2.42",
"link_pointtopoint": true,
"broadcast": "203.0.113.42",
"promiscuity": 0,
"linkinfo": {
"info_kind": "gre",
"info_data": {
"remote": "203.0.113.42",
"local": "192.0.2.42",
"ttl": 0,
"pmtudisc": true,
"ikey": "0.0.0.42",
"okey": "0.0.0.42"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
$
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_gre.c | 147 ++++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 98 insertions(+), 49 deletions(-)
diff --git a/ip/link_gre.c b/ip/link_gre.c
index c2ec5f26..3c9f8194 100644
--- a/ip/link_gre.c
+++ b/ip/link_gre.c
@@ -389,7 +389,7 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
remote = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "remote %s ", remote);
+ print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_GRE_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]);
@@ -398,36 +398,52 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
local = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "local %s ", local);
+ print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
- if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
- fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
- else
- fprintf(f, "ttl inherit ");
+ if (tb[IFLA_GRE_TTL]) {
+ __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]);
+
+ if (ttl)
+ print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
+ else
+ print_int(PRINT_JSON, "ttl", NULL, ttl);
+ } else {
+ print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
+ }
if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) {
int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]);
- fputs("tos ", f);
- if (tos == 1)
- fputs("inherit ", f);
- else
- fprintf(f, "0x%x ", tos);
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%x", tos);
+ print_string(PRINT_JSON, "tos", NULL, b1);
+ } else {
+ fputs("tos ", f);
+ if (tos == 1)
+ fputs("inherit ", f);
+ else
+ fprintf(f, "0x%x ", tos);
+ }
}
- if (tb[IFLA_GRE_PMTUDISC] &&
- !rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
- fputs("nopmtudisc ", f);
+ if (tb[IFLA_GRE_PMTUDISC]) {
+ if (!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
+ print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
+ else
+ print_bool(PRINT_JSON, "pmtudisc", NULL, true);
+ }
if (tb[IFLA_GRE_IFLAGS])
iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
@@ -437,26 +453,31 @@ static void gre_print_direct_opt(FILE *f, struct rtattr *tb[])
if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
- fprintf(f, "ikey %s ", s2);
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
- fprintf(f, "okey %s ", s2);
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
if (iflags & GRE_SEQ)
- fputs("iseq ", f);
+ print_bool(PRINT_ANY, "iseq", "iseq ", true);
if (oflags & GRE_SEQ)
- fputs("oseq ", f);
+ print_bool(PRINT_ANY, "oseq", "oseq ", true);
if (iflags & GRE_CSUM)
- fputs("icsum ", f);
+ print_bool(PRINT_ANY, "icsum", "icsum ", true);
if (oflags & GRE_CSUM)
- fputs("ocsum ", f);
+ print_bool(PRINT_ANY, "ocsum", "ocsum ", true);
+
+ if (tb[IFLA_GRE_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]);
+
+ if (fwmark) {
+ snprintf(s2, sizeof(s2), "0x%x", fwmark);
- if (tb[IFLA_GRE_FWMARK] && rta_getattr_u32(tb[IFLA_GRE_FWMARK])) {
- fprintf(f, "fwmark 0x%x ",
- rta_getattr_u32(tb[IFLA_GRE_FWMARK]));
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ }
}
}
@@ -468,10 +489,10 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if (!tb[IFLA_GRE_COLLECT_METADATA])
gre_print_direct_opt(f, tb);
else
- fputs("external ", f);
+ print_bool(PRINT_ANY, "external", "external ", true);
if (tb[IFLA_GRE_IGNORE_DF] && rta_getattr_u8(tb[IFLA_GRE_IGNORE_DF]))
- fputs("ignore-df ", f);
+ print_bool(PRINT_ANY, "ignore_df", "ignore-df ", true);
if (tb[IFLA_GRE_ENCAP_TYPE] &&
rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
@@ -480,45 +501,73 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
__u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]);
__u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]);
- fputs("encap ", f);
+
+ open_json_object("encap");
+ print_string(PRINT_FP, NULL, "encap ", NULL);
+
switch (type) {
case TUNNEL_ENCAP_FOU:
- fputs("fou ", f);
+ print_string(PRINT_ANY, "type", "%s ", "fou");
break;
case TUNNEL_ENCAP_GUE:
- fputs("gue ", f);
+ print_string(PRINT_ANY, "type", "%s ", "gue");
break;
default:
- fputs("unknown ", f);
+ print_null(PRINT_ANY, "type", "%s ", "unknown");
break;
}
- if (sport == 0)
- fputs("encap-sport auto ", f);
- else
- fprintf(f, "encap-sport %u", ntohs(sport));
+ if (is_json_context()) {
+ print_uint(PRINT_JSON,
+ "sport",
+ NULL,
+ sport ? ntohs(sport) : 0);
+ print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
+
+ print_bool(PRINT_JSON,
+ "csum",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM);
+
+ print_bool(PRINT_JSON,
+ "csum6",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM6);
+
+ print_bool(PRINT_JSON,
+ "remcsum",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_REMCSUM);
+
+ close_json_object();
+ } else {
+ if (sport == 0)
+ fputs("encap-sport auto ", f);
+ else
+ fprintf(f, "encap-sport %u", ntohs(sport));
- fprintf(f, "encap-dport %u ", ntohs(dport));
+ fprintf(f, "encap-dport %u ", ntohs(dport));
- if (flags & TUNNEL_ENCAP_FLAG_CSUM)
- fputs("encap-csum ", f);
- else
- fputs("noencap-csum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM)
+ fputs("encap-csum ", f);
+ else
+ fputs("noencap-csum ", f);
- if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
- fputs("encap-csum6 ", f);
- else
- fputs("noencap-csum6 ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
+ fputs("encap-csum6 ", f);
+ else
+ fputs("noencap-csum6 ", f);
- if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
- fputs("encap-remcsum ", f);
- else
- fputs("noencap-remcsum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
+ fputs("encap-remcsum ", f);
+ else
+ fputs("noencap-remcsum ", f);
+ }
}
}
static void gre_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_usage(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 21/27] ip: link_gre6.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"remote": {
"type": "string",
"attr": "IFLA_GRE_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_GRE_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_GRE_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ttl": {
"type": "int",
"attr": "IFLA_GRE_TTL"
},
"ip6_tnl_f_ign_encap_limit": {
"type": "bool",
"attr": "IP6_TNL_F_IGN_ENCAP_LIMIT"
},
"encap_limit": {
"type": "int",
"attr": "IFLA_GRE_ENCAP_LIMIT"
},
"ip6_tnl_f_use_orig_flowlabel": {
"type": "bool",
"attr": "IP6_TNL_F_USE_ORIG_FLOWLABEL"
},
"flowlabel": {
"type": "string",
"attr": "IP6_FLOWINFO_FLOWLABEL"
},
"ip6_tnl_f_rcv_dscp_copy": {
"type": "bool",
"attr": "IP6_TNL_F_RCV_DSCP_COPY"
},
"ikey": {
"type": "string",
"attr": "IFLA_GRE_IKEY"
},
"okey": {
"type": "string",
"attr": "IFLA_GRE_OKEY"
},
"iseq": {
"type": "bool",
"attr": "IFLA_GRE_IFLAGS & GRE_SEQ"
},
"oseq": {
"type": "bool",
"attr": "IFLA_GRE_OFLAGS & GRE_SEQ"
},
"icsum": {
"type": "bool",
"attr": "IFLA_GRE_IFLAGS & GRE_CSUM"
},
"ocsum": {
"type": "bool",
"attr": "IFLA_GRE_OFLAGS & GRE_CSUM"
},
"encap": {
"type": "dict",
"attr": "IFLA_GRE_ENCAP_TYPE != TUNNEL_ENCAP_NONE",
"dict": {
"type": {
"type": "string",
"attr": "IFLA_GRE_ENCAP_TYPE"
},
"sport": {
"type": "uint",
"attr": "IFLA_GRE_ENCAP_SPORT"
},
"dport": {
"type": "uint",
"attr": "IFLA_GRE_ENCAP_DPORT"
},
"csum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM"
},
"csum6": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM6"
},
"remcsum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_REMCSUM"
}
}
}
}
$ ip link show
$ ip -6 tunnel add name tun6 mode ip6gre local 2001:db8:1::1/64 remote
2001:0db8:85a3:0000:0000:8a2e:0370:7334
$ ip link show
10: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT
group default
link/tunnel6 :: brd ::
11: ip6gre0@NONE: <NOARP> mtu 1448 qdisc noop state DOWN mode DEFAULT
group default
link/gre6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd
00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
12: tun6@NONE: <POINTOPOINT,NOARP> mtu 1448 qdisc noop state DOWN mode
DEFAULT group default
link/gre6 20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01 peer
20:01:0d:b8:85:a3:00:00:00:00:8a:2e:03:70:73:34
➜ ~ ./ip -details -json link show
[{
"ifindex": 10,
"ifname": "ip6tnl0",
"link": null,
"flags": ["NOARP"],
"mtu": 1452,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "tunnel6",
"address": "::",
"broadcast": "::",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6tnl",
"info_data": {
"proto": "ip6ip6",
"remote": "::",
"local": "::",
"encap_limit": 0,
"ttl": 0,
"flowinfo_tclass": "0x00",
"flowlabel": "0x00000",
"flowinfo": "0x00000000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "ip6gre0",
"link": null,
"flags": ["NOARP"],
"mtu": 1448,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre6",
"address": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"broadcast": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6gre",
"info_data": {
"remote": "any",
"local": "any",
"ttl": 0,
"encap_limit": 0,
"flowlabel": "0x00000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 12,
"ifname": "tun6",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1448,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre6",
"address": "20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01",
"link_pointtopoint": true,
"broadcast": "20:01:0d:b8:85:a3:00:00:00:00:8a:2e:03:70:73:34",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6gre",
"info_data": {
"remote": "2001:db8:85a3::8a2e:370:7334",
"local": "2001:db8:1::1",
"ttl": 64,
"encap_limit": 4,
"flowlabel": "0x00000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
$
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_gre6.c | 142 ++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 99 insertions(+), 43 deletions(-)
diff --git a/ip/link_gre6.c b/ip/link_gre6.c
index 4d3d4b54..957853d6 100644
--- a/ip/link_gre6.c
+++ b/ip/link_gre6.c
@@ -423,7 +423,7 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
remote = format_host(AF_INET6, sizeof(addr), &addr);
}
- fprintf(f, "remote %s ", remote);
+ print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_GRE_LOCAL]) {
struct in6_addr addr;
@@ -434,36 +434,65 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
local = format_host(AF_INET6, sizeof(addr), &addr);
}
- fprintf(f, "local %s ", local);
+ print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
- if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
- fprintf(f, "hoplimit %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
+ if (tb[IFLA_GRE_TTL]) {
+ __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]);
+
+ if (ttl)
+ print_int(PRINT_ANY, "ttl", "hoplimit %d ", ttl);
+ else
+ print_int(PRINT_JSON, "ttl", NULL, ttl);
+ }
if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT)
- fprintf(f, "encaplimit none ");
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_ign_encap_limit",
+ "encaplimit none ",
+ true);
else if (tb[IFLA_GRE_ENCAP_LIMIT]) {
int encap_limit = rta_getattr_u8(tb[IFLA_GRE_ENCAP_LIMIT]);
- fprintf(f, "encaplimit %d ", encap_limit);
+ print_int(PRINT_ANY,
+ "encap_limit",
+ "encaplimit %d ",
+ encap_limit);
}
- if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
- fprintf(f, "flowlabel inherit ");
- else
- fprintf(f, "flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) {
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_use_orig_flowlabel",
+ "flowlabel inherit ",
+ true);
+ } else {
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%05x",
+ ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ print_string(PRINT_JSON, "flowlabel", NULL, b1);
+
+ } else {
+ fprintf(f, "flowlabel 0x%05x ",
+ ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ }
+ }
if (flags & IP6_TNL_F_RCV_DSCP_COPY)
- fprintf(f, "dscp inherit ");
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_rcv_dscp_copy",
+ "dscp inherit ",
+ true);
if (tb[IFLA_GRE_IFLAGS])
iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
@@ -473,27 +502,37 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
- fprintf(f, "ikey %s ", s2);
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
- fprintf(f, "okey %s ", s2);
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
if (iflags & GRE_SEQ)
- fputs("iseq ", f);
+ print_bool(PRINT_ANY, "iseq", "iseq ", true);
if (oflags & GRE_SEQ)
- fputs("oseq ", f);
+ print_bool(PRINT_ANY, "oseq", "oseq ", true);
if (iflags & GRE_CSUM)
- fputs("icsum ", f);
+ print_bool(PRINT_ANY, "icsum", "icsum ", true);
if (oflags & GRE_CSUM)
- fputs("ocsum ", f);
+ print_bool(PRINT_ANY, "ocsum", "ocsum ", true);
if (flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fprintf(f, "fwmark inherit ");
- else if (tb[IFLA_GRE_FWMARK] && rta_getattr_u32(tb[IFLA_GRE_FWMARK]))
- fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_GRE_FWMARK]));
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_use_orig_fwmark",
+ "fwmark inherit ",
+ true);
+ else if (tb[IFLA_GRE_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]);
+
+ if (fwmark) {
+ snprintf(s2, sizeof(s2), "0x%x", fwmark);
+
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ }
+ }
if (tb[IFLA_GRE_ENCAP_TYPE] &&
rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
@@ -502,40 +541,57 @@ static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
__u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]);
__u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]);
- fputs("encap ", f);
+ open_json_object("encap");
+
+ print_string(PRINT_FP, NULL, "encap ", NULL);
switch (type) {
case TUNNEL_ENCAP_FOU:
- fputs("fou ", f);
+ print_string(PRINT_ANY, "type", "%s ", "fou");
break;
case TUNNEL_ENCAP_GUE:
- fputs("gue ", f);
+ print_string(PRINT_ANY, "type", "%s ", "gue");
break;
default:
- fputs("unknown ", f);
+ print_null(PRINT_ANY, "type", "unknown ", NULL);
break;
}
- if (sport == 0)
- fputs("encap-sport auto ", f);
- else
- fprintf(f, "encap-sport %u", ntohs(sport));
+ if (is_json_context()) {
+ print_uint(PRINT_JSON,
+ "sport",
+ NULL,
+ sport ? ntohs(sport) : 0);
+ print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
+ print_bool(PRINT_JSON, "csum", NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM);
+ print_bool(PRINT_JSON, "csum6", NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM6);
+ print_bool(PRINT_JSON, "remcsum", NULL,
+ flags & TUNNEL_ENCAP_FLAG_REMCSUM);
+ close_json_object();
+ } else {
+ if (sport == 0)
+ fputs("encap-sport auto ", f);
+ else
+ fprintf(f, "encap-sport %u", ntohs(sport));
- fprintf(f, "encap-dport %u ", ntohs(dport));
+ fprintf(f, "encap-dport %u ", ntohs(dport));
- if (flags & TUNNEL_ENCAP_FLAG_CSUM)
- fputs("encap-csum ", f);
- else
- fputs("noencap-csum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM)
+ fputs("encap-csum ", f);
+ else
+ fputs("noencap-csum ", f);
- if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
- fputs("encap-csum6 ", f);
- else
- fputs("noencap-csum6 ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
+ fputs("encap-csum6 ", f);
+ else
+ fputs("noencap-csum6 ", f);
- if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
- fputs("encap-remcsum ", f);
- else
- fputs("noencap-remcsum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
+ fputs("encap-remcsum ", f);
+ else
+ fputs("noencap-remcsum ", f);
+ }
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH 22/27] ip: link_ip6tnl.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"proto": {
"type": "string",
"attr": "IFLA_IPTUN_PROTO"
},
"remote": {
"type": "string",
"attr": "IFLA_IPTUN_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_IPTUN_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_IPTUN_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ip6_tnl_f_ign_encap_limit": {
"type": "bool",
"attr": "IP6_TNL_F_IGN_ENCAP_LIMIT"
},
"encap_limit": {
"type": "uint",
"attr": "IFLA_IPTUN_ENCAP_LIMIT"
},
"ttl": {
"type": "uint",
"attr": "IFLA_IPTUN_TTL"
},
"ip6_tnl_f_use_orig_tclass": {
"type": "",
"attr": "IP6_TNL_F_USE_ORIG_TCLASS"
},
"flowinfo_tclass": {
"type": "string",
"attr": "IP6_FLOWINFO_TCLASS"
},
"ip6_tnl_f_use_orig_flowlabel": {
"type": "bool",
"attr": "IP6_TNL_F_USE_ORIG_FLOWLABEL"
},
"flowlabel": {
"type": "string",
"attr": "IP6_FLOWINFO_FLOWLABEL"
},
"flowinfo": {
"type": "string"
},
"ip6_tnl_f_rcv_dscp_copy": {
"type": "bool",
"attr": "IP6_TNL_F_RCV_DSCP_COPY"
},
"ip6_tnl_f_mip6_dev": {
"type": "bool",
"attr": "IP6_TNL_F_MIP6_DEV"
},
"ip6_tnl_f_use_orig_fwmark": {
"type": "bool",
"attr": "IP6_TNL_F_USE_ORIG_FWMARK"
},
"encap": {
"type": "dict",
"attr": "IFLA_IPTUN_ENCAP_TYPE",
"dict": {
"type": {
"type": "string",
"attr": "IFLA_IPTUN_ENCAP_TYPE"
},
"sport": {
"type": "uint",
"attr": "IFLA_IPTUN_ENCAP_SPORT"
},
"dport": {
"type": "uint",
"attr": "IFLA_IPTUN_ENCAP_DPORT"
},
"csum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM"
},
"csum6": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM6"
},
"remcsum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_REMCSUM"
}
}
}
}
$ ip link show
$ ip -6 tunnel add name tun6 mode ip6gre local 2001:db8:1::1/64 remote
2001:0db8:85a3:0000:0000:8a2e:0370:7334
$ ip link show
10: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT group
default
link/tunnel6 :: brd ::
11: ip6gre0@NONE: <NOARP> mtu 1448 qdisc noop state DOWN mode DEFAULT group
default
link/gre6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd
00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
12: tun6@NONE: <POINTOPOINT,NOARP> mtu 1448 qdisc noop state DOWN mode
DEFAULT group default
link/gre6 20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01 peer
20:01:0d:b8:85:a3:00:00:00:00:8a:2e:03:70:73:34
➜ ~ ./ip -details -json link show
[{
"ifindex": 10,
"ifname": "ip6tnl0",
"link": null,
"flags": ["NOARP"],
"mtu": 1452,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "tunnel6",
"address": "::",
"broadcast": "::",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6tnl",
"info_data": {
"proto": "ip6ip6",
"remote": "::",
"local": "::",
"encap_limit": 0,
"ttl": 0,
"flowinfo_tclass": "0x00",
"flowlabel": "0x00000",
"flowinfo": "0x00000000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "ip6gre0",
"link": null,
"flags": ["NOARP"],
"mtu": 1448,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre6",
"address": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"broadcast": "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6gre",
"info_data": {
"remote": "any",
"local": "any",
"ttl": 0,
"encap_limit": 0,
"flowlabel": "0x00000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 12,
"ifname": "tun6",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1448,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "gre6",
"address": "20:01:0d:b8:00:01:00:00:00:00:00:00:00:00:00:01",
"link_pointtopoint": true,
"broadcast": "20:01:0d:b8:85:a3:00:00:00:00:8a:2e:03:70:73:34",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6gre",
"info_data": {
"remote": "2001:db8:85a3::8a2e:370:7334",
"local": "2001:db8:1::1",
"ttl": 64,
"encap_limit": 4,
"flowlabel": "0x00000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
$
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_ip6tnl.c | 172 +++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 122 insertions(+), 50 deletions(-)
diff --git a/ip/link_ip6tnl.c b/ip/link_ip6tnl.c
index 505fb476..a4199006 100644
--- a/ip/link_ip6tnl.c
+++ b/ip/link_ip6tnl.c
@@ -346,25 +346,29 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
if (tb[IFLA_IPTUN_PROTO]) {
switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) {
case IPPROTO_IPIP:
- fprintf(f, "ipip6 ");
+ print_string(PRINT_ANY, "proto", "%s ", "ipip6");
break;
case IPPROTO_IPV6:
- fprintf(f, "ip6ip6 ");
+ print_string(PRINT_ANY, "proto", "%s ", "ip6ip6");
break;
case 0:
- fprintf(f, "any ");
+ print_string(PRINT_ANY, "proto", "%s ", "any");
break;
}
}
if (tb[IFLA_IPTUN_REMOTE]) {
- fprintf(f, "remote %s ",
- rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_REMOTE]));
+ print_string(PRINT_ANY,
+ "remote",
+ "remote %s ",
+ rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_REMOTE]));
}
if (tb[IFLA_IPTUN_LOCAL]) {
- fprintf(f, "local %s ",
- rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL]));
+ print_string(PRINT_ANY,
+ "local",
+ "local %s ",
+ rt_addr_n2a_rta(AF_INET6, tb[IFLA_IPTUN_LOCAL]));
}
if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
@@ -372,93 +376,161 @@ static void ip6tunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
if (flags & IP6_TNL_F_IGN_ENCAP_LIMIT)
- printf("encaplimit none ");
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_ign_encap_limit",
+ "encaplimit none ",
+ true);
else if (tb[IFLA_IPTUN_ENCAP_LIMIT])
- fprintf(f, "encaplimit %u ",
- rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]));
+ print_uint(PRINT_ANY,
+ "encap_limit",
+ "encaplimit %u ",
+ rta_getattr_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]));
if (tb[IFLA_IPTUN_TTL])
- fprintf(f, "hoplimit %u ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
+ print_uint(PRINT_ANY,
+ "ttl",
+ "hoplimit %u ",
+ rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
if (flags & IP6_TNL_F_USE_ORIG_TCLASS)
- printf("tclass inherit ");
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_use_orig_tclass",
+ "tclass inherit ",
+ true);
else if (tb[IFLA_IPTUN_FLOWINFO]) {
__u32 val = ntohl(flowinfo & IP6_FLOWINFO_TCLASS);
- printf("tclass 0x%02x ", (__u8)(val >> 20));
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%02x", (__u8)(val >> 20));
+ print_string(PRINT_JSON, "flowinfo_tclass", NULL, b1);
+ } else {
+ printf("tclass 0x%02x ", (__u8)(val >> 20));
+ }
+ }
+
+ if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) {
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_use_orig_flowlabel",
+ "flowlabel inherit ",
+ true);
+ } else {
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%05x",
+ ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ print_string(PRINT_JSON, "flowlabel", NULL, b1);
+ } else {
+ printf("flowlabel 0x%05x ",
+ ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ }
}
- if (flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
- printf("flowlabel inherit ");
- else
- printf("flowlabel 0x%05x ", ntohl(flowinfo & IP6_FLOWINFO_FLOWLABEL));
+ if (is_json_context()) {
+ SPRINT_BUF(flwinfo);
- printf("(flowinfo 0x%08x) ", ntohl(flowinfo));
+ snprintf(flwinfo, sizeof(flwinfo), "0x%08x", ntohl(flowinfo));
+ print_string(PRINT_JSON, "flowinfo", NULL, flwinfo);
+ } else {
+ printf("(flowinfo 0x%08x) ", ntohl(flowinfo));
+
+ }
if (flags & IP6_TNL_F_RCV_DSCP_COPY)
- printf("dscp inherit ");
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_rcv_dscp_copy",
+ "dscp inherit ",
+ true);
if (flags & IP6_TNL_F_MIP6_DEV)
- fprintf(f, "mip6 ");
+ print_bool(PRINT_ANY, "ip6_tnl_f_mip6_dev", "mip6 ", true);
+
+ if (flags & IP6_TNL_F_USE_ORIG_FWMARK) {
+ print_bool(PRINT_ANY,
+ "ip6_tnl_f_use_orig_fwmark",
+ "fwmark inherit ",
+ true);
+ } else if (tb[IFLA_IPTUN_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
- if (flags & IP6_TNL_F_USE_ORIG_FWMARK)
- fprintf(f, "fwmark inherit ");
- else if (tb[IFLA_IPTUN_FWMARK] && rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]))
- fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]));
+ if (fwmark) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1), "0x%x", fwmark);
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", b1);
+ }
+ }
if (tb[IFLA_IPTUN_ENCAP_TYPE] &&
- rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) !=
- TUNNEL_ENCAP_NONE) {
+ rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
__u16 type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE]);
__u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]);
__u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
__u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
- fputs("encap ", f);
+ open_json_object("encap");
+ print_string(PRINT_FP, NULL, "encap ", NULL);
switch (type) {
case TUNNEL_ENCAP_FOU:
- fputs("fou ", f);
+ print_string(PRINT_ANY, "type", "%s ", "fou");
break;
case TUNNEL_ENCAP_GUE:
- fputs("gue ", f);
+ print_string(PRINT_ANY, "type", "%s ", "gue");
break;
default:
- fputs("unknown ", f);
+ print_null(PRINT_ANY, "type", "unknown ", NULL);
break;
}
- if (sport == 0)
- fputs("encap-sport auto ", f);
- else
- fprintf(f, "encap-sport %u", ntohs(sport));
+ if (is_json_context()) {
+ print_uint(PRINT_JSON,
+ "sport",
+ NULL,
+ sport ? ntohs(sport) : 0);
+ print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
+ print_bool(PRINT_JSON, "csum", NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM);
+ print_bool(PRINT_JSON, "csum6", NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM6);
+ print_bool(PRINT_JSON, "remcsum", NULL,
+ flags & TUNNEL_ENCAP_FLAG_REMCSUM);
+ close_json_object();
+ } else {
+ if (sport == 0)
+ fputs("encap-sport auto ", f);
+ else
+ fprintf(f, "encap-sport %u", ntohs(sport));
- fprintf(f, "encap-dport %u ", ntohs(dport));
+ fprintf(f, "encap-dport %u ", ntohs(dport));
- if (flags & TUNNEL_ENCAP_FLAG_CSUM)
- fputs("encap-csum ", f);
- else
- fputs("noencap-csum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM)
+ fputs("encap-csum ", f);
+ else
+ fputs("noencap-csum ", f);
- if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
- fputs("encap-csum6 ", f);
- else
- fputs("noencap-csum6 ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
+ fputs("encap-csum6 ", f);
+ else
+ fputs("noencap-csum6 ", f);
- if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
- fputs("encap-remcsum ", f);
- else
- fputs("noencap-remcsum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
+ fputs("encap-remcsum ", f);
+ else
+ fputs("noencap-remcsum ", f);
+ }
}
}
static void ip6tunnel_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_usage(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 23/27] ip: link_iptnl.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema
{
"remote": {
"type": "string",
"attr": "IFLA_IPTUN_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_IPTUN_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_IPTUN_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ttl": {
"type": "int",
"attr": "IFLA_IPTUN_TTL"
},
"tos": {
"type": "string",
"attr": "IFLA_IPTUN_TOS"
},
"pmtudisc": {
"type": "bool",
"attr": "IFLA_IPTUN_PMTUDISC"
},
"isatap": {
"type": "bool",
"attr": "SIT_ISATAP & IFLA_IPTUN_FLAGS"
},
"6rd": {
"type": "dict",
"attr": "IFLA_IPTUN_6RD_PREFIXLEN",
"dict": {
"prefix": {
"type": "string"
},
"prefixlen": {
"type": "uint",
"attr": "IFLA_IPTUN_6RD_PREFIXLEN"
},
"relay_prefix": {
"type": "string"
},
"relay_prefixlen": {
"type": "uint",
"attr": "IFLA_IPTUN_6RD_PREFIXLEN"
}
}
},
"encap": {
"type": "dict",
"attr": "IFLA_IPTUN_ENCAP_TYPE",
"dict": {
"type": {
"type": "string",
"attr": "IFLA_IPTUN_ENCAP_TYPE"
},
"sport": {
"type": "uint",
"attr": "IFLA_IPTUN_ENCAP_SPORT"
},
"dport": {
"type": "uint",
"attr": "IFLA_IPTUN_ENCAP_DPORT"
},
"csum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM"
},
"csum6": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_CSUM6"
},
"remcsum": {
"type": "bool",
"attr": "TUNNEL_ENCAP_FLAG_REMCSUM"
}
}
}
}
$ ip tunnel add tun0 mode ipip local 192.0.2.1 remote 198.51.100.3
$ ip link show
10: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN mode DEFAULT group
default
link/ipip 0.0.0.0 brd 0.0.0.0
11: tun0@NONE: <POINTOPOINT,NOARP> mtu 1480 qdisc noop state DOWN mode
DEFAULT group default
link/ipip 192.0.2.1 peer 198.51.100.3
$ ip -details -json link show
[{
"ifindex": 10,
"ifname": "tunl0",
"link": null,
"flags": ["NOARP"],
"mtu": 1480,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ipip",
"address": "0.0.0.0",
"broadcast": "0.0.0.0",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ipip",
"info_data": {
"remote": "any",
"local": "any",
"ttl": 0,
"pmtudisc": false
}
},
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "tun0",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1480,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ipip",
"address": "192.0.2.1",
"link_pointtopoint": true,
"broadcast": "198.51.100.3",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ipip",
"info_data": {
"remote": "198.51.100.3",
"local": "192.0.2.1",
"ttl": 0,
"pmtudisc": true
}
},
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
$
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_iptnl.c | 155 ++++++++++++++++++++++++++++++++++++++------------------
1 file changed, 106 insertions(+), 49 deletions(-)
diff --git a/ip/link_iptnl.c b/ip/link_iptnl.c
index d24e7376..6a725e91 100644
--- a/ip/link_iptnl.c
+++ b/ip/link_iptnl.c
@@ -398,7 +398,7 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
remote = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "remote %s ", remote);
+ print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_IPTUN_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
@@ -407,43 +407,55 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
local = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "local %s ", local);
+ print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_int(PRINT_ANY, "link_index", "dev %u ", link);
}
- if (tb[IFLA_IPTUN_TTL] && rta_getattr_u8(tb[IFLA_IPTUN_TTL]))
- fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_IPTUN_TTL]));
- else
- fprintf(f, "ttl inherit ");
+ if (tb[IFLA_IPTUN_TTL]) {
+ __u8 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]);
+
+ if (ttl)
+ print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
+ else
+ print_int(PRINT_JSON, "ttl", NULL, ttl);
+ } else {
+ print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
+ }
- if (tb[IFLA_IPTUN_TOS] && rta_getattr_u8(tb[IFLA_IPTUN_TOS])) {
+ if (tb[IFLA_IPTUN_TOS]) {
int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
- fputs("tos ", f);
- if (tos == 1)
- fputs("inherit ", f);
- else
- fprintf(f, "0x%x ", tos);
+ if (tos) {
+ if (is_json_context()) {
+ print_0xhex(PRINT_JSON, "tos", "%#x", tos);
+ } else {
+ fputs("tos ", f);
+ if (tos == 1)
+ fputs("inherit ", f);
+ else
+ fprintf(f, "0x%x ", tos);
+ }
+ }
}
if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
- fprintf(f, "pmtudisc ");
+ print_bool(PRINT_ANY, "pmtudisc", "pmtudisc ", true);
else
- fprintf(f, "nopmtudisc ");
+ print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
if (tb[IFLA_IPTUN_FLAGS]) {
__u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
if (iflags & SIT_ISATAP)
- fprintf(f, "isatap ");
+ print_bool(PRINT_ANY, "isatap", "isatap ", true);
}
if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
@@ -453,14 +465,32 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
__u32 relayprefix =
rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
- printf("6rd-prefix %s/%u ",
- inet_ntop(AF_INET6, RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
- s1, sizeof(s1)),
- prefixlen);
- if (relayprefix) {
- printf("6rd-relay_prefix %s/%u ",
- format_host(AF_INET, 4, &relayprefix),
- relayprefixlen);
+ const char *prefix = inet_ntop(AF_INET6,
+ RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
+ s1, sizeof(s1));
+
+ if (is_json_context()) {
+ print_string(PRINT_JSON, "prefix", NULL, prefix);
+ print_int(PRINT_JSON, "prefixlen", NULL, prefixlen);
+ if (relayprefix) {
+ print_string(PRINT_JSON,
+ "relay_prefix",
+ NULL,
+ format_host(AF_INET,
+ 4,
+ &relayprefix));
+ print_int(PRINT_JSON,
+ "relay_prefixlen",
+ NULL,
+ relayprefixlen);
+ }
+ } else {
+ printf("6rd-prefix %s/%u ", prefix, prefixlen);
+ if (relayprefix) {
+ printf("6rd-relay_prefix %s/%u ",
+ format_host(AF_INET, 4, &relayprefix),
+ relayprefixlen);
+ }
}
}
@@ -470,45 +500,72 @@ static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[
__u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
__u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
- fputs("encap ", f);
+ print_string(PRINT_FP, NULL, "encap ", NULL);
switch (type) {
case TUNNEL_ENCAP_FOU:
- fputs("fou ", f);
+ print_string(PRINT_ANY, "type", "%s ", "fou");
break;
case TUNNEL_ENCAP_GUE:
- fputs("gue ", f);
+ print_string(PRINT_ANY, "type", "%s ", "gue");
break;
default:
- fputs("unknown ", f);
+ print_null(PRINT_ANY, "type", "unknown ", NULL);
break;
}
- if (sport == 0)
- fputs("encap-sport auto ", f);
- else
- fprintf(f, "encap-sport %u", ntohs(sport));
+ if (is_json_context()) {
+ print_uint(PRINT_JSON,
+ "sport",
+ NULL,
+ sport ? ntohs(sport) : 0);
+ print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
+ print_bool(PRINT_JSON,
+ "csum",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM);
+ print_bool(PRINT_JSON,
+ "csum6",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_CSUM6);
+ print_bool(PRINT_JSON,
+ "remcsum",
+ NULL,
+ flags & TUNNEL_ENCAP_FLAG_REMCSUM);
+ close_json_object();
+ } else {
+ if (sport == 0)
+ fputs("encap-sport auto ", f);
+ else
+ fprintf(f, "encap-sport %u", ntohs(sport));
- fprintf(f, "encap-dport %u ", ntohs(dport));
+ fprintf(f, "encap-dport %u ", ntohs(dport));
- if (flags & TUNNEL_ENCAP_FLAG_CSUM)
- fputs("encap-csum ", f);
- else
- fputs("noencap-csum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM)
+ fputs("encap-csum ", f);
+ else
+ fputs("noencap-csum ", f);
- if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
- fputs("encap-csum6 ", f);
- else
- fputs("noencap-csum6 ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
+ fputs("encap-csum6 ", f);
+ else
+ fputs("noencap-csum6 ", f);
- if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
- fputs("encap-remcsum ", f);
- else
- fputs("noencap-remcsum ", f);
+ if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
+ fputs("encap-remcsum ", f);
+ else
+ fputs("noencap-remcsum ", f);
+ }
}
- if (tb[IFLA_IPTUN_FWMARK] && rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]))
- fprintf(f, "fwmark 0x%x ",
- rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]));
+ if (tb[IFLA_IPTUN_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
+
+ if (fwmark) {
+ snprintf(s2, sizeof(s2), "0x%x", fwmark);
+
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ }
+ }
}
static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
--
2.13.3
^ permalink raw reply related
* [PATCH 24/27] ip: link_vti.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"remote": {
"type": "string",
"attr": "IFLA_VTI_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_VTI_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_VTI_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ikey": {
"type": "string",
"attr": "IFLA_VTI_IKEY"
},
"okey": {
"type": "string",
"attr": "IFLA_VTI_OKEY"
}
}
$ ip tunnel add vti0 mode vti local 192.0.2.1 remote 198.51.100.3
$ ip link show
10: ip_vti0@NONE: <NOARP> mtu 1428 qdisc noop state DOWN mode DEFAULT group
default
link/ipip 0.0.0.0 brd 0.0.0.0
11: vti0@NONE: <POINTOPOINT,NOARP> mtu 1428 qdisc noop state DOWN mode
DEFAULT group default
link/ipip 192.0.2.1 peer 198.51.100.3
$ ./ip -details -json link show
[{
"ifindex": 10,
"ifname": "ip_vti0",
"link": null,
"flags": ["NOARP"],
"mtu": 1428,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ipip",
"address": "0.0.0.0",
"broadcast": "0.0.0.0",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vti",
"info_data": {
"remote": "any",
"local": "any",
"ikey": "0.0.0.0",
"okey": "0.0.0.0"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "vti0",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1428,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ipip",
"address": "192.0.2.1",
"link_pointtopoint": true,
"broadcast": "198.51.100.3",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vti",
"info_data": {
"remote": "198.51.100.3",
"local": "192.0.2.1",
"ikey": "0.0.0.0",
"okey": "0.0.0.0"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
$
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_vti.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/ip/link_vti.c b/ip/link_vti.c
index d5242ac7..74336aff 100644
--- a/ip/link_vti.c
+++ b/ip/link_vti.c
@@ -223,7 +223,7 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
remote = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "remote %s ", remote);
+ print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_VTI_LOCAL]) {
unsigned int addr = rta_getattr_u32(tb[IFLA_VTI_LOCAL]);
@@ -232,31 +232,36 @@ static void vti_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
local = format_host(AF_INET, 4, &addr);
}
- fprintf(f, "local %s ", local);
+ print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_VTI_LINK] &&
(link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
if (tb[IFLA_VTI_IKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2));
- fprintf(f, "ikey %s ", s2);
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
if (tb[IFLA_VTI_OKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
- fprintf(f, "okey %s ", s2);
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
- if (tb[IFLA_VTI_FWMARK] && rta_getattr_u32(tb[IFLA_VTI_FWMARK])) {
- fprintf(f, "fwmark 0x%x ",
- rta_getattr_u32(tb[IFLA_VTI_FWMARK]));
+ if (tb[IFLA_VTI_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
+
+ if (fwmark) {
+ snprintf(s2, sizeof(s2), "0x%x", fwmark);
+
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ }
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH 25/27] ip: link_vti6.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"remote": {
"type": "string",
"attr": "IFLA_VTI_REMOTE"
},
"local": {
"type": "string",
"attr": "IFLA_VTI_LOCAL"
},
"link": {
"type": "string",
"attr": "IFLA_VTI_LINK",
"mutually_exclusive": {
"link_index": {
"type": "uint",
}
}
},
"ikey": {
"type": "string",
"attr": "IFLA_VTI_IKEY"
},
"okey": {
"type": "string",
"attr": "IFLA_VTI_OKEY"
}
}
➜ ~ ip -6 tunnel add name vti6 mode vti6 local 2001:db8:1::1/64 remote
2001:0db8:85a3:0000:0000:8a2e:0370:7334
➜ ~ ip link show
10: ip6tnl0@NONE: <NOARP> mtu 1452 qdisc noop state DOWN mode DEFAULT
group default
link/tunnel6 :: brd ::
11: ip6_vti0@NONE: <NOARP> mtu 1500 qdisc noop state DOWN mode DEFAULT
group default
link/tunnel6 :: brd ::
12: vti6@NONE: <POINTOPOINT,NOARP> mtu 1500 qdisc noop state DOWN mode
DEFAULT group default
link/tunnel6 2001:db8:1::1 peer 2001:db8:85a3::8a2e:370:7334
➜ ~ ./ip -details -json link show
[{
"ifindex": 10,
"ifname": "ip6tnl0",
"link": null,
"flags": ["NOARP"],
"mtu": 1452,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "tunnel6",
"address": "::",
"broadcast": "::",
"promiscuity": 0,
"linkinfo": {
"info_kind": "ip6tnl",
"info_data": {
"proto": "ip6ip6",
"remote": "::",
"local": "::",
"encap_limit": 0,
"ttl": 0,
"flowinfo_tclass": "0x00",
"flowlabel": "0x00000",
"flowinfo": "0x00000000"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 11,
"ifname": "ip6_vti0",
"link": null,
"flags": ["NOARP"],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "tunnel6",
"address": "::",
"broadcast": "::",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vti6",
"info_data": {
"remote": "::",
"local": "::",
"ikey": "0.0.0.0",
"okey": "0.0.0.0"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
},{
"ifindex": 12,
"ifname": "vti6",
"link": null,
"flags": ["POINTOPOINT","NOARP"],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "tunnel6",
"address": "2001:db8:1::1",
"link_pointtopoint": true,
"broadcast": "2001:db8:85a3::8a2e:370:7334",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vti6",
"info_data": {
"remote": "2001:db8:85a3::8a2e:370:7334",
"local": "2001:db8:1::1",
"ikey": "0.0.0.0",
"okey": "0.0.0.0"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/link_vti6.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/ip/link_vti6.c b/ip/link_vti6.c
index be4e33ce..7193e30b 100644
--- a/ip/link_vti6.c
+++ b/ip/link_vti6.c
@@ -222,7 +222,7 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
remote = format_host(AF_INET6, 16, &daddr);
}
- fprintf(f, "remote %s ", remote);
+ print_string(PRINT_ANY, "remote", "remote %s ", remote);
if (tb[IFLA_VTI_LOCAL]) {
memcpy(&saddr, RTA_DATA(tb[IFLA_VTI_LOCAL]), sizeof(saddr));
@@ -230,29 +230,35 @@ static void vti6_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
local = format_host(AF_INET6, 16, &saddr);
}
- fprintf(f, "local %s ", local);
+ print_string(PRINT_ANY, "local", "local %s ", local);
if (tb[IFLA_VTI_LINK] && (link = rta_getattr_u32(tb[IFLA_VTI_LINK]))) {
const char *n = if_indextoname(link, s2);
if (n)
- fprintf(f, "dev %s ", n);
+ print_string(PRINT_ANY, "link", "dev %s ", n);
else
- fprintf(f, "dev %u ", link);
+ print_uint(PRINT_ANY, "link_index", "dev %u ", link);
}
if (tb[IFLA_VTI_IKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_IKEY]), s2, sizeof(s2));
- fprintf(f, "ikey %s ", s2);
+ print_string(PRINT_ANY, "ikey", "ikey %s ", s2);
}
if (tb[IFLA_VTI_OKEY]) {
inet_ntop(AF_INET, RTA_DATA(tb[IFLA_VTI_OKEY]), s2, sizeof(s2));
- fprintf(f, "okey %s ", s2);
+ print_string(PRINT_ANY, "okey", "okey %s ", s2);
}
- if (tb[IFLA_VTI_FWMARK] && rta_getattr_u32(tb[IFLA_VTI_FWMARK])) {
- fprintf(f, "fwmark 0x%x ", rta_getattr_u32(tb[IFLA_VTI_FWMARK]));
+ if (tb[IFLA_VTI_FWMARK]) {
+ __u32 fwmark = rta_getattr_u32(tb[IFLA_VTI_FWMARK]);
+
+ if (fwmark) {
+ snprintf(s2, sizeof(s2), "0x%x", fwmark);
+
+ print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
+ }
}
}
--
2.13.3
^ permalink raw reply related
* [PATCH 26/27] ip: link_macvlan.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"mode": {
"type": "string",
"attr": "IFLA_MACVLAN_MODE"
},
"nopromisc": {
"type": "bool",
"attr": "MACVLAN_FLAG_NOPROMISC"
},
"macaddr_count": {
"type": "int",
"attr": "IFLA_MACVLAN_MACADDR_COUNT"
},
"macaddr_data": {
"type": "array",
"attr": "IFLA_MACVLAN_MACADDR_DATA",
"array": [
{
"type": "string"
}
]
},
}
$ ip link add name peth0 link eth0 type macvlan
$ ip -details -json link show peth0
[{
"ifindex": 26,
"ifname": "peth0",
"link": "eth0",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "7a:84:48:3e:7b:1c",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "macvlan",
"info_data": {
"mode": "vepa"
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_macvlan.c | 37 +++++++++++++++++++++++++------------
1 file changed, 25 insertions(+), 12 deletions(-)
diff --git a/ip/iplink_macvlan.c b/ip/iplink_macvlan.c
index 662eb6ff..b966a615 100644
--- a/ip/iplink_macvlan.c
+++ b/ip/iplink_macvlan.c
@@ -193,13 +193,15 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
return;
mode = rta_getattr_u32(tb[IFLA_MACVLAN_MODE]);
- fprintf(f, "mode %s ",
- mode == MACVLAN_MODE_PRIVATE ? "private"
- : mode == MACVLAN_MODE_VEPA ? "vepa"
- : mode == MACVLAN_MODE_BRIDGE ? "bridge"
- : mode == MACVLAN_MODE_PASSTHRU ? "passthru"
- : mode == MACVLAN_MODE_SOURCE ? "source"
- : "unknown");
+ print_string(PRINT_ANY,
+ "mode",
+ "mode %s ",
+ mode == MACVLAN_MODE_PRIVATE ? "private"
+ : mode == MACVLAN_MODE_VEPA ? "vepa"
+ : mode == MACVLAN_MODE_BRIDGE ? "bridge"
+ : mode == MACVLAN_MODE_PASSTHRU ? "passthru"
+ : mode == MACVLAN_MODE_SOURCE ? "source"
+ : "unknown");
if (!tb[IFLA_MACVLAN_FLAGS] ||
RTA_PAYLOAD(tb[IFLA_MACVLAN_FLAGS]) < sizeof(__u16))
@@ -208,7 +210,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
flags = rta_getattr_u16(tb[IFLA_MACVLAN_FLAGS]);
if (flags & MACVLAN_FLAG_NOPROMISC)
- fprintf(f, "nopromisc ");
+ print_bool(PRINT_ANY, "nopromisc", "nopromisc ", true);
/* in source mode, there are more options to print */
@@ -220,7 +222,7 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
return;
count = rta_getattr_u32(tb[IFLA_MACVLAN_MACADDR_COUNT]);
- fprintf(f, "remotes (%d) ", count);
+ print_int(PRINT_ANY, "macaddr_count", "remotes (%d) ", count);
if (!tb[IFLA_MACVLAN_MACADDR_DATA])
return;
@@ -228,18 +230,29 @@ static void macvlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]
rta = RTA_DATA(tb[IFLA_MACVLAN_MACADDR_DATA]);
len = RTA_PAYLOAD(tb[IFLA_MACVLAN_MACADDR_DATA]);
+ open_json_array(PRINT_JSON, "macaddr_data");
for (; RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) {
if (rta->rta_type != IFLA_MACVLAN_MACADDR ||
RTA_PAYLOAD(rta) < 6)
continue;
addr = RTA_DATA(rta);
- fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
- addr[1], addr[2], addr[3], addr[4], addr[5]);
+ if (is_json_context()) {
+ SPRINT_BUF(b1);
+
+ snprintf(b1, sizeof(b1),
+ "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x", addr[0],
+ addr[1], addr[2], addr[3], addr[4], addr[5]);
+ print_string(PRINT_JSON, NULL, NULL, b1);
+ } else {
+ fprintf(f, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x ", addr[0],
+ addr[1], addr[2], addr[3], addr[4], addr[5]);
+ }
}
+ close_json_array(PRINT_JSON, NULL);
}
static void macvlan_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_explain(lu, f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH 27/27] ip: iplink_vlan.c: add json output support
From: Julien Fortin @ 2017-08-03 15:55 UTC (permalink / raw)
To: netdev; +Cc: roopa, nikolay, dsa, Julien Fortin
In-Reply-To: <20170803155515.99226-1-julien@cumulusnetworks.com>
From: Julien Fortin <julien@cumulusnetworks.com>
Schema:
{
"protocol": {
"type": "string",
"attr": "IFLA_VLAN_PROTOCOL"
},
"id": {
"type": "uint",
"attr": "IFLA_VLAN_ID"
},
"flags": {
"type": "array",
"attr": "IFLA_VLAN_FLAGS",
"array": [
{
"type": "string"
}
]
},
"ingress_qos": {
"type": "array",
"attr": "IFLA_VLAN_INGRESS_QOS",
"array": [
{
"type": "dict",
"dict": {
"from": {
"type": "uint"
},
"to": {
"type": "uint"
}
}
}
]
},
"egress_qos": {
"type": "array",
"attr": "IFLA_VLAN_EGRESS_QOS",
"array": [
{
"type": "dict",
"dict": {
"from": {
"type": "uint"
},
"to": {
"type": "uint"
}
}
}
]
}
}
$ ip link add name eth0.42 link eth0 type vlan id 42
$ ip -details -json link show
[{
"ifindex": 30,
"ifname": "eth0.42",
"link": "eth0",
"flags": ["BROADCAST","MULTICAST"],
"mtu": 1500,
"qdisc": "noop",
"operstate": "DOWN",
"linkmode": "DEFAULT",
"group": "default",
"link_type": "ether",
"address": "08:00:27:db:31:88",
"broadcast": "ff:ff:ff:ff:ff:ff",
"promiscuity": 0,
"linkinfo": {
"info_kind": "vlan",
"info_data": {
"protocol": "802.1Q",
"id": 42,
"flags": ["REORDER_HDR"]
}
},
"inet6_addr_gen_mode": "eui64",
"num_tx_queues": 1,
"num_rx_queues": 1,
"gso_max_size": 65536,
"gso_max_segs": 65535
}
]
Signed-off-by: Julien Fortin <julien@cumulusnetworks.com>
---
ip/iplink_vlan.c | 62 ++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 44 insertions(+), 18 deletions(-)
diff --git a/ip/iplink_vlan.c b/ip/iplink_vlan.c
index b47236d8..4d78cf9e 100644
--- a/ip/iplink_vlan.c
+++ b/ip/iplink_vlan.c
@@ -164,37 +164,51 @@ static int vlan_parse_opt(struct link_util *lu, int argc, char **argv,
return 0;
}
-static void vlan_print_map(FILE *f, char *name, struct rtattr *attr)
+static void vlan_print_map(FILE *f,
+ const char *name_json,
+ const char *name_fp,
+ struct rtattr *attr)
{
struct ifla_vlan_qos_mapping *m;
struct rtattr *i;
int rem;
- fprintf(f, "\n %s { ", name);
+ open_json_array(PRINT_JSON, name_json);
+ print_string(PRINT_FP, NULL, "\n %s { ", name_fp);
rem = RTA_PAYLOAD(attr);
for (i = RTA_DATA(attr); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
m = RTA_DATA(i);
- fprintf(f, "%u:%u ", m->from, m->to);
+
+ if (is_json_context()) {
+ open_json_object(NULL);
+ print_uint(PRINT_JSON, "from", NULL, m->from);
+ print_uint(PRINT_JSON, "to", NULL, m->to);
+ close_json_object();
+ } else {
+ fprintf(f, "%u:%u ", m->from, m->to);
+ }
}
- fprintf(f, "} ");
+
+ close_json_array(PRINT_JSON, NULL);
+ print_string(PRINT_FP, NULL, "%s ", "}");
}
static void vlan_print_flags(FILE *fp, __u32 flags)
{
- fprintf(fp, "<");
-#define _PF(f) if (flags & VLAN_FLAG_##f) { \
- flags &= ~VLAN_FLAG_##f; \
- fprintf(fp, #f "%s", flags ? "," : ""); \
- }
+ open_json_array(PRINT_ANY, is_json_context() ? "flags" : "<");
+#define _PF(f) if (flags & VLAN_FLAG_##f) { \
+ flags &= ~VLAN_FLAG_##f; \
+ print_string(PRINT_ANY, NULL, flags ? "%s," : "%s", #f); \
+ }
_PF(REORDER_HDR);
_PF(GVRP);
_PF(MVRP);
_PF(LOOSE_BINDING);
#undef _PF
if (flags)
- fprintf(fp, "%x", flags);
- fprintf(fp, "> ");
+ print_hex(PRINT_ANY, NULL, "%x", flags);
+ close_json_array(PRINT_ANY, "> ");
}
static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
@@ -214,13 +228,19 @@ static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
return;
if (tb[IFLA_VLAN_PROTOCOL])
- fprintf(f, "protocol %s ",
- ll_proto_n2a(rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
+ print_string(PRINT_ANY,
+ "protocol",
+ "protocol %s ",
+ ll_proto_n2a(
+ rta_getattr_u16(tb[IFLA_VLAN_PROTOCOL]),
b1, sizeof(b1)));
else
- fprintf(f, "protocol 802.1q ");
+ print_string(PRINT_ANY, "protocol", "protocol %s ", "802.1q");
- fprintf(f, "id %u ", rta_getattr_u16(tb[IFLA_VLAN_ID]));
+ print_uint(PRINT_ANY,
+ "id",
+ "id %u ",
+ rta_getattr_u16(tb[IFLA_VLAN_ID]));
if (tb[IFLA_VLAN_FLAGS]) {
if (RTA_PAYLOAD(tb[IFLA_VLAN_FLAGS]) < sizeof(*flags))
@@ -229,13 +249,19 @@ static void vlan_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
vlan_print_flags(f, flags->flags);
}
if (tb[IFLA_VLAN_INGRESS_QOS])
- vlan_print_map(f, "ingress-qos-map", tb[IFLA_VLAN_INGRESS_QOS]);
+ vlan_print_map(f,
+ "ingress_qos",
+ "ingress-qos-map",
+ tb[IFLA_VLAN_INGRESS_QOS]);
if (tb[IFLA_VLAN_EGRESS_QOS])
- vlan_print_map(f, "egress-qos-map", tb[IFLA_VLAN_EGRESS_QOS]);
+ vlan_print_map(f,
+ "egress_qos",
+ "egress-qos-map",
+ tb[IFLA_VLAN_EGRESS_QOS]);
}
static void vlan_print_help(struct link_util *lu, int argc, char **argv,
- FILE *f)
+ FILE *f)
{
print_explain(f);
}
--
2.13.3
^ permalink raw reply related
* [PATCH net-next 0/4] IP: cleanup LSRR option processing
From: Paolo Abeni @ 2017-08-03 16:07 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet, Hannes Frederic Sowa
The __ip_options_echo() function expect a valid dst entry in skb->dst;
as result we sometimes need to preserve the dst entry for the whole IP
RX path.
The current usage of skb->dst looks more a relic from ancient past that
a real functional constraint. This patchset tries to remove such usage,
and than drops some hacks currently in place in the IP code to keep
skb->dst around.
__ip_options_echo() uses of skb->dst for two different purposes: retrieving
the netns assicated with the skb, and modify the ingress packet LSRR address
list.
The first patch removes the code modifying the ingress packet, and the second
one provides an explicit netns argument to __ip_options_echo(). The following
patches cleanup the current code keeping arund skb->dst for __ip_options_echo's
sake.
Updating the __ip_options_echo() function has been previously discussed here:
http://marc.info/?l=linux-netdev&m=150064533516348&w=2
Paolo Abeni (4):
IP: do not modify ingress packet IP option in ip_options_echo()
ip/options: explicitly provide net ns to __ip_options_echo()
Revert "ipv4: keep skb->dst around in presence of IP options"
udp: no need to preserve skb->dst
include/net/ip.h | 9 +++++----
include/net/tcp.h | 5 +++--
net/ipv4/icmp.c | 4 ++--
net/ipv4/ip_options.c | 9 +++------
net/ipv4/ip_output.c | 2 +-
net/ipv4/ip_sockglue.c | 16 +++++-----------
net/ipv4/syncookies.c | 2 +-
net/ipv4/tcp_ipv4.c | 2 +-
net/ipv4/udp.c | 13 +++++--------
9 files changed, 26 insertions(+), 36 deletions(-)
--
2.13.3
^ permalink raw reply
* [PATCH net-next 1/4] IP: do not modify ingress packet IP option in ip_options_echo()
From: Paolo Abeni @ 2017-08-03 16:07 UTC (permalink / raw)
To: netdev; +Cc: David S. Miller, Eric Dumazet, Hannes Frederic Sowa
In-Reply-To: <cover.1501775813.git.pabeni@redhat.com>
While computing the response option set for LSRR, ip_options_echo()
also changes the ingress packet LSRR addresses list, setting
the last one to the dst specific address for the ingress packet
- via memset(start[ ...
The only visible effect of such change - beyond possibly damaging
shared/cloned skbs - is modifying the data carried by ICMP replies
changing the header information for reported the ingress packet,
which violates RFC1122 3.2.2.6.
All the others call sites just ignore the ingress packet IP options
after calling ip_options_echo()
Note that the last element in the LSRR option address list for the
reply packet will be properly set later in the ip output path
via ip_options_build().
This buggy memset() predates git history and apparently was present
into the initial ip_options_echo() implementation in linux 1.3.30 but
still looks wrong.
The removal of the fib_compute_spec_dst() call will help
completely dropping the skb->dst usage by __ip_options_echo() with a
later patch.
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
net/ipv4/ip_options.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c
index 93157f2f4758..fdda97308c0b 100644
--- a/net/ipv4/ip_options.c
+++ b/net/ipv4/ip_options.c
@@ -174,9 +174,6 @@ int __ip_options_echo(struct ip_options *dopt, struct sk_buff *skb,
doffset -= 4;
}
if (doffset > 3) {
- __be32 daddr = fib_compute_spec_dst(skb);
-
- memcpy(&start[doffset-1], &daddr, 4);
dopt->faddr = faddr;
dptr[0] = start[0];
dptr[1] = doffset+3;
--
2.13.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox