[RFC 2.6.10 5/22] xfrm: Attempt to offload bundled xfrm_states for outbound xfrms

David Dillow
2004-12-30T08:55:32Z

# 2004/12/30 00:34:46-05:00 dave@thedillows.org
# Plumb in offloading new bundles for outgoing packets.
#
# Signed-off-by: David Dillow <dave@thedillows.org>
#
# net/xfrm/xfrm_policy.c
# 2004/12/30 00:34:28-05:00 dave@thedillows.org +28 -0
# When we create a new bundle for an outbound flow, try to
# offload as much as the destination driver will allow.
#
# Don't forget to clean up....
#
# Signed-off-by: David Dillow <dave@thedillows.org>
#
# include/net/xfrm.h
# 2004/12/30 00:34:28-05:00 dave@thedillows.org +6 -0
# A convenience structure for offloading bundles.
#
# The dst->child field gives us a singly linked list
# from upper protocols to outer transforms. Drivers, however,
# will likely have a limited number of offloads they can
# perform on a particular packet, so they need to offload
# the bundle from the outside in. This list makes it easier
# for them.
#
# Signed-off-by: David Dillow <dave@thedillows.org>
#
# include/net/dst.h
# 2004/12/30 00:34:28-05:00 dave@thedillows.org +1 -0
# Add a field to store the offload information for this part
# of the outgoing bundle (non-NULL if this dst is offloaded.)
#
# Signed-off-by: David Dillow <dave@thedillows.org>
#
diff -Nru a/include/net/dst.h b/include/net/dst.h
--- a/include/net/dst.h 2004-12-30 01:11:18 -05:00
+++ b/include/net/dst.h 2004-12-30 01:11:18 -05:00
@@ -65,6 +65,7 @@
struct neighbour *neighbour;
struct hh_cache *hh;
struct xfrm_state *xfrm;
+ struct xfrm_offload *xfrm_offload;

int (*input)(struct sk_buff*);
int (*output)(struct sk_buff*);
diff -Nru a/include/net/xfrm.h b/include/net/xfrm.h
--- a/include/net/xfrm.h 2004-12-30 01:11:18 -05:00
+++ b/include/net/xfrm.h 2004-12-30 01:11:18 -05:00
@@ -178,6 +178,12 @@
atomic_t refcnt;
};

+struct xfrm_bundle_list
+{
+ struct list_head node;
+ struct dst_entry * dst;
+};
+
struct xfrm_type;
struct xfrm_dst;
struct xfrm_policy_afinfo {
diff -Nru a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
--- a/net/xfrm/xfrm_policy.c 2004-12-30 01:11:18 -05:00
+++ b/net/xfrm/xfrm_policy.c 2004-12-30 01:11:18 -05:00
@@ -705,6 +705,31 @@
};
}

+static void xfrm_accel_bundle(struct dst_entry *dst)
+{
+ struct xfrm_bundle_list bundle, *xbl, *tmp;
+ struct net_device *dev = dst->dev;
+ INIT_LIST_HEAD(&bundle.node);
+
+ if (dev && netif_running(dev) && (dev->features & NETIF_F_IPSEC)) {
+ while (dst) {
+ xbl = kmalloc(sizeof(*xbl), GFP_ATOMIC);
+ if (!xbl)
+ goto out;
+
+ xbl->dst = dst;
+ list_add_tail(&xbl->node, &bundle.node);
+ dst = dst->child;
+ }
+
+ dev->xfrm_bundle_add(dev, &bundle);
+ }
+
+out:
+ list_for_each_entry_safe(xbl, tmp, &bundle.node, node)
+ kfree(xbl);
+}
+
static int stale_bundle(struct dst_entry *dst);

/* Main function: finds/creates a bundle for given flow.
@@ -833,6 +858,7 @@
policy->bundles = dst;
dst_hold(dst);
write_unlock_bh(&policy->lock);
+ xfrm_accel_bundle(dst);
}
*dst_p = dst;
dst_release(dst_orig);
@@ -1023,8 +1049,10 @@
{
if (!dst->xfrm)
return;
+ xfrm_offload_release(dst->xfrm_offload);
xfrm_state_put(dst->xfrm);
dst->xfrm = NULL;
+ dst->xfrm_offload = NULL;
}

static void xfrm_link_failure(struct sk_buff *skb)