mirror of
https://github.com/coolsnowwolf/lede.git
synced 2025-04-16 04:13:31 +00:00
537 lines
17 KiB
Diff
537 lines
17 KiB
Diff
From 0403eceee14bb6eb4e417102cae830b7509b1554 Mon Sep 17 00:00:00 2001
|
|
From: Shivani Soni <quic_soni@quicinc.com>
|
|
Date: Thu, 17 Nov 2022 00:16:38 +0530
|
|
Subject: [PATCH] arm/arm64: Add support for MLO bonding
|
|
|
|
1. Introduced BOND_MODE_MLO to support MLO bonding
|
|
2. Transmit handling according to new mode
|
|
|
|
Change-Id: Ib272e77cce56ee50b0a13305fac8fae76743c206
|
|
Signed-off-by: Shivani Soni <quic_soni@quicinc.com>
|
|
---
|
|
drivers/net/bonding/bond_main.c | 212 ++++++++++++++++++++++++-----
|
|
drivers/net/bonding/bond_options.c | 1 +
|
|
include/net/bonding.h | 30 +++-
|
|
include/uapi/linux/if_bonding.h | 1 +
|
|
4 files changed, 210 insertions(+), 34 deletions(-)
|
|
|
|
--- a/drivers/net/bonding/bond_main.c
|
|
+++ b/drivers/net/bonding/bond_main.c
|
|
@@ -1467,6 +1467,10 @@ static netdev_features_t bond_fix_featur
|
|
return features;
|
|
}
|
|
|
|
+#define BOND_MLO_VLAN_FEATURES (NETIF_F_SG | \
|
|
+ NETIF_F_FRAGLIST | \
|
|
+ NETIF_F_HIGHDMA | NETIF_F_LRO)
|
|
+
|
|
#define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
|
|
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
|
|
NETIF_F_HIGHDMA | NETIF_F_LRO)
|
|
@@ -1497,13 +1501,25 @@ static void bond_compute_features(struct
|
|
|
|
if (!bond_has_slaves(bond))
|
|
goto done;
|
|
+
|
|
+ /*
|
|
+ * Use features specific to bond MLO
|
|
+ */
|
|
+ if (BOND_MODE(bond) == BOND_MODE_MLO) {
|
|
+ vlan_features = BOND_MLO_VLAN_FEATURES;
|
|
+ }
|
|
+
|
|
vlan_features &= NETIF_F_ALL_FOR_ALL;
|
|
mpls_features &= NETIF_F_ALL_FOR_ALL;
|
|
|
|
bond_for_each_slave(bond, slave, iter) {
|
|
- vlan_features = netdev_increment_features(vlan_features,
|
|
- slave->dev->vlan_features, BOND_VLAN_FEATURES);
|
|
-
|
|
+ if (BOND_MODE(bond) == BOND_MODE_MLO) {
|
|
+ vlan_features = netdev_increment_features(vlan_features,
|
|
+ slave->dev->vlan_features, BOND_MLO_VLAN_FEATURES);
|
|
+ } else {
|
|
+ vlan_features = netdev_increment_features(vlan_features,
|
|
+ slave->dev->vlan_features, BOND_VLAN_FEATURES);
|
|
+ }
|
|
enc_features = netdev_increment_features(enc_features,
|
|
slave->dev->hw_enc_features,
|
|
BOND_ENC_FEATURES);
|
|
@@ -1648,6 +1664,16 @@ static rx_handler_result_t bond_handle_f
|
|
bond->dev->addr_len);
|
|
}
|
|
|
|
+ /*
|
|
+ * Set the PACKET_HOST for MLO mode as
|
|
+ * MLO bond netdevice needs to support routing
|
|
+ */
|
|
+ if (BOND_MODE(bond) == BOND_MODE_MLO) {
|
|
+ if (ether_addr_equal(bond->dev->dev_addr, eth_hdr(skb)->h_dest)) {
|
|
+ skb->pkt_type = PACKET_HOST;
|
|
+ }
|
|
+ }
|
|
+
|
|
return ret;
|
|
}
|
|
|
|
@@ -1865,6 +1891,8 @@ int bond_enslave(struct net_device *bond
|
|
return -EPERM;
|
|
}
|
|
|
|
+ ASSERT_RTNL();
|
|
+
|
|
if (!bond->params.use_carrier &&
|
|
slave_dev->ethtool_ops->get_link == NULL &&
|
|
slave_ops->ndo_eth_ioctl == NULL) {
|
|
@@ -1978,13 +2006,17 @@ int bond_enslave(struct net_device *bond
|
|
call_netdevice_notifiers(NETDEV_JOIN, slave_dev);
|
|
|
|
/* If this is the first slave, then we need to set the master's hardware
|
|
- * address to be the same as the slave's.
|
|
+ * address to be the same as the slave's except for BOND_MODE_MLO.
|
|
+ * For BOND_MODE_MLO, master's mac address is MLD address which should
|
|
+ * not be same as slave's address.
|
|
*/
|
|
- if (!bond_has_slaves(bond) &&
|
|
- bond->dev->addr_assign_type == NET_ADDR_RANDOM) {
|
|
- res = bond_set_dev_addr(bond->dev, slave_dev);
|
|
- if (res)
|
|
- goto err_undo_flags;
|
|
+ if (BOND_MODE(bond) != BOND_MODE_MLO) {
|
|
+ if (!bond_has_slaves(bond) &&
|
|
+ bond->dev->addr_assign_type == NET_ADDR_RANDOM) {
|
|
+ res = bond_set_dev_addr(bond->dev, slave_dev);
|
|
+ if (res)
|
|
+ goto err_undo_flags;
|
|
+ }
|
|
}
|
|
|
|
new_slave = bond_alloc_slave(bond, slave_dev);
|
|
@@ -2013,18 +2045,21 @@ int bond_enslave(struct net_device *bond
|
|
bond_hw_addr_copy(new_slave->perm_hwaddr, slave_dev->dev_addr,
|
|
slave_dev->addr_len);
|
|
|
|
- if (!bond->params.fail_over_mac ||
|
|
- BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
|
|
- /* Set slave to master's mac address. The application already
|
|
- * set the master's mac address to that of the first slave
|
|
- */
|
|
- memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len);
|
|
- ss.ss_family = slave_dev->type;
|
|
- res = dev_set_mac_address(slave_dev, (struct sockaddr *)&ss,
|
|
- extack);
|
|
- if (res) {
|
|
- slave_err(bond_dev, slave_dev, "Error %d calling set_mac_address\n", res);
|
|
- goto err_restore_mtu;
|
|
+ /* Set slave to master's mac address except for BOND_MODE_MLO
|
|
+ * as for MLO mode master's mac address is not same as slave's mac address.
|
|
+ * The application already set the master's mac address to that of the first slave
|
|
+ */
|
|
+ if (BOND_MODE(bond) != BOND_MODE_MLO) {
|
|
+ if (!bond->params.fail_over_mac ||
|
|
+ BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
|
|
+ memcpy(ss.__data, bond_dev->dev_addr, bond_dev->addr_len);
|
|
+ ss.ss_family = slave_dev->type;
|
|
+ res = dev_set_mac_address(slave_dev, (struct sockaddr *)&ss,
|
|
+ extack);
|
|
+ if (res) {
|
|
+ slave_err(bond_dev, slave_dev, "Error %d calling set_mac_address\n", res);
|
|
+ goto err_restore_mtu;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -2383,6 +2418,7 @@ err_undo_flags:
|
|
|
|
return res;
|
|
}
|
|
+EXPORT_SYMBOL(bond_enslave);
|
|
|
|
/* Try to release the slave device <slave> from the bond device <master>
|
|
* It is legal to access curr_active_slave without a lock because all the function
|
|
@@ -2504,13 +2540,23 @@ static int __bond_release_one(struct net
|
|
}
|
|
|
|
bond_set_carrier(bond);
|
|
- if (!bond_has_slaves(bond))
|
|
- eth_hw_addr_random(bond_dev);
|
|
+
|
|
+ /*
|
|
+ * Avoid changing the mac address of bond netdevice for MLO case,
|
|
+ * This will only be supported from wifi driver.
|
|
+ */
|
|
+ if (BOND_MODE(bond) != BOND_MODE_MLO) {
|
|
+ if (!bond_has_slaves(bond))
|
|
+ eth_hw_addr_random(bond_dev);
|
|
+ }
|
|
|
|
unblock_netpoll_tx();
|
|
synchronize_rcu();
|
|
bond->slave_cnt--;
|
|
|
|
+ /*
|
|
+ * TODO: Avoid MAC address change notification for BOND_MODE_MLO
|
|
+ */
|
|
if (!bond_has_slaves(bond)) {
|
|
call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
|
|
call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
|
|
@@ -2577,6 +2623,7 @@ int bond_release(struct net_device *bond
|
|
{
|
|
return __bond_release_one(bond_dev, slave_dev, false, false);
|
|
}
|
|
+EXPORT_SYMBOL(bond_release);
|
|
|
|
/* First release a slave and then destroy the bond if no more slaves are left.
|
|
* Must be under rtnl_lock when this function is called.
|
|
@@ -2598,6 +2645,29 @@ static int bond_release_and_destroy(stru
|
|
return ret;
|
|
}
|
|
|
|
+/* Destroy the bond for BOND_MODE_MLO if no more slaves are left.
|
|
+ * Must be under rtnl_lock when this function is called.
|
|
+ */
|
|
+bool bond_destroy_mlo(struct net_device *bond_dev)
|
|
+{
|
|
+ struct bonding *bond = netdev_priv(bond_dev);
|
|
+
|
|
+ ASSERT_RTNL();
|
|
+
|
|
+ if (!bond_has_slaves(bond)) {
|
|
+ bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
|
|
+ netdev_info(bond_dev, "Destroying bond as no slaves are present\n");
|
|
+ bond_remove_proc_entry(bond);
|
|
+ unregister_netdevice(bond_dev);
|
|
+ return true;
|
|
+ }
|
|
+
|
|
+ pr_err("%p: Not able to destroy bond netdevice: %s as slaves are present\n", bond_dev, bond_dev->name);
|
|
+
|
|
+ return false;
|
|
+}
|
|
+EXPORT_SYMBOL(bond_destroy_mlo);
|
|
+
|
|
static void bond_info_query(struct net_device *bond_dev, struct ifbond *info)
|
|
{
|
|
struct bonding *bond = netdev_priv(bond_dev);
|
|
@@ -4249,6 +4319,24 @@ static struct net_device *bond_xor_get_t
|
|
return NULL;
|
|
}
|
|
|
|
+/* Transmit function for BOND_MODE_MLO.
|
|
+ * Get transmit link interface from registered callback.
|
|
+ */
|
|
+struct net_device *bond_mlo_get_tx_dev(struct net_device *bond_dev, u8 *dst_mac)
|
|
+{
|
|
+ struct net_device *slave_dev = NULL;
|
|
+ struct mlo_bond_info *mlo_info = NULL;
|
|
+ void *bond_mlo_ctx;
|
|
+
|
|
+ mlo_info = bond_get_mlo_priv(bond_dev);
|
|
+ if (mlo_info->bond_get_mlo_tx_netdev) {
|
|
+ bond_mlo_ctx = bond_get_mlo_ctx(bond_dev);
|
|
+ slave_dev = mlo_info->bond_get_mlo_tx_netdev(bond_mlo_ctx, dst_mac);
|
|
+ }
|
|
+
|
|
+ return slave_dev;
|
|
+}
|
|
+
|
|
/* bond_get_tx_dev - Calculate egress interface for a given packet.
|
|
*
|
|
* Supports 802.3AD and balance-xor modes
|
|
@@ -4289,6 +4377,9 @@ struct net_device *bond_get_tx_dev(struc
|
|
return bond_3ad_get_tx_dev(skb, src_mac, dst_mac,
|
|
src, dst, protocol,
|
|
bond_dev, layer4hdr);
|
|
+ case BOND_MODE_MLO:
|
|
+ return bond_mlo_get_tx_dev(bond_dev, dst_mac);
|
|
+
|
|
default:
|
|
return NULL;
|
|
}
|
|
@@ -5085,20 +5176,26 @@ static int bond_set_mac_address(struct n
|
|
if (!is_valid_ether_addr(ss->__data))
|
|
return -EADDRNOTAVAIL;
|
|
|
|
- bond_for_each_slave(bond, slave, iter) {
|
|
- slave_dbg(bond_dev, slave->dev, "%s: slave=%p\n",
|
|
- __func__, slave);
|
|
- res = dev_set_mac_address(slave->dev, addr, NULL);
|
|
- if (res) {
|
|
- /* TODO: consider downing the slave
|
|
- * and retry ?
|
|
- * User should expect communications
|
|
- * breakage anyway until ARP finish
|
|
- * updating, so...
|
|
- */
|
|
- slave_dbg(bond_dev, slave->dev, "%s: err %d\n",
|
|
- __func__, res);
|
|
- goto unwind;
|
|
+ /*
|
|
+ * Do not allow mac address change for slave netdevice for BOND_MODE_MLO
|
|
+ * as master's mac address is not same as slave's mac address.
|
|
+ */
|
|
+ if (BOND_MODE(bond) != BOND_MODE_MLO) {
|
|
+ bond_for_each_slave(bond, slave, iter) {
|
|
+ slave_dbg(bond_dev, slave->dev, "%s: slave=%p\n",
|
|
+ __func__, slave);
|
|
+ res = dev_set_mac_address(slave->dev, addr, NULL);
|
|
+ if (res) {
|
|
+ /* TODO: consider downing the slave
|
|
+ * and retry ?
|
|
+ * User should expect communications
|
|
+ * breakage anyway until ARP finish
|
|
+ * updating, so...
|
|
+ */
|
|
+ slave_dbg(bond_dev, slave->dev, "%s: err %d\n",
|
|
+ __func__, res);
|
|
+ goto unwind;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -5762,6 +5859,27 @@ static netdev_tx_t bond_tls_device_xmit(
|
|
}
|
|
#endif
|
|
|
|
+/* In bond_xmit_mlo(), we send the packet and bond netdevice
|
|
+ * to registered callback for final xmit.
|
|
+ */
|
|
+static netdev_tx_t bond_xmit_mlo(struct sk_buff *skb, struct net_device *bond_dev)
|
|
+{
|
|
+ struct bonding *bond = netdev_priv(bond_dev);
|
|
+ int slave_cnt, ret;
|
|
+ struct mlo_bond_info *mlo_info = bond_get_mlo_priv(bond_dev);
|
|
+
|
|
+ slave_cnt = READ_ONCE(bond->slave_cnt);
|
|
+ if (unlikely(slave_cnt == 0) || unlikely(!mlo_info->bond_mlo_xmit_netdev)) {
|
|
+ bond_tx_drop(bond_dev, skb);
|
|
+ } else {
|
|
+ ret = mlo_info->bond_mlo_xmit_netdev(skb, bond_dev);
|
|
+ if (ret != NET_XMIT_SUCCESS)
|
|
+ netdev_err(bond_dev, "Xmit failed with mode %d %p\n", BOND_MODE(bond), skb);
|
|
+ }
|
|
+
|
|
+ return NETDEV_TX_OK;
|
|
+}
|
|
+
|
|
static netdev_tx_t __bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
|
|
{
|
|
struct bonding *bond = netdev_priv(dev);
|
|
@@ -5790,6 +5908,8 @@ static netdev_tx_t __bond_start_xmit(str
|
|
return bond_alb_xmit(skb, dev);
|
|
case BOND_MODE_TLB:
|
|
return bond_tlb_xmit(skb, dev);
|
|
+ case BOND_MODE_MLO:
|
|
+ return bond_xmit_mlo(skb, dev);
|
|
default:
|
|
/* Should never happen, mode already checked */
|
|
netdev_err(dev, "Unknown bonding mode %d\n", BOND_MODE(bond));
|
|
@@ -6132,6 +6252,15 @@ static void bond_destructor(struct net_d
|
|
if (bond->id != (~0U))
|
|
clear_bit(bond->id, &bond_id_mask);
|
|
/* QCA NSS ECM bonding support */
|
|
+
|
|
+ /*
|
|
+ * Wifi driver registered callback to destroy wiphy for MLO bond netdevice
|
|
+ */
|
|
+ if (bond_is_mlo_device(bond_dev)) {
|
|
+ if (bond->mlo_info.bond_mlo_netdev_priv_destructor) {
|
|
+ bond->mlo_info.bond_mlo_netdev_priv_destructor(bond_dev);
|
|
+ }
|
|
+ }
|
|
}
|
|
|
|
void bond_setup(struct net_device *bond_dev)
|
|
@@ -6708,6 +6837,76 @@ out:
|
|
return res;
|
|
}
|
|
|
|
+/* bond_create_mlo()
|
|
+ * Create bond netdevice for BOND_MODE_MLO with MLO specific callback and context.
|
|
+ */
|
|
+struct net_device *bond_create_mlo(struct net *net, const char *name, struct mlo_bond_info *mlo_info)
|
|
+{
|
|
+ struct net_device *bond_dev;
|
|
+ struct bonding *bond;
|
|
+ int res;
|
|
+
|
|
+ ASSERT_RTNL();
|
|
+
|
|
+ bond_dev = alloc_netdev_mq(sizeof(struct bonding),
|
|
+ name ? name : "bond%d", NET_NAME_UNKNOWN,
|
|
+ bond_setup, tx_queues);
|
|
+ if (!bond_dev) {
|
|
+ pr_err("%s: eek! can't alloc netdev!\n", name);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ bond = netdev_priv(bond_dev);
|
|
+
|
|
+ dev_net_set(bond_dev, net);
|
|
+ bond_dev->rtnl_link_ops = &bond_link_ops;
|
|
+
|
|
+ /*
|
|
+ * MLO specific initialization.
|
|
+ */
|
|
+ bond_dev->ieee80211_ptr = mlo_info->wdev;
|
|
+ bond->params.mode = BOND_MODE_MLO;
|
|
+ mlo_info->wdev->netdev = bond_dev;
|
|
+
|
|
+ memcpy((void *)&bond->mlo_info, (void *)mlo_info, sizeof(*mlo_info));
|
|
+ eth_hw_addr_random(bond_dev);
|
|
+
|
|
+ /*
|
|
+ * Disable HW CSUM as wlan driver doesn't support
|
|
+ */
|
|
+ bond_dev->hw_features &= ~(NETIF_F_HW_CSUM);
|
|
+ bond_dev->features &= ~(NETIF_F_HW_CSUM);
|
|
+
|
|
+ res = register_netdevice(bond_dev);
|
|
+ if (res < 0) {
|
|
+ free_netdev(bond_dev);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ netif_carrier_off(bond_dev);
|
|
+ bond_work_init_all(bond);
|
|
+
|
|
+ bond->id = ~0U;
|
|
+ if (bond_id_mask != (~0UL)) {
|
|
+ bond->id = (u32)ffz(bond_id_mask);
|
|
+ set_bit(bond->id, &bond_id_mask);
|
|
+ }
|
|
+
|
|
+ return bond_dev;
|
|
+}
|
|
+EXPORT_SYMBOL(bond_create_mlo);
|
|
+
|
|
+/* bond_get_mlo_ctx
|
|
+ * Returns MLO context stored in netdev priv of bond netdevice
|
|
+ */
|
|
+void *bond_get_mlo_ctx(struct net_device *bond_dev)
|
|
+{
|
|
+ struct mlo_bond_info *mlo_info = bond_get_mlo_priv(bond_dev);
|
|
+
|
|
+ return mlo_info->bond_mlo_ctx;
|
|
+}
|
|
+EXPORT_SYMBOL(bond_get_mlo_ctx);
|
|
+
|
|
static int __net_init bond_net_init(struct net *net)
|
|
{
|
|
struct bond_net *bn = net_generic(net, bond_net_id);
|
|
--- a/drivers/net/bonding/bond_options.c
|
|
+++ b/drivers/net/bonding/bond_options.c
|
|
@@ -94,6 +94,7 @@ static const struct bond_opt_value bond_
|
|
{ "802.3ad", BOND_MODE_8023AD, 0},
|
|
{ "balance-tlb", BOND_MODE_TLB, 0},
|
|
{ "balance-alb", BOND_MODE_ALB, 0},
|
|
+ { "mode mlo", BOND_MODE_MLO, 0},
|
|
{ NULL, -1, 0},
|
|
};
|
|
|
|
--- a/include/net/bonding.h
|
|
+++ b/include/net/bonding.h
|
|
@@ -25,6 +25,7 @@
|
|
#include <linux/etherdevice.h>
|
|
#include <linux/reciprocal_div.h>
|
|
#include <linux/if_link.h>
|
|
+#include <net/cfg80211.h>
|
|
|
|
#include <net/bond_3ad.h>
|
|
#include <net/bond_alb.h>
|
|
@@ -203,6 +204,22 @@ struct bond_up_slave {
|
|
struct slave *arr[];
|
|
};
|
|
|
|
+/**
|
|
+ * mlo_bond_info - mlo_bond_info structure maintains members corresponding to wifi 7
|
|
+ * @bond_mlo_xmit_netdev: Callback function to provide skb to wifi driver for xmit
|
|
+ * @bond_get_mlo_tx_netdev: Callback function to get link interface from wifi driver for transmit
|
|
+ * @bond_mlo_ctx: Private member for wifi driver
|
|
+ * @wdev: ieee80211_ptr for wifi VAP
|
|
+ * @bond_mlo_netdev_priv_destructor: Callback function to remove wiphy instance from wifi driver
|
|
+ */
|
|
+struct mlo_bond_info {
|
|
+ int (*bond_mlo_xmit_netdev)(struct sk_buff *skb, struct net_device *bond_dev);
|
|
+ struct net_device *(*bond_get_mlo_tx_netdev)(void *bond_mlo_ctx, void *dst);
|
|
+ void *bond_mlo_ctx;
|
|
+ struct wireless_dev *wdev;
|
|
+ void (*bond_mlo_netdev_priv_destructor)(struct net_device *bond_dev);
|
|
+};
|
|
+
|
|
/*
|
|
* Link pseudo-state only used internally by monitors
|
|
*/
|
|
@@ -268,6 +285,8 @@ struct bonding {
|
|
#endif /* CONFIG_XFRM_OFFLOAD */
|
|
struct bpf_prog *xdp_prog;
|
|
u32 id; /* QCA NSS ECM bonding support */
|
|
+ /* MLO mode info */
|
|
+ struct mlo_bond_info mlo_info;
|
|
};
|
|
|
|
#define bond_slave_get_rcu(dev) \
|
|
@@ -287,6 +306,19 @@ struct bond_vlan_tag {
|
|
bool bond_sk_check(struct bonding *bond);
|
|
|
|
/**
|
|
+ * Returns False if the net_device is not MLO bond netdvice
|
|
+ *
|
|
+ */
|
|
+static inline bool bond_is_mlo_device(struct net_device *bond_dev)
|
|
+{
|
|
+ struct bonding *bond = netdev_priv(bond_dev);
|
|
+ if (BOND_MODE(bond) == BOND_MODE_MLO)
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
+/**
|
|
* Returns NULL if the net_device does not belong to any of the bond's slaves
|
|
*
|
|
* Caller must hold bond lock for read
|
|
@@ -650,6 +682,12 @@ static inline __be32 bond_confirm_addr(s
|
|
return addr;
|
|
}
|
|
|
|
+static inline struct mlo_bond_info *bond_get_mlo_priv(struct net_device *bond_dev)
|
|
+{
|
|
+ struct bonding *bond = netdev_priv(bond_dev);
|
|
+ return &bond->mlo_info;
|
|
+}
|
|
+
|
|
struct bond_net {
|
|
struct net *net; /* Associated network namespace */
|
|
struct list_head dev_list;
|
|
@@ -663,14 +701,17 @@ int bond_rcv_validate(const struct sk_bu
|
|
netdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev);
|
|
int bond_get_id(struct net_device *bond_dev); /* QCA NSS ECM bonding support */
|
|
int bond_create(struct net *net, const char *name);
|
|
+extern struct net_device *bond_create_mlo(struct net *net, const char *name, struct mlo_bond_info *mlo_info);
|
|
+extern void *bond_get_mlo_ctx(struct net_device *bond_dev);
|
|
+extern bool bond_destroy_mlo(struct net_device *bond_dev);
|
|
int bond_create_sysfs(struct bond_net *net);
|
|
void bond_destroy_sysfs(struct bond_net *net);
|
|
void bond_prepare_sysfs_group(struct bonding *bond);
|
|
int bond_sysfs_slave_add(struct slave *slave);
|
|
void bond_sysfs_slave_del(struct slave *slave);
|
|
-int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
|
|
+extern int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
|
|
struct netlink_ext_ack *extack);
|
|
-int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
|
|
+extern int bond_release(struct net_device *bond_dev, struct net_device *slave_dev);
|
|
u32 bond_xmit_hash(struct bonding *bond, struct sk_buff *skb);
|
|
int bond_set_carrier(struct bonding *bond);
|
|
void bond_select_active_slave(struct bonding *bond);
|
|
--- a/include/uapi/linux/if_bonding.h
|
|
+++ b/include/uapi/linux/if_bonding.h
|
|
@@ -71,6 +71,7 @@
|
|
#define BOND_MODE_8023AD 4
|
|
#define BOND_MODE_TLB 5
|
|
#define BOND_MODE_ALB 6 /* TLB + RLB (receive load balancing) */
|
|
+#define BOND_MODE_MLO 7 /* MLO (Multi link) mode for Wi-Fi 7 AP links */
|
|
|
|
/* each slave's link has 4 states */
|
|
#define BOND_LINK_UP 0 /* link is up and running */
|