2 * Copyright (c) 2009-2012,2016 Microsoft Corp.
3 * Copyright (c) 2010-2012 Citrix Inc.
4 * Copyright (c) 2012 NetApp Inc.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice unmodified, this list of conditions, and the following
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include <sys/param.h>
33 #include <sys/kernel.h>
35 #include <sys/socket.h>
37 #include <sys/mutex.h>
39 #include <net/if_arp.h>
40 #include <net/if_var.h>
41 #include <net/ethernet.h>
42 #include <sys/types.h>
43 #include <machine/atomic.h>
46 #include <vm/vm_param.h>
49 #include <dev/hyperv/include/hyperv.h>
50 #include <dev/hyperv/include/vmbus_xact.h>
51 #include <dev/hyperv/netvsc/hv_net_vsc.h>
52 #include <dev/hyperv/netvsc/hv_rndis.h>
53 #include <dev/hyperv/netvsc/hv_rndis_filter.h>
54 #include <dev/hyperv/netvsc/if_hnreg.h>
56 #define HV_RF_RECVINFO_VLAN 0x1
57 #define HV_RF_RECVINFO_CSUM 0x2
58 #define HV_RF_RECVINFO_HASHINF 0x4
59 #define HV_RF_RECVINFO_HASHVAL 0x8
60 #define HV_RF_RECVINFO_ALL \
61 (HV_RF_RECVINFO_VLAN | \
62 HV_RF_RECVINFO_CSUM | \
63 HV_RF_RECVINFO_HASHINF | \
64 HV_RF_RECVINFO_HASHVAL)
66 #define HN_RNDIS_RID_COMPAT_MASK 0xffff
67 #define HN_RNDIS_RID_COMPAT_MAX HN_RNDIS_RID_COMPAT_MASK
69 #define HN_RNDIS_XFER_SIZE 2048
72 * Forward declarations
74 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
75 uint32_t message_type);
76 static void hv_rf_receive_response(rndis_device *device,
77 const rndis_msg *response);
78 static void hv_rf_receive_indicate_status(rndis_device *device,
79 const rndis_msg *response);
80 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
81 const void *data, int dlen);
82 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
83 void *result, uint32_t *result_size);
84 static inline int hv_rf_query_device_mac(rndis_device *device);
85 static inline int hv_rf_query_device_link_status(rndis_device *device);
86 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
87 static int hv_rf_init_device(rndis_device *device);
88 static int hv_rf_open_device(rndis_device *device);
89 static int hv_rf_close_device(rndis_device *device);
91 hv_rf_send_offload_request(struct hn_softc *sc,
92 rndis_offload_params *offloads);
94 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
95 struct hn_softc *sc, struct vmbus_channel *chan,
96 const void *data, int dlen);
97 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
98 struct hn_softc *sc, struct vmbus_channel *chan,
99 const void *data, int dlen);
101 static __inline uint32_t
102 hn_rndis_rid(struct hn_softc *sc)
107 rid = atomic_fetchadd_int(&sc->hn_rndis_rid, 1);
111 /* Use upper 16 bits for non-compat RNDIS messages. */
112 return ((rid & 0xffff) << 16);
116 * Set the Per-Packet-Info with the specified type
119 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
122 rndis_packet *rndis_pkt;
123 rndis_per_packet_info *rppi;
125 rndis_pkt = &rndis_mesg->msg.packet;
126 rndis_pkt->data_offset += rppi_size;
128 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
129 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
131 rppi->size = rppi_size;
132 rppi->type = pkt_type;
133 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
135 rndis_pkt->per_pkt_info_length += rppi_size;
141 * Get the Per-Packet-Info with the specified type
142 * return NULL if not found.
145 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
147 rndis_per_packet_info *ppi;
150 if (rpkt->per_pkt_info_offset == 0)
153 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
154 rpkt->per_pkt_info_offset);
155 len = rpkt->per_pkt_info_length;
158 if (ppi->type == type)
159 return (void *)((unsigned long)ppi +
160 ppi->per_packet_info_offset);
163 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
171 * Allow module_param to work and override to switch to promiscuous mode.
173 static inline rndis_device *
174 hv_get_rndis_device(void)
176 rndis_device *device;
178 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
180 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
182 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
183 STAILQ_INIT(&device->myrequest_list);
185 device->state = RNDIS_DEV_UNINITIALIZED;
194 hv_put_rndis_device(rndis_device *device)
196 mtx_destroy(&device->req_lock);
197 free(device, M_NETVSC);
203 static inline rndis_request *
204 hv_rndis_request(rndis_device *device, uint32_t message_type,
205 uint32_t message_length)
207 rndis_request *request;
208 rndis_msg *rndis_mesg;
209 rndis_set_request *set;
211 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
213 sema_init(&request->wait_sema, 0, "rndis sema");
215 rndis_mesg = &request->request_msg;
216 rndis_mesg->ndis_msg_type = message_type;
217 rndis_mesg->msg_len = message_length;
220 * Set the request id. This field is always after the rndis header
221 * for request/response packet types so we just use the set_request
224 set = &rndis_mesg->msg.set_request;
225 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1) &
226 HN_RNDIS_RID_COMPAT_MASK;
228 /* Add to the request list */
229 mtx_lock(&device->req_lock);
230 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
231 mtx_unlock(&device->req_lock);
240 hv_put_rndis_request(rndis_device *device, rndis_request *request)
242 mtx_lock(&device->req_lock);
243 /* Fixme: Has O(n) performance */
245 * XXXKYS: Use Doubly linked lists.
247 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
249 mtx_unlock(&device->req_lock);
251 sema_destroy(&request->wait_sema);
252 free(request, M_NETVSC);
259 hv_rf_send_request(rndis_device *device, rndis_request *request,
260 uint32_t message_type)
262 struct hn_softc *sc = device->sc;
263 uint32_t send_buf_section_idx, tot_data_buf_len;
264 struct vmbus_gpa gpa[2];
265 int gpa_cnt, send_buf_section_size;
266 hn_sent_callback_t cb;
268 /* Set up the packet to send it */
269 tot_data_buf_len = request->request_msg.msg_len;
272 gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
273 gpa[0].gpa_len = request->request_msg.msg_len;
274 gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
276 if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
278 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
280 hv_get_phys_addr((char*)&request->request_msg +
281 gpa[0].gpa_len) >> PAGE_SHIFT;
283 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
286 if (message_type != REMOTE_NDIS_HALT_MSG)
287 cb = hn_rndis_sent_cb;
289 cb = hn_rndis_sent_halt;
291 if (tot_data_buf_len < sc->hn_chim_szmax) {
292 send_buf_section_idx = hn_chim_alloc(sc);
293 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
294 uint8_t *dest = sc->hn_chim +
295 (send_buf_section_idx * sc->hn_chim_szmax);
297 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
298 send_buf_section_size = tot_data_buf_len;
302 /* Failed to allocate chimney send buffer; move on */
304 send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
305 send_buf_section_size = 0;
308 hn_send_ctx_init(&request->send_ctx, cb, request,
309 send_buf_section_idx, send_buf_section_size);
310 return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
311 &request->send_ctx, gpa, gpa_cnt);
315 * RNDIS filter receive response
318 hv_rf_receive_response(rndis_device *device, const rndis_msg *response)
320 rndis_request *request = NULL;
321 rndis_request *next_request;
322 boolean_t found = FALSE;
324 mtx_lock(&device->req_lock);
325 request = STAILQ_FIRST(&device->myrequest_list);
326 while (request != NULL) {
328 * All request/response message contains request_id as the
331 if (request->request_msg.msg.init_request.request_id ==
332 response->msg.init_complete.request_id) {
336 next_request = STAILQ_NEXT(request, mylist_entry);
337 request = next_request;
339 mtx_unlock(&device->req_lock);
342 if (response->msg_len <= sizeof(rndis_msg)) {
343 memcpy(&request->response_msg, response,
346 request->response_msg.msg.init_complete.status =
347 RNDIS_STATUS_BUFFER_OVERFLOW;
349 sema_post(&request->wait_sema);
354 hv_rf_send_offload_request(struct hn_softc *sc,
355 rndis_offload_params *offloads)
357 rndis_request *request;
358 rndis_set_request *set;
359 rndis_offload_params *offload_req;
360 rndis_set_complete *set_complete;
361 rndis_device *rndis_dev = sc->rndis_dev;
362 device_t dev = sc->hn_dev;
363 uint32_t extlen = sizeof(rndis_offload_params);
366 if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) {
367 extlen = VERSION_4_OFFLOAD_SIZE;
368 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
369 * UDP checksum offload.
371 offloads->udp_ipv4_csum = 0;
372 offloads->udp_ipv6_csum = 0;
375 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
376 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
380 set = &request->request_msg.msg.set_request;
381 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
382 set->info_buffer_length = extlen;
383 set->info_buffer_offset = sizeof(rndis_set_request);
384 set->device_vc_handle = 0;
386 offload_req = (rndis_offload_params *)((unsigned long)set +
387 set->info_buffer_offset);
388 *offload_req = *offloads;
389 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
390 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
391 offload_req->header.size = extlen;
393 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
395 device_printf(dev, "hv send offload request failed, ret=%d!\n",
400 ret = sema_timedwait(&request->wait_sema, 5 * hz);
402 device_printf(dev, "hv send offload request timeout\n");
406 set_complete = &request->response_msg.msg.set_complete;
407 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
408 device_printf(dev, "hv send offload request succeeded\n");
411 if (set_complete->status == RNDIS_STATUS_NOT_SUPPORTED) {
412 device_printf(dev, "HV Not support offload\n");
415 ret = set_complete->status;
420 hv_put_rndis_request(rndis_dev, request);
426 * RNDIS filter receive indicate status
429 hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response)
431 const rndis_indicate_status *indicate = &response->msg.indicate_status;
433 switch(indicate->status) {
434 case RNDIS_STATUS_MEDIA_CONNECT:
435 netvsc_linkstatus_callback(device->sc, 1);
437 case RNDIS_STATUS_MEDIA_DISCONNECT:
438 netvsc_linkstatus_callback(device->sc, 0);
442 device_printf(device->sc->hn_dev,
443 "unknown status %d received\n", indicate->status);
449 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
451 const rndis_per_packet_info *ppi;
454 info->vlan_info = NULL;
455 info->csum_info = NULL;
456 info->hash_info = NULL;
457 info->hash_value = NULL;
459 if (rpkt->per_pkt_info_offset == 0)
462 ppi = (const rndis_per_packet_info *)
463 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
464 len = rpkt->per_pkt_info_length;
468 const void *ppi_dptr;
471 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
473 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
474 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
477 case ieee_8021q_info:
478 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
480 info->vlan_info = ppi_dptr;
481 mask |= HV_RF_RECVINFO_VLAN;
484 case tcpip_chksum_info:
485 if (__predict_false(ppi_dlen <
486 sizeof(rndis_tcp_ip_csum_info)))
488 info->csum_info = ppi_dptr;
489 mask |= HV_RF_RECVINFO_CSUM;
493 if (__predict_false(ppi_dlen <
494 sizeof(struct rndis_hash_value)))
496 info->hash_value = ppi_dptr;
497 mask |= HV_RF_RECVINFO_HASHVAL;
501 if (__predict_false(ppi_dlen <
502 sizeof(struct rndis_hash_info)))
504 info->hash_info = ppi_dptr;
505 mask |= HV_RF_RECVINFO_HASHINF;
512 if (mask == HV_RF_RECVINFO_ALL) {
513 /* All found; done */
517 if (__predict_false(len < ppi->size))
520 ppi = (const rndis_per_packet_info *)
521 ((const uint8_t *)ppi + ppi->size);
527 * RNDIS filter receive data
530 hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
532 const rndis_msg *message = data;
533 const rndis_packet *rndis_pkt;
534 uint32_t data_offset;
535 struct hn_recvinfo info;
537 rndis_pkt = &message->msg.packet;
540 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
541 * netvsc packet (ie tot_data_buf_len != message_length)
544 /* Remove rndis header, then pass data packet up the stack */
545 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
548 if (dlen < rndis_pkt->data_length) {
549 if_printf(rxr->hn_ifp,
550 "total length %u is less than data length %u\n",
551 dlen, rndis_pkt->data_length);
555 dlen = rndis_pkt->data_length;
556 data = (const uint8_t *)data + data_offset;
558 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
559 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
562 netvsc_recv(rxr, data, dlen, &info);
566 * RNDIS filter on receive
569 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
570 const void *data, int dlen)
572 rndis_device *rndis_dev;
573 const rndis_msg *rndis_hdr;
574 const struct rndis_comp_hdr *comp;
576 rndis_dev = sc->rndis_dev;
577 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
581 switch (rndis_hdr->ndis_msg_type) {
583 case REMOTE_NDIS_PACKET_MSG:
584 hv_rf_receive_data(rxr, data, dlen);
587 /* completion messages */
588 case REMOTE_NDIS_INITIALIZE_CMPLT:
589 case REMOTE_NDIS_QUERY_CMPLT:
590 case REMOTE_NDIS_SET_CMPLT:
591 case REMOTE_NDIS_KEEPALIVE_CMPLT:
593 if (comp->rm_rid <= HN_RNDIS_RID_COMPAT_MAX) {
594 /* Transition time compat code */
595 hv_rf_receive_response(rndis_dev, rndis_hdr);
597 vmbus_xact_ctx_wakeup(sc->hn_xact, data, dlen);
601 /* notification message */
602 case REMOTE_NDIS_INDICATE_STATUS_MSG:
603 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
606 case REMOTE_NDIS_RESET_CMPLT:
608 * Reset completed, no rid.
611 * RESET is not issued by hn(4), so this message should
614 if_printf(sc->hn_ifp, "RESET CMPLT received\n");
618 if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
619 rndis_hdr->ndis_msg_type);
626 * RNDIS filter query device
629 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
630 uint32_t *result_size)
632 rndis_request *request;
633 uint32_t in_result_size = *result_size;
634 rndis_query_request *query;
635 rndis_query_complete *query_complete;
639 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
640 RNDIS_MESSAGE_SIZE(rndis_query_request));
641 if (request == NULL) {
646 /* Set up the rndis query */
647 query = &request->request_msg.msg.query_request;
649 query->info_buffer_offset = sizeof(rndis_query_request);
650 query->info_buffer_length = 0;
651 query->device_vc_handle = 0;
653 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
654 struct rndis_recv_scale_cap *cap;
656 request->request_msg.msg_len +=
657 sizeof(struct rndis_recv_scale_cap);
658 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
659 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
660 query->info_buffer_offset);
661 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
662 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
663 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
666 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
668 /* Fixme: printf added */
669 printf("RNDISFILTER request failed to Send!\n");
673 sema_wait(&request->wait_sema);
675 /* Copy the response back */
676 query_complete = &request->response_msg.msg.query_complete;
678 if (query_complete->info_buffer_length > in_result_size) {
683 memcpy(result, (void *)((unsigned long)query_complete +
684 query_complete->info_buffer_offset),
685 query_complete->info_buffer_length);
687 *result_size = query_complete->info_buffer_length;
691 hv_put_rndis_request(device, request);
697 * RNDIS filter query device MAC address
700 hv_rf_query_device_mac(rndis_device *device)
702 uint32_t size = ETHER_ADDR_LEN;
704 return (hv_rf_query_device(device,
705 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
709 * RNDIS filter query device link status
712 hv_rf_query_device_link_status(rndis_device *device)
714 uint32_t size = sizeof(uint32_t);
716 return (hv_rf_query_device(device,
717 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
720 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
721 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
722 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
723 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
724 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
725 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
729 * RNDIS set vRSS parameters
732 hv_rf_set_rss_param(rndis_device *device, int num_queue)
734 rndis_request *request;
735 rndis_set_request *set;
736 rndis_set_complete *set_complete;
737 rndis_recv_scale_param *rssp;
738 uint32_t extlen = sizeof(rndis_recv_scale_param) +
739 (4 * ITAB_NUM) + HASH_KEYLEN;
740 uint32_t *itab, status;
745 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
746 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
747 if (request == NULL) {
749 printf("Netvsc: No memory to set vRSS parameters.\n");
754 set = &request->request_msg.msg.set_request;
755 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
756 set->info_buffer_length = extlen;
757 set->info_buffer_offset = sizeof(rndis_set_request);
758 set->device_vc_handle = 0;
760 /* Fill out the rssp parameter structure */
761 rssp = (rndis_recv_scale_param *)(set + 1);
762 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
763 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
764 rssp->hdr.size = sizeof(rndis_recv_scale_param);
766 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
767 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
768 rssp->indirect_tabsize = 4 * ITAB_NUM;
769 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
770 rssp->hashkey_size = HASH_KEYLEN;
771 rssp->hashkey_offset = rssp->indirect_taboffset +
772 rssp->indirect_tabsize;
774 /* Set indirection table entries */
775 itab = (uint32_t *)(rssp + 1);
776 for (i = 0; i < ITAB_NUM; i++)
777 itab[i] = i % num_queue;
779 /* Set hash key values */
780 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
781 for (i = 0; i < HASH_KEYLEN; i++)
782 keyp[i] = netvsc_hash_key[i];
784 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
790 * Wait for the response from the host. Another thread will signal
791 * us when the response has arrived. In the failure case,
792 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
794 ret = sema_timedwait(&request->wait_sema, 5 * hz);
796 /* Response received, check status */
797 set_complete = &request->response_msg.msg.set_complete;
798 status = set_complete->status;
799 if (status != RNDIS_STATUS_SUCCESS) {
800 /* Bad response status, return error */
802 printf("Netvsc: Failed to set vRSS "
807 printf("Netvsc: Successfully set vRSS "
812 * We cannot deallocate the request since we may still
813 * receive a send completion for it.
815 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
816 request->request_msg.msg.init_request.request_id, ret);
821 if (request != NULL) {
822 hv_put_rndis_request(device, request);
829 * RNDIS filter set packet filter
830 * Sends an rndis request with the new filter, then waits for a response
832 * Returns zero on success, non-zero on failure.
835 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
837 rndis_request *request;
838 rndis_set_request *set;
839 rndis_set_complete *set_complete;
843 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
844 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
845 if (request == NULL) {
850 /* Set up the rndis set */
851 set = &request->request_msg.msg.set_request;
852 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
853 set->info_buffer_length = sizeof(uint32_t);
854 set->info_buffer_offset = sizeof(rndis_set_request);
856 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
857 &new_filter, sizeof(uint32_t));
859 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
865 * Wait for the response from the host. Another thread will signal
866 * us when the response has arrived. In the failure case,
867 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
869 ret = sema_timedwait(&request->wait_sema, 5 * hz);
871 /* Response received, check status */
872 set_complete = &request->response_msg.msg.set_complete;
873 status = set_complete->status;
874 if (status != RNDIS_STATUS_SUCCESS) {
875 /* Bad response status, return error */
880 * We cannot deallocate the request since we may still
881 * receive a send completion for it.
887 if (request != NULL) {
888 hv_put_rndis_request(device, request);
895 hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
896 size_t reqlen, size_t min_complen, uint32_t comp_type)
898 struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
899 const struct rndis_comp_hdr *comp;
904 KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
905 KASSERT(reqlen <= HN_XACT_REQ_SIZE && reqlen > 0,
906 ("invalid request length %zu", reqlen));
907 KASSERT(min_complen >= sizeof(*comp),
908 ("invalid minimum complete len %zu", min_complen));
913 paddr = vmbus_xact_req_paddr(xact);
914 KASSERT((paddr & PAGE_MASK) == 0,
915 ("vmbus xact request is not page aligned 0x%jx", (uintmax_t)paddr));
916 for (gpa_cnt = 0; gpa_cnt < HN_XACT_REQ_PGCNT; ++gpa_cnt) {
924 gpa[gpa_cnt].gpa_page = atop(paddr) + gpa_cnt;
925 gpa[gpa_cnt].gpa_len = len;
926 gpa[gpa_cnt].gpa_ofs = 0;
930 KASSERT(reqlen == 0, ("still have %zu request data left", reqlen));
933 * Send this RNDIS control message and wait for its completion
936 vmbus_xact_activate(xact);
937 error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
938 &hn_send_ctx_none, gpa, gpa_cnt);
940 vmbus_xact_deactivate(xact);
941 if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
944 comp = vmbus_xact_wait(xact, &comp_len);
947 * Check this RNDIS complete message.
949 if (comp_len < min_complen) {
950 if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n", comp_len);
953 if (comp->rm_len < min_complen) {
954 if_printf(sc->hn_ifp, "invalid RNDIS comp msglen %u\n",
958 if (comp->rm_type != comp_type) {
959 if_printf(sc->hn_ifp, "unexpected RNDIS comp 0x%08x, "
960 "expect 0x%08x\n", comp->rm_type, comp_type);
963 if (comp->rm_rid != rid) {
964 if_printf(sc->hn_ifp, "RNDIS comp rid mismatch %u, "
965 "expect %u\n", comp->rm_rid, rid);
973 * RNDIS filter init device
976 hv_rf_init_device(rndis_device *device)
978 struct hn_softc *sc = device->sc;
979 struct rndis_init_req *req;
980 const struct rndis_init_comp *comp;
981 struct vmbus_xact *xact;
986 device->state = RNDIS_DEV_INITIALIZED;
988 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
990 if_printf(sc->hn_ifp, "no xact for RNDIS init\n");
993 rid = hn_rndis_rid(sc);
994 req = vmbus_xact_req_data(xact);
995 req->rm_type = REMOTE_NDIS_INITIALIZE_MSG;
996 req->rm_len = sizeof(*req);
998 req->rm_ver_major = RNDIS_VERSION_MAJOR;
999 req->rm_ver_minor = RNDIS_VERSION_MINOR;
1000 req->rm_max_xfersz = HN_RNDIS_XFER_SIZE;
1002 comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req),
1003 RNDIS_INIT_COMP_SIZE_MIN, REMOTE_NDIS_INITIALIZE_CMPLT);
1005 if_printf(sc->hn_ifp, "exec RNDIS init failed\n");
1010 if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
1011 if_printf(sc->hn_ifp, "RNDIS init failed: status 0x%08x\n",
1017 if_printf(sc->hn_ifp, "RNDIS ver %u.%u, pktsz %u, pktcnt %u\n",
1018 comp->rm_ver_major, comp->rm_ver_minor,
1019 comp->rm_pktmaxsz, comp->rm_pktmaxcnt);
1025 vmbus_xact_put(xact);
1029 #define HALT_COMPLETION_WAIT_COUNT 25
1032 * RNDIS filter halt device
1035 hv_rf_halt_device(rndis_device *device)
1037 rndis_request *request;
1040 /* Attempt to do a rndis device halt */
1041 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
1042 RNDIS_MESSAGE_SIZE(rndis_halt_request));
1043 if (request == NULL) {
1047 /* initialize "poor man's semaphore" */
1048 request->halt_complete_flag = 0;
1050 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
1056 * Wait for halt response from halt callback. We must wait for
1057 * the transaction response before freeing the request and other
1060 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
1061 if (request->halt_complete_flag != 0) {
1070 device->state = RNDIS_DEV_UNINITIALIZED;
1072 hv_put_rndis_request(device, request);
1078 * RNDIS filter open device
1081 hv_rf_open_device(rndis_device *device)
1085 if (device->state != RNDIS_DEV_INITIALIZED) {
1089 if (hv_promisc_mode != 1) {
1090 ret = hv_rf_set_packet_filter(device,
1091 NDIS_PACKET_TYPE_BROADCAST |
1092 NDIS_PACKET_TYPE_ALL_MULTICAST |
1093 NDIS_PACKET_TYPE_DIRECTED);
1095 ret = hv_rf_set_packet_filter(device,
1096 NDIS_PACKET_TYPE_PROMISCUOUS);
1100 device->state = RNDIS_DEV_DATAINITIALIZED;
1107 * RNDIS filter close device
1110 hv_rf_close_device(rndis_device *device)
1114 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1118 ret = hv_rf_set_packet_filter(device, 0);
1120 device->state = RNDIS_DEV_INITIALIZED;
1127 * RNDIS filter on device add
1130 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1131 int *nchan0, struct hn_rx_ring *rxr)
1134 rndis_device *rndis_dev;
1135 rndis_offload_params offloads;
1136 struct rndis_recv_scale_cap rsscaps;
1137 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1138 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1139 device_t dev = sc->hn_dev;
1140 struct hn_nvs_subch_req *req;
1141 const struct hn_nvs_subch_resp *resp;
1143 struct vmbus_xact *xact = NULL;
1144 uint32_t status, nsubch;
1145 int nchan = *nchan0;
1147 rndis_dev = hv_get_rndis_device();
1148 if (rndis_dev == NULL) {
1151 sc->rndis_dev = rndis_dev;
1155 * Let the inner driver handle this first to create the netvsc channel
1156 * NOTE! Once the channel is created, we may get a receive callback
1157 * (hv_rf_on_receive()) before this call is completed.
1158 * Note: Earlier code used a function pointer here.
1160 ret = hv_nv_on_device_add(sc, rxr);
1162 hv_put_rndis_device(rndis_dev);
1167 * Initialize the rndis device
1170 /* Send the rndis initialization message */
1171 ret = hv_rf_init_device(rndis_dev);
1174 * TODO: If rndis init failed, we will need to shut down
1179 /* Get the mac address */
1180 ret = hv_rf_query_device_mac(rndis_dev);
1182 /* TODO: shut down rndis device and the channel */
1185 /* config csum offload and send request to host */
1186 memset(&offloads, 0, sizeof(offloads));
1187 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1188 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1189 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1190 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1191 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1192 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1194 ret = hv_rf_send_offload_request(sc, &offloads);
1196 /* TODO: shut down rndis device and the channel */
1198 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1201 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1203 hv_rf_query_device_link_status(rndis_dev);
1205 dev_info->link_state = rndis_dev->link_status;
1207 if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1210 memset(&rsscaps, 0, rsscaps_size);
1211 ret = hv_rf_query_device(rndis_dev,
1212 RNDIS_OID_GEN_RSS_CAPABILITIES,
1213 &rsscaps, &rsscaps_size);
1214 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1215 device_printf(dev, "hv_rf_query_device failed or "
1216 "rsscaps.num_recv_que < 2 \n");
1219 device_printf(dev, "channel, offered %u, requested %d\n",
1220 rsscaps.num_recv_que, nchan);
1221 if (nchan > rsscaps.num_recv_que)
1222 nchan = rsscaps.num_recv_que;
1225 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1230 * Ask NVS to allocate sub-channels.
1232 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1234 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1238 req = vmbus_xact_req_data(xact);
1239 req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1240 req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1241 req->nvs_nsubch = nchan - 1;
1243 resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1245 if_printf(sc->hn_ifp, "exec subch failed\n");
1249 if (resp_len < sizeof(*resp)) {
1250 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1255 if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1256 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1262 status = resp->nvs_status;
1263 nsubch = resp->nvs_nsubch;
1264 vmbus_xact_put(xact);
1267 if (status != HN_NVS_STATUS_OK) {
1268 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1272 if (nsubch > nchan - 1) {
1273 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1279 ret = hv_rf_set_rss_param(rndis_dev, nchan);
1283 vmbus_xact_put(xact);
1288 * RNDIS filter on device remove
1291 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1293 rndis_device *rndis_dev = sc->rndis_dev;
1296 /* Halt and release the rndis device */
1297 ret = hv_rf_halt_device(rndis_dev);
1299 sc->rndis_dev = NULL;
1300 hv_put_rndis_device(rndis_dev);
1302 /* Pass control to inner driver to remove the device */
1303 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1309 * RNDIS filter on open
1312 hv_rf_on_open(struct hn_softc *sc)
1315 return (hv_rf_open_device(sc->rndis_dev));
1319 * RNDIS filter on close
1322 hv_rf_on_close(struct hn_softc *sc)
1325 return (hv_rf_close_device(sc->rndis_dev));
1329 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1330 struct vmbus_channel *chan __unused, const void *data __unused,
1333 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1334 hn_chim_free(sc, sndc->hn_chim_idx);
1338 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1339 struct vmbus_channel *chan __unused, const void *data __unused,
1342 rndis_request *request = sndc->hn_cbarg;
1344 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1345 hn_chim_free(sc, sndc->hn_chim_idx);
1348 * Notify hv_rf_halt_device() about halt completion.
1349 * The halt code must wait for completion before freeing
1350 * the transaction resources.
1352 request->halt_complete_flag = 1;
1356 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1359 netvsc_channel_rollup(rxr, txr);