Blame ip/iplink_bond.c

Packit Service 3880ab
/*
Packit Service 3880ab
 * iplink_bond.c	Bonding device support
Packit Service 3880ab
 *
Packit Service 3880ab
 *              This program is free software; you can redistribute it and/or
Packit Service 3880ab
 *              modify it under the terms of the GNU General Public License
Packit Service 3880ab
 *              as published by the Free Software Foundation; either version
Packit Service 3880ab
 *              2 of the License, or (at your option) any later version.
Packit Service 3880ab
 *
Packit Service 3880ab
 * Authors:     Jiri Pirko <jiri@resnulli.us>
Packit Service 3880ab
 *              Scott Feldman <sfeldma@cumulusnetworks.com>
Packit Service 3880ab
 */
Packit Service 3880ab
Packit Service 3880ab
#include <stdio.h>
Packit Service 3880ab
#include <stdlib.h>
Packit Service 3880ab
#include <string.h>
Packit Service 3880ab
#include <linux/if_bonding.h>
Packit Service 3880ab
Packit Service 3880ab
#include "rt_names.h"
Packit Service 3880ab
#include "utils.h"
Packit Service 3880ab
#include "ip_common.h"
Packit Service 3880ab
#include "json_print.h"
Packit Service 3880ab
Packit Service 3880ab
#define BOND_MAX_ARP_TARGETS    16
Packit Service 3880ab
Packit Service 3880ab
static unsigned int xstats_print_attr;
Packit Service 3880ab
static int filter_index;
Packit Service 3880ab
Packit Service 3880ab
static const char *mode_tbl[] = {
Packit Service 3880ab
	"balance-rr",
Packit Service 3880ab
	"active-backup",
Packit Service 3880ab
	"balance-xor",
Packit Service 3880ab
	"broadcast",
Packit Service 3880ab
	"802.3ad",
Packit Service 3880ab
	"balance-tlb",
Packit Service 3880ab
	"balance-alb",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *arp_validate_tbl[] = {
Packit Service 3880ab
	"none",
Packit Service 3880ab
	"active",
Packit Service 3880ab
	"backup",
Packit Service 3880ab
	"all",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *arp_all_targets_tbl[] = {
Packit Service 3880ab
	"any",
Packit Service 3880ab
	"all",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *primary_reselect_tbl[] = {
Packit Service 3880ab
	"always",
Packit Service 3880ab
	"better",
Packit Service 3880ab
	"failure",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *fail_over_mac_tbl[] = {
Packit Service 3880ab
	"none",
Packit Service 3880ab
	"active",
Packit Service 3880ab
	"follow",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *xmit_hash_policy_tbl[] = {
Packit Service 3880ab
	"layer2",
Packit Service 3880ab
	"layer3+4",
Packit Service 3880ab
	"layer2+3",
Packit Service 3880ab
	"encap2+3",
Packit Service 3880ab
	"encap3+4",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *lacp_rate_tbl[] = {
Packit Service 3880ab
	"slow",
Packit Service 3880ab
	"fast",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *ad_select_tbl[] = {
Packit Service 3880ab
	"stable",
Packit Service 3880ab
	"bandwidth",
Packit Service 3880ab
	"count",
Packit Service 3880ab
	NULL,
Packit Service 3880ab
};
Packit Service 3880ab
Packit Service 3880ab
static const char *get_name(const char **tbl, int index)
Packit Service 3880ab
{
Packit Service 3880ab
	int i;
Packit Service 3880ab
Packit Service 3880ab
	for (i = 0; tbl[i]; i++)
Packit Service 3880ab
		if (i == index)
Packit Service 3880ab
			return tbl[i];
Packit Service 3880ab
Packit Service 3880ab
	return "UNKNOWN";
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static int get_index(const char **tbl, char *name)
Packit Service 3880ab
{
Packit Service 3880ab
	int i, index;
Packit Service 3880ab
Packit Service 3880ab
	/* check for integer index passed in instead of name */
Packit Service 3880ab
	if (get_integer(&index, name, 10) == 0)
Packit Service 3880ab
		for (i = 0; tbl[i]; i++)
Packit Service 3880ab
			if (i == index)
Packit Service 3880ab
				return i;
Packit Service 3880ab
Packit Service 3880ab
	for (i = 0; tbl[i]; i++)
Packit Service 3880ab
		if (strcmp(tbl[i], name) == 0)
Packit Service 3880ab
			return i;
Packit Service 3880ab
Packit Service 3880ab
	return -1;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void print_explain(FILE *f)
Packit Service 3880ab
{
Packit Service 3880ab
	fprintf(f,
Packit Service 3880ab
		"Usage: ... bond [ mode BONDMODE ] [ active_slave SLAVE_DEV ]\n"
Packit Service 3880ab
		"                [ clear_active_slave ] [ miimon MIIMON ]\n"
Packit Service 3880ab
		"                [ updelay UPDELAY ] [ downdelay DOWNDELAY ]\n"
Packit Service 3880ab
		"                [ peer_notify_delay DELAY ]\n"
Packit Service 3880ab
		"                [ use_carrier USE_CARRIER ]\n"
Packit Service 3880ab
		"                [ arp_interval ARP_INTERVAL ]\n"
Packit Service 3880ab
		"                [ arp_validate ARP_VALIDATE ]\n"
Packit Service 3880ab
		"                [ arp_all_targets ARP_ALL_TARGETS ]\n"
Packit Service 3880ab
		"                [ arp_ip_target [ ARP_IP_TARGET, ... ] ]\n"
Packit Service 3880ab
		"                [ primary SLAVE_DEV ]\n"
Packit Service 3880ab
		"                [ primary_reselect PRIMARY_RESELECT ]\n"
Packit Service 3880ab
		"                [ fail_over_mac FAIL_OVER_MAC ]\n"
Packit Service 3880ab
		"                [ xmit_hash_policy XMIT_HASH_POLICY ]\n"
Packit Service 3880ab
		"                [ resend_igmp RESEND_IGMP ]\n"
Packit Service 3880ab
		"                [ num_grat_arp|num_unsol_na NUM_GRAT_ARP|NUM_UNSOL_NA ]\n"
Packit Service 3880ab
		"                [ all_slaves_active ALL_SLAVES_ACTIVE ]\n"
Packit Service 3880ab
		"                [ min_links MIN_LINKS ]\n"
Packit Service 3880ab
		"                [ lp_interval LP_INTERVAL ]\n"
Packit Service 3880ab
		"                [ packets_per_slave PACKETS_PER_SLAVE ]\n"
Packit Service 3880ab
		"                [ tlb_dynamic_lb TLB_DYNAMIC_LB ]\n"
Packit Service 3880ab
		"                [ lacp_rate LACP_RATE ]\n"
Packit Service 3880ab
		"                [ ad_select AD_SELECT ]\n"
Packit Service 3880ab
		"                [ ad_user_port_key PORTKEY ]\n"
Packit Service 3880ab
		"                [ ad_actor_sys_prio SYSPRIO ]\n"
Packit Service 3880ab
		"                [ ad_actor_system LLADDR ]\n"
Packit Service 3880ab
		"\n"
Packit Service 3880ab
		"BONDMODE := balance-rr|active-backup|balance-xor|broadcast|802.3ad|balance-tlb|balance-alb\n"
Packit Service 3880ab
		"ARP_VALIDATE := none|active|backup|all\n"
Packit Service 3880ab
		"ARP_ALL_TARGETS := any|all\n"
Packit Service 3880ab
		"PRIMARY_RESELECT := always|better|failure\n"
Packit Service 3880ab
		"FAIL_OVER_MAC := none|active|follow\n"
Packit Service 3880ab
		"XMIT_HASH_POLICY := layer2|layer2+3|layer3+4|encap2+3|encap3+4\n"
Packit Service 3880ab
		"LACP_RATE := slow|fast\n"
Packit Service 3880ab
		"AD_SELECT := stable|bandwidth|count\n"
Packit Service 3880ab
	);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void explain(void)
Packit Service 3880ab
{
Packit Service 3880ab
	print_explain(stderr);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static int bond_parse_opt(struct link_util *lu, int argc, char **argv,
Packit Service 3880ab
			  struct nlmsghdr *n)
Packit Service 3880ab
{
Packit Service 3880ab
	__u8 mode, use_carrier, primary_reselect, fail_over_mac;
Packit Service 3880ab
	__u8 xmit_hash_policy, num_peer_notif, all_slaves_active;
Packit Service 3880ab
	__u8 lacp_rate, ad_select, tlb_dynamic_lb;
Packit Service 3880ab
	__u16 ad_user_port_key, ad_actor_sys_prio;
Packit Service 3880ab
	__u32 miimon, updelay, downdelay, peer_notify_delay, arp_interval, arp_validate;
Packit Service 3880ab
	__u32 arp_all_targets, resend_igmp, min_links, lp_interval;
Packit Service 3880ab
	__u32 packets_per_slave;
Packit Service 3880ab
	unsigned int ifindex;
Packit Service 3880ab
Packit Service 3880ab
	while (argc > 0) {
Packit Service 3880ab
		if (matches(*argv, "mode") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(mode_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid mode", *argv);
Packit Service 3880ab
			mode = get_index(mode_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_MODE, mode);
Packit Service 3880ab
		} else if (matches(*argv, "active_slave") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			ifindex = ll_name_to_index(*argv);
Packit Service 3880ab
			if (!ifindex)
Packit Service 3880ab
				return nodev(*argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, ifindex);
Packit Service 3880ab
		} else if (matches(*argv, "clear_active_slave") == 0) {
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_ACTIVE_SLAVE, 0);
Packit Service 3880ab
		} else if (matches(*argv, "miimon") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&miimon, *argv, 0))
Packit Service 3880ab
				invarg("invalid miimon", *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_MIIMON, miimon);
Packit Service 3880ab
		} else if (matches(*argv, "updelay") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&updelay, *argv, 0))
Packit Service 3880ab
				invarg("invalid updelay", *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_UPDELAY, updelay);
Packit Service 3880ab
		} else if (matches(*argv, "downdelay") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&downdelay, *argv, 0))
Packit Service 3880ab
				invarg("invalid downdelay", *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_DOWNDELAY, downdelay);
Packit Service 3880ab
		} else if (matches(*argv, "peer_notify_delay") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&peer_notify_delay, *argv, 0))
Packit Service 3880ab
				invarg("invalid peer_notify_delay", *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_PEER_NOTIF_DELAY, peer_notify_delay);
Packit Service 3880ab
		} else if (matches(*argv, "use_carrier") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u8(&use_carrier, *argv, 0))
Packit Service 3880ab
				invarg("invalid use_carrier", *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_USE_CARRIER, use_carrier);
Packit Service 3880ab
		} else if (matches(*argv, "arp_interval") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&arp_interval, *argv, 0))
Packit Service 3880ab
				invarg("invalid arp_interval", *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_ARP_INTERVAL, arp_interval);
Packit Service 3880ab
		} else if (matches(*argv, "arp_ip_target") == 0) {
Packit Service 3880ab
			struct rtattr *nest = addattr_nest(n, 1024,
Packit Service 3880ab
				IFLA_BOND_ARP_IP_TARGET);
Packit Service 3880ab
			if (NEXT_ARG_OK()) {
Packit Service 3880ab
				NEXT_ARG();
Packit Service 3880ab
				char *targets = strdupa(*argv);
Packit Service 3880ab
				char *target = strtok(targets, ",");
Packit Service 3880ab
				int i;
Packit Service 3880ab
Packit Service 3880ab
				for (i = 0; target && i < BOND_MAX_ARP_TARGETS; i++) {
Packit Service 3880ab
					__u32 addr = get_addr32(target);
Packit Service 3880ab
Packit Service 3880ab
					addattr32(n, 1024, i, addr);
Packit Service 3880ab
					target = strtok(NULL, ",");
Packit Service 3880ab
				}
Packit Service 3880ab
				addattr_nest_end(n, nest);
Packit Service 3880ab
			}
Packit Service 3880ab
			addattr_nest_end(n, nest);
Packit Service 3880ab
		} else if (matches(*argv, "arp_validate") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(arp_validate_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid arp_validate", *argv);
Packit Service 3880ab
			arp_validate = get_index(arp_validate_tbl, *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_ARP_VALIDATE, arp_validate);
Packit Service 3880ab
		} else if (matches(*argv, "arp_all_targets") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(arp_all_targets_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid arp_all_targets", *argv);
Packit Service 3880ab
			arp_all_targets = get_index(arp_all_targets_tbl, *argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_ARP_ALL_TARGETS, arp_all_targets);
Packit Service 3880ab
		} else if (matches(*argv, "primary") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			ifindex = ll_name_to_index(*argv);
Packit Service 3880ab
			if (!ifindex)
Packit Service 3880ab
				return nodev(*argv);
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_PRIMARY, ifindex);
Packit Service 3880ab
		} else if (matches(*argv, "primary_reselect") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(primary_reselect_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid primary_reselect", *argv);
Packit Service 3880ab
			primary_reselect = get_index(primary_reselect_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_PRIMARY_RESELECT,
Packit Service 3880ab
				 primary_reselect);
Packit Service 3880ab
		} else if (matches(*argv, "fail_over_mac") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(fail_over_mac_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid fail_over_mac", *argv);
Packit Service 3880ab
			fail_over_mac = get_index(fail_over_mac_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_FAIL_OVER_MAC,
Packit Service 3880ab
				 fail_over_mac);
Packit Service 3880ab
		} else if (matches(*argv, "xmit_hash_policy") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(xmit_hash_policy_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid xmit_hash_policy", *argv);
Packit Service 3880ab
Packit Service 3880ab
			xmit_hash_policy = get_index(xmit_hash_policy_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_XMIT_HASH_POLICY,
Packit Service 3880ab
				 xmit_hash_policy);
Packit Service 3880ab
		} else if (matches(*argv, "resend_igmp") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&resend_igmp, *argv, 0))
Packit Service 3880ab
				invarg("invalid resend_igmp", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_RESEND_IGMP, resend_igmp);
Packit Service 3880ab
		} else if (matches(*argv, "num_grat_arp") == 0 ||
Packit Service 3880ab
			   matches(*argv, "num_unsol_na") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u8(&num_peer_notif, *argv, 0))
Packit Service 3880ab
				invarg("invalid num_grat_arp|num_unsol_na",
Packit Service 3880ab
				       *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_NUM_PEER_NOTIF,
Packit Service 3880ab
				 num_peer_notif);
Packit Service 3880ab
		} else if (matches(*argv, "all_slaves_active") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u8(&all_slaves_active, *argv, 0))
Packit Service 3880ab
				invarg("invalid all_slaves_active", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_ALL_SLAVES_ACTIVE,
Packit Service 3880ab
				 all_slaves_active);
Packit Service 3880ab
		} else if (matches(*argv, "min_links") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&min_links, *argv, 0))
Packit Service 3880ab
				invarg("invalid min_links", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_MIN_LINKS, min_links);
Packit Service 3880ab
		} else if (matches(*argv, "lp_interval") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&lp_interval, *argv, 0))
