diff options
Diffstat (limited to 'drivers/net/bonding/bond_main.c')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 122 |
1 files changed, 97 insertions, 25 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bb9c3d6ef435..b560644ee1b1 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -419,6 +419,41 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, #ifdef CONFIG_XFRM_OFFLOAD /** + * bond_ipsec_dev - Get active device for IPsec offload + * @xs: pointer to transformer state struct + * + * Context: caller must hold rcu_read_lock. + * + * Return: the device for ipsec offload, or NULL if not exist. + **/ +static struct net_device *bond_ipsec_dev(struct xfrm_state *xs) +{ + struct net_device *bond_dev = xs->xso.dev; + struct bonding *bond; + struct slave *slave; + + if (!bond_dev) + return NULL; + + bond = netdev_priv(bond_dev); + if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) + return NULL; + + slave = rcu_dereference(bond->curr_active_slave); + if (!slave) + return NULL; + + if (!xs->xso.real_dev) + return NULL; + + if (xs->xso.real_dev != slave->dev) + pr_warn_ratelimited("%s: (slave %s): not same with IPsec offload real dev %s\n", + bond_dev->name, slave->dev->name, xs->xso.real_dev->name); + + return slave->dev; +} + +/** * bond_ipsec_add_sa - program device with a security association * @xs: pointer to transformer state struct * @extack: extack point to fill failure reason @@ -640,23 +675,12 @@ out: **/ static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs) { - struct net_device *bond_dev = xs->xso.dev; struct net_device *real_dev; - struct slave *curr_active; - struct bonding *bond; bool ok = false; - bond = netdev_priv(bond_dev); rcu_read_lock(); - curr_active = rcu_dereference(bond->curr_active_slave); - if (!curr_active) - goto out; - real_dev = curr_active->dev; - - if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) - goto out; - - if (!xs->xso.real_dev) + real_dev = bond_ipsec_dev(xs); + if (!real_dev) goto out; if (!real_dev->xfrmdev_ops || @@ -670,11 +694,61 @@ out: return ok; } +/** + * bond_advance_esn_state - ESN support for IPSec HW offload + * @xs: pointer to transformer state struct + **/ +static void bond_advance_esn_state(struct xfrm_state *xs) +{ + struct net_device *real_dev; + + rcu_read_lock(); + real_dev = bond_ipsec_dev(xs); + if (!real_dev) + goto out; + + if (!real_dev->xfrmdev_ops || + !real_dev->xfrmdev_ops->xdo_dev_state_advance_esn) { + pr_warn_ratelimited("%s: %s doesn't support xdo_dev_state_advance_esn\n", __func__, real_dev->name); + goto out; + } + + real_dev->xfrmdev_ops->xdo_dev_state_advance_esn(xs); +out: + rcu_read_unlock(); +} + +/** + * bond_xfrm_update_stats - Update xfrm state + * @xs: pointer to transformer state struct + **/ +static void bond_xfrm_update_stats(struct xfrm_state *xs) +{ + struct net_device *real_dev; + + rcu_read_lock(); + real_dev = bond_ipsec_dev(xs); + if (!real_dev) + goto out; + + if (!real_dev->xfrmdev_ops || + !real_dev->xfrmdev_ops->xdo_dev_state_update_stats) { + pr_warn_ratelimited("%s: %s doesn't support xdo_dev_state_update_stats\n", __func__, real_dev->name); + goto out; + } + + real_dev->xfrmdev_ops->xdo_dev_state_update_stats(xs); +out: + rcu_read_unlock(); +} + static const struct xfrmdev_ops bond_xfrmdev_ops = { .xdo_dev_state_add = bond_ipsec_add_sa, .xdo_dev_state_delete = bond_ipsec_del_sa, .xdo_dev_state_free = bond_ipsec_free_sa, .xdo_dev_offload_ok = bond_ipsec_offload_ok, + .xdo_dev_state_advance_esn = bond_advance_esn_state, + .xdo_dev_state_update_stats = bond_xfrm_update_stats, }; #endif /* CONFIG_XFRM_OFFLOAD */ @@ -2300,7 +2374,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev, goto err_sysfs_del; } - res = slave_dev->netdev_ops->ndo_bpf(slave_dev, &xdp); + res = dev_xdp_propagate(slave_dev, &xdp); if (res < 0) { /* ndo_bpf() sets extack error message */ slave_dbg(bond_dev, slave_dev, "Error %d calling ndo_bpf\n", res); @@ -2436,7 +2510,7 @@ static int __bond_release_one(struct net_device *bond_dev, .prog = NULL, .extack = NULL, }; - if (slave_dev->netdev_ops->ndo_bpf(slave_dev, &xdp)) + if (dev_xdp_propagate(slave_dev, &xdp)) slave_warn(bond_dev, slave_dev, "failed to unload XDP program\n"); } @@ -5626,7 +5700,7 @@ static int bond_xdp_set(struct net_device *dev, struct bpf_prog *prog, goto err; } - err = slave_dev->netdev_ops->ndo_bpf(slave_dev, &xdp); + err = dev_xdp_propagate(slave_dev, &xdp); if (err < 0) { /* ndo_bpf() sets extack error message */ slave_err(dev, slave_dev, "Error %d calling ndo_bpf\n", err); @@ -5658,7 +5732,7 @@ err: if (slave == rollback_slave) break; - err_unwind = slave_dev->netdev_ops->ndo_bpf(slave_dev, &xdp); + err_unwind = dev_xdp_propagate(slave_dev, &xdp); if (err_unwind < 0) slave_err(dev, slave_dev, "Error %d when unwinding XDP program change\n", err_unwind); @@ -5812,9 +5886,6 @@ static int bond_ethtool_get_ts_info(struct net_device *bond_dev, if (real_dev) { ret = ethtool_get_ts_info_by_layer(real_dev, info); } else { - info->phc_index = -1; - info->so_timestamping = SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE; /* Check if all slaves support software tx timestamping */ rcu_read_lock(); bond_for_each_slave_rcu(bond, slave, iter) { @@ -5928,7 +5999,10 @@ void bond_setup(struct net_device *bond_dev) #endif /* CONFIG_XFRM_OFFLOAD */ /* don't acquire bond device's netif_tx_lock when transmitting */ - bond_dev->features |= NETIF_F_LLTX; + bond_dev->lltx = true; + + /* Don't allow bond devices to change network namespaces. */ + bond_dev->netns_local = true; /* By default, we declare the bond to be fully * VLAN hardware accelerated capable. Special @@ -5937,9 +6011,6 @@ void bond_setup(struct net_device *bond_dev) * capable */ - /* Don't allow bond devices to change network namespaces. */ - bond_dev->features |= NETIF_F_NETNS_LOCAL; - bond_dev->hw_features = BOND_VLAN_FEATURES | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER | @@ -6384,7 +6455,8 @@ static int bond_init(struct net_device *bond_dev) netdev_dbg(bond_dev, "Begin bond_init\n"); - bond->wq = alloc_ordered_workqueue(bond_dev->name, WQ_MEM_RECLAIM); + bond->wq = alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, + bond_dev->name); if (!bond->wq) return -ENOMEM; |