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 hn_softc *sc,
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;
254 packet->gpa[0].gpa_page =
255 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
256 packet->gpa[0].gpa_len = request->request_msg.msg_len;
257 packet->gpa[0].gpa_ofs =
258 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
260 if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) {
262 packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs;
263 packet->gpa[1].gpa_page =
264 hv_get_phys_addr((char*)&request->request_msg +
265 packet->gpa[0].gpa_len) >> PAGE_SHIFT;
266 packet->gpa[1].gpa_ofs = 0;
267 packet->gpa[1].gpa_len = request->request_msg.msg_len -
268 packet->gpa[0].gpa_len;
271 packet->compl.send.send_completion_context = request; /* packet */
272 if (message_type != REMOTE_NDIS_HALT_MSG) {
273 packet->compl.send.on_send_completion =
274 hv_rf_on_send_request_completion;
276 packet->compl.send.on_send_completion =
277 hv_rf_on_send_request_halt_completion;
279 packet->compl.send.send_completion_tid = (unsigned long)device;
280 if (packet->tot_data_buf_len < net_dev->send_section_size) {
281 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
282 if (send_buf_section_idx !=
283 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
284 char *dest = ((char *)net_dev->send_buf +
285 send_buf_section_idx * net_dev->send_section_size);
287 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
288 packet->send_buf_section_idx = send_buf_section_idx;
289 packet->send_buf_section_size = packet->tot_data_buf_len;
293 /* Failed to allocate chimney send buffer; move on */
295 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
296 packet->send_buf_section_size = 0;
299 ret = hv_nv_on_send(device->net_dev->sc->hn_prichan, packet);
305 * RNDIS filter receive response
308 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
310 rndis_request *request = NULL;
311 rndis_request *next_request;
312 boolean_t found = FALSE;
314 mtx_lock(&device->req_lock);
315 request = STAILQ_FIRST(&device->myrequest_list);
316 while (request != NULL) {
318 * All request/response message contains request_id as the
321 if (request->request_msg.msg.init_request.request_id ==
322 response->msg.init_complete.request_id) {
326 next_request = STAILQ_NEXT(request, mylist_entry);
327 request = next_request;
329 mtx_unlock(&device->req_lock);
332 if (response->msg_len <= sizeof(rndis_msg)) {
333 memcpy(&request->response_msg, response,
336 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
337 /* Does not have a request id field */
338 request->response_msg.msg.reset_complete.status =
339 STATUS_BUFFER_OVERFLOW;
341 request->response_msg.msg.init_complete.status =
342 STATUS_BUFFER_OVERFLOW;
346 sema_post(&request->wait_sema);
351 hv_rf_send_offload_request(struct hn_softc *sc,
352 rndis_offload_params *offloads)
354 rndis_request *request;
355 rndis_set_request *set;
356 rndis_offload_params *offload_req;
357 rndis_set_complete *set_complete;
358 rndis_device *rndis_dev;
359 device_t dev = sc->hn_dev;
360 netvsc_dev *net_dev = sc->net_dev;
361 uint32_t vsp_version = net_dev->nvsp_version;
362 uint32_t extlen = sizeof(rndis_offload_params);
365 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
366 extlen = VERSION_4_OFFLOAD_SIZE;
367 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
368 * UDP checksum offload.
370 offloads->udp_ipv4_csum = 0;
371 offloads->udp_ipv6_csum = 0;
374 rndis_dev = net_dev->extension;
376 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
377 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
381 set = &request->request_msg.msg.set_request;
382 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
383 set->info_buffer_length = extlen;
384 set->info_buffer_offset = sizeof(rndis_set_request);
385 set->device_vc_handle = 0;
387 offload_req = (rndis_offload_params *)((unsigned long)set +
388 set->info_buffer_offset);
389 *offload_req = *offloads;
390 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
391 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
392 offload_req->header.size = extlen;
394 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
396 device_printf(dev, "hv send offload request failed, ret=%d!\n",
401 ret = sema_timedwait(&request->wait_sema, 5 * hz);
403 device_printf(dev, "hv send offload request timeout\n");
407 set_complete = &request->response_msg.msg.set_complete;
408 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
409 device_printf(dev, "hv send offload request succeeded\n");
412 if (set_complete->status == STATUS_NOT_SUPPORTED) {
413 device_printf(dev, "HV Not support offload\n");
416 ret = set_complete->status;
421 hv_put_rndis_request(rndis_dev, request);
427 * RNDIS filter receive indicate status
430 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
432 rndis_indicate_status *indicate = &response->msg.indicate_status;
434 switch(indicate->status) {
435 case RNDIS_STATUS_MEDIA_CONNECT:
436 netvsc_linkstatus_callback(device->net_dev->sc, 1);
438 case RNDIS_STATUS_MEDIA_DISCONNECT:
439 netvsc_linkstatus_callback(device->net_dev->sc, 0);
443 device_printf(device->net_dev->sc->hn_dev,
444 "unknown status %d received\n", indicate->status);
450 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
452 const rndis_per_packet_info *ppi;
455 info->vlan_info = NULL;
456 info->csum_info = NULL;
457 info->hash_info = NULL;
458 info->hash_value = NULL;
460 if (rpkt->per_pkt_info_offset == 0)
463 ppi = (const rndis_per_packet_info *)
464 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
465 len = rpkt->per_pkt_info_length;
469 const void *ppi_dptr;
472 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
474 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
475 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
478 case ieee_8021q_info:
479 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
481 info->vlan_info = ppi_dptr;
482 mask |= HV_RF_RECVINFO_VLAN;
485 case tcpip_chksum_info:
486 if (__predict_false(ppi_dlen <
487 sizeof(rndis_tcp_ip_csum_info)))
489 info->csum_info = ppi_dptr;
490 mask |= HV_RF_RECVINFO_CSUM;
494 if (__predict_false(ppi_dlen <
495 sizeof(struct rndis_hash_value)))
497 info->hash_value = ppi_dptr;
498 mask |= HV_RF_RECVINFO_HASHVAL;
502 if (__predict_false(ppi_dlen <
503 sizeof(struct rndis_hash_info)))
505 info->hash_info = ppi_dptr;
506 mask |= HV_RF_RECVINFO_HASHINF;
513 if (mask == HV_RF_RECVINFO_ALL) {
514 /* All found; done */
518 if (__predict_false(len < ppi->size))
521 ppi = (const rndis_per_packet_info *)
522 ((const uint8_t *)ppi + ppi->size);
528 * RNDIS filter receive data
531 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
532 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
534 rndis_packet *rndis_pkt;
535 uint32_t data_offset;
536 device_t dev = device->net_dev->sc->hn_dev;
537 struct hv_rf_recvinfo info;
539 rndis_pkt = &message->msg.packet;
542 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
543 * netvsc packet (ie tot_data_buf_len != message_length)
546 /* Remove rndis header, then pass data packet up the stack */
547 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
549 pkt->tot_data_buf_len -= data_offset;
550 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
551 pkt->status = nvsp_status_failure;
553 "total length %u is less than data length %u\n",
554 pkt->tot_data_buf_len, rndis_pkt->data_length);
558 pkt->tot_data_buf_len = rndis_pkt->data_length;
559 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
561 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
562 pkt->status = nvsp_status_failure;
563 device_printf(dev, "recvinfo parsing failed\n");
567 if (info.vlan_info != NULL)
568 pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
572 netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value);
576 * RNDIS filter on receive
579 hv_rf_on_receive(netvsc_dev *net_dev,
580 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
582 rndis_device *rndis_dev;
583 rndis_msg *rndis_hdr;
585 /* Make sure the rndis device state is initialized */
586 if (net_dev->extension == NULL) {
587 pkt->status = nvsp_status_failure;
591 rndis_dev = (rndis_device *)net_dev->extension;
592 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
593 pkt->status = nvsp_status_failure;
597 rndis_hdr = pkt->data;
599 switch (rndis_hdr->ndis_msg_type) {
602 case REMOTE_NDIS_PACKET_MSG:
603 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
605 /* completion messages */
606 case REMOTE_NDIS_INITIALIZE_CMPLT:
607 case REMOTE_NDIS_QUERY_CMPLT:
608 case REMOTE_NDIS_SET_CMPLT:
609 case REMOTE_NDIS_RESET_CMPLT:
610 case REMOTE_NDIS_KEEPALIVE_CMPLT:
611 hv_rf_receive_response(rndis_dev, rndis_hdr);
613 /* notification message */
614 case REMOTE_NDIS_INDICATE_STATUS_MSG:
615 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
618 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
619 rndis_hdr->ndis_msg_type);
627 * RNDIS filter query device
630 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
631 uint32_t *result_size)
633 rndis_request *request;
634 uint32_t in_result_size = *result_size;
635 rndis_query_request *query;
636 rndis_query_complete *query_complete;
640 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
641 RNDIS_MESSAGE_SIZE(rndis_query_request));
642 if (request == NULL) {
647 /* Set up the rndis query */
648 query = &request->request_msg.msg.query_request;
650 query->info_buffer_offset = sizeof(rndis_query_request);
651 query->info_buffer_length = 0;
652 query->device_vc_handle = 0;
654 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
655 struct rndis_recv_scale_cap *cap;
657 request->request_msg.msg_len +=
658 sizeof(struct rndis_recv_scale_cap);
659 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
660 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
661 query->info_buffer_offset);
662 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
663 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
664 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
667 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
669 /* Fixme: printf added */
670 printf("RNDISFILTER request failed to Send!\n");
674 sema_wait(&request->wait_sema);
676 /* Copy the response back */
677 query_complete = &request->response_msg.msg.query_complete;
679 if (query_complete->info_buffer_length > in_result_size) {
684 memcpy(result, (void *)((unsigned long)query_complete +
685 query_complete->info_buffer_offset),
686 query_complete->info_buffer_length);
688 *result_size = query_complete->info_buffer_length;
692 hv_put_rndis_request(device, request);
698 * RNDIS filter query device MAC address
701 hv_rf_query_device_mac(rndis_device *device)
703 uint32_t size = HW_MACADDR_LEN;
705 return (hv_rf_query_device(device,
706 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
710 * RNDIS filter query device link status
713 hv_rf_query_device_link_status(rndis_device *device)
715 uint32_t size = sizeof(uint32_t);
717 return (hv_rf_query_device(device,
718 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
721 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
722 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
723 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
724 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
725 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
726 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
730 * RNDIS set vRSS parameters
733 hv_rf_set_rss_param(rndis_device *device, int num_queue)
735 rndis_request *request;
736 rndis_set_request *set;
737 rndis_set_complete *set_complete;
738 rndis_recv_scale_param *rssp;
739 uint32_t extlen = sizeof(rndis_recv_scale_param) +
740 (4 * ITAB_NUM) + HASH_KEYLEN;
741 uint32_t *itab, status;
746 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
747 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
748 if (request == NULL) {
750 printf("Netvsc: No memory to set vRSS parameters.\n");
755 set = &request->request_msg.msg.set_request;
756 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
757 set->info_buffer_length = extlen;
758 set->info_buffer_offset = sizeof(rndis_set_request);
759 set->device_vc_handle = 0;
761 /* Fill out the rssp parameter structure */
762 rssp = (rndis_recv_scale_param *)(set + 1);
763 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
764 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
765 rssp->hdr.size = sizeof(rndis_recv_scale_param);
767 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
768 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
769 rssp->indirect_tabsize = 4 * ITAB_NUM;
770 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
771 rssp->hashkey_size = HASH_KEYLEN;
772 rssp->hashkey_offset = rssp->indirect_taboffset +
773 rssp->indirect_tabsize;
775 /* Set indirection table entries */
776 itab = (uint32_t *)(rssp + 1);
777 for (i = 0; i < ITAB_NUM; i++)
778 itab[i] = i % num_queue;
780 /* Set hash key values */
781 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
782 for (i = 0; i < HASH_KEYLEN; i++)
783 keyp[i] = netvsc_hash_key[i];
785 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
791 * Wait for the response from the host. Another thread will signal
792 * us when the response has arrived. In the failure case,
793 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
795 ret = sema_timedwait(&request->wait_sema, 5 * hz);
797 /* Response received, check status */
798 set_complete = &request->response_msg.msg.set_complete;
799 status = set_complete->status;
800 if (status != RNDIS_STATUS_SUCCESS) {
801 /* Bad response status, return error */
803 printf("Netvsc: Failed to set vRSS "
808 printf("Netvsc: Successfully set vRSS "
813 * We cannot deallocate the request since we may still
814 * receive a send completion for it.
816 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
817 request->request_msg.msg.init_request.request_id, ret);
822 if (request != NULL) {
823 hv_put_rndis_request(device, request);
830 * RNDIS filter set packet filter
831 * Sends an rndis request with the new filter, then waits for a response
833 * Returns zero on success, non-zero on failure.
836 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
838 rndis_request *request;
839 rndis_set_request *set;
840 rndis_set_complete *set_complete;
844 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
845 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
846 if (request == NULL) {
851 /* Set up the rndis set */
852 set = &request->request_msg.msg.set_request;
853 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
854 set->info_buffer_length = sizeof(uint32_t);
855 set->info_buffer_offset = sizeof(rndis_set_request);
857 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
858 &new_filter, sizeof(uint32_t));
860 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
866 * Wait for the response from the host. Another thread will signal
867 * us when the response has arrived. In the failure case,
868 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
870 ret = sema_timedwait(&request->wait_sema, 5 * hz);
872 /* Response received, check status */
873 set_complete = &request->response_msg.msg.set_complete;
874 status = set_complete->status;
875 if (status != RNDIS_STATUS_SUCCESS) {
876 /* Bad response status, return error */
881 * We cannot deallocate the request since we may still
882 * receive a send completion for it.
888 if (request != NULL) {
889 hv_put_rndis_request(device, request);
896 * RNDIS filter init device
899 hv_rf_init_device(rndis_device *device)
901 rndis_request *request;
902 rndis_initialize_request *init;
903 rndis_initialize_complete *init_complete;
907 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
908 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
914 /* Set up the rndis set */
915 init = &request->request_msg.msg.init_request;
916 init->major_version = RNDIS_MAJOR_VERSION;
917 init->minor_version = RNDIS_MINOR_VERSION;
919 * Per the RNDIS document, this should be set to the max MTU
920 * plus the header size. However, 2048 works fine, so leaving
923 init->max_xfer_size = 2048;
925 device->state = RNDIS_DEV_INITIALIZING;
927 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
929 device->state = RNDIS_DEV_UNINITIALIZED;
933 sema_wait(&request->wait_sema);
935 init_complete = &request->response_msg.msg.init_complete;
936 status = init_complete->status;
937 if (status == RNDIS_STATUS_SUCCESS) {
938 device->state = RNDIS_DEV_INITIALIZED;
941 device->state = RNDIS_DEV_UNINITIALIZED;
947 hv_put_rndis_request(device, request);
953 #define HALT_COMPLETION_WAIT_COUNT 25
956 * RNDIS filter halt device
959 hv_rf_halt_device(rndis_device *device)
961 rndis_request *request;
962 rndis_halt_request *halt;
965 /* Attempt to do a rndis device halt */
966 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
967 RNDIS_MESSAGE_SIZE(rndis_halt_request));
968 if (request == NULL) {
972 /* initialize "poor man's semaphore" */
973 request->halt_complete_flag = 0;
975 /* Set up the rndis set */
976 halt = &request->request_msg.msg.halt_request;
977 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
978 /* Increment to get the new value (call above returns old value) */
979 halt->request_id += 1;
981 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
987 * Wait for halt response from halt callback. We must wait for
988 * the transaction response before freeing the request and other
991 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
992 if (request->halt_complete_flag != 0) {
1001 device->state = RNDIS_DEV_UNINITIALIZED;
1003 hv_put_rndis_request(device, request);
1009 * RNDIS filter open device
1012 hv_rf_open_device(rndis_device *device)
1016 if (device->state != RNDIS_DEV_INITIALIZED) {
1020 if (hv_promisc_mode != 1) {
1021 ret = hv_rf_set_packet_filter(device,
1022 NDIS_PACKET_TYPE_BROADCAST |
1023 NDIS_PACKET_TYPE_ALL_MULTICAST |
1024 NDIS_PACKET_TYPE_DIRECTED);
1026 ret = hv_rf_set_packet_filter(device,
1027 NDIS_PACKET_TYPE_PROMISCUOUS);
1031 device->state = RNDIS_DEV_DATAINITIALIZED;
1038 * RNDIS filter close device
1041 hv_rf_close_device(rndis_device *device)
1045 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1049 ret = hv_rf_set_packet_filter(device, 0);
1051 device->state = RNDIS_DEV_INITIALIZED;
1058 * RNDIS filter on device add
1061 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1065 netvsc_dev *net_dev;
1066 rndis_device *rndis_dev;
1068 rndis_offload_params offloads;
1069 struct rndis_recv_scale_cap rsscaps;
1070 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1071 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1072 device_t dev = sc->hn_dev;
1074 rndis_dev = hv_get_rndis_device();
1075 if (rndis_dev == NULL) {
1080 * Let the inner driver handle this first to create the netvsc channel
1081 * NOTE! Once the channel is created, we may get a receive callback
1082 * (hv_rf_on_receive()) before this call is completed.
1083 * Note: Earlier code used a function pointer here.
1085 net_dev = hv_nv_on_device_add(sc, additl_info);
1087 hv_put_rndis_device(rndis_dev);
1093 * Initialize the rndis device
1096 net_dev->extension = rndis_dev;
1097 rndis_dev->net_dev = net_dev;
1099 /* Send the rndis initialization message */
1100 ret = hv_rf_init_device(rndis_dev);
1103 * TODO: If rndis init failed, we will need to shut down
1108 /* Get the mac address */
1109 ret = hv_rf_query_device_mac(rndis_dev);
1111 /* TODO: shut down rndis device and the channel */
1114 /* config csum offload and send request to host */
1115 memset(&offloads, 0, sizeof(offloads));
1116 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1117 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1118 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1119 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1120 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1121 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1123 ret = hv_rf_send_offload_request(sc, &offloads);
1125 /* TODO: shut down rndis device and the channel */
1127 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1130 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1132 hv_rf_query_device_link_status(rndis_dev);
1134 dev_info->link_state = rndis_dev->link_status;
1136 net_dev->num_channel = 1;
1137 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1140 memset(&rsscaps, 0, rsscaps_size);
1141 ret = hv_rf_query_device(rndis_dev,
1142 RNDIS_OID_GEN_RSS_CAPABILITIES,
1143 &rsscaps, &rsscaps_size);
1144 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1145 device_printf(dev, "hv_rf_query_device failed or "
1146 "rsscaps.num_recv_que < 2 \n");
1149 device_printf(dev, "channel, offered %u, requested %d\n",
1150 rsscaps.num_recv_que, nchan);
1151 if (nchan > rsscaps.num_recv_que)
1152 nchan = rsscaps.num_recv_que;
1153 net_dev->num_channel = nchan;
1155 if (net_dev->num_channel == 1) {
1156 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1160 /* request host to create sub channels */
1161 init_pkt = &net_dev->channel_init_packet;
1162 memset(init_pkt, 0, sizeof(nvsp_msg));
1164 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1165 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1166 NVSP_SUBCHANNE_ALLOCATE;
1167 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1168 net_dev->num_channel - 1;
1170 ret = vmbus_chan_send(sc->hn_prichan,
1171 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
1172 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt);
1174 device_printf(dev, "Fail to allocate subchannel\n");
1178 sema_wait(&net_dev->channel_init_sema);
1180 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1181 nvsp_status_success) {
1183 device_printf(dev, "sub channel complete error\n");
1187 net_dev->num_channel = 1 +
1188 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1190 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1194 net_dev->num_channel = 1;
1200 * RNDIS filter on device remove
1203 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1205 netvsc_dev *net_dev = sc->net_dev;
1206 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1209 /* Halt and release the rndis device */
1210 ret = hv_rf_halt_device(rndis_dev);
1212 hv_put_rndis_device(rndis_dev);
1213 net_dev->extension = NULL;
1215 /* Pass control to inner driver to remove the device */
1216 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1222 * RNDIS filter on open
1225 hv_rf_on_open(struct hn_softc *sc)
1227 netvsc_dev *net_dev = sc->net_dev;
1229 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1233 * RNDIS filter on close
1236 hv_rf_on_close(struct hn_softc *sc)
1238 netvsc_dev *net_dev = sc->net_dev;
1240 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1244 * RNDIS filter on send request completion callback
1247 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1248 void *context __unused)
1253 * RNDIS filter on send request (halt only) completion callback
1256 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1259 rndis_request *request = context;
1262 * Notify hv_rf_halt_device() about halt completion.
1263 * The halt code must wait for completion before freeing
1264 * the transaction resources.
1266 request->halt_complete_flag = 1;
1270 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1273 netvsc_channel_rollup(chan);