Packit Service 3880ab
				invarg("invalid lp_interval", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_LP_INTERVAL, lp_interval);
Packit Service 3880ab
		} else if (matches(*argv, "packets_per_slave") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u32(&packets_per_slave, *argv, 0))
Packit Service 3880ab
				invarg("invalid packets_per_slave", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr32(n, 1024, IFLA_BOND_PACKETS_PER_SLAVE,
Packit Service 3880ab
				  packets_per_slave);
Packit Service 3880ab
		} else if (matches(*argv, "lacp_rate") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(lacp_rate_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid lacp_rate", *argv);
Packit Service 3880ab
Packit Service 3880ab
			lacp_rate = get_index(lacp_rate_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_AD_LACP_RATE, lacp_rate);
Packit Service 3880ab
		} else if (matches(*argv, "ad_select") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_index(ad_select_tbl, *argv) < 0)
Packit Service 3880ab
				invarg("invalid ad_select", *argv);
Packit Service 3880ab
Packit Service 3880ab
			ad_select = get_index(ad_select_tbl, *argv);
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_AD_SELECT, ad_select);
Packit Service 3880ab
		} else if (matches(*argv, "ad_user_port_key") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u16(&ad_user_port_key, *argv, 0))
Packit Service 3880ab
				invarg("invalid ad_user_port_key", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr16(n, 1024, IFLA_BOND_AD_USER_PORT_KEY,
Packit Service 3880ab
				  ad_user_port_key);
Packit Service 3880ab
		} else if (matches(*argv, "ad_actor_sys_prio") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u16(&ad_actor_sys_prio, *argv, 0))
