From 3fc6ac6dc78388c7b705bd4709f6b70c60f63c02 Mon Sep 17 00:00:00 2001 From: Paul Durrant Date: Fri, 9 Oct 2015 14:53:15 +0100 Subject: [PATCH] xen-netback: pass an L4 or L3 skb hash value to the frontend If the frontend indicates it's capable (see netif.h for details) and an skb has an L4 or L3 hash value then pass the value to the frontend in a xen_netif_extra_info segment. Signed-off-by: Paul Durrant Cc: Ian Campbell Cc: Wei Liu --- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/netback.c | 72 +++++++++++++++++++++++++------ drivers/net/xen-netback/xenbus.c | 5 +++ 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index f3e0e01e8a32..07fff824de74 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -227,6 +227,7 @@ struct xenvif { u8 ip_csum:1; u8 ipv6_csum:1; u8 multicast_control:1; + u8 hash_extra:1; /* Is this interface disabled? True when backend discovers * frontend is rogue. diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f820f63b20bc..d207bc573f8e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -150,10 +150,17 @@ static inline pending_ring_idx_t pending_index(unsigned i) static int xenvif_rx_ring_slots_needed(struct xenvif *vif) { - if (vif->gso_mask) - return DIV_ROUND_UP(vif->dev->gso_max_size, PAGE_SIZE) + 1; + int needed; + + if (vif->gso_mask || vif->gso_prefix_mask) + needed = DIV_ROUND_UP(vif->dev->gso_max_size, PAGE_SIZE) + 1; else - return DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); + needed = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE); + + if (vif->hash_extra) + needed++; + + return needed; } static bool xenvif_rx_ring_slots_available(struct xenvif_queue *queue) @@ -385,6 +392,12 @@ static int xenvif_gop_skb(struct sk_buff *skb, if ((1 << gso_type) & vif->gso_mask) queue->rx.req_cons++; + /* Skip a hash extra segment, if necessary */ + if (vif->hash_extra && + (skb->protocol == htons(ETH_P_IP) || + skb->protocol == htons(ETH_P_IPV6))) + queue->rx.req_cons++; + data = skb->data; while (data < skb_tail_pointer(skb)) { unsigned int offset = offset_in_page(data); @@ -504,6 +517,7 @@ static void xenvif_rx_action(struct xenvif_queue *queue) while ((skb = __skb_dequeue(&rxq)) != NULL) { struct xenvif *vif = queue->vif; int gso_type = XEN_NETIF_GSO_TYPE_NONE; + struct xen_netif_extra_info *extra = NULL; if (skb_is_gso(skb)) { if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) @@ -551,20 +565,54 @@ static void xenvif_rx_action(struct xenvif_queue *queue) flags); if ((1 << gso_type) & vif->gso_mask) { - struct xen_netif_extra_info *gso = - (struct xen_netif_extra_info *) + resp->flags |= XEN_NETRXF_extra_info; + + extra = (struct xen_netif_extra_info *) RING_GET_RESPONSE(&queue->rx, queue->rx.rsp_prod_pvt++); - resp->flags |= XEN_NETRXF_extra_info; + extra->u.gso.type = gso_type; + extra->u.gso.size = skb_shinfo(skb)->gso_size; + extra->u.gso.pad = 0; + extra->u.gso.features = 0; + + extra->type = XEN_NETIF_EXTRA_TYPE_GSO; + extra->flags = 0; + } + + if (vif->hash_extra && + (skb->protocol == htons(ETH_P_IP) || + skb->protocol == htons(ETH_P_IPV6))) { + if (resp->flags & XEN_NETRXF_extra_info) + extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE; + else + resp->flags |= XEN_NETRXF_extra_info; - gso->u.gso.type = gso_type; - gso->u.gso.size = skb_shinfo(skb)->gso_size; - gso->u.gso.pad = 0; - gso->u.gso.features = 0; + extra = (struct xen_netif_extra_info *) + RING_GET_RESPONSE(&queue->rx, + queue->rx.rsp_prod_pvt++); + + if (skb_hash_type(skb) == PKT_HASH_TYPE_L4) { + extra->u.hash.type = + skb->protocol == htons(ETH_P_IP) ? + XEN_NETIF_HASH_TYPE_TCPV4 : + XEN_NETIF_HASH_TYPE_TCPV6; + *(uint32_t *)extra->u.hash.value = + skb_get_hash_raw(skb); + } else if (skb_hash_type(skb) == PKT_HASH_TYPE_L3) { + extra->u.hash.type = + skb->protocol == htons(ETH_P_IP) ? + XEN_NETIF_HASH_TYPE_IPV4 : + XEN_NETIF_HASH_TYPE_IPV6; + *(uint32_t *)extra->u.hash.value = + skb_get_hash_raw(skb); + } else { + extra->u.hash.type = XEN_NETIF_HASH_TYPE_NONE; + *(uint32_t *)extra->u.hash.value = 0; + } - gso->type = XEN_NETIF_EXTRA_TYPE_GSO; - gso->flags = 0; + extra->type = XEN_NETIF_EXTRA_TYPE_HASH; + extra->flags = 0; } xenvif_add_frag_responses(queue, status, diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 2fa8a16fcf0f..a31bceed8749 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -1037,6 +1037,11 @@ static int read_xenbus_vif_flags(struct backend_info *be) val = 0; vif->multicast_control = !!val; + if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-hash", + "%d", &val) < 0) + val = 0; + vif->hash_extra = !!val; + return 0; } -- 2.39.5