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>
38 #include <net/if_arp.h>
39 #include <net/if_var.h>
40 #include <net/ethernet.h>
41 #include <sys/types.h>
42 #include <machine/atomic.h>
45 #include <vm/vm_param.h>
48 #include <dev/hyperv/include/hyperv.h>
49 #include <dev/hyperv/include/vmbus_xact.h>
50 #include <dev/hyperv/netvsc/hv_net_vsc.h>
51 #include <dev/hyperv/netvsc/hv_rndis.h>
52 #include <dev/hyperv/netvsc/hv_rndis_filter.h>
53 #include <dev/hyperv/netvsc/if_hnreg.h>
55 #define HV_RF_RECVINFO_VLAN 0x1
56 #define HV_RF_RECVINFO_CSUM 0x2
57 #define HV_RF_RECVINFO_HASHINF 0x4
58 #define HV_RF_RECVINFO_HASHVAL 0x8
59 #define HV_RF_RECVINFO_ALL \
60 (HV_RF_RECVINFO_VLAN | \
61 HV_RF_RECVINFO_CSUM | \
62 HV_RF_RECVINFO_HASHINF | \
63 HV_RF_RECVINFO_HASHVAL)
66 * Forward declarations
68 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
69 uint32_t message_type);
70 static void hv_rf_receive_response(rndis_device *device, rndis_msg *response);
71 static void hv_rf_receive_indicate_status(rndis_device *device,
73 static void hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message,
75 static int hv_rf_query_device(rndis_device *device, uint32_t oid,
76 void *result, uint32_t *result_size);
77 static inline int hv_rf_query_device_mac(rndis_device *device);
78 static inline int hv_rf_query_device_link_status(rndis_device *device);
79 static int hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
80 static int hv_rf_init_device(rndis_device *device);
81 static int hv_rf_open_device(rndis_device *device);
82 static int hv_rf_close_device(rndis_device *device);
84 hv_rf_send_offload_request(struct hn_softc *sc,
85 rndis_offload_params *offloads);
87 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
88 struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
89 const void *data, int dlen);
90 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
91 struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
92 const void *data, int dlen);
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)
242 netvsc_dev *net_dev = device->net_dev;
243 uint32_t send_buf_section_idx, tot_data_buf_len;
244 struct vmbus_gpa gpa[2];
245 int gpa_cnt, send_buf_section_size;
246 hn_sent_callback_t cb;
248 /* Set up the packet to send it */
249 tot_data_buf_len = request->request_msg.msg_len;
252 gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
253 gpa[0].gpa_len = request->request_msg.msg_len;
254 gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
256 if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
258 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
260 hv_get_phys_addr((char*)&request->request_msg +
261 gpa[0].gpa_len) >> PAGE_SHIFT;
263 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
266 if (message_type != REMOTE_NDIS_HALT_MSG)
267 cb = hn_rndis_sent_cb;
269 cb = hn_rndis_sent_halt;
271 if (tot_data_buf_len < net_dev->send_section_size) {
272 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
273 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
274 char *dest = ((char *)net_dev->send_buf +
275 send_buf_section_idx * net_dev->send_section_size);
277 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
278 send_buf_section_size = tot_data_buf_len;
282 /* Failed to allocate chimney send buffer; move on */
284 send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
285 send_buf_section_size = 0;
288 hn_send_ctx_init(&request->send_ctx, cb, request,
289 send_buf_section_idx, send_buf_section_size);
290 return hv_nv_on_send(device->net_dev->sc->hn_prichan,
291 HN_NVS_RNDIS_MTYPE_CTRL, &request->send_ctx, gpa, gpa_cnt);
295 * RNDIS filter receive response
298 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
300 rndis_request *request = NULL;
301 rndis_request *next_request;
302 boolean_t found = FALSE;
304 mtx_lock(&device->req_lock);
305 request = STAILQ_FIRST(&device->myrequest_list);
306 while (request != NULL) {
308 * All request/response message contains request_id as the
311 if (request->request_msg.msg.init_request.request_id ==
312 response->msg.init_complete.request_id) {
316 next_request = STAILQ_NEXT(request, mylist_entry);
317 request = next_request;
319 mtx_unlock(&device->req_lock);
322 if (response->msg_len <= sizeof(rndis_msg)) {
323 memcpy(&request->response_msg, response,
326 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
327 /* Does not have a request id field */
328 request->response_msg.msg.reset_complete.status =
329 STATUS_BUFFER_OVERFLOW;
331 request->response_msg.msg.init_complete.status =
332 STATUS_BUFFER_OVERFLOW;
336 sema_post(&request->wait_sema);
341 hv_rf_send_offload_request(struct hn_softc *sc,
342 rndis_offload_params *offloads)
344 rndis_request *request;
345 rndis_set_request *set;
346 rndis_offload_params *offload_req;
347 rndis_set_complete *set_complete;
348 rndis_device *rndis_dev;
349 device_t dev = sc->hn_dev;
350 netvsc_dev *net_dev = sc->net_dev;
351 uint32_t vsp_version = net_dev->nvsp_version;
352 uint32_t extlen = sizeof(rndis_offload_params);
355 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
356 extlen = VERSION_4_OFFLOAD_SIZE;
357 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
358 * UDP checksum offload.
360 offloads->udp_ipv4_csum = 0;
361 offloads->udp_ipv6_csum = 0;
364 rndis_dev = net_dev->extension;
366 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
367 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
371 set = &request->request_msg.msg.set_request;
372 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
373 set->info_buffer_length = extlen;
374 set->info_buffer_offset = sizeof(rndis_set_request);
375 set->device_vc_handle = 0;
377 offload_req = (rndis_offload_params *)((unsigned long)set +
378 set->info_buffer_offset);
379 *offload_req = *offloads;
380 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
381 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
382 offload_req->header.size = extlen;
384 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
386 device_printf(dev, "hv send offload request failed, ret=%d!\n",
391 ret = sema_timedwait(&request->wait_sema, 5 * hz);
393 device_printf(dev, "hv send offload request timeout\n");
397 set_complete = &request->response_msg.msg.set_complete;
398 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
399 device_printf(dev, "hv send offload request succeeded\n");
402 if (set_complete->status == STATUS_NOT_SUPPORTED) {
403 device_printf(dev, "HV Not support offload\n");
406 ret = set_complete->status;
411 hv_put_rndis_request(rndis_dev, request);
417 * RNDIS filter receive indicate status
420 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
422 rndis_indicate_status *indicate = &response->msg.indicate_status;
424 switch(indicate->status) {
425 case RNDIS_STATUS_MEDIA_CONNECT:
426 netvsc_linkstatus_callback(device->net_dev->sc, 1);
428 case RNDIS_STATUS_MEDIA_DISCONNECT:
429 netvsc_linkstatus_callback(device->net_dev->sc, 0);
433 device_printf(device->net_dev->sc->hn_dev,
434 "unknown status %d received\n", indicate->status);
440 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
442 const rndis_per_packet_info *ppi;
445 info->vlan_info = NULL;
446 info->csum_info = NULL;
447 info->hash_info = NULL;
448 info->hash_value = NULL;
450 if (rpkt->per_pkt_info_offset == 0)
453 ppi = (const rndis_per_packet_info *)
454 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
455 len = rpkt->per_pkt_info_length;
459 const void *ppi_dptr;
462 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
464 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
465 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
468 case ieee_8021q_info:
469 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
471 info->vlan_info = ppi_dptr;
472 mask |= HV_RF_RECVINFO_VLAN;
475 case tcpip_chksum_info:
476 if (__predict_false(ppi_dlen <
477 sizeof(rndis_tcp_ip_csum_info)))
479 info->csum_info = ppi_dptr;
480 mask |= HV_RF_RECVINFO_CSUM;
484 if (__predict_false(ppi_dlen <
485 sizeof(struct rndis_hash_value)))
487 info->hash_value = ppi_dptr;
488 mask |= HV_RF_RECVINFO_HASHVAL;
492 if (__predict_false(ppi_dlen <
493 sizeof(struct rndis_hash_info)))
495 info->hash_info = ppi_dptr;
496 mask |= HV_RF_RECVINFO_HASHINF;
503 if (mask == HV_RF_RECVINFO_ALL) {
504 /* All found; done */
508 if (__predict_false(len < ppi->size))
511 ppi = (const rndis_per_packet_info *)
512 ((const uint8_t *)ppi + ppi->size);
518 * RNDIS filter receive data
521 hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message,
524 rndis_packet *rndis_pkt;
525 uint32_t data_offset;
526 struct hn_recvinfo info;
528 rndis_pkt = &message->msg.packet;
531 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
532 * netvsc packet (ie tot_data_buf_len != message_length)
535 /* Remove rndis header, then pass data packet up the stack */
536 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
538 pkt->tot_data_buf_len -= data_offset;
539 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
540 pkt->status = HN_NVS_STATUS_FAILED;
541 if_printf(rxr->hn_ifp,
542 "total length %u is less than data length %u\n",
543 pkt->tot_data_buf_len, rndis_pkt->data_length);
547 pkt->tot_data_buf_len = rndis_pkt->data_length;
548 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
550 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
551 pkt->status = HN_NVS_STATUS_FAILED;
552 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
555 netvsc_recv(rxr, pkt, &info);
559 * RNDIS filter on receive
562 hv_rf_on_receive(netvsc_dev *net_dev,
563 struct hn_rx_ring *rxr, netvsc_packet *pkt)
565 rndis_device *rndis_dev;
566 rndis_msg *rndis_hdr;
568 /* Make sure the rndis device state is initialized */
569 if (net_dev->extension == NULL) {
570 pkt->status = HN_NVS_STATUS_FAILED;
574 rndis_dev = (rndis_device *)net_dev->extension;
575 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
576 pkt->status = HN_NVS_STATUS_FAILED;
580 rndis_hdr = pkt->data;
582 switch (rndis_hdr->ndis_msg_type) {
585 case REMOTE_NDIS_PACKET_MSG:
586 hv_rf_receive_data(rxr, rndis_hdr, pkt);
588 /* completion messages */
589 case REMOTE_NDIS_INITIALIZE_CMPLT:
590 case REMOTE_NDIS_QUERY_CMPLT:
591 case REMOTE_NDIS_SET_CMPLT:
592 case REMOTE_NDIS_RESET_CMPLT:
593 case REMOTE_NDIS_KEEPALIVE_CMPLT:
594 hv_rf_receive_response(rndis_dev, rndis_hdr);
596 /* notification message */
597 case REMOTE_NDIS_INDICATE_STATUS_MSG:
598 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
601 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
602 rndis_hdr->ndis_msg_type);
610 * RNDIS filter query device
613 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
614 uint32_t *result_size)
616 rndis_request *request;
617 uint32_t in_result_size = *result_size;
618 rndis_query_request *query;
619 rndis_query_complete *query_complete;
623 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
624 RNDIS_MESSAGE_SIZE(rndis_query_request));
625 if (request == NULL) {
630 /* Set up the rndis query */
631 query = &request->request_msg.msg.query_request;
633 query->info_buffer_offset = sizeof(rndis_query_request);
634 query->info_buffer_length = 0;
635 query->device_vc_handle = 0;
637 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
638 struct rndis_recv_scale_cap *cap;
640 request->request_msg.msg_len +=
641 sizeof(struct rndis_recv_scale_cap);
642 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
643 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
644 query->info_buffer_offset);
645 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
646 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
647 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
650 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
652 /* Fixme: printf added */
653 printf("RNDISFILTER request failed to Send!\n");
657 sema_wait(&request->wait_sema);
659 /* Copy the response back */
660 query_complete = &request->response_msg.msg.query_complete;
662 if (query_complete->info_buffer_length > in_result_size) {
667 memcpy(result, (void *)((unsigned long)query_complete +
668 query_complete->info_buffer_offset),
669 query_complete->info_buffer_length);
671 *result_size = query_complete->info_buffer_length;
675 hv_put_rndis_request(device, request);
681 * RNDIS filter query device MAC address
684 hv_rf_query_device_mac(rndis_device *device)
686 uint32_t size = ETHER_ADDR_LEN;
688 return (hv_rf_query_device(device,
689 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
693 * RNDIS filter query device link status
696 hv_rf_query_device_link_status(rndis_device *device)
698 uint32_t size = sizeof(uint32_t);
700 return (hv_rf_query_device(device,
701 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
704 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
705 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
706 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
707 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
708 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
709 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
713 * RNDIS set vRSS parameters
716 hv_rf_set_rss_param(rndis_device *device, int num_queue)
718 rndis_request *request;
719 rndis_set_request *set;
720 rndis_set_complete *set_complete;
721 rndis_recv_scale_param *rssp;
722 uint32_t extlen = sizeof(rndis_recv_scale_param) +
723 (4 * ITAB_NUM) + HASH_KEYLEN;
724 uint32_t *itab, status;
729 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
730 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
731 if (request == NULL) {
733 printf("Netvsc: No memory to set vRSS parameters.\n");
738 set = &request->request_msg.msg.set_request;
739 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
740 set->info_buffer_length = extlen;
741 set->info_buffer_offset = sizeof(rndis_set_request);
742 set->device_vc_handle = 0;
744 /* Fill out the rssp parameter structure */
745 rssp = (rndis_recv_scale_param *)(set + 1);
746 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
747 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
748 rssp->hdr.size = sizeof(rndis_recv_scale_param);
750 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
751 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
752 rssp->indirect_tabsize = 4 * ITAB_NUM;
753 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
754 rssp->hashkey_size = HASH_KEYLEN;
755 rssp->hashkey_offset = rssp->indirect_taboffset +
756 rssp->indirect_tabsize;
758 /* Set indirection table entries */
759 itab = (uint32_t *)(rssp + 1);
760 for (i = 0; i < ITAB_NUM; i++)
761 itab[i] = i % num_queue;
763 /* Set hash key values */
764 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
765 for (i = 0; i < HASH_KEYLEN; i++)
766 keyp[i] = netvsc_hash_key[i];
768 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
774 * Wait for the response from the host. Another thread will signal
775 * us when the response has arrived. In the failure case,
776 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
778 ret = sema_timedwait(&request->wait_sema, 5 * hz);
780 /* Response received, check status */
781 set_complete = &request->response_msg.msg.set_complete;
782 status = set_complete->status;
783 if (status != RNDIS_STATUS_SUCCESS) {
784 /* Bad response status, return error */
786 printf("Netvsc: Failed to set vRSS "
791 printf("Netvsc: Successfully set vRSS "
796 * We cannot deallocate the request since we may still
797 * receive a send completion for it.
799 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
800 request->request_msg.msg.init_request.request_id, ret);
805 if (request != NULL) {
806 hv_put_rndis_request(device, request);
813 * RNDIS filter set packet filter
814 * Sends an rndis request with the new filter, then waits for a response
816 * Returns zero on success, non-zero on failure.
819 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
821 rndis_request *request;
822 rndis_set_request *set;
823 rndis_set_complete *set_complete;
827 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
828 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
829 if (request == NULL) {
834 /* Set up the rndis set */
835 set = &request->request_msg.msg.set_request;
836 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
837 set->info_buffer_length = sizeof(uint32_t);
838 set->info_buffer_offset = sizeof(rndis_set_request);
840 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
841 &new_filter, sizeof(uint32_t));
843 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
849 * Wait for the response from the host. Another thread will signal
850 * us when the response has arrived. In the failure case,
851 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
853 ret = sema_timedwait(&request->wait_sema, 5 * hz);
855 /* Response received, check status */
856 set_complete = &request->response_msg.msg.set_complete;
857 status = set_complete->status;
858 if (status != RNDIS_STATUS_SUCCESS) {
859 /* Bad response status, return error */
864 * We cannot deallocate the request since we may still
865 * receive a send completion for it.
871 if (request != NULL) {
872 hv_put_rndis_request(device, request);
879 * RNDIS filter init device
882 hv_rf_init_device(rndis_device *device)
884 rndis_request *request;
885 rndis_initialize_request *init;
886 rndis_initialize_complete *init_complete;
890 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
891 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
897 /* Set up the rndis set */
898 init = &request->request_msg.msg.init_request;
899 init->major_version = RNDIS_MAJOR_VERSION;
900 init->minor_version = RNDIS_MINOR_VERSION;
902 * Per the RNDIS document, this should be set to the max MTU
903 * plus the header size. However, 2048 works fine, so leaving
906 init->max_xfer_size = 2048;
908 device->state = RNDIS_DEV_INITIALIZING;
910 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
912 device->state = RNDIS_DEV_UNINITIALIZED;
916 sema_wait(&request->wait_sema);
918 init_complete = &request->response_msg.msg.init_complete;
919 status = init_complete->status;
920 if (status == RNDIS_STATUS_SUCCESS) {
921 device->state = RNDIS_DEV_INITIALIZED;
924 device->state = RNDIS_DEV_UNINITIALIZED;
930 hv_put_rndis_request(device, request);
936 #define HALT_COMPLETION_WAIT_COUNT 25
939 * RNDIS filter halt device
942 hv_rf_halt_device(rndis_device *device)
944 rndis_request *request;
945 rndis_halt_request *halt;
948 /* Attempt to do a rndis device halt */
949 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
950 RNDIS_MESSAGE_SIZE(rndis_halt_request));
951 if (request == NULL) {
955 /* initialize "poor man's semaphore" */
956 request->halt_complete_flag = 0;
958 /* Set up the rndis set */
959 halt = &request->request_msg.msg.halt_request;
960 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
961 /* Increment to get the new value (call above returns old value) */
962 halt->request_id += 1;
964 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
970 * Wait for halt response from halt callback. We must wait for
971 * the transaction response before freeing the request and other
974 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
975 if (request->halt_complete_flag != 0) {
984 device->state = RNDIS_DEV_UNINITIALIZED;
986 hv_put_rndis_request(device, request);
992 * RNDIS filter open device
995 hv_rf_open_device(rndis_device *device)
999 if (device->state != RNDIS_DEV_INITIALIZED) {
1003 if (hv_promisc_mode != 1) {
1004 ret = hv_rf_set_packet_filter(device,
1005 NDIS_PACKET_TYPE_BROADCAST |
1006 NDIS_PACKET_TYPE_ALL_MULTICAST |
1007 NDIS_PACKET_TYPE_DIRECTED);
1009 ret = hv_rf_set_packet_filter(device,
1010 NDIS_PACKET_TYPE_PROMISCUOUS);
1014 device->state = RNDIS_DEV_DATAINITIALIZED;
1021 * RNDIS filter close device
1024 hv_rf_close_device(rndis_device *device)
1028 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1032 ret = hv_rf_set_packet_filter(device, 0);
1034 device->state = RNDIS_DEV_INITIALIZED;
1041 * RNDIS filter on device add
1044 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1045 int nchan, struct hn_rx_ring *rxr)
1047 struct hn_send_ctx sndc;
1049 netvsc_dev *net_dev;
1050 rndis_device *rndis_dev;
1051 rndis_offload_params offloads;
1052 struct rndis_recv_scale_cap rsscaps;
1053 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1054 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1055 device_t dev = sc->hn_dev;
1056 struct hn_nvs_subch_req *req;
1057 const struct hn_nvs_subch_resp *resp;
1059 struct vmbus_xact *xact;
1060 uint32_t status, nsubch;
1062 rndis_dev = hv_get_rndis_device();
1063 if (rndis_dev == NULL) {
1068 * Let the inner driver handle this first to create the netvsc channel
1069 * NOTE! Once the channel is created, we may get a receive callback
1070 * (hv_rf_on_receive()) before this call is completed.
1071 * Note: Earlier code used a function pointer here.
1073 net_dev = hv_nv_on_device_add(sc, additl_info, rxr);
1075 hv_put_rndis_device(rndis_dev);
1081 * Initialize the rndis device
1084 net_dev->extension = rndis_dev;
1085 rndis_dev->net_dev = net_dev;
1087 /* Send the rndis initialization message */
1088 ret = hv_rf_init_device(rndis_dev);
1091 * TODO: If rndis init failed, we will need to shut down
1096 /* Get the mac address */
1097 ret = hv_rf_query_device_mac(rndis_dev);
1099 /* TODO: shut down rndis device and the channel */
1102 /* config csum offload and send request to host */
1103 memset(&offloads, 0, sizeof(offloads));
1104 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1105 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1106 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1107 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1108 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1109 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1111 ret = hv_rf_send_offload_request(sc, &offloads);
1113 /* TODO: shut down rndis device and the channel */
1115 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1118 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1120 hv_rf_query_device_link_status(rndis_dev);
1122 dev_info->link_state = rndis_dev->link_status;
1124 net_dev->num_channel = 1;
1125 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1128 memset(&rsscaps, 0, rsscaps_size);
1129 ret = hv_rf_query_device(rndis_dev,
1130 RNDIS_OID_GEN_RSS_CAPABILITIES,
1131 &rsscaps, &rsscaps_size);
1132 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1133 device_printf(dev, "hv_rf_query_device failed or "
1134 "rsscaps.num_recv_que < 2 \n");
1137 device_printf(dev, "channel, offered %u, requested %d\n",
1138 rsscaps.num_recv_que, nchan);
1139 if (nchan > rsscaps.num_recv_que)
1140 nchan = rsscaps.num_recv_que;
1141 net_dev->num_channel = nchan;
1143 if (net_dev->num_channel == 1) {
1144 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1149 * Ask NVS to allocate sub-channels.
1151 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1153 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1158 req = vmbus_xact_req_data(xact);
1159 req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1160 req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1161 req->nvs_nsubch = net_dev->num_channel - 1;
1163 hn_send_ctx_init_simple(&sndc, hn_nvs_sent_xact, xact);
1164 vmbus_xact_activate(xact);
1166 ret = hn_nvs_send(sc->hn_prichan, VMBUS_CHANPKT_FLAG_RC,
1167 req, sizeof(*req), &sndc);
1169 if_printf(sc->hn_ifp, "send nvs subch req failed: %d\n", ret);
1170 vmbus_xact_deactivate(xact);
1171 vmbus_xact_put(xact);
1175 resp = vmbus_xact_wait(xact, &resp_len);
1176 if (resp_len < sizeof(*resp)) {
1177 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1179 vmbus_xact_put(xact);
1183 if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1184 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1186 vmbus_xact_put(xact);
1191 status = resp->nvs_status;
1192 nsubch = resp->nvs_nsubch;
1193 vmbus_xact_put(xact);
1195 if (status != HN_NVS_STATUS_OK) {
1196 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1200 if (nsubch > net_dev->num_channel - 1) {
1201 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1202 nsubch, net_dev->num_channel - 1);
1203 nsubch = net_dev->num_channel - 1;
1205 net_dev->num_channel = nsubch + 1;
1207 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1211 net_dev->num_channel = 1;
1217 * RNDIS filter on device remove
1220 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1222 netvsc_dev *net_dev = sc->net_dev;
1223 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1226 /* Halt and release the rndis device */
1227 ret = hv_rf_halt_device(rndis_dev);
1229 hv_put_rndis_device(rndis_dev);
1230 net_dev->extension = NULL;
1232 /* Pass control to inner driver to remove the device */
1233 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1239 * RNDIS filter on open
1242 hv_rf_on_open(struct hn_softc *sc)
1244 netvsc_dev *net_dev = sc->net_dev;
1246 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1250 * RNDIS filter on close
1253 hv_rf_on_close(struct hn_softc *sc)
1255 netvsc_dev *net_dev = sc->net_dev;
1257 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1261 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
1262 struct vmbus_channel *chan __unused, const void *data __unused,
1265 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1266 hn_chim_free(net_dev, sndc->hn_chim_idx);
1270 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
1271 struct vmbus_channel *chan __unused, const void *data __unused,
1274 rndis_request *request = sndc->hn_cbarg;
1276 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1277 hn_chim_free(net_dev, sndc->hn_chim_idx);
1280 * Notify hv_rf_halt_device() about halt completion.
1281 * The halt code must wait for completion before freeing
1282 * the transaction resources.
1284 request->halt_complete_flag = 1;
1288 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1291 netvsc_channel_rollup(rxr, txr);