Packit Service 3880ab
				invarg("invalid ad_actor_sys_prio", *argv);
Packit Service 3880ab
Packit Service 3880ab
			addattr16(n, 1024, IFLA_BOND_AD_ACTOR_SYS_PRIO,
Packit Service 3880ab
				  ad_actor_sys_prio);
Packit Service 3880ab
		} else if (matches(*argv, "ad_actor_system") == 0) {
Packit Service 3880ab
			int len;
Packit Service 3880ab
			char abuf[32];
Packit Service 3880ab
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			len = ll_addr_a2n(abuf, sizeof(abuf), *argv);
Packit Service 3880ab
			if (len < 0)
Packit Service 3880ab
				return -1;
Packit Service 3880ab
			addattr_l(n, 1024, IFLA_BOND_AD_ACTOR_SYSTEM,
Packit Service 3880ab
				  abuf, len);
Packit Service 3880ab
		} else if (matches(*argv, "tlb_dynamic_lb") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			if (get_u8(&tlb_dynamic_lb, *argv, 0)) {
Packit Service 3880ab
				invarg("invalid tlb_dynamic_lb", *argv);
Packit Service 3880ab
				return -1;
Packit Service 3880ab
			}
Packit Service 3880ab
			addattr8(n, 1024, IFLA_BOND_TLB_DYNAMIC_LB,
Packit Service 3880ab
				 tlb_dynamic_lb);
Packit Service 3880ab
		} else if (matches(*argv, "help") == 0) {
Packit Service 3880ab
			explain();
Packit Service 3880ab
			return -1;
Packit Service 3880ab
		} else {
Packit Service 3880ab
			fprintf(stderr, "bond: unknown command \"%s\"?\n", *argv);
Packit Service 3880ab
			explain();
Packit Service 3880ab
			return -1;
Packit Service 3880ab
		}
