svn commit: r299888 - head/sys/dev/hyperv/netvsc
Sepherosa Ziehau
sephe at FreeBSD.org
Mon May 16 03:26:18 UTC 2016
Author: sephe
Date: Mon May 16 03:26:16 2016
New Revision: 299888
URL: https://svnweb.freebsd.org/changeset/base/299888
Log:
hyperv/hn: Combine per-packet-information parsing.
MFC after: 1 week
Sponsored by: Microsoft OSTC
Modified:
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_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon May 16 02:44:22 2016 (r299887)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c Mon May 16 03:26:16 2016 (r299888)
@@ -1291,7 +1291,7 @@ 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,
+ const rndis_tcp_ip_csum_info *csum_info,
const struct rndis_hash_info *hash_info,
const struct rndis_hash_value *hash_value)
{
Modified: head/sys/dev/hyperv/netvsc/hv_rndis.h
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis.h Mon May 16 02:44:22 2016 (r299887)
+++ head/sys/dev/hyperv/netvsc/hv_rndis.h Mon May 16 03:26:16 2016 (r299888)
@@ -1085,7 +1085,7 @@ 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, const 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);
Modified: head/sys/dev/hyperv/netvsc/hv_rndis_filter.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Mon May 16 02:44:22 2016 (r299887)
+++ head/sys/dev/hyperv/netvsc/hv_rndis_filter.c Mon May 16 03:26:16 2016 (r299888)
@@ -49,6 +49,22 @@ __FBSDID("$FreeBSD$");
#include "hv_rndis.h"
#include "hv_rndis_filter.h"
+struct hv_rf_recvinfo {
+ const ndis_8021q_info *vlan_info;
+ const rndis_tcp_ip_csum_info *csum_info;
+ const struct rndis_hash_info *hash_info;
+ const struct rndis_hash_value *hash_value;
+};
+
+#define HV_RF_RECVINFO_VLAN 0x1
+#define HV_RF_RECVINFO_CSUM 0x2
+#define HV_RF_RECVINFO_HASHINF 0x4
+#define HV_RF_RECVINFO_HASHVAL 0x8
+#define HV_RF_RECVINFO_ALL \
+ (HV_RF_RECVINFO_VLAN | \
+ HV_RF_RECVINFO_CSUM | \
+ HV_RF_RECVINFO_HASHINF | \
+ HV_RF_RECVINFO_HASHVAL)
/*
* Forward declarations
@@ -433,6 +449,84 @@ hv_rf_receive_indicate_status(rndis_devi
}
}
+static int
+hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
+{
+ const rndis_per_packet_info *ppi;
+ uint32_t mask, len;
+
+ info->vlan_info = NULL;
+ info->csum_info = NULL;
+ info->hash_info = NULL;
+ info->hash_value = NULL;
+
+ if (rpkt->per_pkt_info_offset == 0)
+ return 0;
+
+ ppi = (const rndis_per_packet_info *)
+ ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
+ len = rpkt->per_pkt_info_length;
+ mask = 0;
+
+ while (len != 0) {
+ const void *ppi_dptr;
+ uint32_t ppi_dlen;
+
+ if (__predict_false(ppi->size < ppi->per_packet_info_offset))
+ return EINVAL;
+ ppi_dlen = ppi->size - ppi->per_packet_info_offset;
+ ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
+
+ switch (ppi->type) {
+ case ieee_8021q_info:
+ if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
+ return EINVAL;
+ info->vlan_info = ppi_dptr;
+ mask |= HV_RF_RECVINFO_VLAN;
+ break;
+
+ case tcpip_chksum_info:
+ if (__predict_false(ppi_dlen <
+ sizeof(rndis_tcp_ip_csum_info)))
+ return EINVAL;
+ info->csum_info = ppi_dptr;
+ mask |= HV_RF_RECVINFO_CSUM;
+ break;
+
+ case nbl_hash_value:
+ if (__predict_false(ppi_dlen <
+ sizeof(struct rndis_hash_value)))
+ return EINVAL;
+ info->hash_value = ppi_dptr;
+ mask |= HV_RF_RECVINFO_HASHVAL;
+ break;
+
+ case nbl_hash_info:
+ if (__predict_false(ppi_dlen <
+ sizeof(struct rndis_hash_info)))
+ return EINVAL;
+ info->hash_info = ppi_dptr;
+ mask |= HV_RF_RECVINFO_HASHINF;
+ break;
+
+ default:
+ goto skip;
+ }
+
+ if (mask == HV_RF_RECVINFO_ALL) {
+ /* All found; done */
+ break;
+ }
+skip:
+ if (__predict_false(len < ppi->size))
+ return EINVAL;
+ len -= ppi->size;
+ ppi = (const rndis_per_packet_info *)
+ ((const uint8_t *)ppi + ppi->size);
+ }
+ return 0;
+}
+
/*
* RNDIS filter receive data
*/
@@ -441,12 +535,9 @@ hv_rf_receive_data(rndis_device *device,
struct hv_vmbus_channel *chan, netvsc_packet *pkt)
{
rndis_packet *rndis_pkt;
- 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;
+ struct hv_rf_recvinfo info;
rndis_pkt = &message->msg.packet;
@@ -470,17 +561,18 @@ hv_rf_receive_data(rndis_device *device,
pkt->tot_data_buf_len = rndis_pkt->data_length;
pkt->data = (void *)((unsigned long)pkt->data + data_offset);
- rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
- if (rppi_vlan_info) {
- pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
- } else {
- pkt->vlan_tci = 0;
+ if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
+ pkt->status = nvsp_status_failure;
+ device_printf(dev, "recvinfo parsing failed\n");
+ return;
}
- csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_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);
+ if (info.vlan_info != NULL)
+ pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
+ else
+ pkt->vlan_tci = 0;
+
+ netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value);
}
/*
More information about the svn-src-head
mailing list