From fedbc8c132bcf836358103195d8b6df6c03d9daf Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Tue, 4 Oct 2016 10:29:13 +0100 Subject: xen-netback: retire guest rx side prefix GSO feature As far as I am aware only very old Windows network frontends make use of this style of passing GSO packets from backend to frontend. These frontends can easily be replaced by the freely available Xen Project Windows PV network frontend, which uses the 'default' mechanism for passing GSO packets, which is also used by all Linux frontends. NOTE: Removal of this feature will not cause breakage in old Windows frontends. They simply will no longer receive GSO packets - the packets instead being fragmented in the backend. Signed-off-by: Paul Durrant Reviewed-by: David Vrabel Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index fb50c6d5f6c3..211d542a830b 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -319,9 +319,9 @@ static netdev_features_t xenvif_fix_features(struct net_device *dev, if (!vif->can_sg) features &= ~NETIF_F_SG; - if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV4)) + if (~(vif->gso_mask) & GSO_BIT(TCPV4)) features &= ~NETIF_F_TSO; - if (~(vif->gso_mask | vif->gso_prefix_mask) & GSO_BIT(TCPV6)) + if (~(vif->gso_mask) & GSO_BIT(TCPV6)) features &= ~NETIF_F_TSO6; if (!vif->ip_csum) features &= ~NETIF_F_IP_CSUM; -- cgit From 2167ca029c2449018314fdf8637c1eb3f123036e Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Tue, 4 Oct 2016 10:29:18 +0100 Subject: xen/netback: add fraglist support for to-guest rx This allows full 64K skbuffs (with 1500 mtu ethernet, composed of 45 fragments) to be handled by netback for to-guest rx. Signed-off-by: Ross Lagerwall [re-based] Signed-off-by: Paul Durrant Reviewed-by: David Vrabel Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 2 +- drivers/net/xen-netback/rx.c | 38 ++++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 211d542a830b..4af532a67d95 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -467,7 +467,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, dev->netdev_ops = &xenvif_netdev_ops; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6; + NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_FRAGLIST; dev->features = dev->hw_features | NETIF_F_RXCSUM; dev->ethtool_ops = &xenvif_ethtool_ops; diff --git a/drivers/net/xen-netback/rx.c b/drivers/net/xen-netback/rx.c index 8c8c5b5883eb..8e9ade6ccf18 100644 --- a/drivers/net/xen-netback/rx.c +++ b/drivers/net/xen-netback/rx.c @@ -215,7 +215,8 @@ static unsigned int xenvif_gso_type(struct sk_buff *skb) struct xenvif_pkt_state { struct sk_buff *skb; size_t remaining_len; - int frag; /* frag == -1 => skb->head */ + struct sk_buff *frag_iter; + int frag; /* frag == -1 => frag_iter->head */ unsigned int frag_offset; struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX - 1]; unsigned int extra_count; @@ -237,6 +238,7 @@ static void xenvif_rx_next_skb(struct xenvif_queue *queue, memset(pkt, 0, sizeof(struct xenvif_pkt_state)); pkt->skb = skb; + pkt->frag_iter = skb; pkt->remaining_len = skb->len; pkt->frag = -1; @@ -293,20 +295,40 @@ static void xenvif_rx_complete(struct xenvif_queue *queue, __skb_queue_tail(queue->rx_copy.completed, pkt->skb); } +static void xenvif_rx_next_frag(struct xenvif_pkt_state *pkt) +{ + struct sk_buff *frag_iter = pkt->frag_iter; + unsigned int nr_frags = skb_shinfo(frag_iter)->nr_frags; + + pkt->frag++; + pkt->frag_offset = 0; + + if (pkt->frag >= nr_frags) { + if (frag_iter == pkt->skb) + pkt->frag_iter = skb_shinfo(frag_iter)->frag_list; + else + pkt->frag_iter = frag_iter->next; + + pkt->frag = -1; + } +} + static void xenvif_rx_next_chunk(struct xenvif_queue *queue, struct xenvif_pkt_state *pkt, unsigned int offset, void **data, size_t *len) { - struct sk_buff *skb = pkt->skb; + struct sk_buff *frag_iter = pkt->frag_iter; void *frag_data; size_t frag_len, chunk_len; + BUG_ON(!frag_iter); + if (pkt->frag == -1) { - frag_data = skb->data; - frag_len = skb_headlen(skb); + frag_data = frag_iter->data; + frag_len = skb_headlen(frag_iter); } else { - skb_frag_t *frag = &skb_shinfo(skb)->frags[pkt->frag]; + skb_frag_t *frag = &skb_shinfo(frag_iter)->frags[pkt->frag]; frag_data = skb_frag_address(frag); frag_len = skb_frag_size(frag); @@ -322,10 +344,8 @@ static void xenvif_rx_next_chunk(struct xenvif_queue *queue, pkt->frag_offset += chunk_len; /* Advance to next frag? */ - if (frag_len == chunk_len) { - pkt->frag++; - pkt->frag_offset = 0; - } + if (frag_len == chunk_len) + xenvif_rx_next_frag(pkt); *data = frag_data; *len = chunk_len; -- cgit From 912e27e85e070596ed4964ebde29fa9781390f2a Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Fri, 7 Oct 2016 09:32:31 +0100 Subject: xen-netback: make sure that hashes are not send to unaware frontends In the case when a frontend only negotiates a single queue with xen- netback it is possible for a skbuff with a s/w hash to result in a hash extra_info segment being sent to the frontend even when no hash algorithm has been configured. (The ndo_select_queue() entry point makes sure the hash is not set if no algorithm is configured, but this entry point is not called when there is only a single queue). This can result in a frontend that is unable to handle extra_info segments being given such a segment, causing it to crash. This patch fixes the problem by clearing the hash in ndo_start_xmit() instead, which is clearly guaranteed to be called irrespective of the number of queues. Signed-off-by: Paul Durrant Cc: Wei Liu Acked-by: Wei Liu Signed-off-by: David S. Miller --- drivers/net/xen-netback/interface.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'drivers/net/xen-netback/interface.c') diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 4af532a67d95..74dc2bf71428 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -149,17 +149,8 @@ static u16 xenvif_select_queue(struct net_device *dev, struct sk_buff *skb, struct xenvif *vif = netdev_priv(dev); unsigned int size = vif->hash.size; - if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) { - u16 index = fallback(dev, skb) % dev->real_num_tx_queues; - - /* Make sure there is no hash information in the socket - * buffer otherwise it would be incorrectly forwarded - * to the frontend. - */ - skb_clear_hash(skb); - - return index; - } + if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) + return fallback(dev, skb) % dev->real_num_tx_queues; xenvif_set_skb_hash(vif, skb); @@ -208,6 +199,13 @@ static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev) cb = XENVIF_RX_CB(skb); cb->expires = jiffies + vif->drain_timeout; + /* If there is no hash algorithm configured then make sure there + * is no hash information in the socket buffer otherwise it + * would be incorrectly forwarded to the frontend. + */ + if (vif->hash.alg == XEN_NETIF_CTRL_HASH_ALGORITHM_NONE) + skb_clear_hash(skb); + xenvif_rx_queue_tail(queue, skb); xenvif_kick_thread(queue); -- cgit