Packit Service 3880ab
		argc--, argv++;
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	return 0;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
Packit Service 3880ab
{
Packit Service 3880ab
	if (!tb)
Packit Service 3880ab
		return;
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_MODE]) {
Packit Service 3880ab
		const char *mode = get_name(mode_tbl,
Packit Service 3880ab
					    rta_getattr_u8(tb[IFLA_BOND_MODE]));
Packit Service 3880ab
		print_string(PRINT_ANY, "mode", "mode %s ", mode);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ACTIVE_SLAVE]) {
Packit Service 3880ab
		unsigned int ifindex =
Packit Service 3880ab
			rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]);
Packit Service 3880ab
Packit Service 3880ab
		if (ifindex) {
Packit Service 3880ab
			print_string(PRINT_ANY,
Packit Service 3880ab
				     "active_slave",
Packit Service 3880ab
				     "active_slave %s ",
Packit Service 3880ab
				     ll_index_to_name(ifindex));
Packit Service 3880ab
		}
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_MIIMON])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "miimon",
Packit Service 3880ab
			   "miimon %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_MIIMON]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_UPDELAY])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "updelay",
Packit Service 3880ab
			   "updelay %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_UPDELAY]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_DOWNDELAY])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "downdelay",
Packit Service 3880ab
			   "downdelay %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_PEER_NOTIF_DELAY])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "peer_notify_delay",
