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>
54 #include <dev/hyperv/netvsc/ndis.h>
56 #define HV_RF_RECVINFO_VLAN 0x1
57 #define HV_RF_RECVINFO_CSUM 0x2
58 #define HV_RF_RECVINFO_HASHINF 0x4
59 #define HV_RF_RECVINFO_HASHVAL 0x8
60 #define HV_RF_RECVINFO_ALL \
61 (HV_RF_RECVINFO_VLAN | \
62 HV_RF_RECVINFO_CSUM | \
63 HV_RF_RECVINFO_HASHINF | \
64 HV_RF_RECVINFO_HASHVAL)
66 #define HN_RNDIS_RID_COMPAT_MASK 0xffff
67 #define HN_RNDIS_RID_COMPAT_MAX HN_RNDIS_RID_COMPAT_MASK
69 #define HN_RNDIS_XFER_SIZE 2048
72 * Forward declarations
74 static int hv_rf_send_request(rndis_device *device, rndis_request *request,
75 uint32_t message_type);
76 static void hv_rf_receive_response(rndis_device *device,
77 const rndis_msg *response);
78 static void hv_rf_receive_indicate_status(rndis_device *device,
79 const rndis_msg *response);
80 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
81 const void *data, int dlen);
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 hn_softc *sc, struct vmbus_channel *chan,
94 const void *data, int dlen);
95 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
96 struct hn_softc *sc, struct vmbus_channel *chan,
97 const void *data, int dlen);
98 static int hn_rndis_query(struct hn_softc *sc, uint32_t oid,
99 const void *idata, size_t idlen, void *odata, size_t *odlen0);
100 static int hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data,
102 static int hn_rndis_conf_offload(struct hn_softc *sc);
103 static int hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt);
105 static __inline uint32_t
106 hn_rndis_rid(struct hn_softc *sc)
111 rid = atomic_fetchadd_int(&sc->hn_rndis_rid, 1);
115 /* Use upper 16 bits for non-compat RNDIS messages. */
116 return ((rid & 0xffff) << 16);
120 * Set the Per-Packet-Info with the specified type
123 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
126 rndis_packet *rndis_pkt;
127 rndis_per_packet_info *rppi;
129 rndis_pkt = &rndis_mesg->msg.packet;
130 rndis_pkt->data_offset += rppi_size;
132 rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
133 rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
135 rppi->size = rppi_size;
136 rppi->type = pkt_type;
137 rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
139 rndis_pkt->per_pkt_info_length += rppi_size;
145 * Get the Per-Packet-Info with the specified type
146 * return NULL if not found.
149 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
151 rndis_per_packet_info *ppi;
154 if (rpkt->per_pkt_info_offset == 0)
157 ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
158 rpkt->per_pkt_info_offset);
159 len = rpkt->per_pkt_info_length;
162 if (ppi->type == type)
163 return (void *)((unsigned long)ppi +
164 ppi->per_packet_info_offset);
167 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
175 * Allow module_param to work and override to switch to promiscuous mode.
177 static inline rndis_device *
178 hv_get_rndis_device(void)
180 rndis_device *device;
182 device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
184 mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
186 /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
187 STAILQ_INIT(&device->myrequest_list);
189 device->state = RNDIS_DEV_UNINITIALIZED;
198 hv_put_rndis_device(rndis_device *device)
200 mtx_destroy(&device->req_lock);
201 free(device, M_NETVSC);
207 static inline rndis_request *
208 hv_rndis_request(rndis_device *device, uint32_t message_type,
209 uint32_t message_length)
211 rndis_request *request;
212 rndis_msg *rndis_mesg;
213 rndis_set_request *set;
215 request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
217 sema_init(&request->wait_sema, 0, "rndis sema");
219 rndis_mesg = &request->request_msg;
220 rndis_mesg->ndis_msg_type = message_type;
221 rndis_mesg->msg_len = message_length;
224 * Set the request id. This field is always after the rndis header
225 * for request/response packet types so we just use the set_request
228 set = &rndis_mesg->msg.set_request;
229 set->request_id = atomic_fetchadd_int(&device->new_request_id, 1) &
230 HN_RNDIS_RID_COMPAT_MASK;
232 /* Add to the request list */
233 mtx_lock(&device->req_lock);
234 STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
235 mtx_unlock(&device->req_lock);
244 hv_put_rndis_request(rndis_device *device, rndis_request *request)
246 mtx_lock(&device->req_lock);
247 /* Fixme: Has O(n) performance */
249 * XXXKYS: Use Doubly linked lists.
251 STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
253 mtx_unlock(&device->req_lock);
255 sema_destroy(&request->wait_sema);
256 free(request, M_NETVSC);
263 hv_rf_send_request(rndis_device *device, rndis_request *request,
264 uint32_t message_type)
266 struct hn_softc *sc = device->sc;
267 uint32_t send_buf_section_idx, tot_data_buf_len;
268 struct vmbus_gpa gpa[2];
269 int gpa_cnt, send_buf_section_size;
270 hn_sent_callback_t cb;
272 /* Set up the packet to send it */
273 tot_data_buf_len = request->request_msg.msg_len;
276 gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
277 gpa[0].gpa_len = request->request_msg.msg_len;
278 gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
280 if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
282 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
284 hv_get_phys_addr((char*)&request->request_msg +
285 gpa[0].gpa_len) >> PAGE_SHIFT;
287 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
290 if (message_type != REMOTE_NDIS_HALT_MSG)
291 cb = hn_rndis_sent_cb;
293 cb = hn_rndis_sent_halt;
295 if (tot_data_buf_len < sc->hn_chim_szmax) {
296 send_buf_section_idx = hn_chim_alloc(sc);
297 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
298 uint8_t *dest = sc->hn_chim +
299 (send_buf_section_idx * sc->hn_chim_szmax);
301 memcpy(dest, &request->request_msg, request->request_msg.msg_len);
302 send_buf_section_size = tot_data_buf_len;
306 /* Failed to allocate chimney send buffer; move on */
308 send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
309 send_buf_section_size = 0;
312 hn_send_ctx_init(&request->send_ctx, cb, request,
313 send_buf_section_idx, send_buf_section_size);
314 return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
315 &request->send_ctx, gpa, gpa_cnt);
319 * RNDIS filter receive response
322 hv_rf_receive_response(rndis_device *device, const rndis_msg *response)
324 rndis_request *request = NULL;
325 rndis_request *next_request;
326 boolean_t found = FALSE;
328 mtx_lock(&device->req_lock);
329 request = STAILQ_FIRST(&device->myrequest_list);
330 while (request != NULL) {
332 * All request/response message contains request_id as the
335 if (request->request_msg.msg.init_request.request_id ==
336 response->msg.init_complete.request_id) {
340 next_request = STAILQ_NEXT(request, mylist_entry);
341 request = next_request;
343 mtx_unlock(&device->req_lock);
346 if (response->msg_len <= sizeof(rndis_msg)) {
347 memcpy(&request->response_msg, response,
350 request->response_msg.msg.init_complete.status =
351 RNDIS_STATUS_BUFFER_OVERFLOW;
353 sema_post(&request->wait_sema);
358 hv_rf_send_offload_request(struct hn_softc *sc,
359 rndis_offload_params *offloads)
361 rndis_request *request;
362 rndis_set_request *set;
363 rndis_offload_params *offload_req;
364 rndis_set_complete *set_complete;
365 rndis_device *rndis_dev = sc->rndis_dev;
366 device_t dev = sc->hn_dev;
367 uint32_t extlen = sizeof(rndis_offload_params);
370 if (sc->hn_nvs_ver <= NVSP_PROTOCOL_VERSION_4) {
371 extlen = VERSION_4_OFFLOAD_SIZE;
372 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
373 * UDP checksum offload.
375 offloads->udp_ipv4_csum = 0;
376 offloads->udp_ipv6_csum = 0;
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 == RNDIS_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, const rndis_msg *response)
435 const rndis_indicate_status *indicate = &response->msg.indicate_status;
437 switch(indicate->status) {
438 case RNDIS_STATUS_MEDIA_CONNECT:
439 netvsc_linkstatus_callback(device->sc, 1);
441 case RNDIS_STATUS_MEDIA_DISCONNECT:
442 netvsc_linkstatus_callback(device->sc, 0);
446 device_printf(device->sc->hn_dev,
447 "unknown status %d received\n", indicate->status);
453 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_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(struct hn_rx_ring *rxr, const void *data, int dlen)
536 const rndis_msg *message = data;
537 const rndis_packet *rndis_pkt;
538 uint32_t data_offset;
539 struct hn_recvinfo info;
541 rndis_pkt = &message->msg.packet;
544 * Fixme: Handle multiple rndis pkt msgs that may be enclosed in this
545 * netvsc packet (ie tot_data_buf_len != message_length)
548 /* Remove rndis header, then pass data packet up the stack */
549 data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
552 if (dlen < rndis_pkt->data_length) {
553 if_printf(rxr->hn_ifp,
554 "total length %u is less than data length %u\n",
555 dlen, rndis_pkt->data_length);
559 dlen = rndis_pkt->data_length;
560 data = (const uint8_t *)data + data_offset;
562 if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
563 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
566 netvsc_recv(rxr, data, dlen, &info);
570 * RNDIS filter on receive
573 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
574 const void *data, int dlen)
576 rndis_device *rndis_dev;
577 const rndis_msg *rndis_hdr;
578 const struct rndis_comp_hdr *comp;
580 rndis_dev = sc->rndis_dev;
581 if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
585 switch (rndis_hdr->ndis_msg_type) {
587 case REMOTE_NDIS_PACKET_MSG:
588 hv_rf_receive_data(rxr, data, dlen);
591 /* completion messages */
592 case REMOTE_NDIS_INITIALIZE_CMPLT:
593 case REMOTE_NDIS_QUERY_CMPLT:
594 case REMOTE_NDIS_SET_CMPLT:
595 case REMOTE_NDIS_KEEPALIVE_CMPLT:
597 if (comp->rm_rid <= HN_RNDIS_RID_COMPAT_MAX) {
598 /* Transition time compat code */
599 hv_rf_receive_response(rndis_dev, rndis_hdr);
601 vmbus_xact_ctx_wakeup(sc->hn_xact, data, dlen);
605 /* notification message */
606 case REMOTE_NDIS_INDICATE_STATUS_MSG:
607 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
610 case REMOTE_NDIS_RESET_CMPLT:
612 * Reset completed, no rid.
615 * RESET is not issued by hn(4), so this message should
618 if_printf(sc->hn_ifp, "RESET CMPLT received\n");
622 if_printf(sc->hn_ifp, "unknown RNDIS message 0x%x\n",
623 rndis_hdr->ndis_msg_type);
630 * RNDIS filter query device MAC address
633 hv_rf_query_device_mac(rndis_device *device)
635 struct hn_softc *sc = device->sc;
639 hwaddr_len = ETHER_ADDR_LEN;
640 error = hn_rndis_query(sc, OID_802_3_PERMANENT_ADDRESS, NULL, 0,
641 device->hw_mac_addr, &hwaddr_len);
644 if (hwaddr_len != ETHER_ADDR_LEN) {
645 if_printf(sc->hn_ifp, "invalid hwaddr len %zu\n", hwaddr_len);
652 * RNDIS filter query device link status
655 hv_rf_query_device_link_status(rndis_device *device)
657 struct hn_softc *sc = device->sc;
661 size = sizeof(uint32_t);
662 error = hn_rndis_query(sc, OID_GEN_MEDIA_CONNECT_STATUS, NULL, 0,
663 &device->link_status, &size);
666 if (size != sizeof(uint32_t)) {
667 if_printf(sc->hn_ifp, "invalid link status len %zu\n", size);
673 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
674 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
675 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
676 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
677 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
678 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
682 * RNDIS set vRSS parameters
685 hv_rf_set_rss_param(rndis_device *device, int num_queue)
687 rndis_request *request;
688 rndis_set_request *set;
689 rndis_set_complete *set_complete;
690 rndis_recv_scale_param *rssp;
691 uint32_t extlen = sizeof(rndis_recv_scale_param) +
692 (4 * ITAB_NUM) + HASH_KEYLEN;
693 uint32_t *itab, status;
698 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
699 RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
700 if (request == NULL) {
702 printf("Netvsc: No memory to set vRSS parameters.\n");
707 set = &request->request_msg.msg.set_request;
708 set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
709 set->info_buffer_length = extlen;
710 set->info_buffer_offset = sizeof(rndis_set_request);
711 set->device_vc_handle = 0;
713 /* Fill out the rssp parameter structure */
714 rssp = (rndis_recv_scale_param *)(set + 1);
715 rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
716 rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
717 rssp->hdr.size = sizeof(rndis_recv_scale_param);
719 rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
720 RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
721 rssp->indirect_tabsize = 4 * ITAB_NUM;
722 rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
723 rssp->hashkey_size = HASH_KEYLEN;
724 rssp->hashkey_offset = rssp->indirect_taboffset +
725 rssp->indirect_tabsize;
727 /* Set indirection table entries */
728 itab = (uint32_t *)(rssp + 1);
729 for (i = 0; i < ITAB_NUM; i++)
730 itab[i] = i % num_queue;
732 /* Set hash key values */
733 keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
734 for (i = 0; i < HASH_KEYLEN; i++)
735 keyp[i] = netvsc_hash_key[i];
737 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
743 * Wait for the response from the host. Another thread will signal
744 * us when the response has arrived. In the failure case,
745 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
747 ret = sema_timedwait(&request->wait_sema, 5 * hz);
749 /* Response received, check status */
750 set_complete = &request->response_msg.msg.set_complete;
751 status = set_complete->status;
752 if (status != RNDIS_STATUS_SUCCESS) {
753 /* Bad response status, return error */
755 printf("Netvsc: Failed to set vRSS "
760 printf("Netvsc: Successfully set vRSS "
765 * We cannot deallocate the request since we may still
766 * receive a send completion for it.
768 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
769 request->request_msg.msg.init_request.request_id, ret);
774 if (request != NULL) {
775 hv_put_rndis_request(device, request);
782 * RNDIS filter set packet filter
783 * Sends an rndis request with the new filter, then waits for a response
785 * Returns zero on success, non-zero on failure.
788 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
790 rndis_request *request;
791 rndis_set_request *set;
792 rndis_set_complete *set_complete;
796 request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
797 RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
798 if (request == NULL) {
803 /* Set up the rndis set */
804 set = &request->request_msg.msg.set_request;
805 set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
806 set->info_buffer_length = sizeof(uint32_t);
807 set->info_buffer_offset = sizeof(rndis_set_request);
809 memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
810 &new_filter, sizeof(uint32_t));
812 ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
818 * Wait for the response from the host. Another thread will signal
819 * us when the response has arrived. In the failure case,
820 * sema_timedwait() returns a non-zero status after waiting 5 seconds.
822 ret = sema_timedwait(&request->wait_sema, 5 * hz);
824 /* Response received, check status */
825 set_complete = &request->response_msg.msg.set_complete;
826 status = set_complete->status;
827 if (status != RNDIS_STATUS_SUCCESS) {
828 /* Bad response status, return error */
833 * We cannot deallocate the request since we may still
834 * receive a send completion for it.
840 if (request != NULL) {
841 hv_put_rndis_request(device, request);
848 hn_rndis_xact_execute(struct hn_softc *sc, struct vmbus_xact *xact, uint32_t rid,
849 size_t reqlen, size_t *comp_len0, uint32_t comp_type)
851 struct vmbus_gpa gpa[HN_XACT_REQ_PGCNT];
852 const struct rndis_comp_hdr *comp;
854 size_t comp_len, min_complen = *comp_len0;
857 KASSERT(rid > HN_RNDIS_RID_COMPAT_MAX, ("invalid rid %u\n", rid));
858 KASSERT(reqlen <= HN_XACT_REQ_SIZE && reqlen > 0,
859 ("invalid request length %zu", reqlen));
860 KASSERT(min_complen >= sizeof(*comp),
861 ("invalid minimum complete len %zu", min_complen));
866 paddr = vmbus_xact_req_paddr(xact);
867 KASSERT((paddr & PAGE_MASK) == 0,
868 ("vmbus xact request is not page aligned 0x%jx", (uintmax_t)paddr));
869 for (gpa_cnt = 0; gpa_cnt < HN_XACT_REQ_PGCNT; ++gpa_cnt) {
877 gpa[gpa_cnt].gpa_page = atop(paddr) + gpa_cnt;
878 gpa[gpa_cnt].gpa_len = len;
879 gpa[gpa_cnt].gpa_ofs = 0;
883 KASSERT(reqlen == 0, ("still have %zu request data left", reqlen));
886 * Send this RNDIS control message and wait for its completion
889 vmbus_xact_activate(xact);
890 error = hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
891 &hn_send_ctx_none, gpa, gpa_cnt);
893 vmbus_xact_deactivate(xact);
894 if_printf(sc->hn_ifp, "RNDIS ctrl send failed: %d\n", error);
897 comp = vmbus_xact_wait(xact, &comp_len);
900 * Check this RNDIS complete message.
902 if (comp_len < min_complen) {
903 if (comp_len >= sizeof(*comp)) {
904 /* rm_status field is valid */
905 if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu, "
906 "status 0x%08x\n", comp_len, comp->rm_status);
908 if_printf(sc->hn_ifp, "invalid RNDIS comp len %zu\n",
913 if (comp->rm_len < min_complen) {
914 if_printf(sc->hn_ifp, "invalid RNDIS comp msglen %u\n",
918 if (comp->rm_type != comp_type) {
919 if_printf(sc->hn_ifp, "unexpected RNDIS comp 0x%08x, "
920 "expect 0x%08x\n", comp->rm_type, comp_type);
923 if (comp->rm_rid != rid) {
924 if_printf(sc->hn_ifp, "RNDIS comp rid mismatch %u, "
925 "expect %u\n", comp->rm_rid, rid);
929 *comp_len0 = comp_len;
934 hn_rndis_query(struct hn_softc *sc, uint32_t oid,
935 const void *idata, size_t idlen, void *odata, size_t *odlen0)
937 struct rndis_query_req *req;
938 const struct rndis_query_comp *comp;
939 struct vmbus_xact *xact;
940 size_t reqlen, odlen = *odlen0, comp_len;
944 reqlen = sizeof(*req) + idlen;
945 xact = vmbus_xact_get(sc->hn_xact, reqlen);
947 if_printf(sc->hn_ifp, "no xact for RNDIS query 0x%08x\n", oid);
950 rid = hn_rndis_rid(sc);
951 req = vmbus_xact_req_data(xact);
952 req->rm_type = REMOTE_NDIS_QUERY_MSG;
953 req->rm_len = reqlen;
958 * This is _not_ RNDIS Spec conforming:
959 * "This MUST be set to 0 when there is no input data
960 * associated with the OID."
962 * If this field was set to 0 according to the RNDIS Spec,
963 * Hyper-V would set non-SUCCESS status in the query
966 req->rm_infobufoffset = RNDIS_QUERY_REQ_INFOBUFOFFSET;
969 req->rm_infobuflen = idlen;
970 /* Input data immediately follows RNDIS query. */
971 memcpy(req + 1, idata, idlen);
974 comp_len = sizeof(*comp) + odlen;
975 comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
976 REMOTE_NDIS_QUERY_CMPLT);
978 if_printf(sc->hn_ifp, "exec RNDIS query 0x%08x failed\n", oid);
983 if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
984 if_printf(sc->hn_ifp, "RNDIS query 0x%08x failed: "
985 "status 0x%08x\n", oid, comp->rm_status);
989 if (comp->rm_infobuflen == 0 || comp->rm_infobufoffset == 0) {
990 /* No output data! */
991 if_printf(sc->hn_ifp, "RNDIS query 0x%08x, no data\n", oid);
998 * Check output data length and offset.
1000 /* ofs is the offset from the beginning of comp. */
1001 ofs = RNDIS_QUERY_COMP_INFOBUFABS(comp->rm_infobufoffset);
1002 if (ofs < sizeof(*comp) || ofs + comp->rm_infobuflen > comp_len) {
1003 if_printf(sc->hn_ifp, "RNDIS query invalid comp ib off/len, "
1004 "%u/%u\n", comp->rm_infobufoffset, comp->rm_infobuflen);
1012 if (comp->rm_infobuflen < odlen)
1013 odlen = comp->rm_infobuflen;
1014 memcpy(odata, ((const uint8_t *)comp) + ofs, odlen);
1019 vmbus_xact_put(xact);
1024 hn_rndis_get_rsscaps(struct hn_softc *sc, int *rxr_cnt)
1026 struct ndis_rss_caps in, caps;
1031 * Only NDIS 6.30+ is supported.
1033 KASSERT(sc->hn_ndis_ver >= NDIS_VERSION_6_30,
1034 ("NDIS 6.30+ is required, NDIS version 0x%08x", sc->hn_ndis_ver));
1037 memset(&in, 0, sizeof(in));
1038 in.ndis_hdr.ndis_type = NDIS_OBJTYPE_RSS_CAPS;
1039 in.ndis_hdr.ndis_rev = NDIS_RSS_CAPS_REV_2;
1040 in.ndis_hdr.ndis_size = NDIS_RSS_CAPS_SIZE;
1042 caps_len = NDIS_RSS_CAPS_SIZE;
1043 error = hn_rndis_query(sc, OID_GEN_RSS_CAPABILITIES,
1044 &in, NDIS_RSS_CAPS_SIZE, &caps, &caps_len);
1047 if (caps_len < NDIS_RSS_CAPS_SIZE_6_0) {
1048 if_printf(sc->hn_ifp, "invalid NDIS RSS caps len %zu",
1053 if (caps.ndis_nrxr == 0) {
1054 if_printf(sc->hn_ifp, "0 RX rings!?\n");
1057 *rxr_cnt = caps.ndis_nrxr;
1059 if (caps_len == NDIS_RSS_CAPS_SIZE) {
1061 if_printf(sc->hn_ifp, "RSS indirect table size %u\n",
1069 hn_rndis_set(struct hn_softc *sc, uint32_t oid, const void *data, size_t dlen)
1071 struct rndis_set_req *req;
1072 const struct rndis_set_comp *comp;
1073 struct vmbus_xact *xact;
1074 size_t reqlen, comp_len;
1078 KASSERT(dlen > 0, ("invalid dlen %zu", dlen));
1080 reqlen = sizeof(*req) + dlen;
1081 xact = vmbus_xact_get(sc->hn_xact, reqlen);
1083 if_printf(sc->hn_ifp, "no xact for RNDIS set 0x%08x\n", oid);
1086 rid = hn_rndis_rid(sc);
1087 req = vmbus_xact_req_data(xact);
1088 req->rm_type = REMOTE_NDIS_SET_MSG;
1089 req->rm_len = reqlen;
1092 req->rm_infobuflen = dlen;
1093 req->rm_infobufoffset = RNDIS_SET_REQ_INFOBUFOFFSET;
1094 /* Data immediately follows RNDIS set. */
1095 memcpy(req + 1, data, dlen);
1097 comp_len = sizeof(*comp);
1098 comp = hn_rndis_xact_execute(sc, xact, rid, reqlen, &comp_len,
1099 REMOTE_NDIS_SET_CMPLT);
1101 if_printf(sc->hn_ifp, "exec RNDIS set 0x%08x failed\n", oid);
1106 if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
1107 if_printf(sc->hn_ifp, "RNDIS set 0x%08x failed: "
1108 "status 0x%08x\n", oid, comp->rm_status);
1114 vmbus_xact_put(xact);
1119 hn_rndis_conf_offload(struct hn_softc *sc)
1121 struct ndis_offload_params params;
1125 /* NOTE: 0 means "no change" */
1126 memset(¶ms, 0, sizeof(params));
1128 params.ndis_hdr.ndis_type = NDIS_OBJTYPE_DEFAULT;
1129 if (sc->hn_ndis_ver < NDIS_VERSION_6_30) {
1130 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_2;
1131 paramsz = NDIS_OFFLOAD_PARAMS_SIZE_6_1;
1133 params.ndis_hdr.ndis_rev = NDIS_OFFLOAD_PARAMS_REV_3;
1134 paramsz = NDIS_OFFLOAD_PARAMS_SIZE;
1136 params.ndis_hdr.ndis_size = paramsz;
1138 params.ndis_ip4csum = NDIS_OFFLOAD_PARAM_TXRX;
1139 params.ndis_tcp4csum = NDIS_OFFLOAD_PARAM_TXRX;
1140 params.ndis_tcp6csum = NDIS_OFFLOAD_PARAM_TXRX;
1141 if (sc->hn_ndis_ver >= NDIS_VERSION_6_30) {
1142 params.ndis_udp4csum = NDIS_OFFLOAD_PARAM_TXRX;
1143 params.ndis_udp6csum = NDIS_OFFLOAD_PARAM_TXRX;
1145 params.ndis_lsov2_ip4 = NDIS_OFFLOAD_LSOV2_ON;
1146 /* XXX ndis_lsov2_ip6 = NDIS_OFFLOAD_LSOV2_ON */
1148 error = hn_rndis_set(sc, OID_TCP_OFFLOAD_PARAMETERS, ¶ms, paramsz);
1150 if_printf(sc->hn_ifp, "offload config failed: %d\n", error);
1153 if_printf(sc->hn_ifp, "offload config done\n");
1159 * RNDIS filter init device
1162 hv_rf_init_device(rndis_device *device)
1164 struct hn_softc *sc = device->sc;
1165 struct rndis_init_req *req;
1166 const struct rndis_init_comp *comp;
1167 struct vmbus_xact *xact;
1173 device->state = RNDIS_DEV_INITIALIZED;
1175 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1177 if_printf(sc->hn_ifp, "no xact for RNDIS init\n");
1180 rid = hn_rndis_rid(sc);
1181 req = vmbus_xact_req_data(xact);
1182 req->rm_type = REMOTE_NDIS_INITIALIZE_MSG;
1183 req->rm_len = sizeof(*req);
1185 req->rm_ver_major = RNDIS_VERSION_MAJOR;
1186 req->rm_ver_minor = RNDIS_VERSION_MINOR;
1187 req->rm_max_xfersz = HN_RNDIS_XFER_SIZE;
1189 comp_len = RNDIS_INIT_COMP_SIZE_MIN;
1190 comp = hn_rndis_xact_execute(sc, xact, rid, sizeof(*req), &comp_len,
1191 REMOTE_NDIS_INITIALIZE_CMPLT);
1193 if_printf(sc->hn_ifp, "exec RNDIS init failed\n");
1198 if (comp->rm_status != RNDIS_STATUS_SUCCESS) {
1199 if_printf(sc->hn_ifp, "RNDIS init failed: status 0x%08x\n",
1205 if_printf(sc->hn_ifp, "RNDIS ver %u.%u, pktsz %u, pktcnt %u\n",
1206 comp->rm_ver_major, comp->rm_ver_minor,
1207 comp->rm_pktmaxsz, comp->rm_pktmaxcnt);
1213 vmbus_xact_put(xact);
1217 #define HALT_COMPLETION_WAIT_COUNT 25
1220 * RNDIS filter halt device
1223 hv_rf_halt_device(rndis_device *device)
1225 rndis_request *request;
1228 /* Attempt to do a rndis device halt */
1229 request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
1230 RNDIS_MESSAGE_SIZE(rndis_halt_request));
1231 if (request == NULL) {
1235 /* initialize "poor man's semaphore" */
1236 request->halt_complete_flag = 0;
1238 ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
1244 * Wait for halt response from halt callback. We must wait for
1245 * the transaction response before freeing the request and other
1248 for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
1249 if (request->halt_complete_flag != 0) {
1258 device->state = RNDIS_DEV_UNINITIALIZED;
1260 hv_put_rndis_request(device, request);
1266 * RNDIS filter open device
1269 hv_rf_open_device(rndis_device *device)
1273 if (device->state != RNDIS_DEV_INITIALIZED) {
1277 if (hv_promisc_mode != 1) {
1278 ret = hv_rf_set_packet_filter(device,
1279 NDIS_PACKET_TYPE_BROADCAST |
1280 NDIS_PACKET_TYPE_ALL_MULTICAST |
1281 NDIS_PACKET_TYPE_DIRECTED);
1283 ret = hv_rf_set_packet_filter(device,
1284 NDIS_PACKET_TYPE_PROMISCUOUS);
1288 device->state = RNDIS_DEV_DATAINITIALIZED;
1295 * RNDIS filter close device
1298 hv_rf_close_device(rndis_device *device)
1302 if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1306 ret = hv_rf_set_packet_filter(device, 0);
1308 device->state = RNDIS_DEV_INITIALIZED;
1315 * RNDIS filter on device add
1318 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1319 int *nchan0, struct hn_rx_ring *rxr)
1322 rndis_device *rndis_dev;
1323 netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1324 device_t dev = sc->hn_dev;
1325 struct hn_nvs_subch_req *req;
1326 const struct hn_nvs_subch_resp *resp;
1328 struct vmbus_xact *xact = NULL;
1329 uint32_t status, nsubch;
1330 int nchan = *nchan0;
1333 rndis_dev = hv_get_rndis_device();
1334 if (rndis_dev == NULL) {
1337 sc->rndis_dev = rndis_dev;
1341 * Let the inner driver handle this first to create the netvsc channel
1342 * NOTE! Once the channel is created, we may get a receive callback
1343 * (hv_rf_on_receive()) before this call is completed.
1344 * Note: Earlier code used a function pointer here.
1346 ret = hv_nv_on_device_add(sc, rxr);
1348 hv_put_rndis_device(rndis_dev);
1353 * Initialize the rndis device
1356 /* Send the rndis initialization message */
1357 ret = hv_rf_init_device(rndis_dev);
1360 * TODO: If rndis init failed, we will need to shut down
1365 /* Get the mac address */
1366 ret = hv_rf_query_device_mac(rndis_dev);
1368 /* TODO: shut down rndis device and the channel */
1371 /* Configure NDIS offload settings */
1372 hn_rndis_conf_offload(sc);
1374 memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1376 hv_rf_query_device_link_status(rndis_dev);
1378 dev_info->link_state = rndis_dev->link_status;
1380 if (sc->hn_ndis_ver < NDIS_VERSION_6_30 || nchan == 1)
1384 * Get RSS capabilities, e.g. # of RX rings, and # of indirect
1387 ret = hn_rndis_get_rsscaps(sc, &rxr_cnt);
1389 /* This is benign. */
1393 if (nchan > rxr_cnt)
1395 if_printf(sc->hn_ifp, "RX rings offered %u, requested %d\n",
1399 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1404 * Ask NVS to allocate sub-channels.
1406 xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1408 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1412 req = vmbus_xact_req_data(xact);
1413 req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1414 req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1415 req->nvs_nsubch = nchan - 1;
1417 resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1419 if_printf(sc->hn_ifp, "exec subch failed\n");
1423 if (resp_len < sizeof(*resp)) {
1424 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1429 if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1430 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1436 status = resp->nvs_status;
1437 nsubch = resp->nvs_nsubch;
1438 vmbus_xact_put(xact);
1441 if (status != HN_NVS_STATUS_OK) {
1442 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1446 if (nsubch > nchan - 1) {
1447 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1453 ret = hv_rf_set_rss_param(rndis_dev, nchan);
1457 vmbus_xact_put(xact);
1462 * RNDIS filter on device remove
1465 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1467 rndis_device *rndis_dev = sc->rndis_dev;
1470 /* Halt and release the rndis device */
1471 ret = hv_rf_halt_device(rndis_dev);
1473 sc->rndis_dev = NULL;
1474 hv_put_rndis_device(rndis_dev);
1476 /* Pass control to inner driver to remove the device */
1477 ret |= hv_nv_on_device_remove(sc, destroy_channel);
1483 * RNDIS filter on open
1486 hv_rf_on_open(struct hn_softc *sc)
1489 return (hv_rf_open_device(sc->rndis_dev));
1493 * RNDIS filter on close
1496 hv_rf_on_close(struct hn_softc *sc)
1499 return (hv_rf_close_device(sc->rndis_dev));
1503 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1504 struct vmbus_channel *chan __unused, const void *data __unused,
1507 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1508 hn_chim_free(sc, sndc->hn_chim_idx);
1512 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1513 struct vmbus_channel *chan __unused, const void *data __unused,
1516 rndis_request *request = sndc->hn_cbarg;
1518 if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1519 hn_chim_free(sc, sndc->hn_chim_idx);
1522 * Notify hv_rf_halt_device() about halt completion.
1523 * The halt code must wait for completion before freeing
1524 * the transaction resources.
1526 request->halt_complete_flag = 1;
1530 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1533 netvsc_channel_rollup(rxr, txr);