Skip to content

Commit 18cb261

Browse files
jarodwilsondavem330
authored andcommitted
bonding: support hardware encryption offload to slaves
Currently, this support is limited to active-backup mode, as I'm not sure about the feasilibity of mapping an xfrm_state's offload handle to multiple hardware devices simultaneously, and we rely on being able to pass some hints to both the xfrm and NIC driver about whether or not they're operating on a slave device. I've tested this atop an Intel x520 device (ixgbe) using libreswan in transport mode, succesfully achieving ~4.3Gbps throughput with netperf (more or less identical to throughput on a bare NIC in this system), as well as successful failover and recovery mid-netperf. v2: just use CONFIG_XFRM_OFFLOAD for wrapping, isolate more code with it CC: Jay Vosburgh <[email protected]> CC: Veaceslav Falico <[email protected]> CC: Andy Gospodarek <[email protected]> CC: "David S. Miller" <[email protected]> CC: Jeff Kirsher <[email protected]> CC: Jakub Kicinski <[email protected]> CC: Steffen Klassert <[email protected]> CC: Herbert Xu <[email protected]> CC: [email protected] CC: [email protected] Signed-off-by: Jarod Wilson <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent bf3a058 commit 18cb261

File tree

2 files changed

+128
-2
lines changed

2 files changed

+128
-2
lines changed

drivers/net/bonding/bond_main.c

+125-2
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
#include <net/pkt_sched.h>
8080
#include <linux/rculist.h>
8181
#include <net/flow_dissector.h>
82+
#include <net/xfrm.h>
8283
#include <net/bonding.h>
8384
#include <net/bond_3ad.h>
8485
#include <net/bond_alb.h>
@@ -278,8 +279,6 @@ const char *bond_mode_name(int mode)
278279
return names[mode];
279280
}
280281

281-
/*---------------------------------- VLAN -----------------------------------*/
282-
283282
/**
284283
* bond_dev_queue_xmit - Prepare skb for xmit.
285284
*
@@ -302,6 +301,8 @@ netdev_tx_t bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
302301
return dev_queue_xmit(skb);
303302
}
304303

304+
/*---------------------------------- VLAN -----------------------------------*/
305+
305306
/* In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
306307
* We don't protect the slave list iteration with a lock because:
307308
* a. This operation is performed in IOCTL context,
@@ -372,6 +373,84 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev,
372373
return 0;
373374
}
374375

376+
/*---------------------------------- XFRM -----------------------------------*/
377+
378+
#ifdef CONFIG_XFRM_OFFLOAD
379+
/**
380+
* bond_ipsec_add_sa - program device with a security association
381+
* @xs: pointer to transformer state struct
382+
**/
383+
static int bond_ipsec_add_sa(struct xfrm_state *xs)
384+
{
385+
struct net_device *bond_dev = xs->xso.dev;
386+
struct bonding *bond = netdev_priv(bond_dev);
387+
struct slave *slave = rtnl_dereference(bond->curr_active_slave);
388+
389+
xs->xso.slave_dev = slave->dev;
390+
bond->xs = xs;
391+
392+
if (!(slave->dev->xfrmdev_ops
393+
&& slave->dev->xfrmdev_ops->xdo_dev_state_add)) {
394+
slave_warn(bond_dev, slave->dev, "Slave does not support ipsec offload\n");
395+
return -EINVAL;
396+
}
397+
398+
return slave->dev->xfrmdev_ops->xdo_dev_state_add(xs);
399+
}
400+
401+
/**
402+
* bond_ipsec_del_sa - clear out this specific SA
403+
* @xs: pointer to transformer state struct
404+
**/
405+
static void bond_ipsec_del_sa(struct xfrm_state *xs)
406+
{
407+
struct net_device *bond_dev = xs->xso.dev;
408+
struct bonding *bond = netdev_priv(bond_dev);
409+
struct slave *slave = rtnl_dereference(bond->curr_active_slave);
410+
411+
if (!slave)
412+
return;
413+
414+
xs->xso.slave_dev = slave->dev;
415+
416+
if (!(slave->dev->xfrmdev_ops
417+
&& slave->dev->xfrmdev_ops->xdo_dev_state_delete)) {
418+
slave_warn(bond_dev, slave->dev, "%s: no slave xdo_dev_state_delete\n", __func__);
419+
return;
420+
}
421+
422+
slave->dev->xfrmdev_ops->xdo_dev_state_delete(xs);
423+
}
424+
425+
/**
426+
* bond_ipsec_offload_ok - can this packet use the xfrm hw offload
427+
* @skb: current data packet
428+
* @xs: pointer to transformer state struct
429+
**/
430+
static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
431+
{
432+
struct net_device *bond_dev = xs->xso.dev;
433+
struct bonding *bond = netdev_priv(bond_dev);
434+
struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
435+
struct net_device *slave_dev = curr_active->dev;
436+
437+
if (!(slave_dev->xfrmdev_ops
438+
&& slave_dev->xfrmdev_ops->xdo_dev_offload_ok)) {
439+
slave_warn(bond_dev, slave_dev, "%s: no slave xdo_dev_offload_ok\n", __func__);
440+
return false;
441+
}
442+
443+
xs->xso.slave_dev = slave_dev;
444+
return slave_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
445+
}
446+
447+
static const struct xfrmdev_ops bond_xfrmdev_ops = {
448+
.xdo_dev_state_add = bond_ipsec_add_sa,
449+
.xdo_dev_state_delete = bond_ipsec_del_sa,
450+
.xdo_dev_offload_ok = bond_ipsec_offload_ok,
451+
};
452+
#endif /* CONFIG_XFRM_OFFLOAD */
453+
375454
/*------------------------------- Link status -------------------------------*/
376455

