From owner-svn-src-all@freebsd.org Mon May 16 03:26:17 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E8BAEB3CE43; Mon, 16 May 2016 03:26:17 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 95F8F1AB4; Mon, 16 May 2016 03:26:17 +0000 (UTC) (envelope-from sephe@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4G3QGED004774; Mon, 16 May 2016 03:26:16 GMT (envelope-from sephe@FreeBSD.org) Received: (from sephe@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4G3QGIi004771; Mon, 16 May 2016 03:26:16 GMT (envelope-from sephe@FreeBSD.org) Message-Id: <201605160326.u4G3QGIi004771@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: sephe set sender to sephe@FreeBSD.org using -f From: Sepherosa Ziehau Date: Mon, 16 May 2016 03:26:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r299888 - head/sys/dev/hyperv/netvsc X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 May 2016 03:26:18 -0000 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); } /*