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 hv_device *device,
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;
251 packet->page_buf_count = 1;
253 packet->page_buffers[0].pfn =
254 hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
255 packet->page_buffers[0].length = request->request_msg.msg_len;
256 packet->page_buffers[0].offset =
257 (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
259 if (packet->page_buffers[0].offset +
260 packet->page_buffers[0].length > PAGE_SIZE) {
261 packet->page_buf_count = 2;
262 packet->page_buffers[0].length =
263 PAGE_SIZE - packet->page_buffers[0].offset;
264 packet->page_buffers[1].pfn =
265 hv_get_phys_addr((char*)&request->request_msg +
266 packet->page_buffers[0].length) >> PAGE_SHIFT;
267 packet->page_buffers[1].offset = 0;
268 packet->page_buffers[1].length =
269 request->request_msg.msg_len -
270 packet->page_buffers[0].length;
273 packet->compl.send.send_completion_context = request; /* packet */
274 if (message_type != REMOTE_NDIS_HALT_MSG) {
275 packet->compl.send.on_send_completion =
276 hv_rf_on_send_request_completion;
278 packet->compl.send.on_send_completion =
279 hv_rf_on_send_request_halt_completion;
281 packet->compl.send.send_completion_tid = (unsigned long)device;
282 if (packet->tot_data_buf_len < net_dev->send_section_size) {
283 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
284 if (send_buf_section_idx !=
285 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
286 char *dest = ((char *)net_dev->send_buf +
287 send_buf_section_idx * net_dev->send_section_size);
289 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
290 packet->send_buf_section_idx = send_buf_section_idx;
291 packet->send_buf_section_size = packet->tot_data_buf_len;
292 packet->page_buf_count = 0;
295 /* Failed to allocate chimney send buffer; move on */
297 packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
298 packet->send_buf_section_size = 0;
301 ret = hv_nv_on_send(device->net_dev->dev->channel, packet);
307 * RNDIS filter receive response
310 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
312 rndis_request *request = NULL;
313 rndis_request *next_request;
314 boolean_t found = FALSE;
316 mtx_lock(&device->req_lock);
317 request = STAILQ_FIRST(&device->myrequest_list);
318 while (request != NULL) {
320 * All request/response message contains request_id as the
323 if (request->request_msg.msg.init_request.request_id ==
324 response->msg.init_complete.request_id) {
328 next_request = STAILQ_NEXT(request, mylist_entry);
329 request = next_request;
331 mtx_unlock(&device->req_lock);
334 if (response->msg_len <= sizeof(rndis_msg)) {
335 memcpy(&request->response_msg, response,
338 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
339 /* Does not have a request id field */
340 request->response_msg.msg.reset_complete.status =
341 STATUS_BUFFER_OVERFLOW;
343 request->response_msg.msg.init_complete.status =
344 STATUS_BUFFER_OVERFLOW;
348 sema_post(&request->wait_sema);
353 hv_rf_send_offload_request(struct hv_device *device,
354 rndis_offload_params *offloads)
356 rndis_request *request;
357 rndis_set_request *set;
358 rndis_offload_params *offload_req;
359 rndis_set_complete *set_complete;
360 rndis_device *rndis_dev;
361 hn_softc_t *sc = device_get_softc(device->device);
362 device_t dev = device->device;
363 netvsc_dev *net_dev = sc->net_dev;
364 uint32_t vsp_version = net_dev->nvsp_version;
365 uint32_t extlen = sizeof(rndis_offload_params);
368 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
369 extlen = VERSION_4_OFFLOAD_SIZE;
370 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
371 * UDP checksum offload.
373 offloads->udp_ipv4_csum = 0;
374 offloads->udp_ipv6_csum = 0;
377 rndis_dev = net_dev->extension;
379 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
380 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
384 set = &request->request_msg.msg.set_request;
385 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
386 set->info_buffer_length = extlen;
387 set->info_buffer_offset = sizeof(rndis_set_request);
388 set->device_vc_handle = 0;
390 offload_req = (rndis_offload_params *)((unsigned long)set +
391 set->info_buffer_offset);
392 *offload_req = *offloads;
393 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
394 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
395 offload_req->header.size = extlen;
397 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
399 device_printf(dev, "hv send offload request failed, ret=%d!\n",
404 ret = sema_timedwait(&request->wait_sema, 5 * hz);
406 device_printf(dev, "hv send offload request timeout\n");
410 set_complete = &request->response_msg.msg.set_complete;
411 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
412 device_printf(dev, "hv send offload request succeeded\n");
415 if (set_complete->status == STATUS_NOT_SUPPORTED) {
416 device_printf(dev, "HV Not support offload\n");
419 ret = set_complete->status;
424 hv_put_rndis_request(rndis_dev, request);
430 * RNDIS filter receive indicate status
433 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
435 rndis_indicate_status *indicate = &response->msg.indicate_status;
437 switch(indicate->status) {
438 case RNDIS_STATUS_MEDIA_CONNECT:
439 netvsc_linkstatus_callback(device->net_dev->dev, 1);
441 case RNDIS_STATUS_MEDIA_DISCONNECT:
442 netvsc_linkstatus_callback(device->net_dev->dev, 0);
446 device_printf(device->net_dev->dev->device,
447 "unknown status %d received\n", indicate->status);
453 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
455 const rndis_per_packet_info *ppi;
458 info->vlan_info = NULL;
459 info->csum_info = NULL;
460 info->hash_info = NULL;
461 info->hash_value = NULL;
463 if (rpkt->per_pkt_info_offset == 0)
466 ppi = (const rndis_per_packet_info *)
467 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
468 len = rpkt->per_pkt_info_length;
472 const void *ppi_dptr;
475 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
477 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
478 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
481 case ieee_8021q_info:
482 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
484 info->vlan_info = ppi_dptr;
485 mask |= HV_RF_RECVINFO_VLAN;
488 case tcpip_chksum_info:
489 if (__predict_false(ppi_dlen <
490 sizeof(rndis_tcp_ip_csum_info)))
492 info->csum_info = ppi_dptr;
493 mask |= HV_RF_RECVINFO_CSUM;
497 if (__predict_false(ppi_dlen <
498 sizeof(struct rndis_hash_value)))
500 info->hash_value = ppi_dptr;
501 mask |= HV_RF_RECVINFO_HASHVAL;
505 if (__predict_false(ppi_dlen <
506 sizeof(struct rndis_hash_info)))
508 info->hash_info = ppi_dptr;
509 mask |= HV_RF_RECVINFO_HASHINF;
516 if (mask == HV_RF_RECVINFO_ALL) {
517 /* All found; done */
521 if (__predict_false(len < ppi->size))
524 ppi = (const rndis_per_packet_info *)
525 ((const uint8_t *)ppi + ppi->size);
531 * RNDIS filter receive data
534 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
535 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
537 rndis_packet *rndis_pkt;
538 uint32_t data_offset;
539 device_t dev = device->net_dev->dev->device;
540 struct hv_rf_recvinfo info;
542 rndis_pkt = &message->msg.packet;
545 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
546 * netvsc packet (ie tot_data_buf_len != message_length)
549 /* Remove rndis header, then pass data packet up the stack */
550 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
552 pkt->tot_data_buf_len -= data_offset;
553 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
554 pkt->status = nvsp_status_failure;
556 "total length %u is less than data length %u\n",
557 pkt->tot_data_buf_len, rndis_pkt->data_length);
561 pkt->tot_data_buf_len = rndis_pkt->data_length;
562 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
564 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
565 pkt->status = nvsp_status_failure;
566 device_printf(dev, "recvinfo parsing failed\n");
570 if (info.vlan_info != NULL)
571 pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
575 netvsc_recv(chan, pkt, info.csum_info, info.hash_info, info.hash_value);
579 * RNDIS filter on receive
582 hv_rf_on_receive(netvsc_dev *net_dev, struct hv_device *device,
583 struct hv_vmbus_channel *chan, netvsc_packet *pkt)
585 rndis_device *rndis_dev;
586 rndis_msg *rndis_hdr;
588 /* Make sure the rndis device state is initialized */
589 if (net_dev->extension == NULL) {
590 pkt->status = nvsp_status_failure;
594 rndis_dev = (rndis_device *)net_dev->extension;
595 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
596 pkt->status = nvsp_status_failure;
600 rndis_hdr = pkt->data;
602 switch (rndis_hdr->ndis_msg_type) {
605 case REMOTE_NDIS_PACKET_MSG:
606 hv_rf_receive_data(rndis_dev, rndis_hdr, chan, pkt);
608 /* completion messages */
609 case REMOTE_NDIS_INITIALIZE_CMPLT:
610 case REMOTE_NDIS_QUERY_CMPLT:
611 case REMOTE_NDIS_SET_CMPLT:
612 case REMOTE_NDIS_RESET_CMPLT:
613 case REMOTE_NDIS_KEEPALIVE_CMPLT:
614 hv_rf_receive_response(rndis_dev, rndis_hdr);
616 /* notification message */
617 case REMOTE_NDIS_INDICATE_STATUS_MSG:
618 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
621 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
622 rndis_hdr->ndis_msg_type);
630 * RNDIS filter query device
633 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
634 uint32_t *result_size)
636 rndis_request *request;
637 uint32_t in_result_size = *result_size;
638 rndis_query_request *query;
639 rndis_query_complete *query_complete;
643 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
644 RNDIS_MESSAGE_SIZE(rndis_query_request));
645 if (request == NULL) {
650 /* Set up the rndis query */
651 query = &request->request_msg.msg.query_request;
653 query->info_buffer_offset = sizeof(rndis_query_request);
654 query->info_buffer_length = 0;
655 query->device_vc_handle = 0;
657 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
658 struct rndis_recv_scale_cap *cap;
660 request->request_msg.msg_len +=
661 sizeof(struct rndis_recv_scale_cap);
662 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
663 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
664 query->info_buffer_offset);
665 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
666 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
667 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
670 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
672 /* Fixme: printf added */
673 printf("RNDISFILTER request failed to Send!\n");
677 sema_wait(&request->wait_sema);
679 /* Copy the response back */
680 query_complete = &request->response_msg.msg.query_complete;
682 if (query_complete->info_buffer_length > in_result_size) {
687 memcpy(result, (void *)((unsigned long)query_complete +
688 query_complete->info_buffer_offset),
689 query_complete->info_buffer_length);
691 *result_size = query_complete->info_buffer_length;
695 hv_put_rndis_request(device, request);
701 * RNDIS filter query device MAC address
704 hv_rf_query_device_mac(rndis_device *device)
706 uint32_t size = HW_MACADDR_LEN;
708 return (hv_rf_query_device(device,
709 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
713 * RNDIS filter query device link status
716 hv_rf_query_device_link_status(rndis_device *device)
718 uint32_t size = sizeof(uint32_t);
720 return (hv_rf_query_device(device,
721 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
724 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
725 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
726 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
727 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
728 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
729 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
733 * RNDIS set vRSS parameters
736 hv_rf_set_rss_param(rndis_device *device, int num_queue)
738 rndis_request *request;
739 rndis_set_request *set;
740 rndis_set_complete *set_complete;
741 rndis_recv_scale_param *rssp;
742 uint32_t extlen = sizeof(rndis_recv_scale_param) +
743 (4 * ITAB_NUM) + HASH_KEYLEN;
744 uint32_t *itab, status;
749 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
750 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
751 if (request == NULL) {
753 printf("Netvsc: No memory to set vRSS parameters.\n");
758 set = &request->request_msg.msg.set_request;
759 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
760 set->info_buffer_length = extlen;
761 set->info_buffer_offset = sizeof(rndis_set_request);
762 set->device_vc_handle = 0;
764 /* Fill out the rssp parameter structure */
765 rssp = (rndis_recv_scale_param *)(set + 1);
766 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
767 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
768 rssp->hdr.size = sizeof(rndis_recv_scale_param);
770 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
771 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
772 rssp->indirect_tabsize = 4 * ITAB_NUM;
773 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
774 rssp->hashkey_size = HASH_KEYLEN;
775 rssp->hashkey_offset = rssp->indirect_taboffset +
776 rssp->indirect_tabsize;
778 /* Set indirection table entries */
779 itab = (uint32_t *)(rssp + 1);
780 for (i = 0; i < ITAB_NUM; i++)
781 itab[i] = i % num_queue;
783 /* Set hash key values */
784 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
785 for (i = 0; i < HASH_KEYLEN; i++)
786 keyp[i] = netvsc_hash_key[i];
788 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
794 * Wait for the response from the host. Another thread will signal
795 * us when the response has arrived. In the failure case,
796 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
798 ret = sema_timedwait(&request->wait_sema, 5 * hz);
800 /* Response received, check status */
801 set_complete = &request->response_msg.msg.set_complete;
802 status = set_complete->status;
803 if (status != RNDIS_STATUS_SUCCESS) {
804 /* Bad response status, return error */
806 printf("Netvsc: Failed to set vRSS "
811 printf("Netvsc: Successfully set vRSS "
816 * We cannot deallocate the request since we may still
817 * receive a send completion for it.
819 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
820 request->request_msg.msg.init_request.request_id, ret);
825 if (request != NULL) {
826 hv_put_rndis_request(device, request);
833 * RNDIS filter set packet filter
834 * Sends an rndis request with the new filter, then waits for a response
836 * Returns zero on success, non-zero on failure.
839 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
841 rndis_request *request;
842 rndis_set_request *set;
843 rndis_set_complete *set_complete;
847 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
848 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
849 if (request == NULL) {
854 /* Set up the rndis set */
855 set = &request->request_msg.msg.set_request;
856 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
857 set->info_buffer_length = sizeof(uint32_t);
858 set->info_buffer_offset = sizeof(rndis_set_request);
860 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
861 &new_filter, sizeof(uint32_t));
863 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
869 * Wait for the response from the host. Another thread will signal
870 * us when the response has arrived. In the failure case,
871 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
873 ret = sema_timedwait(&request->wait_sema, 5 * hz);
875 /* Response received, check status */
876 set_complete = &request->response_msg.msg.set_complete;
877 status = set_complete->status;
878 if (status != RNDIS_STATUS_SUCCESS) {
879 /* Bad response status, return error */
884 * We cannot deallocate the request since we may still
885 * receive a send completion for it.
891 if (request != NULL) {
892 hv_put_rndis_request(device, request);
899 * RNDIS filter init device
902 hv_rf_init_device(rndis_device *device)
904 rndis_request *request;
905 rndis_initialize_request *init;
906 rndis_initialize_complete *init_complete;
910 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
911 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
917 /* Set up the rndis set */
918 init = &request->request_msg.msg.init_request;
919 init->major_version = RNDIS_MAJOR_VERSION;
920 init->minor_version = RNDIS_MINOR_VERSION;
922 * Per the RNDIS document, this should be set to the max MTU
923 * plus the header size. However, 2048 works fine, so leaving
926 init->max_xfer_size = 2048;
928 device->state = RNDIS_DEV_INITIALIZING;
930 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
932 device->state = RNDIS_DEV_UNINITIALIZED;
936 sema_wait(&request->wait_sema);
938 init_complete = &request->response_msg.msg.init_complete;
939 status = init_complete->status;
940 if (status == RNDIS_STATUS_SUCCESS) {
941 device->state = RNDIS_DEV_INITIALIZED;
944 device->state = RNDIS_DEV_UNINITIALIZED;
950 hv_put_rndis_request(device, request);
956 #define HALT_COMPLETION_WAIT_COUNT 25
959 * RNDIS filter halt device
962 hv_rf_halt_device(rndis_device *device)
964 rndis_request *request;
965 rndis_halt_request *halt;
968 /* Attempt to do a rndis device halt */
969 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
970 RNDIS_MESSAGE_SIZE(rndis_halt_request));
971 if (request == NULL) {
975 /* initialize "poor man's semaphore" */
976 request->halt_complete_flag = 0;
978 /* Set up the rndis set */
979 halt = &request->request_msg.msg.halt_request;
980 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
981 /* Increment to get the new value (call above returns old value) */
982 halt->request_id += 1;
984 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
990 * Wait for halt response from halt callback. We must wait for
991 * the transaction response before freeing the request and other
994 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
995 if (request->halt_complete_flag != 0) {
1004 device->state = RNDIS_DEV_UNINITIALIZED;
1006 hv_put_rndis_request(device, request);
1012 * RNDIS filter open device
1015 hv_rf_open_device(rndis_device *device)
1019 if (device->state != RNDIS_DEV_INITIALIZED) {
1023 if (hv_promisc_mode != 1) {
1024 ret = hv_rf_set_packet_filter(device,
1025 NDIS_PACKET_TYPE_BROADCAST |
1026 NDIS_PACKET_TYPE_ALL_MULTICAST |
1027 NDIS_PACKET_TYPE_DIRECTED);
1029 ret = hv_rf_set_packet_filter(device,
1030 NDIS_PACKET_TYPE_PROMISCUOUS);
1034 device->state = RNDIS_DEV_DATAINITIALIZED;
1041 * RNDIS filter close device
1044 hv_rf_close_device(rndis_device *device)
1048 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1052 ret = hv_rf_set_packet_filter(device, 0);
1054 device->state = RNDIS_DEV_INITIALIZED;
1061 * RNDIS filter on device add
1064 hv_rf_on_device_add(struct hv_device *device, void *additl_info,
1068 netvsc_dev *net_dev;
1069 rndis_device *rndis_dev;
1071 rndis_offload_params offloads;
1072 struct rndis_recv_scale_cap rsscaps;
1073 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1074 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1075 device_t dev = device->device;
1077 rndis_dev = hv_get_rndis_device();
1078 if (rndis_dev == NULL) {
1083 * Let the inner driver handle this first to create the netvsc channel
1084 * NOTE! Once the channel is created, we may get a receive callback
1085 * (hv_rf_on_receive()) before this call is completed.
1086 * Note: Earlier code used a function pointer here.
1088 net_dev = hv_nv_on_device_add(device, additl_info);
1090 hv_put_rndis_device(rndis_dev);
1096 * Initialize the rndis device
1099 net_dev->extension = rndis_dev;
1100 rndis_dev->net_dev = net_dev;
1102 /* Send the rndis initialization message */
1103 ret = hv_rf_init_device(rndis_dev);
1106 * TODO: If rndis init failed, we will need to shut down
1111 /* Get the mac address */
1112 ret = hv_rf_query_device_mac(rndis_dev);
1114 /* TODO: shut down rndis device and the channel */
1117 /* config csum offload and send request to host */
1118 memset(&offloads, 0, sizeof(offloads));
1119 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1120 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1121 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1122 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1123 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1124 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1126 ret = hv_rf_send_offload_request(device, &offloads);
1128 /* TODO: shut down rndis device and the channel */
1130 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1133 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, HW_MACADDR_LEN);
1135 hv_rf_query_device_link_status(rndis_dev);
1137 dev_info->link_state = rndis_dev->link_status;
1139 net_dev->num_channel = 1;
1140 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1143 memset(&rsscaps, 0, rsscaps_size);
1144 ret = hv_rf_query_device(rndis_dev,
1145 RNDIS_OID_GEN_RSS_CAPABILITIES,
1146 &rsscaps, &rsscaps_size);
1147 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1148 device_printf(dev, "hv_rf_query_device failed or "
1149 "rsscaps.num_recv_que < 2 \n");
1152 device_printf(dev, "channel, offered %u, requested %d\n",
1153 rsscaps.num_recv_que, nchan);
1154 if (nchan > rsscaps.num_recv_que)
1155 nchan = rsscaps.num_recv_que;
1156 net_dev->num_channel = nchan;
1158 if (net_dev->num_channel == 1) {
1159 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1163 /* request host to create sub channels */
1164 init_pkt = &net_dev->channel_init_packet;
1165 memset(init_pkt, 0, sizeof(nvsp_msg));
1167 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1168 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1169 NVSP_SUBCHANNE_ALLOCATE;
1170 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1171 net_dev->num_channel - 1;
1173 ret = hv_vmbus_channel_send_packet(device->channel, init_pkt,
1174 sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1175 HV_VMBUS_PACKET_TYPE_DATA_IN_BAND,
1176 HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
1178 device_printf(dev, "Fail to allocate subchannel\n");
1182 sema_wait(&net_dev->channel_init_sema);
1184 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1185 nvsp_status_success) {
1187 device_printf(dev, "sub channel complete error\n");
1191 net_dev->num_channel = 1 +
1192 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1194 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1198 net_dev->num_channel = 1;
1204 * RNDIS filter on device remove
1207 hv_rf_on_device_remove(struct hv_device *device, boolean_t destroy_channel)
1209 hn_softc_t *sc = device_get_softc(device->device);
1210 netvsc_dev *net_dev = sc->net_dev;
1211 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1214 /* Halt and release the rndis device */
1215 ret = hv_rf_halt_device(rndis_dev);
1217 hv_put_rndis_device(rndis_dev);
1218 net_dev->extension = NULL;
1220 /* Pass control to inner driver to remove the device */
1221 ret |= hv_nv_on_device_remove(device, destroy_channel);
1227 * RNDIS filter on open
1230 hv_rf_on_open(struct hv_device *device)
1232 hn_softc_t *sc = device_get_softc(device->device);
1233 netvsc_dev *net_dev = sc->net_dev;
1235 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1239 * RNDIS filter on close
1242 hv_rf_on_close(struct hv_device *device)
1244 hn_softc_t *sc = device_get_softc(device->device);
1245 netvsc_dev *net_dev = sc->net_dev;
1247 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1251 * RNDIS filter on send request completion callback
1254 hv_rf_on_send_request_completion(struct hv_vmbus_channel *chan __unused,
1255 void *context __unused)
1260 * RNDIS filter on send request (halt only) completion callback
1263 hv_rf_on_send_request_halt_completion(struct hv_vmbus_channel *chan __unused,
1266 rndis_request *request = context;
1269 * Notify hv_rf_halt_device() about halt completion.
1270 * The halt code must wait for completion before freeing
1271 * the transaction resources.
1273 request->halt_complete_flag = 1;
1277 hv_rf_channel_rollup(struct hv_vmbus_channel *chan)
1280 netvsc_channel_rollup(chan);