| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * drivers/net/bond/bond_netlink.c - Netlink interface for bonding |
|---|
| 3 | 4 | * Copyright (c) 2013 Jiri Pirko <jiri@resnulli.us> |
|---|
| 4 | 5 | * Copyright (c) 2013 Scott Feldman <sfeldma@cumulusnetworks.com> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 7 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 8 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 9 | | - * (at your option) any later version. |
|---|
| 10 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 112 | 108 | [IFLA_BOND_AD_ACTOR_SYSTEM] = { .type = NLA_BINARY, |
|---|
| 113 | 109 | .len = ETH_ALEN }, |
|---|
| 114 | 110 | [IFLA_BOND_TLB_DYNAMIC_LB] = { .type = NLA_U8 }, |
|---|
| 111 | + [IFLA_BOND_PEER_NOTIF_DELAY] = { .type = NLA_U32 }, |
|---|
| 115 | 112 | }; |
|---|
| 116 | 113 | |
|---|
| 117 | 114 | static const struct nla_policy bond_slave_policy[IFLA_BOND_SLAVE_MAX + 1] = { |
|---|
| .. | .. |
|---|
| 216 | 213 | |
|---|
| 217 | 214 | bond_opt_initval(&newval, downdelay); |
|---|
| 218 | 215 | err = __bond_opt_set(bond, BOND_OPT_DOWNDELAY, &newval); |
|---|
| 216 | + if (err) |
|---|
| 217 | + return err; |
|---|
| 218 | + } |
|---|
| 219 | + if (data[IFLA_BOND_PEER_NOTIF_DELAY]) { |
|---|
| 220 | + int delay = nla_get_u32(data[IFLA_BOND_PEER_NOTIF_DELAY]); |
|---|
| 221 | + |
|---|
| 222 | + bond_opt_initval(&newval, delay); |
|---|
| 223 | + err = __bond_opt_set(bond, BOND_OPT_PEER_NOTIF_DELAY, &newval); |
|---|
| 219 | 224 | if (err) |
|---|
| 220 | 225 | return err; |
|---|
| 221 | 226 | } |
|---|
| .. | .. |
|---|
| 497 | 502 | nla_total_size(sizeof(u16)) + /* IFLA_BOND_AD_USER_PORT_KEY */ |
|---|
| 498 | 503 | nla_total_size(ETH_ALEN) + /* IFLA_BOND_AD_ACTOR_SYSTEM */ |
|---|
| 499 | 504 | nla_total_size(sizeof(u8)) + /* IFLA_BOND_TLB_DYNAMIC_LB */ |
|---|
| 505 | + nla_total_size(sizeof(u32)) + /* IFLA_BOND_PEER_NOTIF_DELAY */ |
|---|
| 500 | 506 | 0; |
|---|
| 501 | 507 | } |
|---|
| 502 | 508 | |
|---|
| .. | .. |
|---|
| 539 | 545 | bond->params.downdelay * bond->params.miimon)) |
|---|
| 540 | 546 | goto nla_put_failure; |
|---|
| 541 | 547 | |
|---|
| 548 | + if (nla_put_u32(skb, IFLA_BOND_PEER_NOTIF_DELAY, |
|---|
| 549 | + bond->params.peer_notif_delay * bond->params.miimon)) |
|---|
| 550 | + goto nla_put_failure; |
|---|
| 551 | + |
|---|
| 542 | 552 | if (nla_put_u8(skb, IFLA_BOND_USE_CARRIER, bond->params.use_carrier)) |
|---|
| 543 | 553 | goto nla_put_failure; |
|---|
| 544 | 554 | |
|---|
| 545 | 555 | if (nla_put_u32(skb, IFLA_BOND_ARP_INTERVAL, bond->params.arp_interval)) |
|---|
| 546 | 556 | goto nla_put_failure; |
|---|
| 547 | 557 | |
|---|
| 548 | | - targets = nla_nest_start(skb, IFLA_BOND_ARP_IP_TARGET); |
|---|
| 558 | + targets = nla_nest_start_noflag(skb, IFLA_BOND_ARP_IP_TARGET); |
|---|
| 549 | 559 | if (!targets) |
|---|
| 550 | 560 | goto nla_put_failure; |
|---|
| 551 | 561 | |
|---|
| .. | .. |
|---|
| 643 | 653 | if (!bond_3ad_get_active_agg_info(bond, &info)) { |
|---|
| 644 | 654 | struct nlattr *nest; |
|---|
| 645 | 655 | |
|---|
| 646 | | - nest = nla_nest_start(skb, IFLA_BOND_AD_INFO); |
|---|
| 656 | + nest = nla_nest_start_noflag(skb, IFLA_BOND_AD_INFO); |
|---|
| 647 | 657 | if (!nest) |
|---|
| 648 | 658 | goto nla_put_failure; |
|---|
| 649 | 659 | |
|---|
| .. | .. |
|---|
| 674 | 684 | return -EMSGSIZE; |
|---|
| 675 | 685 | } |
|---|
| 676 | 686 | |
|---|
| 687 | +static size_t bond_get_linkxstats_size(const struct net_device *dev, int attr) |
|---|
| 688 | +{ |
|---|
| 689 | + switch (attr) { |
|---|
| 690 | + case IFLA_STATS_LINK_XSTATS: |
|---|
| 691 | + case IFLA_STATS_LINK_XSTATS_SLAVE: |
|---|
| 692 | + break; |
|---|
| 693 | + default: |
|---|
| 694 | + return 0; |
|---|
| 695 | + } |
|---|
| 696 | + |
|---|
| 697 | + return bond_3ad_stats_size() + nla_total_size(0); |
|---|
| 698 | +} |
|---|
| 699 | + |
|---|
| 700 | +static int bond_fill_linkxstats(struct sk_buff *skb, |
|---|
| 701 | + const struct net_device *dev, |
|---|
| 702 | + int *prividx, int attr) |
|---|
| 703 | +{ |
|---|
| 704 | + struct nlattr *nla __maybe_unused; |
|---|
| 705 | + struct slave *slave = NULL; |
|---|
| 706 | + struct nlattr *nest, *nest2; |
|---|
| 707 | + struct bonding *bond; |
|---|
| 708 | + |
|---|
| 709 | + switch (attr) { |
|---|
| 710 | + case IFLA_STATS_LINK_XSTATS: |
|---|
| 711 | + bond = netdev_priv(dev); |
|---|
| 712 | + break; |
|---|
| 713 | + case IFLA_STATS_LINK_XSTATS_SLAVE: |
|---|
| 714 | + slave = bond_slave_get_rtnl(dev); |
|---|
| 715 | + if (!slave) |
|---|
| 716 | + return 0; |
|---|
| 717 | + bond = slave->bond; |
|---|
| 718 | + break; |
|---|
| 719 | + default: |
|---|
| 720 | + return -EINVAL; |
|---|
| 721 | + } |
|---|
| 722 | + |
|---|
| 723 | + nest = nla_nest_start_noflag(skb, LINK_XSTATS_TYPE_BOND); |
|---|
| 724 | + if (!nest) |
|---|
| 725 | + return -EMSGSIZE; |
|---|
| 726 | + if (BOND_MODE(bond) == BOND_MODE_8023AD) { |
|---|
| 727 | + struct bond_3ad_stats *stats; |
|---|
| 728 | + |
|---|
| 729 | + if (slave) |
|---|
| 730 | + stats = &SLAVE_AD_INFO(slave)->stats; |
|---|
| 731 | + else |
|---|
| 732 | + stats = &BOND_AD_INFO(bond).stats; |
|---|
| 733 | + |
|---|
| 734 | + nest2 = nla_nest_start_noflag(skb, BOND_XSTATS_3AD); |
|---|
| 735 | + if (!nest2) { |
|---|
| 736 | + nla_nest_end(skb, nest); |
|---|
| 737 | + return -EMSGSIZE; |
|---|
| 738 | + } |
|---|
| 739 | + |
|---|
| 740 | + if (bond_3ad_stats_fill(skb, stats)) { |
|---|
| 741 | + nla_nest_cancel(skb, nest2); |
|---|
| 742 | + nla_nest_end(skb, nest); |
|---|
| 743 | + return -EMSGSIZE; |
|---|
| 744 | + } |
|---|
| 745 | + nla_nest_end(skb, nest2); |
|---|
| 746 | + } |
|---|
| 747 | + nla_nest_end(skb, nest); |
|---|
| 748 | + |
|---|
| 749 | + return 0; |
|---|
| 750 | +} |
|---|
| 751 | + |
|---|
| 677 | 752 | struct rtnl_link_ops bond_link_ops __read_mostly = { |
|---|
| 678 | 753 | .kind = "bond", |
|---|
| 679 | 754 | .priv_size = sizeof(struct bonding), |
|---|
| .. | .. |
|---|
| 688 | 763 | .get_num_tx_queues = bond_get_num_tx_queues, |
|---|
| 689 | 764 | .get_num_rx_queues = bond_get_num_tx_queues, /* Use the same number |
|---|
| 690 | 765 | as for TX queues */ |
|---|
| 766 | + .fill_linkxstats = bond_fill_linkxstats, |
|---|
| 767 | + .get_linkxstats_size = bond_get_linkxstats_size, |
|---|
| 691 | 768 | .slave_maxtype = IFLA_BOND_SLAVE_MAX, |
|---|
| 692 | 769 | .slave_policy = bond_slave_policy, |
|---|
| 693 | 770 | .slave_changelink = bond_slave_changelink, |
|---|