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>
38 #include <net/if_arp.h>
39 #include <net/ethernet.h>
40 #include <sys/types.h>
41 #include <machine/atomic.h>
44 #include <vm/vm_param.h>
47 #include <dev/hyperv/include/hyperv.h>
48 #include <dev/hyperv/vmbus/hv_vmbus_priv.h>
49 #include "hv_net_vsc.h"
51 #include "hv_rndis_filter.h"
55 * Forward declarations
57 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
58 uint32_t message_type);
59 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
60 static void hv_rf_receive_indicate_status(rndis_device *device,
62 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
63 struct hv_vmbus_channel *chan,
65 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
66 void *result, uint32_t *result_size);
67 static inline int hv_rf_query_device_mac(rndis_device *device);
68 static inline int hv_rf_query_device_link_status(rndis_device *device);
69 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
70 static int hv_rf_init_device(rndis_device *device);
71 static int hv_rf_open_device(rndis_device *device);
72 static int hv_rf_close_device(rndis_device *device);
73 static void hv_rf_on_send_request_completion(struct hv_vmbus_channel *, void *context);
74 static void hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *, void *context);
76 hv_rf_send_offload_request(struct hv_device *device,
77 rndis_offload_params *offloads);
79 * Set the Per-Packet-Info with the specified type
82 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
85 rndis_packet *rndis_pkt;
86 rndis_per_packet_info *rppi;
88 rndis_pkt = &rndis_mesg->msg.packet;
89 rndis_pkt->data_offset += rppi_size;
91 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
92 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
94 rppi->size = rppi_size;
95 rppi->type = pkt_type;
96 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
98 rndis_pkt->per_pkt_info_length += rppi_size;
104 * Get the Per-Packet-Info with the specified type
105 * return NULL if not found.
108 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
110 rndis_per_packet_info *ppi;
113 if (rpkt->per_pkt_info_offset == 0)
116 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
117 rpkt->per_pkt_info_offset);
118 len = rpkt->per_pkt_info_length;
121 if (ppi->type == type)
122 return (void *)((unsigned long)ppi +
123 ppi->per_packet_info_offset);
126 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
134 * Allow module_param to work and override to switch to promiscuous mode.
136 static inline rndis_device *
137 hv_get_rndis_device(void)
139 rndis_device *device;
141 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
143 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
145 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
146 STAILQ_INIT(&device->myrequest_list);
148 device->state = RNDIS_DEV_UNINITIALIZED;
157 hv_put_rndis_device(rndis_device *device)
159 mtx_destroy(&device->req_lock);
160 free(device, M_NETVSC);
166 static inline rndis_request *
167 hv_rndis_request(rndis_device *device, uint32_t message_type,
168 uint32_t message_length)
170 rndis_request *request;
171 rndis_msg *rndis_mesg;
172 rndis_set_request *set;
174 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
176 sema_init(&request->wait_sema, 0, "rndis sema");
178 rndis_mesg = &request->request_msg;
179 rndis_mesg->ndis_msg_type = message_type;
180 rndis_mesg->msg_len = message_length;
183 * Set the request id. This field is always after the rndis header
184 * for request/response packet types so we just use the set_request
187 set = &rndis_mesg->msg.set_request;
188 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
189 /* Increment to get the new value (call above returns old value) */
190 set->request_id += 1;
192 /* Add to the request list */
193 mtx_lock(&device->req_lock);
194 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
195 mtx_unlock(&device->req_lock);
204 hv_put_rndis_request(rndis_device *device, rndis_request *request)
206 mtx_lock(&device->req_lock);
207 /* Fixme: Has O(n) performance */
209 * XXXKYS: Use Doubly linked lists.
211 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
213 mtx_unlock(&device->req_lock);
215 sema_destroy(&request->wait_sema);
216 free(request, M_NETVSC);
223 hv_rf_send_request(rndis_device *device, rndis_request *request,
224 uint32_t message_type)
227 netvsc_packet *packet;
228 netvsc_dev *net_dev = device->net_dev;
229 int send_buf_section_idx;
231 /* Set up the packet to send it */
232 packet = &request->pkt;
234 packet->is_data_pkt = FALSE;
235 packet->tot_data_buf_len = request->request_msg.msg_len;
236 packet->page_buf_count = 1;
238 packet->page_buffers[0].pfn =
239 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
240 packet->page_buffers[0].length = request->request_msg.msg_len;
241 packet->page_buffers[0].offset =
242 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
244 if (packet->page_buffers[0].offset +
245 packet->page_buffers[0].length > PAGE_SIZE) {
246 packet->page_buf_count = 2;
247 packet->page_buffers[0].length =
248 PAGE_SIZE - packet->page_buffers[0].offset;
249 packet->page_buffers[1].pfn =
250 hv_get_phys_addr((char*)&request->request_msg +
251 packet->page_buffers[0].length) >> PAGE_SHIFT;
252 packet->page_buffers[1].offset = 0;
253 packet->page_buffers[1].length =
254 request->request_msg.msg_len -
255 packet->page_buffers[0].length;
258 packet->compl.send.send_completion_context = request; /* packet */
259 if (message_type != REMOTE_NDIS_HALT_MSG) {
260 packet->compl.send.on_send_completion =
261 hv_rf_on_send_request_completion;
263 packet->compl.send.on_send_completion =
264 hv_rf_on_send_request_halt_completion;
266 packet->compl.send.send_completion_tid = (unsigned long)device;
267 if (packet->tot_data_buf_len < net_dev->send_section_size) {
268 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
269 if (send_buf_section_idx !=
270 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
271 char *dest = ((char *)net_dev->send_buf +
272 send_buf_section_idx * net_dev->send_section_size);
274 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
275 packet->send_buf_section_idx = send_buf_section_idx;
276 packet->send_buf_section_size = packet->tot_data_buf_len;
277 packet->page_buf_count = 0;
280 /* Failed to allocate chimney send buffer; move on */
282 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
283 packet->send_buf_section_size = 0;
286 ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
292 * RNDIS filter receive response
295 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
297 rndis_request *request = NULL;
298 rndis_request *next_request;
299 boolean_t found = FALSE;
301 mtx_lock(&device->req_lock);
302 request = STAILQ_FIRST(&device->myrequest_list);
303 while (request != NULL) {
305 * All request/response message contains request_id as the
308 if (request->request_msg.msg.init_request.request_id ==
309 response->msg.init_complete.request_id) {
313 next_request = STAILQ_NEXT(request, mylist_entry);
314 request = next_request;
316 mtx_unlock(&device->req_lock);
319 if (response->msg_len <= sizeof(rndis_msg)) {
320 memcpy(&request->response_msg, response,
323 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
324 /* Does not have a request id field */
325 request->response_msg.msg.reset_complete.status =
326 STATUS_BUFFER_OVERFLOW;
328 request->response_msg.msg.init_complete.status =
329 STATUS_BUFFER_OVERFLOW;
333 sema_post(&request->wait_sema);
338 hv_rf_send_offload_request(struct hv_device *device,
339 rndis_offload_params *offloads)
341 rndis_request *request;
342 rndis_set_request *set;
343 rndis_offload_params *offload_req;
344 rndis_set_complete *set_complete;
345 rndis_device *rndis_dev;
346 hn_softc_t *sc = device_get_softc(device->device);
347 device_t dev = device->device;
348 netvsc_dev *net_dev = sc->net_dev;
349 uint32_t vsp_version = net_dev->nvsp_version;
350 uint32_t extlen = sizeof(rndis_offload_params);
353 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
354 extlen = VERSION_4_OFFLOAD_SIZE;
355 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
356 * UDP checksum offload.
358 offloads->udp_ipv4_csum = 0;
359 offloads->udp_ipv6_csum = 0;
362 rndis_dev = net_dev->extension;
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, rndis_msg *response)
420 rndis_indicate_status *indicate = &response->msg.indicate_status;
422 switch(indicate->status) {
423 case RNDIS_STATUS_MEDIA_CONNECT:
424 netvsc_linkstatus_callback(device->net_dev->dev, 1);
426 case RNDIS_STATUS_MEDIA_DISCONNECT:
427 netvsc_linkstatus_callback(device->net_dev->dev, 0);
431 device_printf(device->net_dev->dev->device,
432 "unknown status %d received\n", indicate->status);
438 * RNDIS filter receive data
441 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
442 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
444 rndis_packet *rndis_pkt;
445 ndis_8021q_info *rppi_vlan_info;
446 uint32_t data_offset;
447 rndis_tcp_ip_csum_info *csum_info = NULL;
448 device_t dev = device->net_dev->dev->device;
450 rndis_pkt = &message->msg.packet;
453 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
454 * netvsc packet (ie tot_data_buf_len != message_length)
457 /* Remove rndis header, then pass data packet up the stack */
458 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
460 pkt->tot_data_buf_len -= data_offset;
461 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
462 pkt->status = nvsp_status_failure;
464 "total length %u is less than data length %u\n",
465 pkt->tot_data_buf_len, rndis_pkt->data_length);
469 pkt->tot_data_buf_len = rndis_pkt->data_length;
470 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
472 rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
473 if (rppi_vlan_info) {
474 pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
479 csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
480 netvsc_recv(chan, pkt, csum_info);
484 * RNDIS filter on receive
487 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
488 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
490 rndis_device *rndis_dev;
491 rndis_msg *rndis_hdr;
493 /* Make sure the rndis device state is initialized */
494 if (net_dev->extension == NULL) {
495 pkt->status = nvsp_status_failure;
499 rndis_dev = (rndis_device *)net_dev->extension;
500 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
501 pkt->status = nvsp_status_failure;
505 rndis_hdr = pkt->data;
507 switch (rndis_hdr->ndis_msg_type) {
510 case REMOTE_NDIS_PACKET_MSG:
511 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
513 /* completion messages */
514 case REMOTE_NDIS_INITIALIZE_CMPLT:
515 case REMOTE_NDIS_QUERY_CMPLT:
516 case REMOTE_NDIS_SET_CMPLT:
517 case REMOTE_NDIS_RESET_CMPLT:
518 case REMOTE_NDIS_KEEPALIVE_CMPLT:
519 hv_rf_receive_response(rndis_dev, rndis_hdr);
521 /* notification message */
522 case REMOTE_NDIS_INDICATE_STATUS_MSG:
523 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
526 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
527 rndis_hdr->ndis_msg_type);
535 * RNDIS filter query device
538 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
539 uint32_t *result_size)
541 rndis_request *request;
542 uint32_t in_result_size = *result_size;
543 rndis_query_request *query;
544 rndis_query_complete *query_complete;
548 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
549 RNDIS_MESSAGE_SIZE(rndis_query_request));
550 if (request == NULL) {
555 /* Set up the rndis query */
556 query = &request->request_msg.msg.query_request;
558 query->info_buffer_offset = sizeof(rndis_query_request);
559 query->info_buffer_length = 0;
560 query->device_vc_handle = 0;
562 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
563 struct rndis_recv_scale_cap *cap;
565 request->request_msg.msg_len +=
566 sizeof(struct rndis_recv_scale_cap);
567 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
568 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
569 query->info_buffer_offset);
570 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
571 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
572 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
575 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
577 /* Fixme: printf added */
578 printf("RNDISFILTER request failed to Send!\n");
582 sema_wait(&request->wait_sema);
584 /* Copy the response back */
585 query_complete = &request->response_msg.msg.query_complete;
587 if (query_complete->info_buffer_length > in_result_size) {
592 memcpy(result, (void *)((unsigned long)query_complete +
593 query_complete->info_buffer_offset),
594 query_complete->info_buffer_length);
596 *result_size = query_complete->info_buffer_length;
600 hv_put_rndis_request(device, request);
606 * RNDIS filter query device MAC address
609 hv_rf_query_device_mac(rndis_device *device)
611 uint32_t size = HW_MACADDR_LEN;
613 return (hv_rf_query_device(device,
614 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
618 * RNDIS filter query device link status
621 hv_rf_query_device_link_status(rndis_device *device)
623 uint32_t size = sizeof(uint32_t);
625 return (hv_rf_query_device(device,
626 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
629 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
630 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
631 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
632 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
633 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
634 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
638 * RNDIS set vRSS parameters
641 hv_rf_set_rss_param(rndis_device *device, int num_queue)
643 rndis_request *request;
644 rndis_set_request *set;
645 rndis_set_complete *set_complete;
646 rndis_recv_scale_param *rssp;
647 uint32_t extlen = sizeof(rndis_recv_scale_param) +
648 (4 * ITAB_NUM) + HASH_KEYLEN;
649 uint32_t *itab, status;
654 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
655 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
656 if (request == NULL) {
658 printf("Netvsc: No memory to set vRSS parameters.\n");
663 set = &request->request_msg.msg.set_request;
664 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
665 set->info_buffer_length = extlen;
666 set->info_buffer_offset = sizeof(rndis_set_request);
667 set->device_vc_handle = 0;
669 /* Fill out the rssp parameter structure */
670 rssp = (rndis_recv_scale_param *)(set + 1);
671 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
672 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
673 rssp->hdr.size = sizeof(rndis_recv_scale_param);
675 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
676 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
677 rssp->indirect_tabsize = 4 * ITAB_NUM;
678 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
679 rssp->hashkey_size = HASH_KEYLEN;
680 rssp->hashkey_offset = rssp->indirect_taboffset +
681 rssp->indirect_tabsize;
683 /* Set indirection table entries */
684 itab = (uint32_t *)(rssp + 1);
685 for (i = 0; i < ITAB_NUM; i++)
686 itab[i] = i % num_queue;
688 /* Set hash key values */
689 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
690 for (i = 0; i < HASH_KEYLEN; i++)
691 keyp[i] = netvsc_hash_key[i];
693 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
699 * Wait for the response from the host. Another thread will signal
700 * us when the response has arrived. In the failure case,
701 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
703 ret = sema_timedwait(&request->wait_sema, 5 * hz);
705 /* Response received, check status */
706 set_complete = &request->response_msg.msg.set_complete;
707 status = set_complete->status;
708 if (status != RNDIS_STATUS_SUCCESS) {
709 /* Bad response status, return error */
711 printf("Netvsc: Failed to set vRSS "
716 printf("Netvsc: Successfully set vRSS "
721 * We cannot deallocate the request since we may still
722 * receive a send completion for it.
724 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
725 request->request_msg.msg.init_request.request_id, ret);
730 if (request != NULL) {
731 hv_put_rndis_request(device, request);
738 * RNDIS filter set packet filter
739 * Sends an rndis request with the new filter, then waits for a response
741 * Returns zero on success, non-zero on failure.
744 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
746 rndis_request *request;
747 rndis_set_request *set;
748 rndis_set_complete *set_complete;
752 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
753 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
754 if (request == NULL) {
759 /* Set up the rndis set */
760 set = &request->request_msg.msg.set_request;
761 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
762 set->info_buffer_length = sizeof(uint32_t);
763 set->info_buffer_offset = sizeof(rndis_set_request);
765 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
766 &new_filter, sizeof(uint32_t));
768 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
774 * Wait for the response from the host. Another thread will signal
775 * us when the response has arrived. In the failure case,
776 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
778 ret = sema_timedwait(&request->wait_sema, 5 * hz);
780 /* Response received, check status */
781 set_complete = &request->response_msg.msg.set_complete;
782 status = set_complete->status;
783 if (status != RNDIS_STATUS_SUCCESS) {
784 /* Bad response status, return error */
789 * We cannot deallocate the request since we may still
790 * receive a send completion for it.
796 if (request != NULL) {
797 hv_put_rndis_request(device, request);
804 * RNDIS filter init device
807 hv_rf_init_device(rndis_device *device)
809 rndis_request *request;
810 rndis_initialize_request *init;
811 rndis_initialize_complete *init_complete;
815 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
816 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
822 /* Set up the rndis set */
823 init = &request->request_msg.msg.init_request;
824 init->major_version = RNDIS_MAJOR_VERSION;
825 init->minor_version = RNDIS_MINOR_VERSION;
827 * Per the RNDIS document, this should be set to the max MTU
828 * plus the header size. However, 2048 works fine, so leaving
831 init->max_xfer_size = 2048;
833 device->state = RNDIS_DEV_INITIALIZING;
835 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
837 device->state = RNDIS_DEV_UNINITIALIZED;
841 sema_wait(&request->wait_sema);
843 init_complete = &request->response_msg.msg.init_complete;
844 status = init_complete->status;
845 if (status == RNDIS_STATUS_SUCCESS) {
846 device->state = RNDIS_DEV_INITIALIZED;
849 device->state = RNDIS_DEV_UNINITIALIZED;
855 hv_put_rndis_request(device, request);
861 #define HALT_COMPLETION_WAIT_COUNT 25
864 * RNDIS filter halt device
867 hv_rf_halt_device(rndis_device *device)
869 rndis_request *request;
870 rndis_halt_request *halt;
873 /* Attempt to do a rndis device halt */
874 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
875 RNDIS_MESSAGE_SIZE(rndis_halt_request));
876 if (request == NULL) {
880 /* initialize "poor man's semaphore" */
881 request->halt_complete_flag = 0;
883 /* Set up the rndis set */
884 halt = &request->request_msg.msg.halt_request;
885 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
886 /* Increment to get the new value (call above returns old value) */
887 halt->request_id += 1;
889 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
895 * Wait for halt response from halt callback. We must wait for
896 * the transaction response before freeing the request and other
899 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
900 if (request->halt_complete_flag != 0) {
909 device->state = RNDIS_DEV_UNINITIALIZED;
911 hv_put_rndis_request(device, request);
917 * RNDIS filter open device
920 hv_rf_open_device(rndis_device *device)
924 if (device->state != RNDIS_DEV_INITIALIZED) {
928 if (hv_promisc_mode != 1) {
929 ret = hv_rf_set_packet_filter(device,
930 NDIS_PACKET_TYPE_BROADCAST |
931 NDIS_PACKET_TYPE_ALL_MULTICAST |
932 NDIS_PACKET_TYPE_DIRECTED);
934 ret = hv_rf_set_packet_filter(device,
935 NDIS_PACKET_TYPE_PROMISCUOUS);
939 device->state = RNDIS_DEV_DATAINITIALIZED;
946 * RNDIS filter close device
949 hv_rf_close_device(rndis_device *device)
953 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
957 ret = hv_rf_set_packet_filter(device, 0);
959 device->state = RNDIS_DEV_INITIALIZED;
966 * RNDIS filter on device add
969 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
974 rndis_device *rndis_dev;
976 rndis_offload_params offloads;
977 struct rndis_recv_scale_cap rsscaps;
978 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
979 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
980 device_t dev = device->device;
982 rndis_dev = hv_get_rndis_device();
983 if (rndis_dev == NULL) {
988 * Let the inner driver handle this first to create the netvsc channel
989 * NOTE! Once the channel is created, we may get a receive callback
990 * (hv_rf_on_receive()) before this call is completed.
991 * Note: Earlier code used a function pointer here.
993 net_dev = hv_nv_on_device_add(device, additl_info);
995 hv_put_rndis_device(rndis_dev);
1001 * Initialize the rndis device
1004 net_dev->extension = rndis_dev;
1005 rndis_dev->net_dev = net_dev;
1007 /* Send the rndis initialization message */
1008 ret = hv_rf_init_device(rndis_dev);
1011 * TODO: If rndis init failed, we will need to shut down
1016 /* Get the mac address */
1017 ret = hv_rf_query_device_mac(rndis_dev);
1019 /* TODO: shut down rndis device and the channel */
1022 /* config csum offload and send request to host */
1023 memset(&offloads, 0, sizeof(offloads));
1024 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1025 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1026 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1027 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1028 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1029 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1031 ret = hv_rf_send_offload_request(device, &offloads);
1033 /* TODO: shut down rndis device and the channel */
1035 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1038 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1040 hv_rf_query_device_link_status(rndis_dev);
1042 dev_info->link_state = rndis_dev->link_status;
1044 net_dev->num_channel = 1;
1045 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1048 memset(&rsscaps, 0, rsscaps_size);
1049 ret = hv_rf_query_device(rndis_dev,
1050 RNDIS_OID_GEN_RSS_CAPABILITIES,
1051 &rsscaps, &rsscaps_size);
1052 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1053 device_printf(dev, "hv_rf_query_device failed or "
1054 "rsscaps.num_recv_que < 2 \n");
1057 device_printf(dev, "channel, offered %u, requested %d\n",
1058 rsscaps.num_recv_que, nchan);
1059 if (nchan > rsscaps.num_recv_que)
1060 nchan = rsscaps.num_recv_que;
1061 net_dev->num_channel = nchan;
1063 if (net_dev->num_channel == 1) {
1064 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1068 /* request host to create sub channels */
1069 init_pkt = &net_dev->channel_init_packet;
1070 memset(init_pkt, 0, sizeof(nvsp_msg));
1072 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1073 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1074 NVSP_SUBCHANNE_ALLOCATE;
1075 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1076 net_dev->num_channel - 1;
1078 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1079 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1080 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1081 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1083 device_printf(dev, "Fail to allocate subchannel\n");
1087 sema_wait(&net_dev->channel_init_sema);
1089 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1090 nvsp_status_success) {
1092 device_printf(dev, "sub channel complete error\n");
1096 net_dev->num_channel = 1 +
1097 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1099 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1103 net_dev->num_channel = 1;
1109 * RNDIS filter on device remove
1112 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1114 hn_softc_t *sc = device_get_softc(device->device);
1115 netvsc_dev *net_dev = sc->net_dev;
1116 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1119 /* Halt and release the rndis device */
1120 ret = hv_rf_halt_device(rndis_dev);
1122 hv_put_rndis_device(rndis_dev);
1123 net_dev->extension = NULL;
1125 /* Pass control to inner driver to remove the device */
1126 ret |= hv_nv_on_device_remove(device, destroy_channel);
1132 * RNDIS filter on open
1135 hv_rf_on_open(struct hv_device *device)
1137 hn_softc_t *sc = device_get_softc(device->device);
1138 netvsc_dev *net_dev = sc->net_dev;
1140 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1144 * RNDIS filter on close
1147 hv_rf_on_close(struct hv_device *device)
1149 hn_softc_t *sc = device_get_softc(device->device);
1150 netvsc_dev *net_dev = sc->net_dev;
1152 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1156 * RNDIS filter on send request completion callback
1159 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1160 void *context __unused)
1165 * RNDIS filter on send request (halt only) completion callback
1168 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1171 rndis_request *request = context;
1174 * Notify hv_rf_halt_device() about halt completion.
1175 * The halt code must wait for completion before freeing
1176 * the transaction resources.
1178 request->halt_complete_flag = 1;
1182 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1185 netvsc_channel_rollup(chan);