Packit Service 3880ab
			   "peer_notify_delay %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_PEER_NOTIF_DELAY]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_USE_CARRIER])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "use_carrier",
Packit Service 3880ab
			   "use_carrier %u ",
Packit Service 3880ab
			   rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ARP_INTERVAL])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "arp_interval",
Packit Service 3880ab
			   "arp_interval %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ARP_IP_TARGET]) {
Packit Service 3880ab
		struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1];
Packit Service 3880ab
		int i;
Packit Service 3880ab
Packit Service 3880ab
		parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS,
Packit Service 3880ab
				    tb[IFLA_BOND_ARP_IP_TARGET]);
Packit Service 3880ab
Packit Service 3880ab
		if (iptb[0]) {
Packit Service 3880ab
			open_json_array(PRINT_JSON, "arp_ip_target");
Packit Service 3880ab
			print_string(PRINT_FP, NULL, "arp_ip_target ", NULL);
Packit Service 3880ab
		}
Packit Service 3880ab
Packit Service 3880ab
		for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
Packit Service 3880ab
			if (iptb[i])
Packit Service 3880ab
				print_string(PRINT_ANY,
Packit Service 3880ab
					     NULL,
Packit Service 3880ab
					     "%s",
Packit Service 3880ab
					     rt_addr_n2a_rta(AF_INET, iptb[i]));
Packit Service 3880ab
			if (!is_json_context()
Packit Service 3880ab
			    && i < BOND_MAX_ARP_TARGETS-1
Packit Service 3880ab
			    && iptb[i+1])
Packit Service 3880ab
				fprintf(f, ",");
Packit Service 3880ab
		}
Packit Service 3880ab
Packit Service 3880ab
		if (iptb[0]) {
Packit Service 3880ab
			print_string(PRINT_FP, NULL, " ", NULL);
Packit Service 3880ab
			close_json_array(PRINT_JSON, NULL);
Packit Service 3880ab
		}
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ARP_VALIDATE]) {
Packit Service 3880ab
		__u32 arp_v = rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE]);
Packit Service 3880ab
		const char *arp_validate = get_name(arp_validate_tbl, arp_v);
Packit Service 3880ab
Packit Service 3880ab
		if (!arp_v && is_json_context())
Packit Service 3880ab
			print_null(PRINT_JSON, "arp_validate", NULL, NULL);
Packit Service 3880ab
		else
Packit Service 3880ab
			print_string(PRINT_ANY,
Packit Service 3880ab
				     "arp_validate",
Packit Service 3880ab
				     "arp_validate %s ",
Packit Service 3880ab
				     arp_validate);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ARP_ALL_TARGETS]) {
Packit Service 3880ab
		const char *arp_all_targets = get_name(arp_all_targets_tbl,
Packit Service 3880ab
						       rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "arp_all_targets",
Packit Service 3880ab
			     "arp_all_targets %s ",
Packit Service 3880ab
			     arp_all_targets);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_PRIMARY]) {
Packit Service 3880ab
		unsigned int ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]);
Packit Service 3880ab
Packit Service 3880ab
		if (ifindex) {
Packit Service 3880ab
			print_string(PRINT_ANY,
Packit Service 3880ab
				     "primary",
Packit Service 3880ab
				     "primary %s ",
Packit Service 3880ab
				     ll_index_to_name(ifindex));
Packit Service 3880ab
		}
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_PRIMARY_RESELECT]) {
Packit Service 3880ab
		const char *primary_reselect = get_name(primary_reselect_tbl,
Packit Service 3880ab
							rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "primary_reselect",
Packit Service 3880ab
			     "primary_reselect %s ",
Packit Service 3880ab
			     primary_reselect);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_FAIL_OVER_MAC]) {
Packit Service 3880ab
		const char *fail_over_mac = get_name(fail_over_mac_tbl,
Packit Service 3880ab
						     rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "fail_over_mac",
Packit Service 3880ab
			     "fail_over_mac %s ",
Packit Service 3880ab
			     fail_over_mac);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_XMIT_HASH_POLICY]) {
Packit Service 3880ab
		const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl,
Packit Service 3880ab
							rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "xmit_hash_policy",
Packit Service 3880ab
			     "xmit_hash_policy %s ",
Packit Service 3880ab
			     xmit_hash_policy);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_RESEND_IGMP])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "resend_igmp",
