2 * Copyright (c) 2009-2012 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;
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 if (request != NULL) {
912 hv_put_rndis_request(device, request);
919 * RNDIS filter open device
922 hv_rf_open_device(rndis_device *device)
926 if (device->state != RNDIS_DEV_INITIALIZED) {
930 if (hv_promisc_mode != 1) {
931 ret = hv_rf_set_packet_filter(device,
932 NDIS_PACKET_TYPE_BROADCAST |
933 NDIS_PACKET_TYPE_ALL_MULTICAST |
934 NDIS_PACKET_TYPE_DIRECTED);
936 ret = hv_rf_set_packet_filter(device,
937 NDIS_PACKET_TYPE_PROMISCUOUS);
941 device->state = RNDIS_DEV_DATAINITIALIZED;
948 * RNDIS filter close device
951 hv_rf_close_device(rndis_device *device)
955 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
959 ret = hv_rf_set_packet_filter(device, 0);
961 device->state = RNDIS_DEV_INITIALIZED;
968 * RNDIS filter on device add
971 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
976 rndis_device *rndis_dev;
978 rndis_offload_params offloads;
979 struct rndis_recv_scale_cap rsscaps;
980 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
981 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
982 device_t dev = device->device;
984 rndis_dev = hv_get_rndis_device();
985 if (rndis_dev == NULL) {
990 * Let the inner driver handle this first to create the netvsc channel
991 * NOTE! Once the channel is created, we may get a receive callback
992 * (hv_rf_on_receive()) before this call is completed.
993 * Note: Earlier code used a function pointer here.
995 net_dev = hv_nv_on_device_add(device, additl_info);
997 hv_put_rndis_device(rndis_dev);
1003 * Initialize the rndis device
1006 net_dev->extension = rndis_dev;
1007 rndis_dev->net_dev = net_dev;
1009 /* Send the rndis initialization message */
1010 ret = hv_rf_init_device(rndis_dev);
1013 * TODO: If rndis init failed, we will need to shut down
1018 /* Get the mac address */
1019 ret = hv_rf_query_device_mac(rndis_dev);
1021 /* TODO: shut down rndis device and the channel */
1024 /* config csum offload and send request to host */
1025 memset(&offloads, 0, sizeof(offloads));
1026 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1027 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1028 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1029 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1030 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1031 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1033 ret = hv_rf_send_offload_request(device, &offloads);
1035 /* TODO: shut down rndis device and the channel */
1037 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1040 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1042 hv_rf_query_device_link_status(rndis_dev);
1044 dev_info->link_state = rndis_dev->link_status;
1046 net_dev->num_channel = 1;
1047 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1050 memset(&rsscaps, 0, rsscaps_size);
1051 ret = hv_rf_query_device(rndis_dev,
1052 RNDIS_OID_GEN_RSS_CAPABILITIES,
1053 &rsscaps, &rsscaps_size);
1054 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1055 device_printf(dev, "hv_rf_query_device failed or "
1056 "rsscaps.num_recv_que < 2 \n");
1059 device_printf(dev, "channel, offered %u, requested %d\n",
1060 rsscaps.num_recv_que, nchan);
1061 if (nchan > rsscaps.num_recv_que)
1062 nchan = rsscaps.num_recv_que;
1063 net_dev->num_channel = nchan;
1065 if (net_dev->num_channel == 1) {
1066 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1070 /* request host to create sub channels */
1071 init_pkt = &net_dev->channel_init_packet;
1072 memset(init_pkt, 0, sizeof(nvsp_msg));
1074 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1075 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1076 NVSP_SUBCHANNE_ALLOCATE;
1077 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1078 net_dev->num_channel - 1;
1080 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1081 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1082 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1083 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1085 device_printf(dev, "Fail to allocate subchannel\n");
1089 sema_wait(&net_dev->channel_init_sema);
1091 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1092 nvsp_status_success) {
1094 device_printf(dev, "sub channel complete error\n");
1098 net_dev->num_channel = 1 +
1099 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1101 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1105 net_dev->num_channel = 1;
1111 * RNDIS filter on device remove
1114 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1116 hn_softc_t *sc = device_get_softc(device->device);
1117 netvsc_dev *net_dev = sc->net_dev;
1118 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1121 /* Halt and release the rndis device */
1122 ret = hv_rf_halt_device(rndis_dev);
1124 hv_put_rndis_device(rndis_dev);
1125 net_dev->extension = NULL;
1127 /* Pass control to inner driver to remove the device */
1128 ret |= hv_nv_on_device_remove(device, destroy_channel);
1134 * RNDIS filter on open
1137 hv_rf_on_open(struct hv_device *device)
1139 hn_softc_t *sc = device_get_softc(device->device);
1140 netvsc_dev *net_dev = sc->net_dev;
1142 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1146 * RNDIS filter on close
1149 hv_rf_on_close(struct hv_device *device)
1151 hn_softc_t *sc = device_get_softc(device->device);
1152 netvsc_dev *net_dev = sc->net_dev;
1154 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1158 * RNDIS filter on send request completion callback
1161 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1162 void *context __unused)
1167 * RNDIS filter on send request (halt only) completion callback
1170 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1173 rndis_request *request = context;
1176 * Notify hv_rf_halt_device() about halt completion.
1177 * The halt code must wait for completion before freeing
1178 * the transaction resources.
1180 request->halt_complete_flag = 1;
1184 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1187 netvsc_channel_rollup(chan);