On Thu, Nov 22, 2012 at 7:57 AM, Pravin B Shelar <[email protected]> wrote:
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 585aca7..a23df86 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -422,6 +424,7 @@ struct sk_buff {
>                         __u16   csum_offset;
>                 };
>         };
> +       __u16                   tunnel_hlen;

Is it possible to use those new inner header pointers that were added here?

> diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
> index c256008..1ce522a 100644
> --- a/net/ipv4/udp.c
> +++ b/net/ipv4/udp.c
> @@ -2246,31 +2246,79 @@ void __init udp_init(void)
>
>  int udp4_ufo_send_check(struct sk_buff *skb)
>  {
> -       const struct iphdr *iph;
> -       struct udphdr *uh;
> -
> -       if (!pskb_may_pull(skb, sizeof(*uh)))
> +       if (!pskb_may_pull(skb, sizeof(struct udphdr)))
>                 return -EINVAL;
>
> -       iph = ip_hdr(skb);
> -       uh = udp_hdr(skb);
> +       if (!skb->tunnel_hlen) {

Don't we have to pass this down to the encapsulated protocol below
since that's the checksum that we really care about?

> +static struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,
> +               netdev_features_t features)
> +{
> +       struct sk_buff *segs = ERR_PTR(-EINVAL);
> +       int mac_len = skb->mac_len;
> +       unsigned char *mac = skb_mac_header(skb);
> +       int hlen = sizeof(struct udphdr) + skb->tunnel_hlen;
> +       int doffset;
> +       int network_hlen = skb_network_header_len(skb);
> +
> +       skb->tunnel_hlen = 0;
> +       if (unlikely(!pskb_may_pull(skb, hlen)))
> +               goto out;
> +
> +       __skb_pull(skb, hlen);
> +       skb_reset_mac_header(skb);
> +       skb_set_network_header(skb, skb->mac_len);
> +       doffset = skb_mac_header(skb) - mac;
> +
> +       /* segment inner packet. */
> +       segs = skb_gso_segment(skb, 0);
> +       if (!segs || IS_ERR(segs))
> +               goto out;

I have similar questions here as with GRE about whether it is safe to
reuse skb->mac_len and if we can avoid the loop with memcpy() by
calling directly into the next layer for segmentation.

> diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
> index 8234c1d..e02a65a 100644
> --- a/net/ipv6/ip6_offload.c
> +++ b/net/ipv6/ip6_offload.c
> @@ -100,6 +100,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff 
> *skb,
>                        SKB_GSO_DODGY |
>                        SKB_GSO_TCP_ECN |
>                        SKB_GSO_GRE |
> +                      SKB_GSO_UDP_TUNNEL |
>                        SKB_GSO_TCPV6 |
>                        0)))
>                 goto out;

Do we need to do the check to avoid fragmenting UDP for IPv6 as well?

> diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c
> index cf05cf0..8530d57 100644
> --- a/net/ipv6/udp_offload.c
> +++ b/net/ipv6/udp_offload.c
> @@ -21,6 +21,9 @@ static int udp6_ufo_send_check(struct sk_buff *skb)
>         const struct ipv6hdr *ipv6h;
>         struct udphdr *uh;
>
> +       if (skb->tunnel_hlen)
> +               return -EINVAL;

Can't we support IPv6 fairly easily as well?
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev

Reply via email to