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 const struct rndis_hash_info *hash_info;
448 const struct rndis_hash_value *hash_value;
449 device_t dev = device->net_dev->dev->device;
451 rndis_pkt = &message->msg.packet;
454 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
455 * netvsc packet (ie tot_data_buf_len != message_length)
458 /* Remove rndis header, then pass data packet up the stack */
459 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
461 pkt->tot_data_buf_len -= data_offset;
462 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
463 pkt->status = nvsp_status_failure;
465 "total length %u is less than data length %u\n",
466 pkt->tot_data_buf_len, rndis_pkt->data_length);
470 pkt->tot_data_buf_len = rndis_pkt->data_length;
471 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
473 rppi_vlan_info = hv_get_ppi_data(rndis_pkt, ieee_8021q_info);
474 if (rppi_vlan_info) {
475 pkt->vlan_tci = rppi_vlan_info->u1.s1.vlan_id;
480 csum_info = hv_get_ppi_data(rndis_pkt, tcpip_chksum_info);
481 hash_value = hv_get_ppi_data(rndis_pkt, nbl_hash_value);
482 hash_info = hv_get_ppi_data(rndis_pkt, nbl_hash_info);
483 netvsc_recv(chan, pkt, csum_info, hash_info, hash_value);
487 * RNDIS filter on receive
490 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
491 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
493 rndis_device *rndis_dev;
494 rndis_msg *rndis_hdr;
496 /* Make sure the rndis device state is initialized */
497 if (net_dev->extension == NULL) {
498 pkt->status = nvsp_status_failure;
502 rndis_dev = (rndis_device *)net_dev->extension;
503 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
504 pkt->status = nvsp_status_failure;
508 rndis_hdr = pkt->data;
510 switch (rndis_hdr->ndis_msg_type) {
513 case REMOTE_NDIS_PACKET_MSG:
514 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
516 /* completion messages */
517 case REMOTE_NDIS_INITIALIZE_CMPLT:
518 case REMOTE_NDIS_QUERY_CMPLT:
519 case REMOTE_NDIS_SET_CMPLT:
520 case REMOTE_NDIS_RESET_CMPLT:
521 case REMOTE_NDIS_KEEPALIVE_CMPLT:
522 hv_rf_receive_response(rndis_dev, rndis_hdr);
524 /* notification message */
525 case REMOTE_NDIS_INDICATE_STATUS_MSG:
526 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
529 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
530 rndis_hdr->ndis_msg_type);
538 * RNDIS filter query device
541 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
542 uint32_t *result_size)
544 rndis_request *request;
545 uint32_t in_result_size = *result_size;
546 rndis_query_request *query;
547 rndis_query_complete *query_complete;
551 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
552 RNDIS_MESSAGE_SIZE(rndis_query_request));
553 if (request == NULL) {
558 /* Set up the rndis query */
559 query = &request->request_msg.msg.query_request;
561 query->info_buffer_offset = sizeof(rndis_query_request);
562 query->info_buffer_length = 0;
563 query->device_vc_handle = 0;
565 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
566 struct rndis_recv_scale_cap *cap;
568 request->request_msg.msg_len +=
569 sizeof(struct rndis_recv_scale_cap);
570 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
571 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
572 query->info_buffer_offset);
573 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
574 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
575 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
578 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
580 /* Fixme: printf added */
581 printf("RNDISFILTER request failed to Send!\n");
585 sema_wait(&request->wait_sema);
587 /* Copy the response back */
588 query_complete = &request->response_msg.msg.query_complete;
590 if (query_complete->info_buffer_length > in_result_size) {
595 memcpy(result, (void *)((unsigned long)query_complete +
596 query_complete->info_buffer_offset),
597 query_complete->info_buffer_length);
599 *result_size = query_complete->info_buffer_length;
603 hv_put_rndis_request(device, request);
609 * RNDIS filter query device MAC address
612 hv_rf_query_device_mac(rndis_device *device)
614 uint32_t size = HW_MACADDR_LEN;
616 return (hv_rf_query_device(device,
617 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
621 * RNDIS filter query device link status
624 hv_rf_query_device_link_status(rndis_device *device)
626 uint32_t size = sizeof(uint32_t);
628 return (hv_rf_query_device(device,
629 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
632 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
633 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
634 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
635 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
636 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
637 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
641 * RNDIS set vRSS parameters
644 hv_rf_set_rss_param(rndis_device *device, int num_queue)
646 rndis_request *request;
647 rndis_set_request *set;
648 rndis_set_complete *set_complete;
649 rndis_recv_scale_param *rssp;
650 uint32_t extlen = sizeof(rndis_recv_scale_param) +
651 (4 * ITAB_NUM) + HASH_KEYLEN;
652 uint32_t *itab, status;
657 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
658 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
659 if (request == NULL) {
661 printf("Netvsc: No memory to set vRSS parameters.\n");
666 set = &request->request_msg.msg.set_request;
667 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
668 set->info_buffer_length = extlen;
669 set->info_buffer_offset = sizeof(rndis_set_request);
670 set->device_vc_handle = 0;
672 /* Fill out the rssp parameter structure */
673 rssp = (rndis_recv_scale_param *)(set + 1);
674 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
675 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
676 rssp->hdr.size = sizeof(rndis_recv_scale_param);
678 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
679 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
680 rssp->indirect_tabsize = 4 * ITAB_NUM;
681 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
682 rssp->hashkey_size = HASH_KEYLEN;
683 rssp->hashkey_offset = rssp->indirect_taboffset +
684 rssp->indirect_tabsize;
686 /* Set indirection table entries */
687 itab = (uint32_t *)(rssp + 1);
688 for (i = 0; i < ITAB_NUM; i++)
689 itab[i] = i % num_queue;
691 /* Set hash key values */
692 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
693 for (i = 0; i < HASH_KEYLEN; i++)
694 keyp[i] = netvsc_hash_key[i];
696 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
702 * Wait for the response from the host. Another thread will signal
703 * us when the response has arrived. In the failure case,
704 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
706 ret = sema_timedwait(&request->wait_sema, 5 * hz);
708 /* Response received, check status */
709 set_complete = &request->response_msg.msg.set_complete;
710 status = set_complete->status;
711 if (status != RNDIS_STATUS_SUCCESS) {
712 /* Bad response status, return error */
714 printf("Netvsc: Failed to set vRSS "
719 printf("Netvsc: Successfully set vRSS "
724 * We cannot deallocate the request since we may still
725 * receive a send completion for it.
727 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
728 request->request_msg.msg.init_request.request_id, ret);
733 if (request != NULL) {
734 hv_put_rndis_request(device, request);
741 * RNDIS filter set packet filter
742 * Sends an rndis request with the new filter, then waits for a response
744 * Returns zero on success, non-zero on failure.
747 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
749 rndis_request *request;
750 rndis_set_request *set;
751 rndis_set_complete *set_complete;
755 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
756 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
757 if (request == NULL) {
762 /* Set up the rndis set */
763 set = &request->request_msg.msg.set_request;
764 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
765 set->info_buffer_length = sizeof(uint32_t);
766 set->info_buffer_offset = sizeof(rndis_set_request);
768 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
769 &new_filter, sizeof(uint32_t));
771 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
777 * Wait for the response from the host. Another thread will signal
778 * us when the response has arrived. In the failure case,
779 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
781 ret = sema_timedwait(&request->wait_sema, 5 * hz);
783 /* Response received, check status */
784 set_complete = &request->response_msg.msg.set_complete;
785 status = set_complete->status;
786 if (status != RNDIS_STATUS_SUCCESS) {
787 /* Bad response status, return error */
792 * We cannot deallocate the request since we may still
793 * receive a send completion for it.
799 if (request != NULL) {
800 hv_put_rndis_request(device, request);
807 * RNDIS filter init device
810 hv_rf_init_device(rndis_device *device)
812 rndis_request *request;
813 rndis_initialize_request *init;
814 rndis_initialize_complete *init_complete;
818 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
819 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
825 /* Set up the rndis set */
826 init = &request->request_msg.msg.init_request;
827 init->major_version = RNDIS_MAJOR_VERSION;
828 init->minor_version = RNDIS_MINOR_VERSION;
830 * Per the RNDIS document, this should be set to the max MTU
831 * plus the header size. However, 2048 works fine, so leaving
834 init->max_xfer_size = 2048;
836 device->state = RNDIS_DEV_INITIALIZING;
838 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
840 device->state = RNDIS_DEV_UNINITIALIZED;
844 sema_wait(&request->wait_sema);
846 init_complete = &request->response_msg.msg.init_complete;
847 status = init_complete->status;
848 if (status == RNDIS_STATUS_SUCCESS) {
849 device->state = RNDIS_DEV_INITIALIZED;
852 device->state = RNDIS_DEV_UNINITIALIZED;
858 hv_put_rndis_request(device, request);
864 #define HALT_COMPLETION_WAIT_COUNT 25
867 * RNDIS filter halt device
870 hv_rf_halt_device(rndis_device *device)
872 rndis_request *request;
873 rndis_halt_request *halt;
876 /* Attempt to do a rndis device halt */
877 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
878 RNDIS_MESSAGE_SIZE(rndis_halt_request));
879 if (request == NULL) {
883 /* initialize "poor man's semaphore" */
884 request->halt_complete_flag = 0;
886 /* Set up the rndis set */
887 halt = &request->request_msg.msg.halt_request;
888 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
889 /* Increment to get the new value (call above returns old value) */
890 halt->request_id += 1;
892 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
898 * Wait for halt response from halt callback. We must wait for
899 * the transaction response before freeing the request and other
902 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
903 if (request->halt_complete_flag != 0) {
912 device->state = RNDIS_DEV_UNINITIALIZED;
914 hv_put_rndis_request(device, request);
920 * RNDIS filter open device
923 hv_rf_open_device(rndis_device *device)
927 if (device->state != RNDIS_DEV_INITIALIZED) {
931 if (hv_promisc_mode != 1) {
932 ret = hv_rf_set_packet_filter(device,
933 NDIS_PACKET_TYPE_BROADCAST |
934 NDIS_PACKET_TYPE_ALL_MULTICAST |
935 NDIS_PACKET_TYPE_DIRECTED);
937 ret = hv_rf_set_packet_filter(device,
938 NDIS_PACKET_TYPE_PROMISCUOUS);
942 device->state = RNDIS_DEV_DATAINITIALIZED;
949 * RNDIS filter close device
952 hv_rf_close_device(rndis_device *device)
956 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
960 ret = hv_rf_set_packet_filter(device, 0);
962 device->state = RNDIS_DEV_INITIALIZED;
969 * RNDIS filter on device add
972 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
977 rndis_device *rndis_dev;
979 rndis_offload_params offloads;
980 struct rndis_recv_scale_cap rsscaps;
981 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
982 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
983 device_t dev = device->device;
985 rndis_dev = hv_get_rndis_device();
986 if (rndis_dev == NULL) {
991 * Let the inner driver handle this first to create the netvsc channel
992 * NOTE! Once the channel is created, we may get a receive callback
993 * (hv_rf_on_receive()) before this call is completed.
994 * Note: Earlier code used a function pointer here.
996 net_dev = hv_nv_on_device_add(device, additl_info);
998 hv_put_rndis_device(rndis_dev);
1004 * Initialize the rndis device
1007 net_dev->extension = rndis_dev;
1008 rndis_dev->net_dev = net_dev;
1010 /* Send the rndis initialization message */
1011 ret = hv_rf_init_device(rndis_dev);
1014 * TODO: If rndis init failed, we will need to shut down
1019 /* Get the mac address */
1020 ret = hv_rf_query_device_mac(rndis_dev);
1022 /* TODO: shut down rndis device and the channel */
1025 /* config csum offload and send request to host */
1026 memset(&offloads, 0, sizeof(offloads));
1027 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1028 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1029 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1030 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1031 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1032 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1034 ret = hv_rf_send_offload_request(device, &offloads);
1036 /* TODO: shut down rndis device and the channel */
1038 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1041 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1043 hv_rf_query_device_link_status(rndis_dev);
1045 dev_info->link_state = rndis_dev->link_status;
1047 net_dev->num_channel = 1;
1048 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1051 memset(&rsscaps, 0, rsscaps_size);
1052 ret = hv_rf_query_device(rndis_dev,
1053 RNDIS_OID_GEN_RSS_CAPABILITIES,
1054 &rsscaps, &rsscaps_size);
1055 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1056 device_printf(dev, "hv_rf_query_device failed or "
1057 "rsscaps.num_recv_que < 2 \n");
1060 device_printf(dev, "channel, offered %u, requested %d\n",
1061 rsscaps.num_recv_que, nchan);
1062 if (nchan > rsscaps.num_recv_que)
1063 nchan = rsscaps.num_recv_que;
1064 net_dev->num_channel = nchan;
1066 if (net_dev->num_channel == 1) {
1067 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1071 /* request host to create sub channels */
1072 init_pkt = &net_dev->channel_init_packet;
1073 memset(init_pkt, 0, sizeof(nvsp_msg));
1075 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1076 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1077 NVSP_SUBCHANNE_ALLOCATE;
1078 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1079 net_dev->num_channel - 1;
1081 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1082 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1083 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1084 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1086 device_printf(dev, "Fail to allocate subchannel\n");
1090 sema_wait(&net_dev->channel_init_sema);
1092 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1093 nvsp_status_success) {
1095 device_printf(dev, "sub channel complete error\n");
1099 net_dev->num_channel = 1 +
1100 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1102 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1106 net_dev->num_channel = 1;
1112 * RNDIS filter on device remove
1115 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1117 hn_softc_t *sc = device_get_softc(device->device);
1118 netvsc_dev *net_dev = sc->net_dev;
1119 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1122 /* Halt and release the rndis device */
1123 ret = hv_rf_halt_device(rndis_dev);
1125 hv_put_rndis_device(rndis_dev);
1126 net_dev->extension = NULL;
1128 /* Pass control to inner driver to remove the device */
1129 ret |= hv_nv_on_device_remove(device, destroy_channel);
1135 * RNDIS filter on open
1138 hv_rf_on_open(struct hv_device *device)
1140 hn_softc_t *sc = device_get_softc(device->device);
1141 netvsc_dev *net_dev = sc->net_dev;
1143 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1147 * RNDIS filter on close
1150 hv_rf_on_close(struct hv_device *device)
1152 hn_softc_t *sc = device_get_softc(device->device);
1153 netvsc_dev *net_dev = sc->net_dev;
1155 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1159 * RNDIS filter on send request completion callback
1162 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1163 void *context __unused)
1168 * RNDIS filter on send request (halt only) completion callback
1171 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1174 rndis_request *request = context;
1177 * Notify hv_rf_halt_device() about halt completion.
1178 * The halt code must wait for completion before freeing
1179 * the transaction resources.
1181 request->halt_complete_flag = 1;
1185 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1188 netvsc_channel_rollup(chan);