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>
34 #include <sys/socket.h>
36 #include <sys/mutex.h>
37 #include <net/if_arp.h>
38 #include <net/ethernet.h>
39 #include <sys/types.h>
40 #include <machine/atomic.h>
43 #include <vm/vm_param.h>
46 #include <dev/hyperv/include/hyperv.h>
47 #include <dev/hyperv/vmbus/hv_vmbus_priv.h>
48 #include "hv_net_vsc.h"
50 #include "hv_rndis_filter.h"
54 * Forward declarations
56 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
57 uint32_t message_type);
58 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
59 static void hv_rf_receive_indicate_status(rndis_device *device,
61 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
62 struct hv_vmbus_channel *chan,
64 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
65 void *result, uint32_t *result_size);
66 static inline int hv_rf_query_device_mac(rndis_device *device);
67 static inline int hv_rf_query_device_link_status(rndis_device *device);
68 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
69 static int hv_rf_init_device(rndis_device *device);
70 static int hv_rf_open_device(rndis_device *device);
71 static int hv_rf_close_device(rndis_device *device);
72 static void hv_rf_on_send_request_completion(struct hv_vmbus_channel *, void *context);
73 static void hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *, void *context);
75 hv_rf_send_offload_request(struct hv_device *device,
76 rndis_offload_params *offloads);
78 * Set the Per-Packet-Info with the specified type
81 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
84 rndis_packet *rndis_pkt;
85 rndis_per_packet_info *rppi;
87 rndis_pkt = &rndis_mesg->msg.packet;
88 rndis_pkt->data_offset += rppi_size;
90 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
91 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
93 rppi->size = rppi_size;
94 rppi->type = pkt_type;
95 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
97 rndis_pkt->per_pkt_info_length += rppi_size;
103 * Get the Per-Packet-Info with the specified type
104 * return NULL if not found.
107 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
109 rndis_per_packet_info *ppi;
112 if (rpkt->per_pkt_info_offset == 0)
115 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
116 rpkt->per_pkt_info_offset);
117 len = rpkt->per_pkt_info_length;
120 if (ppi->type == type)
121 return (void *)((unsigned long)ppi +
122 ppi->per_packet_info_offset);
125 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
133 * Allow module_param to work and override to switch to promiscuous mode.
135 static inline rndis_device *
136 hv_get_rndis_device(void)
138 rndis_device *device;
140 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
142 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
144 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
145 STAILQ_INIT(&device->myrequest_list);
147 device->state = RNDIS_DEV_UNINITIALIZED;
156 hv_put_rndis_device(rndis_device *device)
158 mtx_destroy(&device->req_lock);
159 free(device, M_NETVSC);
165 static inline rndis_request *
166 hv_rndis_request(rndis_device *device, uint32_t message_type,
167 uint32_t message_length)
169 rndis_request *request;
170 rndis_msg *rndis_mesg;
171 rndis_set_request *set;
173 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
175 sema_init(&request->wait_sema, 0, "rndis sema");
177 rndis_mesg = &request->request_msg;
178 rndis_mesg->ndis_msg_type = message_type;
179 rndis_mesg->msg_len = message_length;
182 * Set the request id. This field is always after the rndis header
183 * for request/response packet types so we just use the set_request
186 set = &rndis_mesg->msg.set_request;
187 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
188 /* Increment to get the new value (call above returns old value) */
189 set->request_id += 1;
191 /* Add to the request list */
192 mtx_lock(&device->req_lock);
193 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
194 mtx_unlock(&device->req_lock);
203 hv_put_rndis_request(rndis_device *device, rndis_request *request)
205 mtx_lock(&device->req_lock);
206 /* Fixme: Has O(n) performance */
208 * XXXKYS: Use Doubly linked lists.
210 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
212 mtx_unlock(&device->req_lock);
214 sema_destroy(&request->wait_sema);
215 free(request, M_NETVSC);
222 hv_rf_send_request(rndis_device *device, rndis_request *request,
223 uint32_t message_type)
226 netvsc_packet *packet;
227 netvsc_dev *net_dev = device->net_dev;
228 int send_buf_section_idx;
230 /* Set up the packet to send it */
231 packet = &request->pkt;
233 packet->is_data_pkt = FALSE;
234 packet->tot_data_buf_len = request->request_msg.msg_len;
235 packet->page_buf_count = 1;
237 packet->page_buffers[0].pfn =
238 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
239 packet->page_buffers[0].length = request->request_msg.msg_len;
240 packet->page_buffers[0].offset =
241 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
243 if (packet->page_buffers[0].offset +
244 packet->page_buffers[0].length > PAGE_SIZE) {
245 packet->page_buf_count = 2;
246 packet->page_buffers[0].length =
247 PAGE_SIZE - packet->page_buffers[0].offset;
248 packet->page_buffers[1].pfn =
249 hv_get_phys_addr((char*)&request->request_msg +
250 packet->page_buffers[0].length) >> PAGE_SHIFT;
251 packet->page_buffers[1].offset = 0;
252 packet->page_buffers[1].length =
253 request->request_msg.msg_len -
254 packet->page_buffers[0].length;
257 packet->compl.send.send_completion_context = request; /* packet */
258 if (message_type != REMOTE_NDIS_HALT_MSG) {
259 packet->compl.send.on_send_completion =
260 hv_rf_on_send_request_completion;
262 packet->compl.send.on_send_completion =
263 hv_rf_on_send_request_halt_completion;
265 packet->compl.send.send_completion_tid = (unsigned long)device;
266 if (packet->tot_data_buf_len < net_dev->send_section_size) {
267 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
268 if (send_buf_section_idx !=
269 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
270 char *dest = ((char *)net_dev->send_buf +
271 send_buf_section_idx * net_dev->send_section_size);
273 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
274 packet->send_buf_section_idx = send_buf_section_idx;
275 packet->send_buf_section_size = packet->tot_data_buf_len;
276 packet->page_buf_count = 0;
279 /* Failed to allocate chimney send buffer; move on */
281 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
282 packet->send_buf_section_size = 0;
285 ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
291 * RNDIS filter receive response
294 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
296 rndis_request *request = NULL;
297 rndis_request *next_request;
298 boolean_t found = FALSE;
300 mtx_lock(&device->req_lock);
301 request = STAILQ_FIRST(&device->myrequest_list);
302 while (request != NULL) {
304 * All request/response message contains request_id as the
307 if (request->request_msg.msg.init_request.request_id ==
308 response->msg.init_complete.request_id) {
312 next_request = STAILQ_NEXT(request, mylist_entry);
313 request = next_request;
315 mtx_unlock(&device->req_lock);
318 if (response->msg_len <= sizeof(rndis_msg)) {
319 memcpy(&request->response_msg, response,
322 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
323 /* Does not have a request id field */
324 request->response_msg.msg.reset_complete.status =
325 STATUS_BUFFER_OVERFLOW;
327 request->response_msg.msg.init_complete.status =
328 STATUS_BUFFER_OVERFLOW;
332 sema_post(&request->wait_sema);
337 hv_rf_send_offload_request(struct hv_device *device,
338 rndis_offload_params *offloads)
340 rndis_request *request;
341 rndis_set_request *set;
342 rndis_offload_params *offload_req;
343 rndis_set_complete *set_complete;
344 rndis_device *rndis_dev;
345 hn_softc_t *sc = device_get_softc(device->device);
346 device_t dev = device->device;
347 netvsc_dev *net_dev = sc->net_dev;
348 uint32_t vsp_version = net_dev->nvsp_version;
349 uint32_t extlen = sizeof(rndis_offload_params);
352 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
353 extlen = VERSION_4_OFFLOAD_SIZE;
354 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
355 * UDP checksum offload.
357 offloads->udp_ipv4_csum = 0;
358 offloads->udp_ipv6_csum = 0;
361 rndis_dev = net_dev->extension;
363 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
364 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
368 set = &request->request_msg.msg.set_request;
369 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
370 set->info_buffer_length = extlen;
371 set->info_buffer_offset = sizeof(rndis_set_request);
372 set->device_vc_handle = 0;
374 offload_req = (rndis_offload_params *)((unsigned long)set +
375 set->info_buffer_offset);
376 *offload_req = *offloads;
377 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
378 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
379 offload_req->header.size = extlen;
381 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
383 device_printf(dev, "hv send offload request failed, ret=%d!\n",
388 ret = sema_timedwait(&request->wait_sema, 5 * hz);
390 device_printf(dev, "hv send offload request timeout\n");
394 set_complete = &request->response_msg.msg.set_complete;
395 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
396 device_printf(dev, "hv send offload request succeeded\n");
399 if (set_complete->status == STATUS_NOT_SUPPORTED) {
400 device_printf(dev, "HV Not support offload\n");
403 ret = set_complete->status;
408 hv_put_rndis_request(rndis_dev, request);
414 * RNDIS filter receive indicate status
417 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
419 rndis_indicate_status *indicate = &response->msg.indicate_status;
421 switch(indicate->status) {
422 case RNDIS_STATUS_MEDIA_CONNECT:
423 netvsc_linkstatus_callback(device->net_dev->dev, 1);
425 case RNDIS_STATUS_MEDIA_DISCONNECT:
426 netvsc_linkstatus_callback(device->net_dev->dev, 0);
430 device_printf(device->net_dev->dev->device,
431 "unknown status %d received\n", indicate->status);
437 * RNDIS filter receive data
440 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
441 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
443 rndis_packet *rndis_pkt;
444 ndis_8021q_info *rppi_vlan_info;
445 uint32_t data_offset;
446 rndis_tcp_ip_csum_info *csum_info = NULL;
447 device_t dev = device->net_dev->dev->device;
449 rndis_pkt = &message->msg.packet;
452 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
453 * netvsc packet (ie tot_data_buf_len != message_length)
456 /* Remove rndis header, then pass data packet up the stack */
457 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
459 pkt->tot_data_buf_len -= data_offset;
460 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
461 pkt->status = nvsp_status_failure;
463 "total length %u is less than data length %u\n",
464 pkt->tot_data_buf_len, rndis_pkt->data_length);
468 pkt->tot_data_buf_len = rndis_pkt->data_length;
469 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
471 rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
472 if (rppi_vlan_info) {
473 pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
478 csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
479 netvsc_recv(chan, pkt, csum_info);
483 * RNDIS filter on receive
486 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
487 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
489 rndis_device *rndis_dev;
490 rndis_msg *rndis_hdr;
492 /* Make sure the rndis device state is initialized */
493 if (net_dev->extension == NULL) {
494 pkt->status = nvsp_status_failure;
498 rndis_dev = (rndis_device *)net_dev->extension;
499 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
500 pkt->status = nvsp_status_failure;
504 rndis_hdr = pkt->data;
506 switch (rndis_hdr->ndis_msg_type) {
509 case REMOTE_NDIS_PACKET_MSG:
510 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
512 /* completion messages */
513 case REMOTE_NDIS_INITIALIZE_CMPLT:
514 case REMOTE_NDIS_QUERY_CMPLT:
515 case REMOTE_NDIS_SET_CMPLT:
516 case REMOTE_NDIS_RESET_CMPLT:
517 case REMOTE_NDIS_KEEPALIVE_CMPLT:
518 hv_rf_receive_response(rndis_dev, rndis_hdr);
520 /* notification message */
521 case REMOTE_NDIS_INDICATE_STATUS_MSG:
522 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
525 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
526 rndis_hdr->ndis_msg_type);
534 * RNDIS filter query device
537 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
538 uint32_t *result_size)
540 rndis_request *request;
541 uint32_t in_result_size = *result_size;
542 rndis_query_request *query;
543 rndis_query_complete *query_complete;
547 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
548 RNDIS_MESSAGE_SIZE(rndis_query_request));
549 if (request == NULL) {
554 /* Set up the rndis query */
555 query = &request->request_msg.msg.query_request;
557 query->info_buffer_offset = sizeof(rndis_query_request);
558 query->info_buffer_length = 0;
559 query->device_vc_handle = 0;
561 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
562 struct rndis_recv_scale_cap *cap;
564 request->request_msg.msg_len +=
565 sizeof(struct rndis_recv_scale_cap);
566 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
567 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
568 query->info_buffer_offset);
569 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
570 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
571 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
574 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
576 /* Fixme: printf added */
577 printf("RNDISFILTER request failed to Send!\n");
581 sema_wait(&request->wait_sema);
583 /* Copy the response back */
584 query_complete = &request->response_msg.msg.query_complete;
586 if (query_complete->info_buffer_length > in_result_size) {
591 memcpy(result, (void *)((unsigned long)query_complete +
592 query_complete->info_buffer_offset),
593 query_complete->info_buffer_length);
595 *result_size = query_complete->info_buffer_length;
599 hv_put_rndis_request(device, request);
605 * RNDIS filter query device MAC address
608 hv_rf_query_device_mac(rndis_device *device)
610 uint32_t size = HW_MACADDR_LEN;
612 return (hv_rf_query_device(device,
613 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
617 * RNDIS filter query device link status
620 hv_rf_query_device_link_status(rndis_device *device)
622 uint32_t size = sizeof(uint32_t);
624 return (hv_rf_query_device(device,
625 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
628 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
629 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
630 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
631 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
632 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
633 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
637 * RNDIS set vRSS parameters
640 hv_rf_set_rss_param(rndis_device *device, int num_queue)
642 rndis_request *request;
643 rndis_set_request *set;
644 rndis_set_complete *set_complete;
645 rndis_recv_scale_param *rssp;
646 uint32_t extlen = sizeof(rndis_recv_scale_param) +
647 (4 * ITAB_NUM) + HASH_KEYLEN;
648 uint32_t *itab, status;
653 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
654 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
655 if (request == NULL) {
657 printf("Netvsc: No memory to set vRSS parameters.\n");
662 set = &request->request_msg.msg.set_request;
663 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
664 set->info_buffer_length = extlen;
665 set->info_buffer_offset = sizeof(rndis_set_request);
666 set->device_vc_handle = 0;
668 /* Fill out the rssp parameter structure */
669 rssp = (rndis_recv_scale_param *)(set + 1);
670 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
671 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
672 rssp->hdr.size = sizeof(rndis_recv_scale_param);
674 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
675 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
676 rssp->indirect_tabsize = 4 * ITAB_NUM;
677 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
678 rssp->hashkey_size = HASH_KEYLEN;
679 rssp->hashkey_offset = rssp->indirect_taboffset +
680 rssp->indirect_tabsize;
682 /* Set indirection table entries */
683 itab = (uint32_t *)(rssp + 1);
684 for (i = 0; i < ITAB_NUM; i++)
685 itab[i] = i % num_queue;
687 /* Set hash key values */
688 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
689 for (i = 0; i < HASH_KEYLEN; i++)
690 keyp[i] = netvsc_hash_key[i];
692 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
698 * Wait for the response from the host. Another thread will signal
699 * us when the response has arrived. In the failure case,
700 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
702 ret = sema_timedwait(&request->wait_sema, 5 * hz);
704 /* Response received, check status */
705 set_complete = &request->response_msg.msg.set_complete;
706 status = set_complete->status;
707 if (status != RNDIS_STATUS_SUCCESS) {
708 /* Bad response status, return error */
710 printf("Netvsc: Failed to set vRSS "
715 printf("Netvsc: Successfully set vRSS "
720 * We cannot deallocate the request since we may still
721 * receive a send completion for it.
723 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
724 request->request_msg.msg.init_request.request_id, ret);
729 if (request != NULL) {
730 hv_put_rndis_request(device, request);
737 * RNDIS filter set packet filter
738 * Sends an rndis request with the new filter, then waits for a response
740 * Returns zero on success, non-zero on failure.
743 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
745 rndis_request *request;
746 rndis_set_request *set;
747 rndis_set_complete *set_complete;
751 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
752 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
753 if (request == NULL) {
758 /* Set up the rndis set */
759 set = &request->request_msg.msg.set_request;
760 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
761 set->info_buffer_length = sizeof(uint32_t);
762 set->info_buffer_offset = sizeof(rndis_set_request);
764 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
765 &new_filter, sizeof(uint32_t));
767 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
773 * Wait for the response from the host. Another thread will signal
774 * us when the response has arrived. In the failure case,
775 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
777 ret = sema_timedwait(&request->wait_sema, 5 * hz);
779 /* Response received, check status */
780 set_complete = &request->response_msg.msg.set_complete;
781 status = set_complete->status;
782 if (status != RNDIS_STATUS_SUCCESS) {
783 /* Bad response status, return error */
788 * We cannot deallocate the request since we may still
789 * receive a send completion for it.
795 if (request != NULL) {
796 hv_put_rndis_request(device, request);
803 * RNDIS filter init device
806 hv_rf_init_device(rndis_device *device)
808 rndis_request *request;
809 rndis_initialize_request *init;
810 rndis_initialize_complete *init_complete;
814 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
815 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
821 /* Set up the rndis set */
822 init = &request->request_msg.msg.init_request;
823 init->major_version = RNDIS_MAJOR_VERSION;
824 init->minor_version = RNDIS_MINOR_VERSION;
826 * Per the RNDIS document, this should be set to the max MTU
827 * plus the header size. However, 2048 works fine, so leaving
830 init->max_xfer_size = 2048;
832 device->state = RNDIS_DEV_INITIALIZING;
834 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
836 device->state = RNDIS_DEV_UNINITIALIZED;
840 sema_wait(&request->wait_sema);
842 init_complete = &request->response_msg.msg.init_complete;
843 status = init_complete->status;
844 if (status == RNDIS_STATUS_SUCCESS) {
845 device->state = RNDIS_DEV_INITIALIZED;
848 device->state = RNDIS_DEV_UNINITIALIZED;
854 hv_put_rndis_request(device, request);
860 #define HALT_COMPLETION_WAIT_COUNT 25
863 * RNDIS filter halt device
866 hv_rf_halt_device(rndis_device *device)
868 rndis_request *request;
869 rndis_halt_request *halt;
872 /* Attempt to do a rndis device halt */
873 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
874 RNDIS_MESSAGE_SIZE(rndis_halt_request));
875 if (request == NULL) {
879 /* initialize "poor man's semaphore" */
880 request->halt_complete_flag = 0;
882 /* Set up the rndis set */
883 halt = &request->request_msg.msg.halt_request;
884 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
885 /* Increment to get the new value (call above returns old value) */
886 halt->request_id += 1;
888 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
894 * Wait for halt response from halt callback. We must wait for
895 * the transaction response before freeing the request and other
898 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
899 if (request->halt_complete_flag != 0) {
908 device->state = RNDIS_DEV_UNINITIALIZED;
910 hv_put_rndis_request(device, request);
916 * RNDIS filter open device
919 hv_rf_open_device(rndis_device *device)
923 if (device->state != RNDIS_DEV_INITIALIZED) {
927 if (hv_promisc_mode != 1) {
928 ret = hv_rf_set_packet_filter(device,
929 NDIS_PACKET_TYPE_BROADCAST |
930 NDIS_PACKET_TYPE_ALL_MULTICAST |
931 NDIS_PACKET_TYPE_DIRECTED);
933 ret = hv_rf_set_packet_filter(device,
934 NDIS_PACKET_TYPE_PROMISCUOUS);
938 device->state = RNDIS_DEV_DATAINITIALIZED;
945 * RNDIS filter close device
948 hv_rf_close_device(rndis_device *device)
952 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
956 ret = hv_rf_set_packet_filter(device, 0);
958 device->state = RNDIS_DEV_INITIALIZED;
965 * RNDIS filter on device add
968 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
973 rndis_device *rndis_dev;
975 rndis_offload_params offloads;
976 struct rndis_recv_scale_cap rsscaps;
977 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
978 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
979 device_t dev = device->device;
981 rndis_dev = hv_get_rndis_device();
982 if (rndis_dev == NULL) {
987 * Let the inner driver handle this first to create the netvsc channel
988 * NOTE! Once the channel is created, we may get a receive callback
989 * (hv_rf_on_receive()) before this call is completed.
990 * Note: Earlier code used a function pointer here.
992 net_dev = hv_nv_on_device_add(device, additl_info);
994 hv_put_rndis_device(rndis_dev);
1000 * Initialize the rndis device
1003 net_dev->extension = rndis_dev;
1004 rndis_dev->net_dev = net_dev;
1006 /* Send the rndis initialization message */
1007 ret = hv_rf_init_device(rndis_dev);
1010 * TODO: If rndis init failed, we will need to shut down
1015 /* Get the mac address */
1016 ret = hv_rf_query_device_mac(rndis_dev);
1018 /* TODO: shut down rndis device and the channel */
1021 /* config csum offload and send request to host */
1022 memset(&offloads, 0, sizeof(offloads));
1023 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1024 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1025 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1026 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1027 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1028 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1030 ret = hv_rf_send_offload_request(device, &offloads);
1032 /* TODO: shut down rndis device and the channel */
1034 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1037 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1039 hv_rf_query_device_link_status(rndis_dev);
1041 dev_info->link_state = rndis_dev->link_status;
1043 net_dev->num_channel = 1;
1044 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1047 memset(&rsscaps, 0, rsscaps_size);
1048 ret = hv_rf_query_device(rndis_dev,
1049 RNDIS_OID_GEN_RSS_CAPABILITIES,
1050 &rsscaps, &rsscaps_size);
1051 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1052 device_printf(dev, "hv_rf_query_device failed or "
1053 "rsscaps.num_recv_que < 2 \n");
1056 device_printf(dev, "channel, offered %u, requested %d\n",
1057 rsscaps.num_recv_que, nchan);
1058 if (nchan > rsscaps.num_recv_que)
1059 nchan = rsscaps.num_recv_que;
1060 net_dev->num_channel = nchan;
1062 if (net_dev->num_channel == 1) {
1063 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1067 /* request host to create sub channels */
1068 init_pkt = &net_dev->channel_init_packet;
1069 memset(init_pkt, 0, sizeof(nvsp_msg));
1071 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1072 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1073 NVSP_SUBCHANNE_ALLOCATE;
1074 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1075 net_dev->num_channel - 1;
1077 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1078 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1079 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1080 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1082 device_printf(dev, "Fail to allocate subchannel\n");
1086 sema_wait(&net_dev->channel_init_sema);
1088 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1089 nvsp_status_success) {
1091 device_printf(dev, "sub channel complete error\n");
1095 net_dev->num_channel = 1 +
1096 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1098 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1102 net_dev->num_channel = 1;
1108 * RNDIS filter on device remove
1111 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1113 hn_softc_t *sc = device_get_softc(device->device);
1114 netvsc_dev *net_dev = sc->net_dev;
1115 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1118 /* Halt and release the rndis device */
1119 ret = hv_rf_halt_device(rndis_dev);
1121 hv_put_rndis_device(rndis_dev);
1122 net_dev->extension = NULL;
1124 /* Pass control to inner driver to remove the device */
1125 ret |= hv_nv_on_device_remove(device, destroy_channel);
1131 * RNDIS filter on open
1134 hv_rf_on_open(struct hv_device *device)
1136 hn_softc_t *sc = device_get_softc(device->device);
1137 netvsc_dev *net_dev = sc->net_dev;
1139 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1143 * RNDIS filter on close
1146 hv_rf_on_close(struct hv_device *device)
1148 hn_softc_t *sc = device_get_softc(device->device);
1149 netvsc_dev *net_dev = sc->net_dev;
1151 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1155 * RNDIS filter on send request completion callback
1158 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1159 void *context __unused)
1164 * RNDIS filter on send request (halt only) completion callback
1167 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1170 rndis_request *request = context;
1173 * Notify hv_rf_halt_device() about halt completion.
1174 * The halt code must wait for completion before freeing
1175 * the transaction resources.
1177 request->halt_complete_flag = 1;
1181 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1184 netvsc_channel_rollup(chan);