#include <net/pkt_sched.h>
 #include <linux/rculist.h>
 #include <net/flow_dissector.h>
+#include <net/xfrm.h>
 #include <net/bonding.h>
 #include <net/bond_3ad.h>
 #include <net/bond_alb.h>
        return names[mode];
 }
 
-/*---------------------------------- VLAN -----------------------------------*/
-
 /**
  * bond_dev_queue_xmit - Prepare skb for xmit.
  *
        return dev_queue_xmit(skb);
 }
 
+/*---------------------------------- VLAN -----------------------------------*/
+
 /* In the following 2 functions, bond_vlan_rx_add_vid and bond_vlan_rx_kill_vid,
  * We don't protect the slave list iteration with a lock because:
  * a. This operation is performed in IOCTL context,
        return 0;
 }
 
+/*---------------------------------- XFRM -----------------------------------*/
+
+#ifdef CONFIG_XFRM_OFFLOAD
+/**
+ * bond_ipsec_add_sa - program device with a security association
+ * @xs: pointer to transformer state struct
+ **/
+static int bond_ipsec_add_sa(struct xfrm_state *xs)
+{
+       struct net_device *bond_dev = xs->xso.dev;
+       struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *slave = rtnl_dereference(bond->curr_active_slave);
+
+       xs->xso.slave_dev = slave->dev;
+       bond->xs = xs;
+
+       if (!(slave->dev->xfrmdev_ops
+             && slave->dev->xfrmdev_ops->xdo_dev_state_add)) {
+               slave_warn(bond_dev, slave->dev, "Slave does not support ipsec offload\n");
+               return -EINVAL;
+       }
+
+       return slave->dev->xfrmdev_ops->xdo_dev_state_add(xs);
+}
+
+/**
+ * bond_ipsec_del_sa - clear out this specific SA
+ * @xs: pointer to transformer state struct
+ **/
+static void bond_ipsec_del_sa(struct xfrm_state *xs)
+{
+       struct net_device *bond_dev = xs->xso.dev;
+       struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *slave = rtnl_dereference(bond->curr_active_slave);
+
+       if (!slave)
+               return;
+
+       xs->xso.slave_dev = slave->dev;
+
+       if (!(slave->dev->xfrmdev_ops
+             && slave->dev->xfrmdev_ops->xdo_dev_state_delete)) {
+               slave_warn(bond_dev, slave->dev, "%s: no slave xdo_dev_state_delete\n", __func__);
+               return;
+       }
+
+       slave->dev->xfrmdev_ops->xdo_dev_state_delete(xs);
+}
+
+/**
+ * bond_ipsec_offload_ok - can this packet use the xfrm hw offload
+ * @skb: current data packet
+ * @xs: pointer to transformer state struct
+ **/
+static bool bond_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *xs)
+{
+       struct net_device *bond_dev = xs->xso.dev;
+       struct bonding *bond = netdev_priv(bond_dev);
+       struct slave *curr_active = rtnl_dereference(bond->curr_active_slave);
+       struct net_device *slave_dev = curr_active->dev;
+
+       if (!(slave_dev->xfrmdev_ops
+             && slave_dev->xfrmdev_ops->xdo_dev_offload_ok)) {
+               slave_warn(bond_dev, slave_dev, "%s: no slave xdo_dev_offload_ok\n", __func__);
+               return false;
+       }
+
+       xs->xso.slave_dev = slave_dev;
+       return slave_dev->xfrmdev_ops->xdo_dev_offload_ok(skb, xs);
+}
+
+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_offload_ok = bond_ipsec_offload_ok,
+};
+#endif /* CONFIG_XFRM_OFFLOAD */
+
 /*------------------------------- Link status -------------------------------*/
 
 /* Set the carrier state for the master according to the state of its
                return;
 
        if (new_active) {
+#ifdef CONFIG_XFRM_OFFLOAD
+               if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP) && bond->xs)
+                       bond_ipsec_del_sa(bond->xs);
+#endif /* CONFIG_XFRM_OFFLOAD */
+
                new_active->last_link_up = jiffies;
 
                if (new_active->link == BOND_LINK_BACK) {
                                        bond_should_notify_peers(bond);
                        }
 
