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"
53 struct hv_rf_recvinfo {
54 const ndis_8021q_info *vlan_info;
55 const rndis_tcp_ip_csum_info *csum_info;
56 const struct rndis_hash_info *hash_info;
57 const struct rndis_hash_value *hash_value;
60 #define HV_RF_RECVINFO_VLAN 0x1
61 #define HV_RF_RECVINFO_CSUM 0x2
62 #define HV_RF_RECVINFO_HASHINF 0x4
63 #define HV_RF_RECVINFO_HASHVAL 0x8
64 #define HV_RF_RECVINFO_ALL \
65 (HV_RF_RECVINFO_VLAN | \
66 HV_RF_RECVINFO_CSUM | \
67 HV_RF_RECVINFO_HASHINF | \
68 HV_RF_RECVINFO_HASHVAL)
71 * Forward declarations
73 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
74 uint32_t message_type);
75 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
76 static void hv_rf_receive_indicate_status(rndis_device *device,
78 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
79 struct hv_vmbus_channel *chan,
81 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
82 void *result, uint32_t *result_size);
83 static inline int hv_rf_query_device_mac(rndis_device *device);
84 static inline int hv_rf_query_device_link_status(rndis_device *device);
85 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
86 static int hv_rf_init_device(rndis_device *device);
87 static int hv_rf_open_device(rndis_device *device);
88 static int hv_rf_close_device(rndis_device *device);
89 static void hv_rf_on_send_request_completion(struct hv_vmbus_channel *, void *context);
90 static void hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *, void *context);
92 hv_rf_send_offload_request(struct hv_device *device,
93 rndis_offload_params *offloads);
95 * Set the Per-Packet-Info with the specified type
98 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
101 rndis_packet *rndis_pkt;
102 rndis_per_packet_info *rppi;
104 rndis_pkt = &rndis_mesg->msg.packet;
105 rndis_pkt->data_offset += rppi_size;
107 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
108 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
110 rppi->size = rppi_size;
111 rppi->type = pkt_type;
112 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
114 rndis_pkt->per_pkt_info_length += rppi_size;
120 * Get the Per-Packet-Info with the specified type
121 * return NULL if not found.
124 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
126 rndis_per_packet_info *ppi;
129 if (rpkt->per_pkt_info_offset == 0)
132 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
133 rpkt->per_pkt_info_offset);
134 len = rpkt->per_pkt_info_length;
137 if (ppi->type == type)
138 return (void *)((unsigned long)ppi +
139 ppi->per_packet_info_offset);
142 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
150 * Allow module_param to work and override to switch to promiscuous mode.
152 static inline rndis_device *
153 hv_get_rndis_device(void)
155 rndis_device *device;
157 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
159 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
161 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
162 STAILQ_INIT(&device->myrequest_list);
164 device->state = RNDIS_DEV_UNINITIALIZED;
173 hv_put_rndis_device(rndis_device *device)
175 mtx_destroy(&device->req_lock);
176 free(device, M_NETVSC);
182 static inline rndis_request *
183 hv_rndis_request(rndis_device *device, uint32_t message_type,
184 uint32_t message_length)
186 rndis_request *request;
187 rndis_msg *rndis_mesg;
188 rndis_set_request *set;
190 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
192 sema_init(&request->wait_sema, 0, "rndis sema");
194 rndis_mesg = &request->request_msg;
195 rndis_mesg->ndis_msg_type = message_type;
196 rndis_mesg->msg_len = message_length;
199 * Set the request id. This field is always after the rndis header
200 * for request/response packet types so we just use the set_request
203 set = &rndis_mesg->msg.set_request;
204 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
205 /* Increment to get the new value (call above returns old value) */
206 set->request_id += 1;
208 /* Add to the request list */
209 mtx_lock(&device->req_lock);
210 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
211 mtx_unlock(&device->req_lock);
220 hv_put_rndis_request(rndis_device *device, rndis_request *request)
222 mtx_lock(&device->req_lock);
223 /* Fixme: Has O(n) performance */
225 * XXXKYS: Use Doubly linked lists.
227 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
229 mtx_unlock(&device->req_lock);
231 sema_destroy(&request->wait_sema);
232 free(request, M_NETVSC);
239 hv_rf_send_request(rndis_device *device, rndis_request *request,
240 uint32_t message_type)
243 netvsc_packet *packet;
244 netvsc_dev *net_dev = device->net_dev;
245 int send_buf_section_idx;
247 /* Set up the packet to send it */
248 packet = &request->pkt;
250 packet->is_data_pkt = FALSE;
251 packet->tot_data_buf_len = request->request_msg.msg_len;
252 packet->page_buf_count = 1;
254 packet->page_buffers[0].pfn =
255 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
256 packet->page_buffers[0].length = request->request_msg.msg_len;
257 packet->page_buffers[0].offset =
258 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
260 if (packet->page_buffers[0].offset +
261 packet->page_buffers[0].length > PAGE_SIZE) {
262 packet->page_buf_count = 2;
263 packet->page_buffers[0].length =
264 PAGE_SIZE - packet->page_buffers[0].offset;
265 packet->page_buffers[1].pfn =
266 hv_get_phys_addr((char*)&request->request_msg +
267 packet->page_buffers[0].length) >> PAGE_SHIFT;
268 packet->page_buffers[1].offset = 0;
269 packet->page_buffers[1].length =
270 request->request_msg.msg_len -
271 packet->page_buffers[0].length;
274 packet->compl.send.send_completion_context = request; /* packet */
275 if (message_type != REMOTE_NDIS_HALT_MSG) {
276 packet->compl.send.on_send_completion =
277 hv_rf_on_send_request_completion;
279 packet->compl.send.on_send_completion =
280 hv_rf_on_send_request_halt_completion;
282 packet->compl.send.send_completion_tid = (unsigned long)device;
283 if (packet->tot_data_buf_len < net_dev->send_section_size) {
284 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
285 if (send_buf_section_idx !=
286 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
287 char *dest = ((char *)net_dev->send_buf +
288 send_buf_section_idx * net_dev->send_section_size);
290 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
291 packet->send_buf_section_idx = send_buf_section_idx;
292 packet->send_buf_section_size = packet->tot_data_buf_len;
293 packet->page_buf_count = 0;
296 /* Failed to allocate chimney send buffer; move on */
298 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
299 packet->send_buf_section_size = 0;
302 ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
308 * RNDIS filter receive response
311 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
313 rndis_request *request = NULL;
314 rndis_request *next_request;
315 boolean_t found = FALSE;
317 mtx_lock(&device->req_lock);
318 request = STAILQ_FIRST(&device->myrequest_list);
319 while (request != NULL) {
321 * All request/response message contains request_id as the
324 if (request->request_msg.msg.init_request.request_id ==
325 response->msg.init_complete.request_id) {
329 next_request = STAILQ_NEXT(request, mylist_entry);
330 request = next_request;
332 mtx_unlock(&device->req_lock);
335 if (response->msg_len <= sizeof(rndis_msg)) {
336 memcpy(&request->response_msg, response,
339 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
340 /* Does not have a request id field */
341 request->response_msg.msg.reset_complete.status =
342 STATUS_BUFFER_OVERFLOW;
344 request->response_msg.msg.init_complete.status =
345 STATUS_BUFFER_OVERFLOW;
349 sema_post(&request->wait_sema);
354 hv_rf_send_offload_request(struct hv_device *device,
355 rndis_offload_params *offloads)
357 rndis_request *request;
358 rndis_set_request *set;
359 rndis_offload_params *offload_req;
360 rndis_set_complete *set_complete;
361 rndis_device *rndis_dev;
362 hn_softc_t *sc = device_get_softc(device->device);
363 device_t dev = device->device;
364 netvsc_dev *net_dev = sc->net_dev;
365 uint32_t vsp_version = net_dev->nvsp_version;
366 uint32_t extlen = sizeof(rndis_offload_params);
369 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
370 extlen = VERSION_4_OFFLOAD_SIZE;
371 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
372 * UDP checksum offload.
374 offloads->udp_ipv4_csum = 0;
375 offloads->udp_ipv6_csum = 0;
378 rndis_dev = net_dev->extension;
380 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
381 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
385 set = &request->request_msg.msg.set_request;
386 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
387 set->info_buffer_length = extlen;
388 set->info_buffer_offset = sizeof(rndis_set_request);
389 set->device_vc_handle = 0;
391 offload_req = (rndis_offload_params *)((unsigned long)set +
392 set->info_buffer_offset);
393 *offload_req = *offloads;
394 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
395 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
396 offload_req->header.size = extlen;
398 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
400 device_printf(dev, "hv send offload request failed, ret=%d!\n",
405 ret = sema_timedwait(&request->wait_sema, 5 * hz);
407 device_printf(dev, "hv send offload request timeout\n");
411 set_complete = &request->response_msg.msg.set_complete;
412 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
413 device_printf(dev, "hv send offload request succeeded\n");
416 if (set_complete->status == STATUS_NOT_SUPPORTED) {
417 device_printf(dev, "HV Not support offload\n");
420 ret = set_complete->status;
425 hv_put_rndis_request(rndis_dev, request);
431 * RNDIS filter receive indicate status
434 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
436 rndis_indicate_status *indicate = &response->msg.indicate_status;
438 switch(indicate->status) {
439 case RNDIS_STATUS_MEDIA_CONNECT:
440 netvsc_linkstatus_callback(device->net_dev->dev, 1);
442 case RNDIS_STATUS_MEDIA_DISCONNECT:
443 netvsc_linkstatus_callback(device->net_dev->dev, 0);
447 device_printf(device->net_dev->dev->device,
448 "unknown status %d received\n", indicate->status);
454 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
456 const rndis_per_packet_info *ppi;
459 info->vlan_info = NULL;
460 info->csum_info = NULL;
461 info->hash_info = NULL;
462 info->hash_value = NULL;
464 if (rpkt->per_pkt_info_offset == 0)
467 ppi = (const rndis_per_packet_info *)
468 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
469 len = rpkt->per_pkt_info_length;
473 const void *ppi_dptr;
476 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
478 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
479 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
482 case ieee_8021q_info:
483 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
485 info->vlan_info = ppi_dptr;
486 mask |= HV_RF_RECVINFO_VLAN;
489 case tcpip_chksum_info:
490 if (__predict_false(ppi_dlen <
491 sizeof(rndis_tcp_ip_csum_info)))
493 info->csum_info = ppi_dptr;
494 mask |= HV_RF_RECVINFO_CSUM;
498 if (__predict_false(ppi_dlen <
499 sizeof(struct rndis_hash_value)))
501 info->hash_value = ppi_dptr;
502 mask |= HV_RF_RECVINFO_HASHVAL;
506 if (__predict_false(ppi_dlen <
507 sizeof(struct rndis_hash_info)))
509 info->hash_info = ppi_dptr;
510 mask |= HV_RF_RECVINFO_HASHINF;
517 if (mask == HV_RF_RECVINFO_ALL) {
518 /* All found; done */
522 if (__predict_false(len < ppi->size))
525 ppi = (const rndis_per_packet_info *)
526 ((const uint8_t *)ppi + ppi->size);
532 * RNDIS filter receive data
535 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
536 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
538 rndis_packet *rndis_pkt;
539 uint32_t data_offset;
540 device_t dev = device->net_dev->dev->device;
541 struct hv_rf_recvinfo info;
543 rndis_pkt = &message->msg.packet;
546 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
547 * netvsc packet (ie tot_data_buf_len != message_length)
550 /* Remove rndis header, then pass data packet up the stack */
551 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
553 pkt->tot_data_buf_len -= data_offset;
554 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
555 pkt->status = nvsp_status_failure;
557 "total length %u is less than data length %u\n",
558 pkt->tot_data_buf_len, rndis_pkt->data_length);
562 pkt->tot_data_buf_len = rndis_pkt->data_length;
563 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
565 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
566 pkt->status = nvsp_status_failure;
567 device_printf(dev, "recvinfo parsing failed\n");
571 if (info.vlan_info != NULL)
572 pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
576 netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value);
580 * RNDIS filter on receive
583 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
584 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
586 rndis_device *rndis_dev;
587 rndis_msg *rndis_hdr;
589 /* Make sure the rndis device state is initialized */
590 if (net_dev->extension == NULL) {
591 pkt->status = nvsp_status_failure;
595 rndis_dev = (rndis_device *)net_dev->extension;
596 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
597 pkt->status = nvsp_status_failure;
601 rndis_hdr = pkt->data;
603 switch (rndis_hdr->ndis_msg_type) {
606 case REMOTE_NDIS_PACKET_MSG:
607 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
609 /* completion messages */
610 case REMOTE_NDIS_INITIALIZE_CMPLT:
611 case REMOTE_NDIS_QUERY_CMPLT:
612 case REMOTE_NDIS_SET_CMPLT:
613 case REMOTE_NDIS_RESET_CMPLT:
614 case REMOTE_NDIS_KEEPALIVE_CMPLT:
615 hv_rf_receive_response(rndis_dev, rndis_hdr);
617 /* notification message */
618 case REMOTE_NDIS_INDICATE_STATUS_MSG:
619 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
622 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
623 rndis_hdr->ndis_msg_type);
631 * RNDIS filter query device
634 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
635 uint32_t *result_size)
637 rndis_request *request;
638 uint32_t in_result_size = *result_size;
639 rndis_query_request *query;
640 rndis_query_complete *query_complete;
644 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
645 RNDIS_MESSAGE_SIZE(rndis_query_request));
646 if (request == NULL) {
651 /* Set up the rndis query */
652 query = &request->request_msg.msg.query_request;
654 query->info_buffer_offset = sizeof(rndis_query_request);
655 query->info_buffer_length = 0;
656 query->device_vc_handle = 0;
658 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
659 struct rndis_recv_scale_cap *cap;
661 request->request_msg.msg_len +=
662 sizeof(struct rndis_recv_scale_cap);
663 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
664 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
665 query->info_buffer_offset);
666 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
667 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
668 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
671 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
673 /* Fixme: printf added */
674 printf("RNDISFILTER request failed to Send!\n");
678 sema_wait(&request->wait_sema);
680 /* Copy the response back */
681 query_complete = &request->response_msg.msg.query_complete;
683 if (query_complete->info_buffer_length > in_result_size) {
688 memcpy(result, (void *)((unsigned long)query_complete +
689 query_complete->info_buffer_offset),
690 query_complete->info_buffer_length);
692 *result_size = query_complete->info_buffer_length;
696 hv_put_rndis_request(device, request);
702 * RNDIS filter query device MAC address
705 hv_rf_query_device_mac(rndis_device *device)
707 uint32_t size = HW_MACADDR_LEN;
709 return (hv_rf_query_device(device,
710 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
714 * RNDIS filter query device link status
717 hv_rf_query_device_link_status(rndis_device *device)
719 uint32_t size = sizeof(uint32_t);
721 return (hv_rf_query_device(device,
722 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
725 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
726 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
727 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
728 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
729 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
730 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
734 * RNDIS set vRSS parameters
737 hv_rf_set_rss_param(rndis_device *device, int num_queue)
739 rndis_request *request;
740 rndis_set_request *set;
741 rndis_set_complete *set_complete;
742 rndis_recv_scale_param *rssp;
743 uint32_t extlen = sizeof(rndis_recv_scale_param) +
744 (4 * ITAB_NUM) + HASH_KEYLEN;
745 uint32_t *itab, status;
750 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
751 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
752 if (request == NULL) {
754 printf("Netvsc: No memory to set vRSS parameters.\n");
759 set = &request->request_msg.msg.set_request;
760 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
761 set->info_buffer_length = extlen;
762 set->info_buffer_offset = sizeof(rndis_set_request);
763 set->device_vc_handle = 0;
765 /* Fill out the rssp parameter structure */
766 rssp = (rndis_recv_scale_param *)(set + 1);
767 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
768 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
769 rssp->hdr.size = sizeof(rndis_recv_scale_param);
771 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
772 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
773 rssp->indirect_tabsize = 4 * ITAB_NUM;
774 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
775 rssp->hashkey_size = HASH_KEYLEN;
776 rssp->hashkey_offset = rssp->indirect_taboffset +
777 rssp->indirect_tabsize;
779 /* Set indirection table entries */
780 itab = (uint32_t *)(rssp + 1);
781 for (i = 0; i < ITAB_NUM; i++)
782 itab[i] = i % num_queue;
784 /* Set hash key values */
785 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
786 for (i = 0; i < HASH_KEYLEN; i++)
787 keyp[i] = netvsc_hash_key[i];
789 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
795 * Wait for the response from the host. Another thread will signal
796 * us when the response has arrived. In the failure case,
797 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
799 ret = sema_timedwait(&request->wait_sema, 5 * hz);
801 /* Response received, check status */
802 set_complete = &request->response_msg.msg.set_complete;
803 status = set_complete->status;
804 if (status != RNDIS_STATUS_SUCCESS) {
805 /* Bad response status, return error */
807 printf("Netvsc: Failed to set vRSS "
812 printf("Netvsc: Successfully set vRSS "
817 * We cannot deallocate the request since we may still
818 * receive a send completion for it.
820 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
821 request->request_msg.msg.init_request.request_id, ret);
826 if (request != NULL) {
827 hv_put_rndis_request(device, request);
834 * RNDIS filter set packet filter
835 * Sends an rndis request with the new filter, then waits for a response
837 * Returns zero on success, non-zero on failure.
840 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
842 rndis_request *request;
843 rndis_set_request *set;
844 rndis_set_complete *set_complete;
848 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
849 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
850 if (request == NULL) {
855 /* Set up the rndis set */
856 set = &request->request_msg.msg.set_request;
857 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
858 set->info_buffer_length = sizeof(uint32_t);
859 set->info_buffer_offset = sizeof(rndis_set_request);
861 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
862 &new_filter, sizeof(uint32_t));
864 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
870 * Wait for the response from the host. Another thread will signal
871 * us when the response has arrived. In the failure case,
872 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
874 ret = sema_timedwait(&request->wait_sema, 5 * hz);
876 /* Response received, check status */
877 set_complete = &request->response_msg.msg.set_complete;
878 status = set_complete->status;
879 if (status != RNDIS_STATUS_SUCCESS) {
880 /* Bad response status, return error */
885 * We cannot deallocate the request since we may still
886 * receive a send completion for it.
892 if (request != NULL) {
893 hv_put_rndis_request(device, request);
900 * RNDIS filter init device
903 hv_rf_init_device(rndis_device *device)
905 rndis_request *request;
906 rndis_initialize_request *init;
907 rndis_initialize_complete *init_complete;
911 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
912 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
918 /* Set up the rndis set */
919 init = &request->request_msg.msg.init_request;
920 init->major_version = RNDIS_MAJOR_VERSION;
921 init->minor_version = RNDIS_MINOR_VERSION;
923 * Per the RNDIS document, this should be set to the max MTU
924 * plus the header size. However, 2048 works fine, so leaving
927 init->max_xfer_size = 2048;
929 device->state = RNDIS_DEV_INITIALIZING;
931 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
933 device->state = RNDIS_DEV_UNINITIALIZED;
937 sema_wait(&request->wait_sema);
939 init_complete = &request->response_msg.msg.init_complete;
940 status = init_complete->status;
941 if (status == RNDIS_STATUS_SUCCESS) {
942 device->state = RNDIS_DEV_INITIALIZED;
945 device->state = RNDIS_DEV_UNINITIALIZED;
951 hv_put_rndis_request(device, request);
957 #define HALT_COMPLETION_WAIT_COUNT 25
960 * RNDIS filter halt device
963 hv_rf_halt_device(rndis_device *device)
965 rndis_request *request;
966 rndis_halt_request *halt;
969 /* Attempt to do a rndis device halt */
970 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
971 RNDIS_MESSAGE_SIZE(rndis_halt_request));
972 if (request == NULL) {
976 /* initialize "poor man's semaphore" */
977 request->halt_complete_flag = 0;
979 /* Set up the rndis set */
980 halt = &request->request_msg.msg.halt_request;
981 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
982 /* Increment to get the new value (call above returns old value) */
983 halt->request_id += 1;
985 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
991 * Wait for halt response from halt callback. We must wait for
992 * the transaction response before freeing the request and other
995 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
996 if (request->halt_complete_flag != 0) {
1005 device->state = RNDIS_DEV_UNINITIALIZED;
1007 hv_put_rndis_request(device, request);
1013 * RNDIS filter open device
1016 hv_rf_open_device(rndis_device *device)
1020 if (device->state != RNDIS_DEV_INITIALIZED) {
1024 if (hv_promisc_mode != 1) {
1025 ret = hv_rf_set_packet_filter(device,
1026 NDIS_PACKET_TYPE_BROADCAST |
1027 NDIS_PACKET_TYPE_ALL_MULTICAST |
1028 NDIS_PACKET_TYPE_DIRECTED);
1030 ret = hv_rf_set_packet_filter(device,
1031 NDIS_PACKET_TYPE_PROMISCUOUS);
1035 device->state = RNDIS_DEV_DATAINITIALIZED;
1042 * RNDIS filter close device
1045 hv_rf_close_device(rndis_device *device)
1049 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1053 ret = hv_rf_set_packet_filter(device, 0);
1055 device->state = RNDIS_DEV_INITIALIZED;
1062 * RNDIS filter on device add
1065 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
1069 netvsc_dev *net_dev;
1070 rndis_device *rndis_dev;
1072 rndis_offload_params offloads;
1073 struct rndis_recv_scale_cap rsscaps;
1074 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1075 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1076 device_t dev = device->device;
1078 rndis_dev = hv_get_rndis_device();
1079 if (rndis_dev == NULL) {
1084 * Let the inner driver handle this first to create the netvsc channel
1085 * NOTE! Once the channel is created, we may get a receive callback
1086 * (hv_rf_on_receive()) before this call is completed.
1087 * Note: Earlier code used a function pointer here.
1089 net_dev = hv_nv_on_device_add(device, additl_info);
1091 hv_put_rndis_device(rndis_dev);
1097 * Initialize the rndis device
1100 net_dev->extension = rndis_dev;
1101 rndis_dev->net_dev = net_dev;
1103 /* Send the rndis initialization message */
1104 ret = hv_rf_init_device(rndis_dev);
1107 * TODO: If rndis init failed, we will need to shut down
1112 /* Get the mac address */
1113 ret = hv_rf_query_device_mac(rndis_dev);
1115 /* TODO: shut down rndis device and the channel */
1118 /* config csum offload and send request to host */
1119 memset(&offloads, 0, sizeof(offloads));
1120 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1121 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1122 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1123 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1124 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1125 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1127 ret = hv_rf_send_offload_request(device, &offloads);
1129 /* TODO: shut down rndis device and the channel */
1131 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1134 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1136 hv_rf_query_device_link_status(rndis_dev);
1138 dev_info->link_state = rndis_dev->link_status;
1140 net_dev->num_channel = 1;
1141 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1144 memset(&rsscaps, 0, rsscaps_size);
1145 ret = hv_rf_query_device(rndis_dev,
1146 RNDIS_OID_GEN_RSS_CAPABILITIES,
1147 &rsscaps, &rsscaps_size);
1148 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1149 device_printf(dev, "hv_rf_query_device failed or "
1150 "rsscaps.num_recv_que < 2 \n");
1153 device_printf(dev, "channel, offered %u, requested %d\n",
1154 rsscaps.num_recv_que, nchan);
1155 if (nchan > rsscaps.num_recv_que)
1156 nchan = rsscaps.num_recv_que;
1157 net_dev->num_channel = nchan;
1159 if (net_dev->num_channel == 1) {
1160 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1164 /* request host to create sub channels */
1165 init_pkt = &net_dev->channel_init_packet;
1166 memset(init_pkt, 0, sizeof(nvsp_msg));
1168 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1169 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1170 NVSP_SUBCHANNE_ALLOCATE;
1171 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1172 net_dev->num_channel - 1;
1174 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1175 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1176 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1177 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1179 device_printf(dev, "Fail to allocate subchannel\n");
1183 sema_wait(&net_dev->channel_init_sema);
1185 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1186 nvsp_status_success) {
1188 device_printf(dev, "sub channel complete error\n");
1192 net_dev->num_channel = 1 +
1193 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1195 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1199 net_dev->num_channel = 1;
1205 * RNDIS filter on device remove
1208 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1210 hn_softc_t *sc = device_get_softc(device->device);
1211 netvsc_dev *net_dev = sc->net_dev;
1212 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1215 /* Halt and release the rndis device */
1216 ret = hv_rf_halt_device(rndis_dev);
1218 hv_put_rndis_device(rndis_dev);
1219 net_dev->extension = NULL;
1221 /* Pass control to inner driver to remove the device */
1222 ret |= hv_nv_on_device_remove(device, destroy_channel);
1228 * RNDIS filter on open
1231 hv_rf_on_open(struct hv_device *device)
1233 hn_softc_t *sc = device_get_softc(device->device);
1234 netvsc_dev *net_dev = sc->net_dev;
1236 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1240 * RNDIS filter on close
1243 hv_rf_on_close(struct hv_device *device)
1245 hn_softc_t *sc = device_get_softc(device->device);
1246 netvsc_dev *net_dev = sc->net_dev;
1248 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1252 * RNDIS filter on send request completion callback
1255 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1256 void *context __unused)
1261 * RNDIS filter on send request (halt only) completion callback
1264 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1267 rndis_request *request = context;
1270 * Notify hv_rf_halt_device() about halt completion.
1271 * The halt code must wait for completion before freeing
1272 * the transaction resources.
1274 request->halt_complete_flag = 1;
1278 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1281 netvsc_channel_rollup(chan);