Packit Service 3880ab
			   "resend_igmp %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_NUM_PEER_NOTIF])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "num_peer_notif",
Packit Service 3880ab
			   "num_grat_arp %u ",
Packit Service 3880ab
			   rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "all_slaves_active",
Packit Service 3880ab
			   "all_slaves_active %u ",
Packit Service 3880ab
			   rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_MIN_LINKS])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "min_links",
Packit Service 3880ab
			   "min_links %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_LP_INTERVAL])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "lp_interval",
Packit Service 3880ab
			   "lp_interval %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_PACKETS_PER_SLAVE])
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "packets_per_slave",
Packit Service 3880ab
			   "packets_per_slave %u ",
Packit Service 3880ab
			   rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE]));
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_LACP_RATE]) {
Packit Service 3880ab
		const char *lacp_rate = get_name(lacp_rate_tbl,
Packit Service 3880ab
						 rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "ad_lacp_rate",
Packit Service 3880ab
			     "lacp_rate %s ",
Packit Service 3880ab
			     lacp_rate);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_SELECT]) {
Packit Service 3880ab
		const char *ad_select = get_name(ad_select_tbl,
Packit Service 3880ab
						 rta_getattr_u8(tb[IFLA_BOND_AD_SELECT]));
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "ad_select",
Packit Service 3880ab
			     "ad_select %s ",
Packit Service 3880ab
			     ad_select);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_INFO]) {
Packit Service 3880ab
		struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1];
Packit Service 3880ab
Packit Service 3880ab
		parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX,
Packit Service 3880ab
				    tb[IFLA_BOND_AD_INFO]);
Packit Service 3880ab
Packit Service 3880ab
		open_json_object("ad_info");
Packit Service 3880ab
Packit Service 3880ab
		if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR])
Packit Service 3880ab
			print_int(PRINT_ANY,
Packit Service 3880ab
				  "aggregator",
Packit Service 3880ab
				  "ad_aggregator %d ",
Packit Service 3880ab
				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR]));
Packit Service 3880ab
Packit Service 3880ab
		if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS])
Packit Service 3880ab
			print_int(PRINT_ANY,
Packit Service 3880ab
				  "num_ports",
Packit Service 3880ab
				  "ad_num_ports %d ",
Packit Service 3880ab
				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS]));
Packit Service 3880ab
Packit Service 3880ab
		if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])
Packit Service 3880ab
			print_int(PRINT_ANY,
Packit Service 3880ab
				  "actor_key",
Packit Service 3880ab
				  "ad_actor_key %d ",
Packit Service 3880ab
				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]));
Packit Service 3880ab
Packit Service 3880ab
		if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])
Packit Service 3880ab
			print_int(PRINT_ANY,
Packit Service 3880ab
				  "partner_key",
Packit Service 3880ab
				  "ad_partner_key %d ",
Packit Service 3880ab
				  rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]));
Packit Service 3880ab
Packit Service 3880ab
		if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) {
Packit Service 3880ab
			unsigned char *p =
Packit Service 3880ab
				RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]);
Packit Service 3880ab
			SPRINT_BUF(b);
Packit Service 3880ab
			print_string(PRINT_ANY,
Packit Service 3880ab
				     "partner_mac",
Packit Service 3880ab
				     "ad_partner_mac %s ",
Packit Service 3880ab
				     ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b)));
Packit Service 3880ab
		}
Packit Service 3880ab
Packit Service 3880ab
		close_json_object();
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]) {
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "ad_actor_sys_prio",
Packit Service 3880ab
			   "ad_actor_sys_prio %u ",
Packit Service 3880ab
			   rta_getattr_u16(tb[IFLA_BOND_AD_ACTOR_SYS_PRIO]));
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_USER_PORT_KEY]) {
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "ad_user_port_key",
Packit Service 3880ab
			   "ad_user_port_key %u ",
Packit Service 3880ab
			   rta_getattr_u16(tb[IFLA_BOND_AD_USER_PORT_KEY]));
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_AD_ACTOR_SYSTEM]) {
Packit Service 3880ab
		/* We assume the l2 address is an Ethernet MAC address */
Packit Service 3880ab
		SPRINT_BUF(b1);
Packit Service 3880ab
Packit Service 3880ab
		print_string(PRINT_ANY,
Packit Service 3880ab
			     "ad_actor_system",
Packit Service 3880ab
			     "ad_actor_system %s ",
Packit Service 3880ab
			     ll_addr_n2a(RTA_DATA(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
Packit Service 3880ab
					 RTA_PAYLOAD(tb[IFLA_BOND_AD_ACTOR_SYSTEM]),
Packit Service 3880ab
					 1 /*ARPHDR_ETHER*/, b1, sizeof(b1)));
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_BOND_TLB_DYNAMIC_LB]) {
Packit Service 3880ab
		print_uint(PRINT_ANY,
Packit Service 3880ab
			   "tlb_dynamic_lb",
Packit Service 3880ab
			   "tlb_dynamic_lb %u ",
Packit Service 3880ab
			   rta_getattr_u8(tb[IFLA_BOND_TLB_DYNAMIC_LB]));
Packit Service 3880ab
	}
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void bond_print_help(struct link_util *lu, int argc, char **argv,
Packit Service 3880ab
			    FILE *f)
