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"
52 struct hv_rf_recvinfo {
53 const ndis_8021q_info *vlan_info;
54 const rndis_tcp_ip_csum_info *csum_info;
55 const struct rndis_hash_info *hash_info;
56 const struct rndis_hash_value *hash_value;
59 #define HV_RF_RECVINFO_VLAN 0x1
60 #define HV_RF_RECVINFO_CSUM 0x2
61 #define HV_RF_RECVINFO_HASHINF 0x4
62 #define HV_RF_RECVINFO_HASHVAL 0x8
63 #define HV_RF_RECVINFO_ALL \
64 (HV_RF_RECVINFO_VLAN | \
65 HV_RF_RECVINFO_CSUM | \
66 HV_RF_RECVINFO_HASHINF | \
67 HV_RF_RECVINFO_HASHVAL)
70 * Forward declarations
72 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
73 uint32_t message_type);
74 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
75 static void hv_rf_receive_indicate_status(rndis_device *device,
77 static void hv_rf_receive_data(rndis_device *device, rndis_msg *message,
78 struct hv_vmbus_channel *chan,
80 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
81 void *result, uint32_t *result_size);
82 static inline int hv_rf_query_device_mac(rndis_device *device);
83 static inline int hv_rf_query_device_link_status(rndis_device *device);
84 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
85 static int hv_rf_init_device(rndis_device *device);
86 static int hv_rf_open_device(rndis_device *device);
87 static int hv_rf_close_device(rndis_device *device);
88 static void hv_rf_on_send_request_completion(struct hv_vmbus_channel *, void *context);
89 static void hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *, void *context);
91 hv_rf_send_offload_request(struct hn_softc *sc,
92 rndis_offload_params *offloads);
94 * Set the Per-Packet-Info with the specified type
97 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
100 rndis_packet *rndis_pkt;
101 rndis_per_packet_info *rppi;
103 rndis_pkt = &rndis_mesg->msg.packet;
104 rndis_pkt->data_offset += rppi_size;
106 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
107 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
109 rppi->size = rppi_size;
110 rppi->type = pkt_type;
111 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
113 rndis_pkt->per_pkt_info_length += rppi_size;
119 * Get the Per-Packet-Info with the specified type
120 * return NULL if not found.
123 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
125 rndis_per_packet_info *ppi;
128 if (rpkt->per_pkt_info_offset == 0)
131 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
132 rpkt->per_pkt_info_offset);
133 len = rpkt->per_pkt_info_length;
136 if (ppi->type == type)
137 return (void *)((unsigned long)ppi +
138 ppi->per_packet_info_offset);
141 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
149 * Allow module_param to work and override to switch to promiscuous mode.
151 static inline rndis_device *
152 hv_get_rndis_device(void)
154 rndis_device *device;
156 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
158 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
160 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
161 STAILQ_INIT(&device->myrequest_list);
163 device->state = RNDIS_DEV_UNINITIALIZED;
172 hv_put_rndis_device(rndis_device *device)
174 mtx_destroy(&device->req_lock);
175 free(device, M_NETVSC);
181 static inline rndis_request *
182 hv_rndis_request(rndis_device *device, uint32_t message_type,
183 uint32_t message_length)
185 rndis_request *request;
186 rndis_msg *rndis_mesg;
187 rndis_set_request *set;
189 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
191 sema_init(&request->wait_sema, 0, "rndis sema");
193 rndis_mesg = &request->request_msg;
194 rndis_mesg->ndis_msg_type = message_type;
195 rndis_mesg->msg_len = message_length;
198 * Set the request id. This field is always after the rndis header
199 * for request/response packet types so we just use the set_request
202 set = &rndis_mesg->msg.set_request;
203 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
204 /* Increment to get the new value (call above returns old value) */
205 set->request_id += 1;
207 /* Add to the request list */
208 mtx_lock(&device->req_lock);
209 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
210 mtx_unlock(&device->req_lock);
219 hv_put_rndis_request(rndis_device *device, rndis_request *request)
221 mtx_lock(&device->req_lock);
222 /* Fixme: Has O(n) performance */
224 * XXXKYS: Use Doubly linked lists.
226 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
228 mtx_unlock(&device->req_lock);
230 sema_destroy(&request->wait_sema);
231 free(request, M_NETVSC);
238 hv_rf_send_request(rndis_device *device, rndis_request *request,
239 uint32_t message_type)
242 netvsc_packet *packet;
243 netvsc_dev *net_dev = device->net_dev;
244 int send_buf_section_idx;
246 /* Set up the packet to send it */
247 packet = &request->pkt;
249 packet->is_data_pkt = FALSE;
250 packet->tot_data_buf_len = request->request_msg.msg_len;
253 packet->gpa[0].gpa_page =
254 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
255 packet->gpa[0].gpa_len = request->request_msg.msg_len;
256 packet->gpa[0].gpa_ofs =
257 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
259 if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) {
261 packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs;
262 packet->gpa[1].gpa_page =
263 hv_get_phys_addr((char*)&request->request_msg +
264 packet->gpa[0].gpa_len) >> PAGE_SHIFT;
265 packet->gpa[1].gpa_ofs = 0;
266 packet->gpa[1].gpa_len = request->request_msg.msg_len -
267 packet->gpa[0].gpa_len;
270 packet->compl.send.send_completion_context = request; /* packet */
271 if (message_type != REMOTE_NDIS_HALT_MSG) {
272 packet->compl.send.on_send_completion =
273 hv_rf_on_send_request_completion;
275 packet->compl.send.on_send_completion =
276 hv_rf_on_send_request_halt_completion;
278 packet->compl.send.send_completion_tid = (unsigned long)device;
279 if (packet->tot_data_buf_len < net_dev->send_section_size) {
280 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
281 if (send_buf_section_idx !=
282 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
283 char *dest = ((char *)net_dev->send_buf +
284 send_buf_section_idx * net_dev->send_section_size);
286 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
287 packet->send_buf_section_idx = send_buf_section_idx;
288 packet->send_buf_section_size = packet->tot_data_buf_len;
292 /* Failed to allocate chimney send buffer; move on */
294 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
295 packet->send_buf_section_size = 0;
298 ret = hv_nv_on_send(device->net_dev->sc->hn_prichan, packet);
304 * RNDIS filter receive response
307 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
309 rndis_request *request = NULL;
310 rndis_request *next_request;
311 boolean_t found = FALSE;
313 mtx_lock(&device->req_lock);
314 request = STAILQ_FIRST(&device->myrequest_list);
315 while (request != NULL) {
317 * All request/response message contains request_id as the
320 if (request->request_msg.msg.init_request.request_id ==
321 response->msg.init_complete.request_id) {
325 next_request = STAILQ_NEXT(request, mylist_entry);
326 request = next_request;
328 mtx_unlock(&device->req_lock);
331 if (response->msg_len <= sizeof(rndis_msg)) {
332 memcpy(&request->response_msg, response,
335 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
336 /* Does not have a request id field */
337 request->response_msg.msg.reset_complete.status =
338 STATUS_BUFFER_OVERFLOW;
340 request->response_msg.msg.init_complete.status =
341 STATUS_BUFFER_OVERFLOW;
345 sema_post(&request->wait_sema);
350 hv_rf_send_offload_request(struct hn_softc *sc,
351 rndis_offload_params *offloads)
353 rndis_request *request;
354 rndis_set_request *set;
355 rndis_offload_params *offload_req;
356 rndis_set_complete *set_complete;
357 rndis_device *rndis_dev;
358 device_t dev = sc->hn_dev;
359 netvsc_dev *net_dev = sc->net_dev;
360 uint32_t vsp_version = net_dev->nvsp_version;
361 uint32_t extlen = sizeof(rndis_offload_params);
364 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
365 extlen = VERSION_4_OFFLOAD_SIZE;
366 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
367 * UDP checksum offload.
369 offloads->udp_ipv4_csum = 0;
370 offloads->udp_ipv6_csum = 0;
373 rndis_dev = net_dev->extension;
375 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
376 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
380 set = &request->request_msg.msg.set_request;
381 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
382 set->info_buffer_length = extlen;
383 set->info_buffer_offset = sizeof(rndis_set_request);
384 set->device_vc_handle = 0;
386 offload_req = (rndis_offload_params *)((unsigned long)set +
387 set->info_buffer_offset);
388 *offload_req = *offloads;
389 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
390 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
391 offload_req->header.size = extlen;
393 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
395 device_printf(dev, "hv send offload request failed, ret=%d!\n",
400 ret = sema_timedwait(&request->wait_sema, 5 * hz);
402 device_printf(dev, "hv send offload request timeout\n");
406 set_complete = &request->response_msg.msg.set_complete;
407 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
408 device_printf(dev, "hv send offload request succeeded\n");
411 if (set_complete->status == STATUS_NOT_SUPPORTED) {
412 device_printf(dev, "HV Not support offload\n");
415 ret = set_complete->status;
420 hv_put_rndis_request(rndis_dev, request);
426 * RNDIS filter receive indicate status
429 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
431 rndis_indicate_status *indicate = &response->msg.indicate_status;
433 switch(indicate->status) {
434 case RNDIS_STATUS_MEDIA_CONNECT:
435 netvsc_linkstatus_callback(device->net_dev->sc, 1);
437 case RNDIS_STATUS_MEDIA_DISCONNECT:
438 netvsc_linkstatus_callback(device->net_dev->sc, 0);
442 device_printf(device->net_dev->sc->hn_dev,
443 "unknown status %d received\n", indicate->status);
449 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
451 const rndis_per_packet_info *ppi;
454 info->vlan_info = NULL;
455 info->csum_info = NULL;
456 info->hash_info = NULL;
457 info->hash_value = NULL;
459 if (rpkt->per_pkt_info_offset == 0)
462 ppi = (const rndis_per_packet_info *)
463 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
464 len = rpkt->per_pkt_info_length;
468 const void *ppi_dptr;
471 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
473 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
474 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
477 case ieee_8021q_info:
478 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
480 info->vlan_info = ppi_dptr;
481 mask |= HV_RF_RECVINFO_VLAN;
484 case tcpip_chksum_info:
485 if (__predict_false(ppi_dlen <
486 sizeof(rndis_tcp_ip_csum_info)))
488 info->csum_info = ppi_dptr;
489 mask |= HV_RF_RECVINFO_CSUM;
493 if (__predict_false(ppi_dlen <
494 sizeof(struct rndis_hash_value)))
496 info->hash_value = ppi_dptr;
497 mask |= HV_RF_RECVINFO_HASHVAL;
501 if (__predict_false(ppi_dlen <
502 sizeof(struct rndis_hash_info)))
504 info->hash_info = ppi_dptr;
505 mask |= HV_RF_RECVINFO_HASHINF;
512 if (mask == HV_RF_RECVINFO_ALL) {
513 /* All found; done */
517 if (__predict_false(len < ppi->size))
520 ppi = (const rndis_per_packet_info *)
521 ((const uint8_t *)ppi + ppi->size);
527 * RNDIS filter receive data
530 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
531 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
533 rndis_packet *rndis_pkt;
534 uint32_t data_offset;
535 device_t dev = device->net_dev->sc->hn_dev;
536 struct hv_rf_recvinfo info;
538 rndis_pkt = &message->msg.packet;
541 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
542 * netvsc packet (ie tot_data_buf_len != message_length)
545 /* Remove rndis header, then pass data packet up the stack */
546 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
548 pkt->tot_data_buf_len -= data_offset;
549 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
550 pkt->status = nvsp_status_failure;
552 "total length %u is less than data length %u\n",
553 pkt->tot_data_buf_len, rndis_pkt->data_length);
557 pkt->tot_data_buf_len = rndis_pkt->data_length;
558 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
560 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
561 pkt->status = nvsp_status_failure;
562 device_printf(dev, "recvinfo parsing failed\n");
566 if (info.vlan_info != NULL)
567 pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
571 netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value);
575 * RNDIS filter on receive
578 hv_rf_on_receive(netvsc_dev *net_dev,
579 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
581 rndis_device *rndis_dev;
582 rndis_msg *rndis_hdr;
584 /* Make sure the rndis device state is initialized */
585 if (net_dev->extension == NULL) {
586 pkt->status = nvsp_status_failure;
590 rndis_dev = (rndis_device *)net_dev->extension;
591 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
592 pkt->status = nvsp_status_failure;
596 rndis_hdr = pkt->data;
598 switch (rndis_hdr->ndis_msg_type) {
601 case REMOTE_NDIS_PACKET_MSG:
602 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
604 /* completion messages */
605 case REMOTE_NDIS_INITIALIZE_CMPLT:
606 case REMOTE_NDIS_QUERY_CMPLT:
607 case REMOTE_NDIS_SET_CMPLT:
608 case REMOTE_NDIS_RESET_CMPLT:
609 case REMOTE_NDIS_KEEPALIVE_CMPLT:
610 hv_rf_receive_response(rndis_dev, rndis_hdr);
612 /* notification message */
613 case REMOTE_NDIS_INDICATE_STATUS_MSG:
614 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
617 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
618 rndis_hdr->ndis_msg_type);
626 * RNDIS filter query device
629 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
630 uint32_t *result_size)
632 rndis_request *request;
633 uint32_t in_result_size = *result_size;
634 rndis_query_request *query;
635 rndis_query_complete *query_complete;
639 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
640 RNDIS_MESSAGE_SIZE(rndis_query_request));
641 if (request == NULL) {
646 /* Set up the rndis query */
647 query = &request->request_msg.msg.query_request;
649 query->info_buffer_offset = sizeof(rndis_query_request);
650 query->info_buffer_length = 0;
651 query->device_vc_handle = 0;
653 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
654 struct rndis_recv_scale_cap *cap;
656 request->request_msg.msg_len +=
657 sizeof(struct rndis_recv_scale_cap);
658 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
659 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
660 query->info_buffer_offset);
661 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
662 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
663 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
666 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
668 /* Fixme: printf added */
669 printf("RNDISFILTER request failed to Send!\n");
673 sema_wait(&request->wait_sema);
675 /* Copy the response back */
676 query_complete = &request->response_msg.msg.query_complete;
678 if (query_complete->info_buffer_length > in_result_size) {
683 memcpy(result, (void *)((unsigned long)query_complete +
684 query_complete->info_buffer_offset),
685 query_complete->info_buffer_length);
687 *result_size = query_complete->info_buffer_length;
691 hv_put_rndis_request(device, request);
697 * RNDIS filter query device MAC address
700 hv_rf_query_device_mac(rndis_device *device)
702 uint32_t size = HW_MACADDR_LEN;
704 return (hv_rf_query_device(device,
705 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
709 * RNDIS filter query device link status
712 hv_rf_query_device_link_status(rndis_device *device)
714 uint32_t size = sizeof(uint32_t);
716 return (hv_rf_query_device(device,
717 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
720 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
721 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
722 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
723 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
724 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
725 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
729 * RNDIS set vRSS parameters
732 hv_rf_set_rss_param(rndis_device *device, int num_queue)
734 rndis_request *request;
735 rndis_set_request *set;
736 rndis_set_complete *set_complete;
737 rndis_recv_scale_param *rssp;
738 uint32_t extlen = sizeof(rndis_recv_scale_param) +
739 (4 * ITAB_NUM) + HASH_KEYLEN;
740 uint32_t *itab, status;
745 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
746 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
747 if (request == NULL) {
749 printf("Netvsc: No memory to set vRSS parameters.\n");
754 set = &request->request_msg.msg.set_request;
755 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
756 set->info_buffer_length = extlen;
757 set->info_buffer_offset = sizeof(rndis_set_request);
758 set->device_vc_handle = 0;
760 /* Fill out the rssp parameter structure */
761 rssp = (rndis_recv_scale_param *)(set + 1);
762 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
763 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
764 rssp->hdr.size = sizeof(rndis_recv_scale_param);
766 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
767 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
768 rssp->indirect_tabsize = 4 * ITAB_NUM;
769 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
770 rssp->hashkey_size = HASH_KEYLEN;
771 rssp->hashkey_offset = rssp->indirect_taboffset +
772 rssp->indirect_tabsize;
774 /* Set indirection table entries */
775 itab = (uint32_t *)(rssp + 1);
776 for (i = 0; i < ITAB_NUM; i++)
777 itab[i] = i % num_queue;
779 /* Set hash key values */
780 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
781 for (i = 0; i < HASH_KEYLEN; i++)
782 keyp[i] = netvsc_hash_key[i];
784 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
790 * Wait for the response from the host. Another thread will signal
791 * us when the response has arrived. In the failure case,
792 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
794 ret = sema_timedwait(&request->wait_sema, 5 * hz);
796 /* Response received, check status */
797 set_complete = &request->response_msg.msg.set_complete;
798 status = set_complete->status;
799 if (status != RNDIS_STATUS_SUCCESS) {
800 /* Bad response status, return error */
802 printf("Netvsc: Failed to set vRSS "
807 printf("Netvsc: Successfully set vRSS "
812 * We cannot deallocate the request since we may still
813 * receive a send completion for it.
815 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
816 request->request_msg.msg.init_request.request_id, ret);
821 if (request != NULL) {
822 hv_put_rndis_request(device, request);
829 * RNDIS filter set packet filter
830 * Sends an rndis request with the new filter, then waits for a response
832 * Returns zero on success, non-zero on failure.
835 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
837 rndis_request *request;
838 rndis_set_request *set;
839 rndis_set_complete *set_complete;
843 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
844 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
845 if (request == NULL) {
850 /* Set up the rndis set */
851 set = &request->request_msg.msg.set_request;
852 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
853 set->info_buffer_length = sizeof(uint32_t);
854 set->info_buffer_offset = sizeof(rndis_set_request);
856 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
857 &new_filter, sizeof(uint32_t));
859 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
865 * Wait for the response from the host. Another thread will signal
866 * us when the response has arrived. In the failure case,
867 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
869 ret = sema_timedwait(&request->wait_sema, 5 * hz);
871 /* Response received, check status */
872 set_complete = &request->response_msg.msg.set_complete;
873 status = set_complete->status;
874 if (status != RNDIS_STATUS_SUCCESS) {
875 /* Bad response status, return error */
880 * We cannot deallocate the request since we may still
881 * receive a send completion for it.
887 if (request != NULL) {
888 hv_put_rndis_request(device, request);
895 * RNDIS filter init device
898 hv_rf_init_device(rndis_device *device)
900 rndis_request *request;
901 rndis_initialize_request *init;
902 rndis_initialize_complete *init_complete;
906 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
907 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
913 /* Set up the rndis set */
914 init = &request->request_msg.msg.init_request;
915 init->major_version = RNDIS_MAJOR_VERSION;
916 init->minor_version = RNDIS_MINOR_VERSION;
918 * Per the RNDIS document, this should be set to the max MTU
919 * plus the header size. However, 2048 works fine, so leaving
922 init->max_xfer_size = 2048;
924 device->state = RNDIS_DEV_INITIALIZING;
926 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
928 device->state = RNDIS_DEV_UNINITIALIZED;
932 sema_wait(&request->wait_sema);
934 init_complete = &request->response_msg.msg.init_complete;
935 status = init_complete->status;
936 if (status == RNDIS_STATUS_SUCCESS) {
937 device->state = RNDIS_DEV_INITIALIZED;
940 device->state = RNDIS_DEV_UNINITIALIZED;
946 hv_put_rndis_request(device, request);
952 #define HALT_COMPLETION_WAIT_COUNT 25
955 * RNDIS filter halt device
958 hv_rf_halt_device(rndis_device *device)
960 rndis_request *request;
961 rndis_halt_request *halt;
964 /* Attempt to do a rndis device halt */
965 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
966 RNDIS_MESSAGE_SIZE(rndis_halt_request));
967 if (request == NULL) {
971 /* initialize "poor man's semaphore" */
972 request->halt_complete_flag = 0;
974 /* Set up the rndis set */
975 halt = &request->request_msg.msg.halt_request;
976 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
977 /* Increment to get the new value (call above returns old value) */
978 halt->request_id += 1;
980 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
986 * Wait for halt response from halt callback. We must wait for
987 * the transaction response before freeing the request and other
990 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
991 if (request->halt_complete_flag != 0) {
1000 device->state = RNDIS_DEV_UNINITIALIZED;
1002 hv_put_rndis_request(device, request);
1008 * RNDIS filter open device
1011 hv_rf_open_device(rndis_device *device)
1015 if (device->state != RNDIS_DEV_INITIALIZED) {
1019 if (hv_promisc_mode != 1) {
1020 ret = hv_rf_set_packet_filter(device,
1021 NDIS_PACKET_TYPE_BROADCAST |
1022 NDIS_PACKET_TYPE_ALL_MULTICAST |
1023 NDIS_PACKET_TYPE_DIRECTED);
1025 ret = hv_rf_set_packet_filter(device,
1026 NDIS_PACKET_TYPE_PROMISCUOUS);
1030 device->state = RNDIS_DEV_DATAINITIALIZED;
1037 * RNDIS filter close device
1040 hv_rf_close_device(rndis_device *device)
1044 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1048 ret = hv_rf_set_packet_filter(device, 0);
1050 device->state = RNDIS_DEV_INITIALIZED;
1057 * RNDIS filter on device add
1060 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1064 netvsc_dev *net_dev;
1065 rndis_device *rndis_dev;
1067 rndis_offload_params offloads;
1068 struct rndis_recv_scale_cap rsscaps;
1069 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1070 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1071 device_t dev = sc->hn_dev;
1073 rndis_dev = hv_get_rndis_device();
1074 if (rndis_dev == NULL) {
1079 * Let the inner driver handle this first to create the netvsc channel
1080 * NOTE! Once the channel is created, we may get a receive callback
1081 * (hv_rf_on_receive()) before this call is completed.
1082 * Note: Earlier code used a function pointer here.
1084 net_dev = hv_nv_on_device_add(sc, additl_info);
1086 hv_put_rndis_device(rndis_dev);
1092 * Initialize the rndis device
1095 net_dev->extension = rndis_dev;
1096 rndis_dev->net_dev = net_dev;
1098 /* Send the rndis initialization message */
1099 ret = hv_rf_init_device(rndis_dev);
1102 * TODO: If rndis init failed, we will need to shut down
1107 /* Get the mac address */
1108 ret = hv_rf_query_device_mac(rndis_dev);
1110 /* TODO: shut down rndis device and the channel */
1113 /* config csum offload and send request to host */
1114 memset(&offloads, 0, sizeof(offloads));
1115 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1116 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1117 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1118 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1119 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1120 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1122 ret = hv_rf_send_offload_request(sc, &offloads);
1124 /* TODO: shut down rndis device and the channel */
1126 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1129 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1131 hv_rf_query_device_link_status(rndis_dev);
1133 dev_info->link_state = rndis_dev->link_status;
1135 net_dev->num_channel = 1;
1136 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1139 memset(&rsscaps, 0, rsscaps_size);
1140 ret = hv_rf_query_device(rndis_dev,
1141 RNDIS_OID_GEN_RSS_CAPABILITIES,
1142 &rsscaps, &rsscaps_size);
1143 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1144 device_printf(dev, "hv_rf_query_device failed or "
1145 "rsscaps.num_recv_que < 2 \n");
1148 device_printf(dev, "channel, offered %u, requested %d\n",
1149 rsscaps.num_recv_que, nchan);
1150 if (nchan > rsscaps.num_recv_que)
1151 nchan = rsscaps.num_recv_que;
1152 net_dev->num_channel = nchan;
1154 if (net_dev->num_channel == 1) {
1155 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1159 /* request host to create sub channels */
1160 init_pkt = &net_dev->channel_init_packet;
1161 memset(init_pkt, 0, sizeof(nvsp_msg));
1163 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1164 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1165 NVSP_SUBCHANNE_ALLOCATE;
1166 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1167 net_dev->num_channel - 1;
1169 ret = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
1170 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1171 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
1173 device_printf(dev, "Fail to allocate subchannel\n");
1177 sema_wait(&net_dev->channel_init_sema);
1179 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1180 nvsp_status_success) {
1182 device_printf(dev, "sub channel complete error\n");
1186 net_dev->num_channel = 1 +
1187 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1189 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1193 net_dev->num_channel = 1;
1199 * RNDIS filter on device remove
1202 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1204 netvsc_dev *net_dev = sc->net_dev;
1205 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1208 /* Halt and release the rndis device */
1209 ret = hv_rf_halt_device(rndis_dev);
1211 hv_put_rndis_device(rndis_dev);
1212 net_dev->extension = NULL;
1214 /* Pass control to inner driver to remove the device */
1215 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1221 * RNDIS filter on open
1224 hv_rf_on_open(struct hn_softc *sc)
1226 netvsc_dev *net_dev = sc->net_dev;
1228 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1232 * RNDIS filter on close
1235 hv_rf_on_close(struct hn_softc *sc)
1237 netvsc_dev *net_dev = sc->net_dev;
1239 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1243 * RNDIS filter on send request completion callback
1246 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1247 void *context __unused)
1252 * RNDIS filter on send request (halt only) completion callback
1255 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1258 rndis_request *request = context;
1261 * Notify hv_rf_halt_device() about halt completion.
1262 * The halt code must wait for completion before freeing
1263 * the transaction resources.
1265 request->halt_complete_flag = 1;
1269 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1272 netvsc_channel_rollup(chan);