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 "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(struct hn_rx_ring *rxr, rndis_msg *message,
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);
89 hv_rf_send_offload_request(struct hn_softc *sc,
90 rndis_offload_params *offloads);
92 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
93 struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
94 const struct nvsp_msg_ *msg, int dlen);
95 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
96 struct netvsc_dev_ *net_dev, struct vmbus_channel *chan,
97 const struct nvsp_msg_ *msg, int dlen);
100 * Set the Per-Packet-Info with the specified type
103 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
106 rndis_packet *rndis_pkt;
107 rndis_per_packet_info *rppi;
109 rndis_pkt = &rndis_mesg->msg.packet;
110 rndis_pkt->data_offset += rppi_size;
112 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
113 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
115 rppi->size = rppi_size;
116 rppi->type = pkt_type;
117 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
119 rndis_pkt->per_pkt_info_length += rppi_size;
125 * Get the Per-Packet-Info with the specified type
126 * return NULL if not found.
129 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
131 rndis_per_packet_info *ppi;
134 if (rpkt->per_pkt_info_offset == 0)
137 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
138 rpkt->per_pkt_info_offset);
139 len = rpkt->per_pkt_info_length;
142 if (ppi->type == type)
143 return (void *)((unsigned long)ppi +
144 ppi->per_packet_info_offset);
147 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
155 * Allow module_param to work and override to switch to promiscuous mode.
157 static inline rndis_device *
158 hv_get_rndis_device(void)
160 rndis_device *device;
162 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
164 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
166 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
167 STAILQ_INIT(&device->myrequest_list);
169 device->state = RNDIS_DEV_UNINITIALIZED;
178 hv_put_rndis_device(rndis_device *device)
180 mtx_destroy(&device->req_lock);
181 free(device, M_NETVSC);
187 static inline rndis_request *
188 hv_rndis_request(rndis_device *device, uint32_t message_type,
189 uint32_t message_length)
191 rndis_request *request;
192 rndis_msg *rndis_mesg;
193 rndis_set_request *set;
195 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
197 sema_init(&request->wait_sema, 0, "rndis sema");
199 rndis_mesg = &request->request_msg;
200 rndis_mesg->ndis_msg_type = message_type;
201 rndis_mesg->msg_len = message_length;
204 * Set the request id. This field is always after the rndis header
205 * for request/response packet types so we just use the set_request
208 set = &rndis_mesg->msg.set_request;
209 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
210 /* Increment to get the new value (call above returns old value) */
211 set->request_id += 1;
213 /* Add to the request list */
214 mtx_lock(&device->req_lock);
215 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
216 mtx_unlock(&device->req_lock);
225 hv_put_rndis_request(rndis_device *device, rndis_request *request)
227 mtx_lock(&device->req_lock);
228 /* Fixme: Has O(n) performance */
230 * XXXKYS: Use Doubly linked lists.
232 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
234 mtx_unlock(&device->req_lock);
236 sema_destroy(&request->wait_sema);
237 free(request, M_NETVSC);
244 hv_rf_send_request(rndis_device *device, rndis_request *request,
245 uint32_t message_type)
247 netvsc_dev *net_dev = device->net_dev;
248 uint32_t send_buf_section_idx, tot_data_buf_len;
249 struct vmbus_gpa gpa[2];
250 int gpa_cnt, send_buf_section_size;
251 hn_sent_callback_t cb;
253 /* Set up the packet to send it */
254 tot_data_buf_len = request->request_msg.msg_len;
257 gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
258 gpa[0].gpa_len = request->request_msg.msg_len;
259 gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
261 if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
263 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
265 hv_get_phys_addr((char*)&request->request_msg +
266 gpa[0].gpa_len) >> PAGE_SHIFT;
268 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
271 if (message_type != REMOTE_NDIS_HALT_MSG)
272 cb = hn_rndis_sent_cb;
274 cb = hn_rndis_sent_halt;
276 if (tot_data_buf_len < net_dev->send_section_size) {
277 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
278 if (send_buf_section_idx !=
279 NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
280 char *dest = ((char *)net_dev->send_buf +
281 send_buf_section_idx * net_dev->send_section_size);
283 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
284 send_buf_section_size = tot_data_buf_len;
288 /* Failed to allocate chimney send buffer; move on */
290 send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
291 send_buf_section_size = 0;
294 hn_send_ctx_init(&request->send_ctx, cb, request,
295 send_buf_section_idx, send_buf_section_size);
296 return hv_nv_on_send(device->net_dev->sc->hn_prichan, false,
297 &request->send_ctx, gpa, gpa_cnt);
301 * RNDIS filter receive response
304 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
306 rndis_request *request = NULL;
307 rndis_request *next_request;
308 boolean_t found = FALSE;
310 mtx_lock(&device->req_lock);
311 request = STAILQ_FIRST(&device->myrequest_list);
312 while (request != NULL) {
314 * All request/response message contains request_id as the
317 if (request->request_msg.msg.init_request.request_id ==
318 response->msg.init_complete.request_id) {
322 next_request = STAILQ_NEXT(request, mylist_entry);
323 request = next_request;
325 mtx_unlock(&device->req_lock);
328 if (response->msg_len <= sizeof(rndis_msg)) {
329 memcpy(&request->response_msg, response,
332 if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
333 /* Does not have a request id field */
334 request->response_msg.msg.reset_complete.status =
335 STATUS_BUFFER_OVERFLOW;
337 request->response_msg.msg.init_complete.status =
338 STATUS_BUFFER_OVERFLOW;
342 sema_post(&request->wait_sema);
347 hv_rf_send_offload_request(struct hn_softc *sc,
348 rndis_offload_params *offloads)
350 rndis_request *request;
351 rndis_set_request *set;
352 rndis_offload_params *offload_req;
353 rndis_set_complete *set_complete;
354 rndis_device *rndis_dev;
355 device_t dev = sc->hn_dev;
356 netvsc_dev *net_dev = sc->net_dev;
357 uint32_t vsp_version = net_dev->nvsp_version;
358 uint32_t extlen = sizeof(rndis_offload_params);
361 if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
362 extlen = VERSION_4_OFFLOAD_SIZE;
363 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
364 * UDP checksum offload.
366 offloads->udp_ipv4_csum = 0;
367 offloads->udp_ipv6_csum = 0;
370 rndis_dev = net_dev->extension;
372 request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
373 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
377 set = &request->request_msg.msg.set_request;
378 set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
379 set->info_buffer_length = extlen;
380 set->info_buffer_offset = sizeof(rndis_set_request);
381 set->device_vc_handle = 0;
383 offload_req = (rndis_offload_params *)((unsigned long)set +
384 set->info_buffer_offset);
385 *offload_req = *offloads;
386 offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
387 offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
388 offload_req->header.size = extlen;
390 ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
392 device_printf(dev, "hv send offload request failed, ret=%d!\n",
397 ret = sema_timedwait(&request->wait_sema, 5 * hz);
399 device_printf(dev, "hv send offload request timeout\n");
403 set_complete = &request->response_msg.msg.set_complete;
404 if (set_complete->status == RNDIS_STATUS_SUCCESS) {
405 device_printf(dev, "hv send offload request succeeded\n");
408 if (set_complete->status == STATUS_NOT_SUPPORTED) {
409 device_printf(dev, "HV Not support offload\n");
412 ret = set_complete->status;
417 hv_put_rndis_request(rndis_dev, request);
423 * RNDIS filter receive indicate status
426 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
428 rndis_indicate_status *indicate = &response->msg.indicate_status;
430 switch(indicate->status) {
431 case RNDIS_STATUS_MEDIA_CONNECT:
432 netvsc_linkstatus_callback(device->net_dev->sc, 1);
434 case RNDIS_STATUS_MEDIA_DISCONNECT:
435 netvsc_linkstatus_callback(device->net_dev->sc, 0);
439 device_printf(device->net_dev->sc->hn_dev,
440 "unknown status %d received\n", indicate->status);
446 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
448 const rndis_per_packet_info *ppi;
451 info->vlan_info = NULL;
452 info->csum_info = NULL;
453 info->hash_info = NULL;
454 info->hash_value = NULL;
456 if (rpkt->per_pkt_info_offset == 0)
459 ppi = (const rndis_per_packet_info *)
460 ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
461 len = rpkt->per_pkt_info_length;
465 const void *ppi_dptr;
468 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
470 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
471 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
474 case ieee_8021q_info:
475 if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
477 info->vlan_info = ppi_dptr;
478 mask |= HV_RF_RECVINFO_VLAN;
481 case tcpip_chksum_info:
482 if (__predict_false(ppi_dlen <
483 sizeof(rndis_tcp_ip_csum_info)))
485 info->csum_info = ppi_dptr;
486 mask |= HV_RF_RECVINFO_CSUM;
490 if (__predict_false(ppi_dlen <
491 sizeof(struct rndis_hash_value)))
493 info->hash_value = ppi_dptr;
494 mask |= HV_RF_RECVINFO_HASHVAL;
498 if (__predict_false(ppi_dlen <
499 sizeof(struct rndis_hash_info)))
501 info->hash_info = ppi_dptr;
502 mask |= HV_RF_RECVINFO_HASHINF;
509 if (mask == HV_RF_RECVINFO_ALL) {
510 /* All found; done */
514 if (__predict_false(len < ppi->size))
517 ppi = (const rndis_per_packet_info *)
518 ((const uint8_t *)ppi + ppi->size);
524 * RNDIS filter receive data
527 hv_rf_receive_data(struct hn_rx_ring *rxr, rndis_msg *message,
530 rndis_packet *rndis_pkt;
531 uint32_t data_offset;
532 struct hv_rf_recvinfo info;
534 rndis_pkt = &message->msg.packet;
537 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
538 * netvsc packet (ie tot_data_buf_len != message_length)
541 /* Remove rndis header, then pass data packet up the stack */
542 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
544 pkt->tot_data_buf_len -= data_offset;
545 if (pkt->tot_data_buf_len < rndis_pkt->data_length) {
546 pkt->status = nvsp_status_failure;
547 if_printf(rxr->hn_ifp,
548 "total length %u is less than data length %u\n",
549 pkt->tot_data_buf_len, rndis_pkt->data_length);
553 pkt->tot_data_buf_len = rndis_pkt->data_length;
554 pkt->data = (void *)((unsigned long)pkt->data + data_offset);
556 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
557 pkt->status = nvsp_status_failure;
558 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
562 if (info.vlan_info != NULL)
563 pkt->vlan_tci = info.vlan_info->u1.s1.vlan_id;
567 netvsc_recv(rxr, pkt, info.csum_info, info.hash_info, info.hash_value);
571 * RNDIS filter on receive
574 hv_rf_on_receive(netvsc_dev *net_dev,
575 struct hn_rx_ring *rxr, netvsc_packet *pkt)
577 rndis_device *rndis_dev;
578 rndis_msg *rndis_hdr;
580 /* Make sure the rndis device state is initialized */
581 if (net_dev->extension == NULL) {
582 pkt->status = nvsp_status_failure;
586 rndis_dev = (rndis_device *)net_dev->extension;
587 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED) {
588 pkt->status = nvsp_status_failure;
592 rndis_hdr = pkt->data;
594 switch (rndis_hdr->ndis_msg_type) {
597 case REMOTE_NDIS_PACKET_MSG:
598 hv_rf_receive_data(rxr, rndis_hdr, pkt);
600 /* completion messages */
601 case REMOTE_NDIS_INITIALIZE_CMPLT:
602 case REMOTE_NDIS_QUERY_CMPLT:
603 case REMOTE_NDIS_SET_CMPLT:
604 case REMOTE_NDIS_RESET_CMPLT:
605 case REMOTE_NDIS_KEEPALIVE_CMPLT:
606 hv_rf_receive_response(rndis_dev, rndis_hdr);
608 /* notification message */
609 case REMOTE_NDIS_INDICATE_STATUS_MSG:
610 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
613 printf("hv_rf_on_receive(): Unknown msg_type 0x%x\n",
614 rndis_hdr->ndis_msg_type);
622 * RNDIS filter query device
625 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
626 uint32_t *result_size)
628 rndis_request *request;
629 uint32_t in_result_size = *result_size;
630 rndis_query_request *query;
631 rndis_query_complete *query_complete;
635 request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
636 RNDIS_MESSAGE_SIZE(rndis_query_request));
637 if (request == NULL) {
642 /* Set up the rndis query */
643 query = &request->request_msg.msg.query_request;
645 query->info_buffer_offset = sizeof(rndis_query_request);
646 query->info_buffer_length = 0;
647 query->device_vc_handle = 0;
649 if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
650 struct rndis_recv_scale_cap *cap;
652 request->request_msg.msg_len +=
653 sizeof(struct rndis_recv_scale_cap);
654 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
655 cap = (struct rndis_recv_scale_cap *)((unsigned long)query +
656 query->info_buffer_offset);
657 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
658 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
659 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
662 ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
664 /* Fixme: printf added */
665 printf("RNDISFILTER request failed to Send!\n");
669 sema_wait(&request->wait_sema);
671 /* Copy the response back */
672 query_complete = &request->response_msg.msg.query_complete;
674 if (query_complete->info_buffer_length > in_result_size) {
679 memcpy(result, (void *)((unsigned long)query_complete +
680 query_complete->info_buffer_offset),
681 query_complete->info_buffer_length);
683 *result_size = query_complete->info_buffer_length;
687 hv_put_rndis_request(device, request);
693 * RNDIS filter query device MAC address
696 hv_rf_query_device_mac(rndis_device *device)
698 uint32_t size = ETHER_ADDR_LEN;
700 return (hv_rf_query_device(device,
701 RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
705 * RNDIS filter query device link status
708 hv_rf_query_device_link_status(rndis_device *device)
710 uint32_t size = sizeof(uint32_t);
712 return (hv_rf_query_device(device,
713 RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
716 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
717 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
718 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
719 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
720 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
721 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
725 * RNDIS set vRSS parameters
728 hv_rf_set_rss_param(rndis_device *device, int num_queue)
730 rndis_request *request;
731 rndis_set_request *set;
732 rndis_set_complete *set_complete;
733 rndis_recv_scale_param *rssp;
734 uint32_t extlen = sizeof(rndis_recv_scale_param) +
735 (4 * ITAB_NUM) + HASH_KEYLEN;
736 uint32_t *itab, status;
741 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
742 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
743 if (request == NULL) {
745 printf("Netvsc: No memory to set vRSS parameters.\n");
750 set = &request->request_msg.msg.set_request;
751 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
752 set->info_buffer_length = extlen;
753 set->info_buffer_offset = sizeof(rndis_set_request);
754 set->device_vc_handle = 0;
756 /* Fill out the rssp parameter structure */
757 rssp = (rndis_recv_scale_param *)(set + 1);
758 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
759 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
760 rssp->hdr.size = sizeof(rndis_recv_scale_param);
762 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
763 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
764 rssp->indirect_tabsize = 4 * ITAB_NUM;
765 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
766 rssp->hashkey_size = HASH_KEYLEN;
767 rssp->hashkey_offset = rssp->indirect_taboffset +
768 rssp->indirect_tabsize;
770 /* Set indirection table entries */
771 itab = (uint32_t *)(rssp + 1);
772 for (i = 0; i < ITAB_NUM; i++)
773 itab[i] = i % num_queue;
775 /* Set hash key values */
776 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
777 for (i = 0; i < HASH_KEYLEN; i++)
778 keyp[i] = netvsc_hash_key[i];
780 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
786 * Wait for the response from the host. Another thread will signal
787 * us when the response has arrived. In the failure case,
788 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
790 ret = sema_timedwait(&request->wait_sema, 5 * hz);
792 /* Response received, check status */
793 set_complete = &request->response_msg.msg.set_complete;
794 status = set_complete->status;
795 if (status != RNDIS_STATUS_SUCCESS) {
796 /* Bad response status, return error */
798 printf("Netvsc: Failed to set vRSS "
803 printf("Netvsc: Successfully set vRSS "
808 * We cannot deallocate the request since we may still
809 * receive a send completion for it.
811 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
812 request->request_msg.msg.init_request.request_id, ret);
817 if (request != NULL) {
818 hv_put_rndis_request(device, request);
825 * RNDIS filter set packet filter
826 * Sends an rndis request with the new filter, then waits for a response
828 * Returns zero on success, non-zero on failure.
831 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
833 rndis_request *request;
834 rndis_set_request *set;
835 rndis_set_complete *set_complete;
839 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
840 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
841 if (request == NULL) {
846 /* Set up the rndis set */
847 set = &request->request_msg.msg.set_request;
848 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
849 set->info_buffer_length = sizeof(uint32_t);
850 set->info_buffer_offset = sizeof(rndis_set_request);
852 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
853 &new_filter, sizeof(uint32_t));
855 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
861 * Wait for the response from the host. Another thread will signal
862 * us when the response has arrived. In the failure case,
863 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
865 ret = sema_timedwait(&request->wait_sema, 5 * hz);
867 /* Response received, check status */
868 set_complete = &request->response_msg.msg.set_complete;
869 status = set_complete->status;
870 if (status != RNDIS_STATUS_SUCCESS) {
871 /* Bad response status, return error */
876 * We cannot deallocate the request since we may still
877 * receive a send completion for it.
883 if (request != NULL) {
884 hv_put_rndis_request(device, request);
891 * RNDIS filter init device
894 hv_rf_init_device(rndis_device *device)
896 rndis_request *request;
897 rndis_initialize_request *init;
898 rndis_initialize_complete *init_complete;
902 request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
903 RNDIS_MESSAGE_SIZE(rndis_initialize_request));
909 /* Set up the rndis set */
910 init = &request->request_msg.msg.init_request;
911 init->major_version = RNDIS_MAJOR_VERSION;
912 init->minor_version = RNDIS_MINOR_VERSION;
914 * Per the RNDIS document, this should be set to the max MTU
915 * plus the header size. However, 2048 works fine, so leaving
918 init->max_xfer_size = 2048;
920 device->state = RNDIS_DEV_INITIALIZING;
922 ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
924 device->state = RNDIS_DEV_UNINITIALIZED;
928 sema_wait(&request->wait_sema);
930 init_complete = &request->response_msg.msg.init_complete;
931 status = init_complete->status;
932 if (status == RNDIS_STATUS_SUCCESS) {
933 device->state = RNDIS_DEV_INITIALIZED;
936 device->state = RNDIS_DEV_UNINITIALIZED;
942 hv_put_rndis_request(device, request);
948 #define HALT_COMPLETION_WAIT_COUNT 25
951 * RNDIS filter halt device
954 hv_rf_halt_device(rndis_device *device)
956 rndis_request *request;
957 rndis_halt_request *halt;
960 /* Attempt to do a rndis device halt */
961 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
962 RNDIS_MESSAGE_SIZE(rndis_halt_request));
963 if (request == NULL) {
967 /* initialize "poor man's semaphore" */
968 request->halt_complete_flag = 0;
970 /* Set up the rndis set */
971 halt = &request->request_msg.msg.halt_request;
972 halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
973 /* Increment to get the new value (call above returns old value) */
974 halt->request_id += 1;
976 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
982 * Wait for halt response from halt callback. We must wait for
983 * the transaction response before freeing the request and other
986 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
987 if (request->halt_complete_flag != 0) {
996 device->state = RNDIS_DEV_UNINITIALIZED;
998 hv_put_rndis_request(device, request);
1004 * RNDIS filter open device
1007 hv_rf_open_device(rndis_device *device)
1011 if (device->state != RNDIS_DEV_INITIALIZED) {
1015 if (hv_promisc_mode != 1) {
1016 ret = hv_rf_set_packet_filter(device,
1017 NDIS_PACKET_TYPE_BROADCAST |
1018 NDIS_PACKET_TYPE_ALL_MULTICAST |
1019 NDIS_PACKET_TYPE_DIRECTED);
1021 ret = hv_rf_set_packet_filter(device,
1022 NDIS_PACKET_TYPE_PROMISCUOUS);
1026 device->state = RNDIS_DEV_DATAINITIALIZED;
1033 * RNDIS filter close device
1036 hv_rf_close_device(rndis_device *device)
1040 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1044 ret = hv_rf_set_packet_filter(device, 0);
1046 device->state = RNDIS_DEV_INITIALIZED;
1053 * RNDIS filter on device add
1056 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1057 int nchan, struct hn_rx_ring *rxr)
1059 struct hn_send_ctx sndc;
1061 netvsc_dev *net_dev;
1062 rndis_device *rndis_dev;
1064 rndis_offload_params offloads;
1065 struct rndis_recv_scale_cap rsscaps;
1066 uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1067 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1068 device_t dev = sc->hn_dev;
1070 rndis_dev = hv_get_rndis_device();
1071 if (rndis_dev == NULL) {
1076 * Let the inner driver handle this first to create the netvsc channel
1077 * NOTE! Once the channel is created, we may get a receive callback
1078 * (hv_rf_on_receive()) before this call is completed.
1079 * Note: Earlier code used a function pointer here.
1081 net_dev = hv_nv_on_device_add(sc, additl_info, rxr);
1083 hv_put_rndis_device(rndis_dev);
1089 * Initialize the rndis device
1092 net_dev->extension = rndis_dev;
1093 rndis_dev->net_dev = net_dev;
1095 /* Send the rndis initialization message */
1096 ret = hv_rf_init_device(rndis_dev);
1099 * TODO: If rndis init failed, we will need to shut down
1104 /* Get the mac address */
1105 ret = hv_rf_query_device_mac(rndis_dev);
1107 /* TODO: shut down rndis device and the channel */
1110 /* config csum offload and send request to host */
1111 memset(&offloads, 0, sizeof(offloads));
1112 offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1113 offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1114 offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1115 offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1116 offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1117 offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1119 ret = hv_rf_send_offload_request(sc, &offloads);
1121 /* TODO: shut down rndis device and the channel */
1123 "hv_rf_send_offload_request failed, ret=%d\n", ret);
1126 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1128 hv_rf_query_device_link_status(rndis_dev);
1130 dev_info->link_state = rndis_dev->link_status;
1132 net_dev->num_channel = 1;
1133 if (net_dev->nvsp_version < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1136 memset(&rsscaps, 0, rsscaps_size);
1137 ret = hv_rf_query_device(rndis_dev,
1138 RNDIS_OID_GEN_RSS_CAPABILITIES,
1139 &rsscaps, &rsscaps_size);
1140 if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1141 device_printf(dev, "hv_rf_query_device failed or "
1142 "rsscaps.num_recv_que < 2 \n");
1145 device_printf(dev, "channel, offered %u, requested %d\n",
1146 rsscaps.num_recv_que, nchan);
1147 if (nchan > rsscaps.num_recv_que)
1148 nchan = rsscaps.num_recv_que;
1149 net_dev->num_channel = nchan;
1151 if (net_dev->num_channel == 1) {
1152 device_printf(dev, "net_dev->num_channel == 1 under VRSS\n");
1156 /* request host to create sub channels */
1157 init_pkt = &net_dev->channel_init_packet;
1158 memset(init_pkt, 0, sizeof(nvsp_msg));
1160 init_pkt->hdr.msg_type = nvsp_msg5_type_subchannel;
1161 init_pkt->msgs.vers_5_msgs.subchannel_request.op =
1162 NVSP_SUBCHANNE_ALLOCATE;
1163 init_pkt->msgs.vers_5_msgs.subchannel_request.num_subchannels =
1164 net_dev->num_channel - 1;
1166 hn_send_ctx_init_simple(&sndc, hn_nvs_sent_wakeup, NULL);
1167 ret = vmbus_chan_send(sc->hn_prichan,
1168 VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC,
1169 init_pkt, sizeof(nvsp_msg), (uint64_t)(uintptr_t)&sndc);
1171 device_printf(dev, "Fail to allocate subchannel\n");
1175 sema_wait(&net_dev->channel_init_sema);
1177 if (init_pkt->msgs.vers_5_msgs.subchn_complete.status !=
1178 nvsp_status_success) {
1180 device_printf(dev, "sub channel complete error\n");
1184 net_dev->num_channel = 1 +
1185 init_pkt->msgs.vers_5_msgs.subchn_complete.num_subchannels;
1187 ret = hv_rf_set_rss_param(rndis_dev, net_dev->num_channel);
1191 net_dev->num_channel = 1;
1197 * RNDIS filter on device remove
1200 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1202 netvsc_dev *net_dev = sc->net_dev;
1203 rndis_device *rndis_dev = (rndis_device *)net_dev->extension;
1206 /* Halt and release the rndis device */
1207 ret = hv_rf_halt_device(rndis_dev);
1209 hv_put_rndis_device(rndis_dev);
1210 net_dev->extension = NULL;
1212 /* Pass control to inner driver to remove the device */
1213 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1219 * RNDIS filter on open
1222 hv_rf_on_open(struct hn_softc *sc)
1224 netvsc_dev *net_dev = sc->net_dev;
1226 return (hv_rf_open_device((rndis_device *)net_dev->extension));
1230 * RNDIS filter on close
1233 hv_rf_on_close(struct hn_softc *sc)
1235 netvsc_dev *net_dev = sc->net_dev;
1237 return (hv_rf_close_device((rndis_device *)net_dev->extension));
1241 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
1242 struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
1245 if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
1246 hn_chim_free(net_dev, sndc->hn_chim_idx);
1250 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct netvsc_dev_ *net_dev,
1251 struct vmbus_channel *chan __unused, const struct nvsp_msg_ *msg __unused,
1254 rndis_request *request = sndc->hn_cbarg;
1256 if (sndc->hn_chim_idx != NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX)
1257 hn_chim_free(net_dev, sndc->hn_chim_idx);
1260 * Notify hv_rf_halt_device() about halt completion.
1261 * The halt code must wait for completion before freeing
1262 * the transaction resources.
1264 request->halt_complete_flag = 1;
1268 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1271 netvsc_channel_rollup(rxr, txr);