Re: NETIF_F_GSO_SOFTWARE vs NETIF_F_GSO
From: Jason A. Donenfeld
Date: Thu Nov 05 2015 - 20:32:56 EST
Hi folks,
I'm still facing some considerable problems. Please see below.
On Thu, Nov 5, 2015 at 5:28 PM, Jason A. Donenfeld <Jason@xxxxxxxxx> wrote:
> As mentioned, I receive packets on ndo_start_xmit, "do something to
> them with function magic()", and then push them out of a UDP socket
> using udp_tunnel_xmit_skb. There appears to be significant overhead
> from calling udp_tunnel_xmit_skb over and over. What I'd really like
> to do is pass the NETIF_F_GSO_SOFTWARE-provided super packet directly
> to udp_tunnel_xmit_skb, but in fact the magic() function mentioned
> above needs to work on an entire MTU-sized IP packet, not a a super
> packet. So, instead, what it's looking like is:
>
> 1. Set NETIF_F_GSO_SOFTWARE to receive super packets.
> 2. For each super packet, break it down using skb_gso_segment().
> 2a. For each segmented packet, "do my magic() function"
> 3. After having done the magic() to each of the segmented packets, I
> *repack the results* into a new super packet. I then pass that super
> packet to udp_tunnel_xmit_skb().
>
> Is this approach a real possibility?
>
> If so, it seems like the best way to get GSO-like qualities out of
> udp_tunnel_xmit_skb. I've successfully done (1) and (2), following the
> example of validate_xmit_skb() from net/core/dev.c. Now I need to
> figure out how to do (3). Hopefully I'll find some nice convenience
> functions for this...
So far implementing (3) is failing miserably. Is there anything wrong
with my general idea that might make this a priori impossible? For
example, will udp_tunnel_xmit_skb not accept super-packets? Or, am I
just not making use of whatever nice convenience functions are
available for constructing super-packets, and thus am doing something
wrong?
Currently, I'm doing essentially what follows below. It seems like it
ought to be working, but it's not.
gso_segs = DIV_ROUND_UP(skb->len, skb_shinfo(skb)->gso_size);
segs = skb_gso_segment(skb, 0);
if (IS_ERR(segs)) {
kfree_skb(skb);
return PTR_ERR(segs);
}
dev_kfree_skb(skb);
gso_size = magic_len(segs->len);
len = gso_size * gso_segs;
outgoing = alloc_skb(len, GFP_ATOMIC);
if (!outgoing) {
kfree_skb_list(segs);
return -ENOMEM;
}
skb_shinfo(outgoing)->gso_type = SKB_GSO_UDP;
skb_shinfo(outgoing)->gso_size = gso_size;
skb_shinfo(outgoing)->gso_segs = 0;
outgoing->ip_summed = CHECKSUM_PARTIAL;
src = segs;
while (src) {
next = src->next;
dst_buffer = skb_put(outgoing, magic_len(src->len));
ret = do_magic(dst_buffer, src);
if (ret) {
dev_kfree_skb(outgoing);
return ret;
}
++skb_shinfo(outgoing)->gso_segs;
src = next;
}
return eventually_udp_tunnel_xmit_skb(outgoing);
Let me know if there is something fundamentally wrong with this
approach. Or if you have any other pointers...
Regards,
Jason
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/