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)
67 * Forward declarations
69 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
70 uint32_t message_type);
71 static void hv_rf_receive_response(rndis_device *device,
72 const rndis_msg *response);
73 static void hv_rf_receive_indicate_status(rndis_device *device,
74 const rndis_msg *response);
75 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
76 const void *data, int dlen);
77 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
78 void *result, uint32_t *result_size);
79 static inline int hv_rf_query_device_mac(rndis_device *device);
80 static inline int hv_rf_query_device_link_status(rndis_device *device);
81 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
82 static int hv_rf_init_device(rndis_device *device);
83 static int hv_rf_open_device(rndis_device *device);
84 static int hv_rf_close_device(rndis_device *device);
86 hv_rf_send_offload_request(struct hn_softc *sc,
87 rndis_offload_params *offloads);
89 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
90 struct hn_softc *sc, struct vmbus_channel *chan,
91 const void *data, int dlen);
92 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
93 struct hn_softc *sc, struct vmbus_channel *chan,
94 const void *data, int dlen);
97 * Set the Per-Packet-Info with the specified type
100 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
103 rndis_packet *rndis_pkt;
104 rndis_per_packet_info *rppi;
106 rndis_pkt = &rndis_mesg->msg.packet;
107 rndis_pkt->data_offset += rppi_size;
109 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
110 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
112 rppi->size = rppi_size;
113 rppi->type = pkt_type;
114 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
116 rndis_pkt->per_pkt_info_length += rppi_size;
122 * Get the Per-Packet-Info with the specified type
123 * return NULL if not found.
126 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
128 rndis_per_packet_info *ppi;
131 if (rpkt->per_pkt_info_offset == 0)
134 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
135 rpkt->per_pkt_info_offset);
136 len = rpkt->per_pkt_info_length;
139 if (ppi->type == type)
140 return (void *)((unsigned long)ppi +
141 ppi->per_packet_info_offset);
144 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
152 * Allow module_param to work and override to switch to promiscuous mode.
154 static inline rndis_device *
155 hv_get_rndis_device(void)
157 rndis_device *device;
159 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
161 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
163 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
164 STAILQ_INIT(&device->myrequest_list);
166 device->state = RNDIS_DEV_UNINITIALIZED;
175 hv_put_rndis_device(rndis_device *device)
177 mtx_destroy(&device->req_lock);
178 free(device, M_NETVSC);
184 static inline rndis_request *
185 hv_rndis_request(rndis_device *device, uint32_t message_type,
186 uint32_t message_length)
188 rndis_request *request;
189 rndis_msg *rndis_mesg;
190 rndis_set_request *set;
192 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
194 sema_init(&request->wait_sema, 0, "rndis sema");
196 rndis_mesg = &request->request_msg;
197 rndis_mesg->ndis_msg_type = message_type;
198 rndis_mesg->msg_len = message_length;
201 * Set the request id. This field is always after the rndis header
202 * for request/response packet types so we just use the set_request
205 set = &rndis_mesg->msg.set_request;
206 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
207 /* Increment to get the new value (call above returns old value) */
208 set->request_id += 1;
210 /* Add to the request list */
211 mtx_lock(&device->req_lock);
212 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
213 mtx_unlock(&device->req_lock);
222 hv_put_rndis_request(rndis_device *device, rndis_request *request)
224 mtx_lock(&device->req_lock);
225 /* Fixme: Has O(n) performance */
227 * XXXKYS: Use Doubly linked lists.
229 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
231 mtx_unlock(&device->req_lock);
233 sema_destroy(&request->wait_sema);
234 free(request, M_NETVSC);
241 hv_rf_send_request(rndis_device *device, rndis_request *request,
242 uint32_t message_type)
244 struct hn_softc *sc = device->sc;
245 uint32_t send_buf_section_idx, tot_data_buf_len;
246 struct vmbus_gpa gpa[2];
247 int gpa_cnt, send_buf_section_size;
248 hn_sent_callback_t cb;
250 /* Set up the packet to send it */
251 tot_data_buf_len = request->request_msg.msg_len;
254 gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
255 gpa[0].gpa_len = request->request_msg.msg_len;
256 gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
258 if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
260 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
262 hv_get_phys_addr((char*)&request->request_msg +
263 gpa[0].gpa_len) >> PAGE_SHIFT;
265 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
268 if (message_type != REMOTE_NDIS_HALT_MSG)
269 cb = hn_rndis_sent_cb;
271 cb = hn_rndis_sent_halt;
273 if (tot_data_buf_len < sc->hn_chim_szmax) {
274 send_buf_section_idx = hn_chim_alloc(sc);
275 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
276 uint8_t *dest = sc->hn_chim +
277 (send_buf_section_idx * sc->hn_chim_szmax);
279 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
280 send_buf_section_size = tot_data_buf_len;
284 /* Failed to allocate chimney send buffer; move on */
286 send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
287 send_buf_section_size = 0;
290 hn_send_ctx_init(&request->send_ctx, cb, request,
291 send_buf_section_idx, send_buf_section_size);
292 return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
293 &request->send_ctx, gpa, gpa_cnt);
297 * RNDIS filter receive response
300 hv_rf_receive_response(rndis_device *device, const rndis_msg *response)
302 rndis_request *request = NULL;
303 rndis_request *next_request;
304 boolean_t found = FALSE;
306 mtx_lock(&device->req_lock);
307 request = STAILQ_FIRST(&device->myrequest_list);
308 while (request != NULL) {
310 * All request/response message contains request_id as the
313 if (request->request_msg.msg.init_request.request_id ==
314 response->msg.init_complete.request_id) {
318 next_request = STAILQ_NEXT(request, mylist_entry);
319 request = next_request;
321 mtx_unlock(&device->req_lock);
324 if (response->msg_len <= sizeof(rndis_msg)) {
325 memcpy(&request->response_msg, response,
328 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
329 /* Does not have a request id field */
330 request->response_msg.msg.reset_complete.status =
331 STATUS_BUFFER_OVERFLOW;
333 request->response_msg.msg.init_complete.status =
334 STATUS_BUFFER_OVERFLOW;
338 sema_post(&request->wait_sema);
343 hv_rf_send_offload_request(struct hn_softc *sc,
344 rndis_offload_params *offloads)
346 rndis_request *request;
347 rndis_set_request *set;
348 rndis_offload_params *offload_req;
349 rndis_set_complete *set_complete;
350 rndis_device *rndis_dev = sc->rndis_dev;
351 device_t dev = sc->hn_dev;
352 uint32_t extlen = sizeof(rndis_offload_params);
355 if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) {
356 extlen = VERSION_4_OFFLOAD_SIZE;
357 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
358 * UDP checksum offload.
360 offloads->udp_ipv4_csum = 0;
361 offloads->udp_ipv6_csum = 0;
364 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
365 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
369 set = &request->request_msg.msg.set_request;
370 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
371 set->info_buffer_length = extlen;
372 set->info_buffer_offset = sizeof(rndis_set_request);
373 set->device_vc_handle = 0;
375 offload_req = (rndis_offload_params *)((unsigned long)set +
376 set->info_buffer_offset);
377 *offload_req = *offloads;
378 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
379 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
380 offload_req->header.size = extlen;
382 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
384 device_printf(dev, "hv send offload request failed, ret=%d!\n",
389 ret = sema_timedwait(&request->wait_sema, 5 * hz);
391 device_printf(dev, "hv send offload request timeout\n");
395 set_complete = &request->response_msg.msg.set_complete;
396 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
397 device_printf(dev, "hv send offload request succeeded\n");
400 if (set_complete->status == STATUS_NOT_SUPPORTED) {
401 device_printf(dev, "HV Not support offload\n");
404 ret = set_complete->status;
409 hv_put_rndis_request(rndis_dev, request);
415 * RNDIS filter receive indicate status
418 hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response)
420 const rndis_indicate_status *indicate = &response->msg.indicate_status;
422 switch(indicate->status) {
423 case RNDIS_STATUS_MEDIA_CONNECT:
424 netvsc_linkstatus_callback(device->sc, 1);
426 case RNDIS_STATUS_MEDIA_DISCONNECT:
427 netvsc_linkstatus_callback(device->sc, 0);
431 device_printf(device->sc->hn_dev,
432 "unknown status %d received\n", indicate->status);
438 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
440 const rndis_per_packet_info *ppi;
443 info->vlan_info = NULL;
444 info->csum_info = NULL;
445 info->hash_info = NULL;
446 info->hash_value = NULL;
448 if (rpkt->per_pkt_info_offset == 0)
451 ppi = (const rndis_per_packet_info *)
452 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
453 len = rpkt->per_pkt_info_length;
457 const void *ppi_dptr;
460 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
462 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
463 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
466 case ieee_8021q_info:
467 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
469 info->vlan_info = ppi_dptr;
470 mask |= HV_RF_RECVINFO_VLAN;
473 case tcpip_chksum_info:
474 if (__predict_false(ppi_dlen <
475 sizeof(rndis_tcp_ip_csum_info)))
477 info->csum_info = ppi_dptr;
478 mask |= HV_RF_RECVINFO_CSUM;
482 if (__predict_false(ppi_dlen <
483 sizeof(struct rndis_hash_value)))
485 info->hash_value = ppi_dptr;
486 mask |= HV_RF_RECVINFO_HASHVAL;
490 if (__predict_false(ppi_dlen <
491 sizeof(struct rndis_hash_info)))
493 info->hash_info = ppi_dptr;
494 mask |= HV_RF_RECVINFO_HASHINF;
501 if (mask == HV_RF_RECVINFO_ALL) {
502 /* All found; done */
506 if (__predict_false(len < ppi->size))
509 ppi = (const rndis_per_packet_info *)
510 ((const uint8_t *)ppi + ppi->size);
516 * RNDIS filter receive data
519 hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
521 const rndis_msg *message = data;
522 const rndis_packet *rndis_pkt;
523 uint32_t data_offset;
524 struct hn_recvinfo info;
526 rndis_pkt = &message->msg.packet;
529 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
530 * netvsc packet (ie tot_data_buf_len != message_length)
533 /* Remove rndis header, then pass data packet up the stack */
534 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
537 if (dlen < rndis_pkt->data_length) {
538 if_printf(rxr->hn_ifp,
539 "total length %u is less than data length %u\n",
540 dlen, rndis_pkt->data_length);
544 dlen = rndis_pkt->data_length;
545 data = (const uint8_t *)data + data_offset;
547 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
548 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
551 netvsc_recv(rxr, data, dlen, &info);
555 * RNDIS filter on receive
558 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
559 const void *data, int dlen)
561 rndis_device *rndis_dev;
562 const rndis_msg *rndis_hdr;
564 rndis_dev = sc->rndis_dev;
565 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
569 switch (rndis_hdr->ndis_msg_type) {
572 case REMOTE_NDIS_PACKET_MSG:
573 hv_rf_receive_data(rxr, data, dlen);
575 /* completion messages */
576 case REMOTE_NDIS_INITIALIZE_CMPLT:
577 case REMOTE_NDIS_QUERY_CMPLT:
578 case REMOTE_NDIS_SET_CMPLT:
579 case REMOTE_NDIS_RESET_CMPLT:
580 case REMOTE_NDIS_KEEPALIVE_CMPLT:
581 hv_rf_receive_response(rndis_dev, rndis_hdr);
583 /* notification message */
584 case REMOTE_NDIS_INDICATE_STATUS_MSG:
585 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
588 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
589 rndis_hdr->ndis_msg_type);
597 * RNDIS filter query device
600 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
601 uint32_t *result_size)
603 rndis_request *request;
604 uint32_t in_result_size = *result_size;
605 rndis_query_request *query;
606 rndis_query_complete *query_complete;
610 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
611 RNDIS_MESSAGE_SIZE(rndis_query_request));
612 if (request == NULL) {
617 /* Set up the rndis query */
618 query = &request->request_msg.msg.query_request;
620 query->info_buffer_offset = sizeof(rndis_query_request);
621 query->info_buffer_length = 0;
622 query->device_vc_handle = 0;
624 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
625 struct rndis_recv_scale_cap *cap;
627 request->request_msg.msg_len +=
628 sizeof(struct rndis_recv_scale_cap);
629 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
630 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
631 query->info_buffer_offset);
632 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
633 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
634 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
637 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
639 /* Fixme: printf added */
640 printf("RNDISFILTER request failed to Send!\n");
644 sema_wait(&request->wait_sema);
646 /* Copy the response back */
647 query_complete = &request->response_msg.msg.query_complete;
649 if (query_complete->info_buffer_length > in_result_size) {
654 memcpy(result, (void *)((unsigned long)query_complete +
655 query_complete->info_buffer_offset),
656 query_complete->info_buffer_length);
658 *result_size = query_complete->info_buffer_length;
662 hv_put_rndis_request(device, request);
668 * RNDIS filter query device MAC address
671 hv_rf_query_device_mac(rndis_device *device)
673 uint32_t size = ETHER_ADDR_LEN;
675 return (hv_rf_query_device(device,
676 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
680 * RNDIS filter query device link status
683 hv_rf_query_device_link_status(rndis_device *device)
685 uint32_t size = sizeof(uint32_t);
687 return (hv_rf_query_device(device,
688 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
691 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
692 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
693 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
694 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
695 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
696 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
700 * RNDIS set vRSS parameters
703 hv_rf_set_rss_param(rndis_device *device, int num_queue)
705 rndis_request *request;
706 rndis_set_request *set;
707 rndis_set_complete *set_complete;
708 rndis_recv_scale_param *rssp;
709 uint32_t extlen = sizeof(rndis_recv_scale_param) +
710 (4 * ITAB_NUM) + HASH_KEYLEN;
711 uint32_t *itab, status;
716 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
717 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
718 if (request == NULL) {
720 printf("Netvsc: No memory to set vRSS parameters.\n");
725 set = &request->request_msg.msg.set_request;
726 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
727 set->info_buffer_length = extlen;
728 set->info_buffer_offset = sizeof(rndis_set_request);
729 set->device_vc_handle = 0;
731 /* Fill out the rssp parameter structure */
732 rssp = (rndis_recv_scale_param *)(set + 1);
733 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
734 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
735 rssp->hdr.size = sizeof(rndis_recv_scale_param);
737 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
738 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
739 rssp->indirect_tabsize = 4 * ITAB_NUM;
740 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
741 rssp->hashkey_size = HASH_KEYLEN;
742 rssp->hashkey_offset = rssp->indirect_taboffset +
743 rssp->indirect_tabsize;
745 /* Set indirection table entries */
746 itab = (uint32_t *)(rssp + 1);
747 for (i = 0; i < ITAB_NUM; i++)
748 itab[i] = i % num_queue;
750 /* Set hash key values */
751 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
752 for (i = 0; i < HASH_KEYLEN; i++)
753 keyp[i] = netvsc_hash_key[i];
755 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
761 * Wait for the response from the host. Another thread will signal
762 * us when the response has arrived. In the failure case,
763 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
765 ret = sema_timedwait(&request->wait_sema, 5 * hz);
767 /* Response received, check status */
768 set_complete = &request->response_msg.msg.set_complete;
769 status = set_complete->status;
770 if (status != RNDIS_STATUS_SUCCESS) {
771 /* Bad response status, return error */
773 printf("Netvsc: Failed to set vRSS "
778 printf("Netvsc: Successfully set vRSS "
783 * We cannot deallocate the request since we may still
784 * receive a send completion for it.
786 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
787 request->request_msg.msg.init_request.request_id, ret);
792 if (request != NULL) {
793 hv_put_rndis_request(device, request);
800 * RNDIS filter set packet filter
801 * Sends an rndis request with the new filter, then waits for a response
803 * Returns zero on success, non-zero on failure.
806 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
808 rndis_request *request;
809 rndis_set_request *set;
810 rndis_set_complete *set_complete;
814 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
815 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
816 if (request == NULL) {
821 /* Set up the rndis set */
822 set = &request->request_msg.msg.set_request;
823 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
824 set->info_buffer_length = sizeof(uint32_t);
825 set->info_buffer_offset = sizeof(rndis_set_request);
827 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
828 &new_filter, sizeof(uint32_t));
830 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
836 * Wait for the response from the host. Another thread will signal
837 * us when the response has arrived. In the failure case,
838 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
840 ret = sema_timedwait(&request->wait_sema, 5 * hz);
842 /* Response received, check status */
843 set_complete = &request->response_msg.msg.set_complete;
844 status = set_complete->status;
845 if (status != RNDIS_STATUS_SUCCESS) {
846 /* Bad response status, return error */
851 * We cannot deallocate the request since we may still
852 * receive a send completion for it.
858 if (request != NULL) {
859 hv_put_rndis_request(device, request);
866 * RNDIS filter init device
869 hv_rf_init_device(rndis_device *device)
871 rndis_request *request;
872 rndis_initialize_request *init;
873 rndis_initialize_complete *init_complete;
877 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
878 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
884 /* Set up the rndis set */
885 init = &request->request_msg.msg.init_request;
886 init->major_version = RNDIS_MAJOR_VERSION;
887 init->minor_version = RNDIS_MINOR_VERSION;
889 * Per the RNDIS document, this should be set to the max MTU
890 * plus the header size. However, 2048 works fine, so leaving
893 init->max_xfer_size = 2048;
895 device->state = RNDIS_DEV_INITIALIZING;
897 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
899 device->state = RNDIS_DEV_UNINITIALIZED;
903 sema_wait(&request->wait_sema);
905 init_complete = &request->response_msg.msg.init_complete;
906 status = init_complete->status;
907 if (status == RNDIS_STATUS_SUCCESS) {
908 device->state = RNDIS_DEV_INITIALIZED;
911 device->state = RNDIS_DEV_UNINITIALIZED;
917 hv_put_rndis_request(device, request);
923 #define HALT_COMPLETION_WAIT_COUNT 25
926 * RNDIS filter halt device
929 hv_rf_halt_device(rndis_device *device)
931 rndis_request *request;
932 rndis_halt_request *halt;
935 /* Attempt to do a rndis device halt */
936 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
937 RNDIS_MESSAGE_SIZE(rndis_halt_request));
938 if (request == NULL) {
942 /* initialize "poor man's semaphore" */
943 request->halt_complete_flag = 0;
945 /* Set up the rndis set */
946 halt = &request->request_msg.msg.halt_request;
947 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
948 /* Increment to get the new value (call above returns old value) */
949 halt->request_id += 1;
951 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
957 * Wait for halt response from halt callback. We must wait for
958 * the transaction response before freeing the request and other
961 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
962 if (request->halt_complete_flag != 0) {
971 device->state = RNDIS_DEV_UNINITIALIZED;
973 hv_put_rndis_request(device, request);
979 * RNDIS filter open device
982 hv_rf_open_device(rndis_device *device)
986 if (device->state != RNDIS_DEV_INITIALIZED) {
990 if (hv_promisc_mode != 1) {
991 ret = hv_rf_set_packet_filter(device,
992 NDIS_PACKET_TYPE_BROADCAST |
993 NDIS_PACKET_TYPE_ALL_MULTICAST |
994 NDIS_PACKET_TYPE_DIRECTED);
996 ret = hv_rf_set_packet_filter(device,
997 NDIS_PACKET_TYPE_PROMISCUOUS);
1001 device->state = RNDIS_DEV_DATAINITIALIZED;
1008 * RNDIS filter close device
1011 hv_rf_close_device(rndis_device *device)
1015 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1019 ret = hv_rf_set_packet_filter(device, 0);
1021 device->state = RNDIS_DEV_INITIALIZED;
1028 * RNDIS filter on device add
1031 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1032 int *nchan0, struct hn_rx_ring *rxr)
1035 rndis_device *rndis_dev;
1036 rndis_offload_params offloads;
1037 struct rndis_recv_scale_cap rsscaps;
1038 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1039 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1040 device_t dev = sc->hn_dev;
1041 struct hn_nvs_subch_req *req;
1042 const struct hn_nvs_subch_resp *resp;
1044 struct vmbus_xact *xact = NULL;
1045 uint32_t status, nsubch;
1046 int nchan = *nchan0;
1048 rndis_dev = hv_get_rndis_device();
1049 if (rndis_dev == NULL) {
1052 sc->rndis_dev = rndis_dev;
1056 * Let the inner driver handle this first to create the netvsc channel
1057 * NOTE! Once the channel is created, we may get a receive callback
1058 * (hv_rf_on_receive()) before this call is completed.
1059 * Note: Earlier code used a function pointer here.
1061 ret = hv_nv_on_device_add(sc, rxr);
1063 hv_put_rndis_device(rndis_dev);
1068 * Initialize the rndis device
1071 /* Send the rndis initialization message */
1072 ret = hv_rf_init_device(rndis_dev);
1075 * TODO: If rndis init failed, we will need to shut down
1080 /* Get the mac address */
1081 ret = hv_rf_query_device_mac(rndis_dev);
1083 /* TODO: shut down rndis device and the channel */
1086 /* config csum offload and send request to host */
1087 memset(&offloads, 0, sizeof(offloads));
1088 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1089 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1090 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1091 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1092 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1093 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1095 ret = hv_rf_send_offload_request(sc, &offloads);
1097 /* TODO: shut down rndis device and the channel */
1099 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1102 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1104 hv_rf_query_device_link_status(rndis_dev);
1106 dev_info->link_state = rndis_dev->link_status;
1108 if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1111 memset(&rsscaps, 0, rsscaps_size);
1112 ret = hv_rf_query_device(rndis_dev,
1113 RNDIS_OID_GEN_RSS_CAPABILITIES,
1114 &rsscaps, &rsscaps_size);
1115 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1116 device_printf(dev, "hv_rf_query_device failed or "
1117 "rsscaps.num_recv_que < 2 \n");
1120 device_printf(dev, "channel, offered %u, requested %d\n",
1121 rsscaps.num_recv_que, nchan);
1122 if (nchan > rsscaps.num_recv_que)
1123 nchan = rsscaps.num_recv_que;
1126 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1131 * Ask NVS to allocate sub-channels.
1133 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1135 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1139 req = vmbus_xact_req_data(xact);
1140 req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1141 req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1142 req->nvs_nsubch = nchan - 1;
1144 resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1146 if_printf(sc->hn_ifp, "exec subch failed\n");
1150 if (resp_len < sizeof(*resp)) {
1151 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1156 if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1157 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1163 status = resp->nvs_status;
1164 nsubch = resp->nvs_nsubch;
1165 vmbus_xact_put(xact);
1168 if (status != HN_NVS_STATUS_OK) {
1169 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1173 if (nsubch > nchan - 1) {
1174 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1180 ret = hv_rf_set_rss_param(rndis_dev, nchan);
1184 vmbus_xact_put(xact);
1189 * RNDIS filter on device remove
1192 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1194 rndis_device *rndis_dev = sc->rndis_dev;
1197 /* Halt and release the rndis device */
1198 ret = hv_rf_halt_device(rndis_dev);
1200 sc->rndis_dev = NULL;
1201 hv_put_rndis_device(rndis_dev);
1203 /* Pass control to inner driver to remove the device */
1204 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1210 * RNDIS filter on open
1213 hv_rf_on_open(struct hn_softc *sc)
1216 return (hv_rf_open_device(sc->rndis_dev));
1220 * RNDIS filter on close
1223 hv_rf_on_close(struct hn_softc *sc)
1226 return (hv_rf_close_device(sc->rndis_dev));
1230 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1231 struct vmbus_channel *chan __unused, const void *data __unused,
1234 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1235 hn_chim_free(sc, sndc->hn_chim_idx);
1239 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1240 struct vmbus_channel *chan __unused, const void *data __unused,
1243 rndis_request *request = sndc->hn_cbarg;
1245 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1246 hn_chim_free(sc, sndc->hn_chim_idx);
1249 * Notify hv_rf_halt_device() about halt completion.
1250 * The halt code must wait for completion before freeing
1251 * the transaction resources.
1253 request->halt_complete_flag = 1;
1257 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1260 netvsc_channel_rollup(rxr, txr);