+#ifdef CONFIG_XFRM_OFFLOAD
+                       if (old_active && bond->xs) {
+                               xfrm_dev_state_flush(dev_net(bond->dev), bond->dev, true);
+                               bond_ipsec_add_sa(bond->xs);
+                       }
+#endif /* CONFIG_XFRM_OFFLOAD */
+
                        call_netdevice_notifiers(NETDEV_BONDING_FAILOVER, bond->dev);
                        if (should_notify_peers) {
                                bond->send_peer_notif--;
 #define BOND_ENC_FEATURES      (NETIF_F_HW_CSUM | NETIF_F_SG | \
                                 NETIF_F_RXCSUM | NETIF_F_ALL_TSO)
 
+#ifdef CONFIG_XFRM_OFFLOAD
+#define BOND_XFRM_FEATURES     (NETIF_F_HW_ESP | NETIF_F_HW_ESP_TX_CSUM | \
+                                NETIF_F_GSO_ESP)
+#endif /* CONFIG_XFRM_OFFLOAD */
+
 #define BOND_MPLS_FEATURES     (NETIF_F_HW_CSUM | NETIF_F_SG | \
                                 NETIF_F_ALL_TSO)
 
+
 static void bond_compute_features(struct bonding *bond)
 {
        unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
                                        IFF_XMIT_DST_RELEASE_PERM;
        netdev_features_t vlan_features = BOND_VLAN_FEATURES;
        netdev_features_t enc_features  = BOND_ENC_FEATURES;
+#ifdef CONFIG_XFRM_OFFLOAD
+       netdev_features_t xfrm_features  = BOND_XFRM_FEATURES;
+#endif /* CONFIG_XFRM_OFFLOAD */
        netdev_features_t mpls_features  = BOND_MPLS_FEATURES;
        struct net_device *bond_dev = bond->dev;
        struct list_head *iter;
                                                         slave->dev->hw_enc_features,
                                                         BOND_ENC_FEATURES);
 
+#ifdef CONFIG_XFRM_OFFLOAD
+               xfrm_features = netdev_increment_features(xfrm_features,
+                                                         slave->dev->hw_enc_features,
+                                                         BOND_XFRM_FEATURES);
+#endif /* CONFIG_XFRM_OFFLOAD */
+
                mpls_features = netdev_increment_features(mpls_features,
                                                          slave->dev->mpls_features,
                                                          BOND_MPLS_FEATURES);
                                    NETIF_F_HW_VLAN_CTAG_TX |
                                    NETIF_F_HW_VLAN_STAG_TX |
                                    NETIF_F_GSO_UDP_L4;
+#ifdef CONFIG_XFRM_OFFLOAD
+       bond_dev->hw_enc_features |= xfrm_features;
+#endif /* CONFIG_XFRM_OFFLOAD */
        bond_dev->mpls_features = mpls_features;
        bond_dev->gso_max_segs = gso_max_segs;
        netif_set_gso_max_size(bond_dev, gso_max_size);
                slave_dbg(bond_dev, slave_dev, "is !NETIF_F_VLAN_CHALLENGED\n");
        }
 
+       if (slave_dev->features & NETIF_F_HW_ESP)
+               slave_dbg(bond_dev, slave_dev, "is esp-hw-offload capable\n");
+
        /* Old ifenslave binaries are no longer supported.  These can
         * be identified with moderate accuracy by the state of the slave:
         * the current ifenslave will set the interface down prior to
        bond_dev->priv_flags |= IFF_BONDING | IFF_UNICAST_FLT | IFF_NO_QUEUE;
        bond_dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
 
+#ifdef CONFIG_XFRM_OFFLOAD
+       /* set up xfrm device ops (only supported in active-backup right now) */
+       if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP))
+               bond_dev->xfrmdev_ops = &bond_xfrmdev_ops;
+       bond->xs = NULL;
+#endif /* CONFIG_XFRM_OFFLOAD */
+
        /* don't acquire bond device's netif_tx_lock when transmitting */
        bond_dev->features |= NETIF_F_LLTX;
 
                                NETIF_F_HW_VLAN_CTAG_FILTER;
 
        bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL | NETIF_F_GSO_UDP_L4;
+#ifdef CONFIG_XFRM_OFFLOAD
+       if ((BOND_MODE(bond) == BOND_MODE_ACTIVEBACKUP))
+               bond_dev->hw_features |= BOND_XFRM_FEATURES;
+#endif /* CONFIG_XFRM_OFFLOAD */
        bond_dev->features |= bond_dev->hw_features;
        bond_dev->features |= NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_STAG_TX;
 }