Author: sephe
Date: Wed May 11 03:31:25 2016
New Revision: 299401
URL: https://svnweb.freebsd.org/changeset/base/299401

Log:
  hyperv/hn: Extract RSS hash value and type.
  
  MFC after:    1 week
  Sponsored by: Microsoft OSTC
  Differential Revision:        https://reviews.freebsd.org/D6287

Modified:
  head/sys/dev/hyperv/netvsc/hv_net_vsc.h
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
  head/sys/dev/hyperv/netvsc/hv_rndis.h
  head/sys/dev/hyperv/netvsc/hv_rndis_filter.c

Modified: head/sys/dev/hyperv/netvsc/hv_net_vsc.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Wed May 11 00:59:06 2016        
(r299400)
+++ head/sys/dev/hyperv/netvsc/hv_net_vsc.h     Wed May 11 03:31:25 2016        
(r299401)
@@ -1164,6 +1164,7 @@ struct hn_rx_ring {
        u_long          hn_lro_tried;
        u_long          hn_small_pkts;
        u_long          hn_pkts;
+       u_long          hn_rss_pkts;
 
        /* Rarely used stuffs */
        struct sysctl_oid *hn_rx_sysctl_tree;

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Wed May 11 00:59:06 
2016        (r299400)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c  Wed May 11 03:31:25 
2016        (r299401)
@@ -140,7 +140,7 @@ __FBSDID("$FreeBSD$");
 
 #define HN_RNDIS_MSG_LEN               \
     (sizeof(rndis_msg) +               \
-     RNDIS_HASH_PPI_SIZE +             \
+     RNDIS_HASHVAL_PPI_SIZE +          \
      RNDIS_VLAN_PPI_SIZE +             \
      RNDIS_TSO_PPI_SIZE +              \
      RNDIS_CSUM_PPI_SIZE)
@@ -866,7 +866,7 @@ hn_encap(struct hn_tx_ring *txr, struct 
        rndis_msg *rndis_mesg;
        rndis_packet *rndis_pkt;
        rndis_per_packet_info *rppi;
-       struct ndis_hash_info *hash_info;
+       struct rndis_hash_value *hash_value;
        uint32_t rndis_msg_size;
 
        packet = &txd->netvsc_pkt;
@@ -892,16 +892,16 @@ hn_encap(struct hn_tx_ring *txr, struct 
        rndis_msg_size = RNDIS_MESSAGE_SIZE(rndis_packet);
 
        /*
-        * Set the hash info for this packet, so that the host could
+        * Set the hash value for this packet, so that the host could
         * dispatch the TX done event for this packet back to this TX
         * ring's channel.
         */
-       rndis_msg_size += RNDIS_HASH_PPI_SIZE;
-       rppi = hv_set_rppi_data(rndis_mesg, RNDIS_HASH_PPI_SIZE,
+       rndis_msg_size += RNDIS_HASHVAL_PPI_SIZE;
+       rppi = hv_set_rppi_data(rndis_mesg, RNDIS_HASHVAL_PPI_SIZE,
            nbl_hash_value);
-       hash_info = (struct ndis_hash_info *)((uint8_t *)rppi +
+       hash_value = (struct rndis_hash_value *)((uint8_t *)rppi +
            rppi->per_packet_info_offset);
-       hash_info->hash = txr->hn_tx_idx;
+       hash_value->hash_value = txr->hn_tx_idx;
 
        if (m_head->m_flags & M_VLANTAG) {
                ndis_8021q_info *rppi_vlan_info;
@@ -1291,7 +1291,9 @@ hv_m_append(struct mbuf *m0, int len, c_
  */
 int
 netvsc_recv(struct hv_vmbus_channel *chan, netvsc_packet *packet,
-    rndis_tcp_ip_csum_info *csum_info)
+    rndis_tcp_ip_csum_info *csum_info,
+    const struct rndis_hash_info *hash_info,
+    const struct rndis_hash_value *hash_value)
 {
        struct hn_rx_ring *rxr = chan->hv_chan_rxr;
        struct ifnet *ifp = rxr->hn_ifp;
@@ -1400,7 +1402,6 @@ netvsc_recv(struct hv_vmbus_channel *cha
                                            CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
                                        m_new->m_pkthdr.csum_data = 0xffff;
                                }
-                               /* Rely on SW csum verification though... */
                                do_lro = 1;
                        } else if (pr == IPPROTO_UDP) {
                                if (do_csum &&
@@ -1427,8 +1428,50 @@ skip:
                m_new->m_flags |= M_VLANTAG;
        }
 
-       m_new->m_pkthdr.flowid = rxr->hn_rx_idx;
-       M_HASHTYPE_SET(m_new, M_HASHTYPE_OPAQUE);
+       if (hash_info != NULL && hash_value != NULL) {
+               int hash_type = M_HASHTYPE_OPAQUE;
+
+               rxr->hn_rss_pkts++;
+               m_new->m_pkthdr.flowid = hash_value->hash_value;
+               if ((hash_info->hash_info & NDIS_HASH_FUNCTION_MASK) ==
+                   NDIS_HASH_FUNCTION_TOEPLITZ) {
+                       uint32_t type =
+                           (hash_info->hash_info & NDIS_HASH_TYPE_MASK);
+
+                       switch (type) {
+                       case NDIS_HASH_IPV4:
+                               hash_type = M_HASHTYPE_RSS_IPV4;
+                               break;
+
+                       case NDIS_HASH_TCP_IPV4:
+                               hash_type = M_HASHTYPE_RSS_TCP_IPV4;
+                               break;
+
+                       case NDIS_HASH_IPV6:
+                               hash_type = M_HASHTYPE_RSS_IPV6;
+                               break;
+
+                       case NDIS_HASH_IPV6_EX:
+                               hash_type = M_HASHTYPE_RSS_IPV6_EX;
+                               break;
+
+                       case NDIS_HASH_TCP_IPV6:
+                               hash_type = M_HASHTYPE_RSS_TCP_IPV6;
+                               break;
+
+                       case NDIS_HASH_TCP_IPV6_EX:
+                               hash_type = M_HASHTYPE_RSS_TCP_IPV6_EX;
+                               break;
+                       }
+               }
+               M_HASHTYPE_SET(m_new, hash_type);
+       } else {
+               if (hash_value != NULL)
+                       m_new->m_pkthdr.flowid = hash_value->hash_value;
+               else
+                       m_new->m_pkthdr.flowid = rxr->hn_rx_idx;
+               M_HASHTYPE_SET(m_new, M_HASHTYPE_OPAQUE);
+       }
 
        /*
         * Note:  Moved RX completion back to hv_nv_on_receive() so all
@@ -2219,6 +2262,11 @@ hn_create_rx_data(struct hn_softc *sc, i
                                    SYSCTL_CHILDREN(rxr->hn_rx_sysctl_tree),
                                    OID_AUTO, "packets", CTLFLAG_RW,
                                    &rxr->hn_pkts, "# of packets received");
+                               SYSCTL_ADD_ULONG(ctx,
+                                   SYSCTL_CHILDREN(rxr->hn_rx_sysctl_tree),
+                                   OID_AUTO, "rss_pkts", CTLFLAG_RW,
+                                   &rxr->hn_rss_pkts,
+                                   "# of packets w/ RSS info received");
                        }
                }
        }

Modified: head/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis.h       Wed May 11 00:59:06 2016        
(r299400)
+++ head/sys/dev/hyperv/netvsc/hv_rndis.h       Wed May 11 03:31:25 2016        
(r299401)
@@ -617,6 +617,7 @@ typedef enum ndis_per_pkt_infotype_ {
 } ndis_per_pkt_infotype;
 
 #define nbl_hash_value pkt_cancel_id
+#define nbl_hash_info  original_netbuf_list
 
 typedef struct ndis_8021q_info_ {
        union {
@@ -630,10 +631,6 @@ typedef struct ndis_8021q_info_ {
        } u1;
 } ndis_8021q_info;
 
-struct ndis_hash_info {
-       uint32_t        hash;
-} __packed;
-
 struct rndis_object_header {
        uint8_t type;
        uint8_t revision;
@@ -694,6 +691,28 @@ typedef struct rndis_tcp_ip_csum_info_ {
        };
 } rndis_tcp_ip_csum_info;
 
+struct rndis_hash_value {
+       uint32_t        hash_value;
+} __packed;
+
+struct rndis_hash_info {
+       uint32_t        hash_info;
+} __packed;
+
+#define NDIS_HASH_FUNCTION_MASK                0x000000FF      /* see hash 
function */
+#define NDIS_HASH_TYPE_MASK            0x00FFFF00      /* see hash type */
+
+/* hash function */
+#define NDIS_HASH_FUNCTION_TOEPLITZ    0x00000001
+
+/* hash type */
+#define NDIS_HASH_IPV4                 0x00000100
+#define NDIS_HASH_TCP_IPV4             0x00000200
+#define NDIS_HASH_IPV6                 0x00000400
+#define NDIS_HASH_IPV6_EX              0x00000800
+#define NDIS_HASH_TCP_IPV6             0x00001000
+#define NDIS_HASH_TCP_IPV6_EX          0x00002000
+
 typedef struct rndis_tcp_tso_info_ {
        union {
                struct {
@@ -727,8 +746,8 @@ typedef struct rndis_tcp_tso_info_ {
        };
 } rndis_tcp_tso_info;
 
-#define RNDIS_HASH_PPI_SIZE    (sizeof(rndis_per_packet_info) + \
-                               sizeof(struct ndis_hash_info))
+#define RNDIS_HASHVAL_PPI_SIZE (sizeof(rndis_per_packet_info) + \
+                               sizeof(struct rndis_hash_value))
 
 #define RNDIS_VLAN_PPI_SIZE    (sizeof(rndis_per_packet_info) + \
                                sizeof(ndis_8021q_info))
@@ -1066,7 +1085,9 @@ typedef struct rndismp_rx_bufs_info_ {
 struct hv_vmbus_channel;
 
 int netvsc_recv(struct hv_vmbus_channel *chan,
-    netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info);
+    netvsc_packet *packet, rndis_tcp_ip_csum_info *csum_info,
+    const struct rndis_hash_info *hash_info,
+    const struct rndis_hash_value *hash_value);
 void netvsc_channel_rollup(struct hv_vmbus_channel *chan);
 
 void* hv_set_rppi_data(rndis_msg *rndis_mesg,

Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Wed May 11 00:59:06 
2016        (r299400)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c        Wed May 11 03:31:25 
2016        (r299401)
@@ -444,6 +444,8 @@ hv_rf_receive_data(rndis_device *device,
        ndis_8021q_info *rppi_vlan_info;
        uint32_t data_offset;
        rndis_tcp_ip_csum_info *csum_info = NULL;
+       const struct rndis_hash_info *hash_info;
+       const struct rndis_hash_value *hash_value;
        device_t dev = device->net_dev->dev->device;
 
        rndis_pkt = &message->msg.packet;
@@ -476,7 +478,9 @@ hv_rf_receive_data(rndis_device *device,
        }
 
        csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
-       netvsc_recv(chan, pkt, csum_info);
+       hash_value = hv_get_ppi_data(rndis_pkt, nbl_hash_value);
+       hash_info = hv_get_ppi_data(rndis_pkt, nbl_hash_info);
+       netvsc_recv(chan, pkt, csum_info, hash_info, hash_value);
 }
 
 /*
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to