Packit Service 3880ab
{
Packit Service 3880ab
	print_explain(f);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void bond_print_xstats_help(struct link_util *lu, FILE *f)
Packit Service 3880ab
{
Packit Service 3880ab
	fprintf(f, "Usage: ... %s [ 802.3ad ] [ dev DEVICE ]\n", lu->id);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void bond_print_3ad_stats(struct rtattr *lacpattr)
Packit Service 3880ab
{
Packit Service 3880ab
	struct rtattr *lacptb[BOND_3AD_STAT_MAX+1];
Packit Service 3880ab
	__u64 val;
Packit Service 3880ab
Packit Service 3880ab
	parse_rtattr(lacptb, BOND_3AD_STAT_MAX, RTA_DATA(lacpattr),
Packit Service 3880ab
		     RTA_PAYLOAD(lacpattr));
Packit Service 3880ab
	open_json_object("802.3ad");
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_LACPDU_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		print_u64(PRINT_ANY, "lacpdu_rx", "LACPDU Rx %llu\n",
Packit Service 3880ab
			  rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_RX]));
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_LACPDU_TX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		print_u64(PRINT_ANY, "lacpdu_tx", "LACPDU Tx %llu\n",
Packit Service 3880ab
			  rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_TX]));
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_UNKNOWN_RX]);
Packit Service 3880ab
		print_u64(PRINT_ANY,
Packit Service 3880ab
			  "lacpdu_unknown_rx",
Packit Service 3880ab
			  "LACPDU Unknown type Rx %llu\n",
Packit Service 3880ab
			  val);
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		val = rta_getattr_u64(lacptb[BOND_3AD_STAT_LACPDU_ILLEGAL_RX]);
Packit Service 3880ab
		print_u64(PRINT_ANY,
Packit Service 3880ab
			  "lacpdu_illegal_rx",
Packit Service 3880ab
			  "LACPDU Illegal Rx %llu\n",
Packit Service 3880ab
			  val);
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_MARKER_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		print_u64(PRINT_ANY, "marker_rx", "Marker Rx %llu\n",
Packit Service 3880ab
			  rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RX]));
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_MARKER_TX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		print_u64(PRINT_ANY, "marker_tx", "Marker Tx %llu\n",
Packit Service 3880ab
			  rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_TX]));
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_MARKER_RESP_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_RX]);
Packit Service 3880ab
		print_u64(PRINT_ANY,
Packit Service 3880ab
			  "marker_response_rx",
Packit Service 3880ab
			  "Marker response Rx %llu\n",
Packit Service 3880ab
			  val);
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_MARKER_RESP_TX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_RESP_TX]);
Packit Service 3880ab
		print_u64(PRINT_ANY,
Packit Service 3880ab
			  "marker_response_tx",
Packit Service 3880ab
			  "Marker response Tx %llu\n",
Packit Service 3880ab
			  val);
Packit Service 3880ab
	}
Packit Service 3880ab
	if (lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]) {
Packit Service 3880ab
		print_string(PRINT_FP, NULL, "%-16s    ", "");
Packit Service 3880ab
		val = rta_getattr_u64(lacptb[BOND_3AD_STAT_MARKER_UNKNOWN_RX]);
Packit Service 3880ab
		print_u64(PRINT_ANY,
Packit Service 3880ab
			  "marker_unknown_rx",
Packit Service 3880ab
			  "Marker unknown type Rx %llu\n",
Packit Service 3880ab
			  val);
Packit Service 3880ab
	}
