diff options
Diffstat (limited to 'drivers/net/xen-netfront.c')
-rw-r--r-- | drivers/net/xen-netfront.c | 96 |
1 files changed, 46 insertions, 50 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 2ab82fe75ede..e955c5692986 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -617,7 +617,9 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev) tx->flags |= XEN_NETTXF_extra_info; gso->u.gso.size = skb_shinfo(skb)->gso_size; - gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4; + gso->u.gso.type = (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) ? + XEN_NETIF_GSO_TYPE_TCPV6 : + XEN_NETIF_GSO_TYPE_TCPV4; gso->u.gso.pad = 0; gso->u.gso.features = 0; @@ -809,15 +811,18 @@ static int xennet_set_skb_gso(struct sk_buff *skb, return -EINVAL; } - /* Currently only TCPv4 S.O. is supported. */ - if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { + if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4 && + gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV6) { if (net_ratelimit()) pr_warn("Bad GSO type %d\n", gso->u.gso.type); return -EINVAL; } skb_shinfo(skb)->gso_size = gso->u.gso.size; - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; + skb_shinfo(skb)->gso_type = + (gso->u.gso.type == XEN_NETIF_GSO_TYPE_TCPV4) ? + SKB_GSO_TCPV4 : + SKB_GSO_TCPV6; /* Header must be checked, and gso_segs computed. */ skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; @@ -859,9 +864,7 @@ static RING_IDX xennet_fill_frags(struct netfront_info *np, static int checksum_setup(struct net_device *dev, struct sk_buff *skb) { - struct iphdr *iph; - int err = -EPROTO; - int recalculate_partial_csum = 0; + bool recalculate_partial_csum = false; /* * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy @@ -873,54 +876,14 @@ static int checksum_setup(struct net_device *dev, struct sk_buff *skb) struct netfront_info *np = netdev_priv(dev); np->rx_gso_checksum_fixup++; skb->ip_summed = CHECKSUM_PARTIAL; - recalculate_partial_csum = 1; + recalculate_partial_csum = true; } /* A non-CHECKSUM_PARTIAL SKB does not require setup. */ if (skb->ip_summed != CHECKSUM_PARTIAL) return 0; - if (skb->protocol != htons(ETH_P_IP)) - goto out; - - iph = (void *)skb->data; - - switch (iph->protocol) { - case IPPROTO_TCP: - if (!skb_partial_csum_set(skb, 4 * iph->ihl, - offsetof(struct tcphdr, check))) - goto out; - - if (recalculate_partial_csum) { - struct tcphdr *tcph = tcp_hdr(skb); - tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - iph->ihl*4, - IPPROTO_TCP, 0); - } - break; - case IPPROTO_UDP: - if (!skb_partial_csum_set(skb, 4 * iph->ihl, - offsetof(struct udphdr, check))) - goto out; - - if (recalculate_partial_csum) { - struct udphdr *udph = udp_hdr(skb); - udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - skb->len - iph->ihl*4, - IPPROTO_UDP, 0); - } - break; - default: - if (net_ratelimit()) - pr_err("Attempting to checksum a non-TCP/UDP packet, dropping a protocol %d packet\n", - iph->protocol); - goto out; - } - - err = 0; - -out: - return err; + return skb_checksum_setup(skb, recalculate_partial_csum); } static int handle_incoming_queue(struct net_device *dev, @@ -1233,6 +1196,15 @@ static netdev_features_t xennet_fix_features(struct net_device *dev, features &= ~NETIF_F_SG; } + if (features & NETIF_F_IPV6_CSUM) { + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, + "feature-ipv6-csum-offload", "%d", &val) < 0) + val = 0; + + if (!val) + features &= ~NETIF_F_IPV6_CSUM; + } + if (features & NETIF_F_TSO) { if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, "feature-gso-tcpv4", "%d", &val) < 0) @@ -1242,6 +1214,15 @@ static netdev_features_t xennet_fix_features(struct net_device *dev, features &= ~NETIF_F_TSO; } + if (features & NETIF_F_TSO6) { + if (xenbus_scanf(XBT_NIL, np->xbdev->otherend, + "feature-gso-tcpv6", "%d", &val) < 0) + val = 0; + + if (!val) + features &= ~NETIF_F_TSO6; + } + return features; } @@ -1380,7 +1361,9 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_napi_add(netdev, &np->napi, xennet_poll, 64); netdev->features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_GSO_ROBUST; - netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO; + netdev->hw_features = NETIF_F_SG | + NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6; /* * Assume that all hw features are available for now. This set @@ -1758,6 +1741,19 @@ again: goto abort_transaction; } + err = xenbus_write(xbt, dev->nodename, "feature-gso-tcpv6", "1"); + if (err) { + message = "writing feature-gso-tcpv6"; + goto abort_transaction; + } + + err = xenbus_write(xbt, dev->nodename, "feature-ipv6-csum-offload", + "1"); + if (err) { + message = "writing feature-ipv6-csum-offload"; + goto abort_transaction; + } + err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) |