[RFC 2.6.10 20/22] typhoon: add management of outbound bundles

From: David Dillow (dave_at_thedillows.org)
Date: 12/30/04

  • Next message: David Dillow: "[RFC 2.6.10 16/22] typhoon: collect crypto offload capabilities"
    Date:	Thu, 30 Dec 2004 03:48:37 -0500
    To: netdev@oss.sgi.com
    
    

    # This is a BitKeeper generated diff -Nru style patch.
    #
    # ChangeSet
    # 2004/12/30 01:04:39-05:00 dave@thedillows.org
    # Add the offloading of outbound bundles.
    #
    # This is a tricky business, because there are restrictions on
    # the types and order of the xfrms we can offload. Some combinations
    # also yield incorrect results, so we have to reduce the amount of
    # offloading we do in those cases.
    #
    # Signed-off-by: David Dillow <dave@thedillows.org>
    #
    # drivers/net/typhoon.c
    # 2004/12/30 01:04:20-05:00 dave@thedillows.org +134 -0
    # Add the offloading of outbound bundles.
    #
    # This is a tricky business, because there are restrictions on
    # the types and order of the xfrms we can offload. Some combinations
    # also yield incorrect results, so we have to reduce the amount of
    # offloading we do in those cases.
    #
    # Signed-off-by: David Dillow <dave@thedillows.org>
    #
    diff -Nru a/drivers/net/typhoon.c b/drivers/net/typhoon.c
    --- a/drivers/net/typhoon.c 2004-12-30 01:08:06 -05:00
    +++ b/drivers/net/typhoon.c 2004-12-30 01:08:06 -05:00
    @@ -2587,6 +2587,140 @@
             spin_unlock_bh(&tp->offload_lock);
     }
     
    +static inline int
    +typhoon_max_offload(struct xfrm_bundle_list *xbl)
    +{
    + /* Pre-scan the bundle to avoid offloading problematic sequences.
    + * Only reduces the offload level to keep as much advantage as
    + * possible.
    + *
    + * For 03.001.002 -- still problematic for 03.001.008, but need
    + * re-verify symptoms.
    + *
    + * inner AH tunnel, outer AH transport
    + * --> 3XP seems to put the inner hash at the wrong location
    + * inner AH tunnel, outer ESP tunnel
    + * --> 3XP corrupts outer hash, maybe wrong place?
    + * inner AH transport, outer ESP tunnel
    + * --> 3XP seems to encrypt the wrong portion of the packet
    + * inner ESP transport, outer AH tunnel
    + * --> 3XP lockup, requires reset
    + */
    + struct xfrm_bundle_list *bundle;
    + struct dst_entry *dst;
    + struct xfrm_state *x;
    + int last_was_ah = 0, last_was_tunnel = 0;
    + int max_level = 2;
    + int proto;
    +
    + list_for_each_entry_reverse(bundle, &xbl->node, node) {
    + dst = bundle->dst;
    + x = dst->xfrm;
    +
    + proto = x ? x->type->proto : IPPROTO_IP;
    +
    + if(proto == IPPROTO_AH && x->props.mode &&
    + (last_was_ah ^ last_was_tunnel))
    + goto problem_offload;
    +
    + if(proto == IPPROTO_AH && !x->props.mode &&
    + (!last_was_ah && last_was_tunnel))
    + goto problem_offload;
    +
    + if(proto == IPPROTO_ESP && last_was_ah && last_was_tunnel)
    + goto problem_offload;
    +
    + last_was_ah = (proto == IPPROTO_AH) ? 1 : 0;
    + last_was_tunnel = x ? x->props.mode : 0;
    + continue;
    +
    +problem_offload:
    + max_level--;
    + break;
    + }
    +
    + return max_level;
    +}
    +
    +static void
    +typhoon_xfrm_bundle_add(struct net_device *dev, struct xfrm_bundle_list *xbl)
    +{
    + /* Walk from the outermost dst back up the chain, offloading
    + * until we hit something we cannot deal with.
    + */
    + struct typhoon *tp = netdev_priv(dev);
    + struct xfrm_bundle_list *bundle;
    + struct dst_entry *dst;
    + struct xfrm_state *x;
    + struct xfrm_offload *xol;
    + struct typhoon_xfrm_offload *txo;
    + int proto;
    + int level = 0, max_level;
    + int last = -1;
    +
    + smp_rmb();
    + if(tp->card_state != Running)
    + return;
    +
    + max_level = typhoon_max_offload(xbl);
    +
    + list_for_each_entry_reverse(bundle, &xbl->node, node) {
    + dst = bundle->dst;
    + x = dst->xfrm;
    +
    + /* Only support IPv4 */
    + if(dst->ops->family != AF_INET)
    + goto cannot_offload;
    +
    + proto = x ? x->type->proto : IPPROTO_IP;
    +
    + switch(proto) {
    + case IPPROTO_IP:
    + case IPPROTO_IPIP:
    + if(last == IPPROTO_IP || last == IPPROTO_IPIP)
    + goto cannot_offload;
    + if(level)
    + level++;
    + last = proto;
    + continue;
    + case IPPROTO_ESP:
    + if(last != IPPROTO_AH)
    + level++;
    + break;
    + case IPPROTO_AH:
    + level++;
    + break;
    + default:
    + goto cannot_offload;
    + }
    +
    + last = proto;
    + if(level > max_level)
    + goto cannot_offload;
    +
    + if(dst->xfrm_offload)
    + continue;
    +
    + xol = xfrm_offload_get(x, dev);
    + if(!xol) {
    + xol = typhoon_offload_ipsec(tp, x);
    + if(xol)
    + xfrm_offload_hold(xol);
    + }
    +
    + if(!xol)
    + goto cannot_offload;
    +
    + dst->xfrm_offload = xol;
    + txo = xfrm_offload_priv(xol);
    + if(txo->tunnel)
    + last = IPPROTO_IPIP;
    + }
    +
    +cannot_offload:
    + return;
    +}
    +
     static void
     typhoon_tx_timeout(struct net_device *dev)
     {
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/


  • Next message: David Dillow: "[RFC 2.6.10 16/22] typhoon: collect crypto offload capabilities"