GSO: Support partial segmentation offload
This patch adds support for something I am referring to as GSO partial. The basic idea is that we can support a broader range of devices for segmentation if we use fixed outer headers and have the hardware only really deal with segmenting the inner header. The idea behind the naming is due to the fact that everything before csum_start will be fixed headers, and everything after will be the region that is handled by hardware. With the current implementation it allows us to add support for the following GSO types with an inner TSO_MANGLEID or TSO6 offload: NETIF_F_GSO_GRE NETIF_F_GSO_GRE_CSUM NETIF_F_GSO_IPIP NETIF_F_GSO_SIT NETIF_F_UDP_TUNNEL NETIF_F_UDP_TUNNEL_CSUM In the case of hardware that already supports tunneling we may be able to extend this further to support TSO_TCPV4 without TSO_MANGLEID if the hardware can support updating inner IPv4 headers. Signed-off-by: Alexander Duyck <aduyck@mirantis.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
1530545ed6
commit
802ab55adc
@@ -3076,8 +3076,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
||||
struct sk_buff *frag_skb = head_skb;
|
||||
unsigned int offset = doffset;
|
||||
unsigned int tnl_hlen = skb_tnl_header_len(head_skb);
|
||||
unsigned int partial_segs = 0;
|
||||
unsigned int headroom;
|
||||
unsigned int len;
|
||||
unsigned int len = head_skb->len;
|
||||
__be16 proto;
|
||||
bool csum;
|
||||
int sg = !!(features & NETIF_F_SG);
|
||||
@@ -3094,6 +3095,15 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb,
|
||||
|
||||
csum = !!can_checksum_protocol(features, proto);
|
||||
|
||||
/* GSO partial only requires that we trim off any excess that
|
||||
* doesn't fit into an MSS sized block, so take care of that
|
||||
* now.
|
||||
*/
|
||||
if (features & NETIF_F_GSO_PARTIAL) {
|
||||
partial_segs = len / mss;
|
||||
mss *= partial_segs;
|
||||
}
|
||||
|
||||
headroom = skb_headroom(head_skb);
|
||||
pos = skb_headlen(head_skb);
|
||||
|
||||
@@ -3281,6 +3291,23 @@ perform_csum_check:
|
||||
*/
|
||||
segs->prev = tail;
|
||||
|
||||
/* Update GSO info on first skb in partial sequence. */
|
||||
if (partial_segs) {
|
||||
int type = skb_shinfo(head_skb)->gso_type;
|
||||
|
||||
/* Update type to add partial and then remove dodgy if set */
|
||||
type |= SKB_GSO_PARTIAL;
|
||||
type &= ~SKB_GSO_DODGY;
|
||||
|
||||
/* Update GSO info and prepare to start updating headers on
|
||||
* our way back down the stack of protocols.
|
||||
*/
|
||||
skb_shinfo(segs)->gso_size = skb_shinfo(head_skb)->gso_size;
|
||||
skb_shinfo(segs)->gso_segs = partial_segs;
|
||||
skb_shinfo(segs)->gso_type = type;
|
||||
SKB_GSO_CB(segs)->data_offset = skb_headroom(segs) + doffset;
|
||||
}
|
||||
|
||||
/* Following permits correct backpressure, for protocols
|
||||
* using skb_set_owner_w().
|
||||
* Idea is to tranfert ownership from head_skb to last segment.
|
||||
|
Reference in New Issue
Block a user