377456
/* Set the carrier state for the master according to the state of its
@@ -879,6 +958,11 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
879958
return;
880959

881960
if (new_active) {
961+
#ifdef CONFIG_XFRM_OFFLOAD
962+
if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) && bond->xs)
963+
bond_ipsec_del_sa(bond->xs);
964+
#endif /* CONFIG_XFRM_OFFLOAD */
965+
882966
new_active->last_link_up = jiffies;
883967

884968
if (new_active->link == BOND_LINK_BACK) {
@@ -941,6 +1025,13 @@ void bond_change_active_slave(struct bonding *bond, struct slave *new_active)
9411025
bond_should_notify_peers(bond);
9421026
}
9431027

1028+
#ifdef CONFIG_XFRM_OFFLOAD
1029+
if (old_active && bond->xs) {
1030+
xfrm_dev_state_flush(dev_net(bond->dev), bond->dev, true);
1031+
bond_ipsec_add_sa(bond->xs);
1032+
}
1033+
#endif /* CONFIG_XFRM_OFFLOAD */
1034+
9441035
call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
9451036
if (should_notify_peers) {
9461037
bond->send_peer_notif--;
@@ -1127,15 +1218,24 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
11271218
#define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
11281219
NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
11291220

1221+
#ifdef CONFIG_XFRM_OFFLOAD
1222+
#define BOND_XFRM_FEATURES (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
1223+
NETIF_F_GSO_ESP)
1224+
#endif /* CONFIG_XFRM_OFFLOAD */
1225+
11301226
#define BOND_MPLS_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
11311227
NETIF_F_ALL_TSO)
11321228

1229+
11331230
static void bond_compute_features(struct bonding *bond)
11341231
{
11351232
unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
11361233
IFF_XMIT_DST_RELEASE_PERM;
11371234
netdev_features_t vlan_features = BOND_VLAN_FEATURES;
11381235
netdev_features_t enc_features = BOND_ENC_FEATURES;
1236+
#ifdef CONFIG_XFRM_OFFLOAD
1237+
netdev_features_t xfrm_features = BOND_XFRM_FEATURES;
1238+
#endif /* CONFIG_XFRM_OFFLOAD */
11391239
netdev_features_t mpls_features = BOND_MPLS_FEATURES;
11401240
struct net_device *bond_dev = bond->dev;
11411241
struct list_head *iter;
@@ -1157,6 +1257,12 @@ static void bond_compute_features(struct bonding *bond)
11571257
slave->dev->hw_enc_features,
11581258
BOND_ENC_FEATURES);
11591259

