--- linux-2.6.23-rc1.orig/include/linux/inet_lro.h 2007-07-25 12:48:48.000000000 -0400 +++ linux-2.6.23-rc1/include/linux/inet_lro.h 2007-07-24 15:07:28.000000000 -0400 @@ -132,7 +132,7 @@ void lro_vlan_hwaccel_receive_skb(struct void lro_receive_frags(struct net_lro_mgr *lro_mgr, struct skb_frag_struct *frags, - int len, int true_size, void *priv); + int len, int true_size, void *priv, __wsum sum); void lro_vlan_hwaccel_receive_frags(struct net_lro_mgr *lro_mgr, struct skb_frag_struct *frags, @@ -140,7 +140,8 @@ void lro_vlan_hwaccel_receive_frags(stru int true_size, struct vlan_group *vgrp, u16 vlan_tag, - void *priv); + void *priv, + __wsum sum); /* * Forward all aggregated SKBs held by lro_mgr to network stack --- linux-2.6.23-rc1.orig/net/ipv4/inet_lro.c 2007-07-25 12:48:48.000000000 -0400 +++ linux-2.6.23-rc1/net/ipv4/inet_lro.c 2007-07-25 10:23:31.000000000 -0400 @@ -341,6 +341,10 @@ int __lro_proc_skb(struct net_lro_mgr *l if (!(flags & LRO_IPV4) || !(flags & LRO_TCP)) goto out; + /* checksum has been verified by get_frag_header() */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->csum = 0; + lro_desc = lro_get_desc(lro_mgr, lro_mgr->lro_arr, iph, tcph); if (!lro_desc) goto out; @@ -437,7 +441,8 @@ struct sk_buff *__lro_proc_segment(struc struct skb_frag_struct *frags, int len, int true_size, struct vlan_group *vgrp, - u16 vlan_tag, void *priv) + u16 vlan_tag, void *priv, + __wsum sum) { struct net_lro_desc *lro_desc; struct iphdr *iph; @@ -446,6 +451,7 @@ struct sk_buff *__lro_proc_segment(struc void *mac_hdr; u64 flags; int hdr_len = 0; + int vlan_hdr_len; if (!lro_mgr->get_frag_header || lro_mgr->get_frag_header(frags, (void *)&mac_hdr, (void *)&iph, @@ -473,8 +479,17 @@ struct sk_buff *__lro_proc_segment(struc if (!skb) goto out; - iph = (void *)(skb->data); - tcph = (void *)((u8 *)skb->data + IP_HDR_LEN(iph)); + /* checksum has been verified by get_frag_header() */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + skb->csum = 0; + + if (skb->protocol == htons(ETH_P_8021Q)) + vlan_hdr_len = VLAN_HLEN; + else + vlan_hdr_len = 0; + + iph = (void *)(skb->data + vlan_hdr_len); + tcph = (void *)((u8 *)skb->data + vlan_hdr_len + IP_HDR_LEN(iph)); lro_init_desc(lro_desc, skb, iph, tcph, 0, NULL); return 0; @@ -501,17 +516,20 @@ out1: /* Original packet has to be post skb = lro_gen_skb(lro_mgr, frags, len, true_size, mac_hdr, max(hdr_len, LRO_MIN_PG_HLEN)); + skb->ip_summed = lro_mgr->ip_summed; + skb->csum = sum; out: return skb; } void lro_receive_frags(struct net_lro_mgr *lro_mgr, struct skb_frag_struct *frags, - int len, int true_size, void *priv) + int len, int true_size, void *priv, __wsum sum) { struct sk_buff *skb; - skb = __lro_proc_segment(lro_mgr, frags, len, true_size, NULL, 0, priv); + skb = __lro_proc_segment(lro_mgr, frags, len, true_size, NULL, 0, + priv, sum); if(skb) netif_receive_skb(skb); } @@ -524,12 +542,13 @@ void lro_vlan_hwaccel_receive_frags(stru int true_size, struct vlan_group *vgrp, u16 vlan_tag, - void *priv) + void *priv, + __wsum sum) { struct sk_buff *skb; skb = __lro_proc_segment(lro_mgr, frags, len, true_size, vgrp, - vlan_tag, priv); + vlan_tag, priv, sum); if(skb) vlan_hwaccel_receive_skb(skb, vgrp, vlan_tag); }