Packit Service 3880ab
	close_json_object();
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static void bond_print_stats_attr(struct rtattr *attr, int ifindex)
Packit Service 3880ab
{
Packit Service 3880ab
	struct rtattr *bondtb[LINK_XSTATS_TYPE_MAX+1];
Packit Service 3880ab
	struct rtattr *i, *list;
Packit Service 3880ab
	const char *ifname = "";
Packit Service 3880ab
	int rem;
Packit Service 3880ab
Packit Service 3880ab
	parse_rtattr(bondtb, LINK_XSTATS_TYPE_MAX+1, RTA_DATA(attr),
Packit Service 3880ab
	RTA_PAYLOAD(attr));
Packit Service 3880ab
	if (!bondtb[LINK_XSTATS_TYPE_BOND])
Packit Service 3880ab
		return;
Packit Service 3880ab
Packit Service 3880ab
	list = bondtb[LINK_XSTATS_TYPE_BOND];
Packit Service 3880ab
	rem = RTA_PAYLOAD(list);
Packit Service 3880ab
	open_json_object(NULL);
Packit Service 3880ab
	ifname = ll_index_to_name(ifindex);
Packit Service 3880ab
	print_string(PRINT_ANY, "ifname", "%-16s\n", ifname);
Packit Service 3880ab
	for (i = RTA_DATA(list); RTA_OK(i, rem); i = RTA_NEXT(i, rem)) {
Packit Service 3880ab
		if (xstats_print_attr && i->rta_type != xstats_print_attr)
Packit Service 3880ab
			continue;
Packit Service 3880ab
Packit Service 3880ab
		switch (i->rta_type) {
Packit Service 3880ab
		case BOND_XSTATS_3AD:
Packit Service 3880ab
			bond_print_3ad_stats(i);
Packit Service 3880ab
			break;
Packit Service 3880ab
		}
Packit Service 3880ab
		break;
Packit Service 3880ab
	}
Packit Service 3880ab
	close_json_object();
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
int bond_print_xstats(struct nlmsghdr *n, void *arg)
Packit Service 3880ab
{
Packit Service 3880ab
	struct if_stats_msg *ifsm = NLMSG_DATA(n);
Packit Service 3880ab
	struct rtattr *tb[IFLA_STATS_MAX+1];
Packit Service 3880ab
	int len = n->nlmsg_len;
Packit Service 3880ab
Packit Service 3880ab
	len -= NLMSG_LENGTH(sizeof(*ifsm));
Packit Service 3880ab
	if (len < 0) {
Packit Service 3880ab
		fprintf(stderr, "BUG: wrong nlmsg len %d\n", len);
Packit Service 3880ab
		return -1;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (filter_index && filter_index != ifsm->ifindex)
Packit Service 3880ab
		return 0;
Packit Service 3880ab
Packit Service 3880ab
	parse_rtattr(tb, IFLA_STATS_MAX, IFLA_STATS_RTA(ifsm), len);
Packit Service 3880ab
	if (tb[IFLA_STATS_LINK_XSTATS])
Packit Service 3880ab
		bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS],
Packit Service 3880ab
				      ifsm->ifindex);
Packit Service 3880ab
Packit Service 3880ab
	if (tb[IFLA_STATS_LINK_XSTATS_SLAVE])
Packit Service 3880ab
		bond_print_stats_attr(tb[IFLA_STATS_LINK_XSTATS_SLAVE],
Packit Service 3880ab
				      ifsm->ifindex);
Packit Service 3880ab
Packit Service 3880ab
	return 0;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
int bond_parse_xstats(struct link_util *lu, int argc, char **argv)
Packit Service 3880ab
{
Packit Service 3880ab
	while (argc > 0) {
Packit Service 3880ab
		if (strcmp(*argv, "lacp") == 0 ||
Packit Service 3880ab
		    strcmp(*argv, "802.3ad") == 0) {
Packit Service 3880ab
			xstats_print_attr = BOND_XSTATS_3AD;
Packit Service 3880ab
		} else if (strcmp(*argv, "dev") == 0) {
Packit Service 3880ab
			NEXT_ARG();
Packit Service 3880ab
			filter_index = ll_name_to_index(*argv);
Packit Service 3880ab
			if (!filter_index)
Packit Service 3880ab
				return nodev(*argv);
Packit Service 3880ab
		} else if (strcmp(*argv, "help") == 0) {
Packit Service 3880ab
			bond_print_xstats_help(lu, stdout);
Packit Service 3880ab
			exit(0);
Packit Service 3880ab
		} else {
Packit Service 3880ab
			invarg("unknown attribute", *argv);
Packit Service 3880ab
		}
Packit Service 3880ab
		argc--; argv++;
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	return 0;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
Packit Service 3880ab
struct link_util bond_link_util = {
Packit Service 3880ab
	.id		= "bond",
Packit Service 3880ab
	.maxattr	= IFLA_BOND_MAX,
Packit Service 3880ab
	.parse_opt	= bond_parse_opt,
Packit Service 3880ab
	.print_opt	= bond_print_opt,
Packit Service 3880ab
	.print_help	= bond_print_help,
Packit Service 3880ab
	.parse_ifla_xstats = bond_parse_xstats,
Packit Service 3880ab
	.print_ifla_xstats = bond_print_xstats,
Packit Service 3880ab
};