1260+
#ifdef CONFIG_XFRM_OFFLOAD
1261+
xfrm_features = netdev_increment_features(xfrm_features,
1262+
slave->dev->hw_enc_features,
1263+
BOND_XFRM_FEATURES);
1264+
#endif /* CONFIG_XFRM_OFFLOAD */
1265+
11601266
mpls_features = netdev_increment_features(mpls_features,
11611267
slave->dev->mpls_features,
11621268
BOND_MPLS_FEATURES);
@@ -1176,6 +1282,9 @@ static void bond_compute_features(struct bonding *bond)
11761282
NETIF_F_HW_VLAN_CTAG_TX |
11771283
NETIF_F_HW_VLAN_STAG_TX |
11781284
NETIF_F_GSO_UDP_L4;
1285+
#ifdef CONFIG_XFRM_OFFLOAD
1286+
bond_dev->hw_enc_features |= xfrm_features;
1287+
#endif /* CONFIG_XFRM_OFFLOAD */
11791288
bond_dev->mpls_features = mpls_features;
11801289
bond_dev->gso_max_segs = gso_max_segs;
11811290
netif_set_gso_max_size(bond_dev, gso_max_size);
@@ -1464,6 +1573,9 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
14641573
slave_dbg(bond_dev, slave_dev, "is !NETIF_F_VLAN_CHALLENGED\n");
14651574
}
14661575

1576+
if (slave_dev->features & NETIF_F_HW_ESP)
1577+
slave_dbg(bond_dev, slave_dev, "is esp-hw-offload capable\n");
1578+
14671579
/* Old ifenslave binaries are no longer supported. These can
14681580
* be identified with moderate accuracy by the state of the slave:
14691581
* the current ifenslave will set the interface down prior to
@@ -4540,6 +4652,13 @@ void bond_setup(struct net_device *bond_dev)
45404652
bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT | IFF_NO_QUEUE;
45414653
bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
45424654

4655+
#ifdef CONFIG_XFRM_OFFLOAD
4656+
/* set up xfrm device ops (only supported in active-backup right now) */
4657+
if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP))
4658+
bond_dev->xfrmdev_ops = &bond_xfrmdev_ops;
4659+
bond->xs = NULL;
4660+
#endif /* CONFIG_XFRM_OFFLOAD */
4661+
45434662
/* don't acquire bond device's netif_tx_lock when transmitting */
45444663
bond_dev->features |= NETIF_F_LLTX;
45454664

@@ -4558,6 +4677,10 @@ void bond_setup(struct net_device *bond_dev)
45584677
NETIF_F_HW_VLAN_CTAG_FILTER;
45594678

45604679
bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4;
4680+
#ifdef CONFIG_XFRM_OFFLOAD
4681+
if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP))
4682+
bond_dev->hw_features |= BOND_XFRM_FEATURES;
4683+
#endif /* CONFIG_XFRM_OFFLOAD */
45614684
bond_dev->features |= bond_dev->hw_features;
45624685
bond_dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
45634686
}

include/net/bonding.h

+3
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,9 @@ struct bonding {
238238
struct dentry *debug_dir;
239239
#endif /* CONFIG_DEBUG_FS */
240240
struct rtnl_link_stats64 bond_stats;
241+
#ifdef CONFIG_XFRM_OFFLOAD
242+
struct xfrm_state *xs;
243+
#endif /* CONFIG_XFRM_OFFLOAD */
241244
};
242245

243246
#define bond_slave_get_rcu(dev) \

0 commit comments

Comments
 (0)