]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - sys/dev/hyperv/netvsc/hv_rndis_filter.c
MFC 304441,304444,304446,304447,304591,304593-304595
[FreeBSD/stable/10.git] / sys / dev / hyperv / netvsc / hv_rndis_filter.c
1 /*-
2  * Copyright (c) 2009-2012,2016 Microsoft Corp.
3  * Copyright (c) 2010-2012 Citrix Inc.
4  * Copyright (c) 2012 NetApp Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice unmodified, this list of conditions, and the following
12  *    disclaimer.
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.
16  *
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.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/param.h>
33 #include <sys/kernel.h>
34 #include <sys/mbuf.h>
35 #include <sys/socket.h>
36 #include <sys/lock.h>
37 #include <sys/mutex.h>
38 #include <net/if.h>
39 #include <net/if_arp.h>
40 #include <net/if_var.h>
41 #include <net/ethernet.h>
42 #include <sys/types.h>
43 #include <machine/atomic.h>
44 #include <sys/sema.h>
45 #include <vm/vm.h>
46 #include <vm/vm_param.h>
47 #include <vm/pmap.h>
48
49 #include <dev/hyperv/include/hyperv.h>
50 #include <dev/hyperv/include/vmbus_xact.h>
51 #include <dev/hyperv/netvsc/hv_net_vsc.h>
52 #include <dev/hyperv/netvsc/hv_rndis.h>
53 #include <dev/hyperv/netvsc/hv_rndis_filter.h>
54 #include <dev/hyperv/netvsc/if_hnreg.h>
55
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)
65
66 /*
67  * Forward declarations
68  */
69 static int  hv_rf_send_request(rndis_device *device, rndis_request *request,
70                                uint32_t message_type);
71 static void hv_rf_receive_response(rndis_device *device,
72     const rndis_msg *response);
73 static void hv_rf_receive_indicate_status(rndis_device *device,
74     const rndis_msg *response);
75 static void hv_rf_receive_data(struct hn_rx_ring *rxr,
76     const void *data, int dlen);
77 static int  hv_rf_query_device(rndis_device *device, uint32_t oid,
78                                void *result, uint32_t *result_size);
79 static inline int hv_rf_query_device_mac(rndis_device *device);
80 static inline int hv_rf_query_device_link_status(rndis_device *device);
81 static int  hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter);
82 static int  hv_rf_init_device(rndis_device *device);
83 static int  hv_rf_open_device(rndis_device *device);
84 static int  hv_rf_close_device(rndis_device *device);
85 int
86 hv_rf_send_offload_request(struct hn_softc *sc,
87     rndis_offload_params *offloads);
88
89 static void hn_rndis_sent_halt(struct hn_send_ctx *sndc,
90     struct hn_softc *sc, struct vmbus_channel *chan,
91     const void *data, int dlen);
92 static void hn_rndis_sent_cb(struct hn_send_ctx *sndc,
93     struct hn_softc *sc, struct vmbus_channel *chan,
94     const void *data, int dlen);
95
96 /*
97  * Set the Per-Packet-Info with the specified type
98  */
99 void *
100 hv_set_rppi_data(rndis_msg *rndis_mesg, uint32_t rppi_size,
101         int pkt_type)
102 {
103         rndis_packet *rndis_pkt;
104         rndis_per_packet_info *rppi;
105
106         rndis_pkt = &rndis_mesg->msg.packet;
107         rndis_pkt->data_offset += rppi_size;
108
109         rppi = (rndis_per_packet_info *)((char *)rndis_pkt +
110             rndis_pkt->per_pkt_info_offset + rndis_pkt->per_pkt_info_length);
111
112         rppi->size = rppi_size;
113         rppi->type = pkt_type;
114         rppi->per_packet_info_offset = sizeof(rndis_per_packet_info);
115
116         rndis_pkt->per_pkt_info_length += rppi_size;
117
118         return (rppi);
119 }
120
121 /*
122  * Get the Per-Packet-Info with the specified type
123  * return NULL if not found.
124  */
125 void *
126 hv_get_ppi_data(rndis_packet *rpkt, uint32_t type)
127 {
128         rndis_per_packet_info *ppi;
129         int len;
130
131         if (rpkt->per_pkt_info_offset == 0)
132                 return (NULL);
133
134         ppi = (rndis_per_packet_info *)((unsigned long)rpkt +
135             rpkt->per_pkt_info_offset);
136         len = rpkt->per_pkt_info_length;
137
138         while (len > 0) {
139                 if (ppi->type == type)
140                         return (void *)((unsigned long)ppi +
141                             ppi->per_packet_info_offset);
142
143                 len -= ppi->size;
144                 ppi = (rndis_per_packet_info *)((unsigned long)ppi + ppi->size);
145         }
146
147         return (NULL);
148 }
149
150
151 /*
152  * Allow module_param to work and override to switch to promiscuous mode.
153  */
154 static inline rndis_device *
155 hv_get_rndis_device(void)
156 {
157         rndis_device *device;
158
159         device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
160
161         mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
162
163         /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
164         STAILQ_INIT(&device->myrequest_list);
165
166         device->state = RNDIS_DEV_UNINITIALIZED;
167
168         return (device);
169 }
170
171 /*
172  *
173  */
174 static inline void
175 hv_put_rndis_device(rndis_device *device)
176 {
177         mtx_destroy(&device->req_lock);
178         free(device, M_NETVSC);
179 }
180
181 /*
182  *
183  */
184 static inline rndis_request *
185 hv_rndis_request(rndis_device *device, uint32_t message_type,
186                  uint32_t message_length)
187 {
188         rndis_request *request;
189         rndis_msg *rndis_mesg;
190         rndis_set_request *set;
191
192         request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
193
194         sema_init(&request->wait_sema, 0, "rndis sema");
195         
196         rndis_mesg = &request->request_msg;
197         rndis_mesg->ndis_msg_type = message_type;
198         rndis_mesg->msg_len = message_length;
199
200         /*
201          * Set the request id. This field is always after the rndis header
202          * for request/response packet types so we just use the set_request
203          * as a template.
204          */
205         set = &rndis_mesg->msg.set_request;
206         set->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
207         /* Increment to get the new value (call above returns old value) */
208         set->request_id += 1;
209
210         /* Add to the request list */
211         mtx_lock(&device->req_lock);
212         STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
213         mtx_unlock(&device->req_lock);
214
215         return (request);
216 }
217
218 /*
219  *
220  */
221 static inline void
222 hv_put_rndis_request(rndis_device *device, rndis_request *request)
223 {
224         mtx_lock(&device->req_lock);
225         /* Fixme:  Has O(n) performance */
226         /*
227          * XXXKYS: Use Doubly linked lists.
228          */
229         STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
230             mylist_entry);
231         mtx_unlock(&device->req_lock);
232
233         sema_destroy(&request->wait_sema);
234         free(request, M_NETVSC);
235 }
236
237 /*
238  *
239  */
240 static int
241 hv_rf_send_request(rndis_device *device, rndis_request *request,
242     uint32_t message_type)
243 {
244         struct hn_softc *sc = device->sc;
245         uint32_t send_buf_section_idx, tot_data_buf_len;
246         struct vmbus_gpa gpa[2];
247         int gpa_cnt, send_buf_section_size;
248         hn_sent_callback_t cb;
249
250         /* Set up the packet to send it */
251         tot_data_buf_len = request->request_msg.msg_len;
252
253         gpa_cnt = 1;
254         gpa[0].gpa_page = hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
255         gpa[0].gpa_len = request->request_msg.msg_len;
256         gpa[0].gpa_ofs = (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
257
258         if (gpa[0].gpa_ofs + gpa[0].gpa_len > PAGE_SIZE) {
259                 gpa_cnt = 2;
260                 gpa[0].gpa_len = PAGE_SIZE - gpa[0].gpa_ofs;
261                 gpa[1].gpa_page =
262                     hv_get_phys_addr((char*)&request->request_msg +
263                     gpa[0].gpa_len) >> PAGE_SHIFT;
264                 gpa[1].gpa_ofs = 0;
265                 gpa[1].gpa_len = request->request_msg.msg_len - gpa[0].gpa_len;
266         }
267
268         if (message_type != REMOTE_NDIS_HALT_MSG)
269                 cb = hn_rndis_sent_cb;
270         else
271                 cb = hn_rndis_sent_halt;
272
273         if (tot_data_buf_len < sc->hn_chim_szmax) {
274                 send_buf_section_idx = hn_chim_alloc(sc);
275                 if (send_buf_section_idx != HN_NVS_CHIM_IDX_INVALID) {
276                         uint8_t *dest = sc->hn_chim +
277                                 (send_buf_section_idx * sc->hn_chim_szmax);
278
279                         memcpy(dest, &request->request_msg, request->request_msg.msg_len);
280                         send_buf_section_size = tot_data_buf_len;
281                         gpa_cnt = 0;
282                         goto sendit;
283                 }
284                 /* Failed to allocate chimney send buffer; move on */
285         }
286         send_buf_section_idx = HN_NVS_CHIM_IDX_INVALID;
287         send_buf_section_size = 0;
288
289 sendit:
290         hn_send_ctx_init(&request->send_ctx, cb, request,
291             send_buf_section_idx, send_buf_section_size);
292         return hv_nv_on_send(sc->hn_prichan, HN_NVS_RNDIS_MTYPE_CTRL,
293             &request->send_ctx, gpa, gpa_cnt);
294 }
295
296 /*
297  * RNDIS filter receive response
298  */
299 static void 
300 hv_rf_receive_response(rndis_device *device, const rndis_msg *response)
301 {
302         rndis_request *request = NULL;
303         rndis_request *next_request;
304         boolean_t found = FALSE;
305
306         mtx_lock(&device->req_lock);
307         request = STAILQ_FIRST(&device->myrequest_list);
308         while (request != NULL) {
309                 /*
310                  * All request/response message contains request_id as the
311                  * first field
312                  */
313                 if (request->request_msg.msg.init_request.request_id ==
314                                       response->msg.init_complete.request_id) {
315                         found = TRUE;
316                         break;
317                 }
318                 next_request = STAILQ_NEXT(request, mylist_entry);
319                 request = next_request;
320         }
321         mtx_unlock(&device->req_lock);
322
323         if (found) {
324                 if (response->msg_len <= sizeof(rndis_msg)) {
325                         memcpy(&request->response_msg, response,
326                             response->msg_len);
327                 } else {
328                         if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
329                                 /* Does not have a request id field */
330                                 request->response_msg.msg.reset_complete.status =
331                                     STATUS_BUFFER_OVERFLOW;
332                         } else {
333                                 request->response_msg.msg.init_complete.status =
334                                     STATUS_BUFFER_OVERFLOW;
335                         }
336                 }
337
338                 sema_post(&request->wait_sema);
339         }
340 }
341
342 int
343 hv_rf_send_offload_request(struct hn_softc *sc,
344     rndis_offload_params *offloads)
345 {
346         rndis_request *request;
347         rndis_set_request *set;
348         rndis_offload_params *offload_req;
349         rndis_set_complete *set_complete;       
350         rndis_device *rndis_dev = sc->rndis_dev;
351         device_t dev = sc->hn_dev;
352         uint32_t extlen = sizeof(rndis_offload_params);
353         int ret;
354
355         if (sc->hn_nvs_ver <= 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.
359                  */
360                 offloads->udp_ipv4_csum = 0;
361                 offloads->udp_ipv6_csum = 0;
362         }
363
364         request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
365             RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
366         if (!request)
367                 return (ENOMEM);
368
369         set = &request->request_msg.msg.set_request;
370         set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
371         set->info_buffer_length = extlen;
372         set->info_buffer_offset = sizeof(rndis_set_request);
373         set->device_vc_handle = 0;
374
375         offload_req = (rndis_offload_params *)((unsigned long)set +
376             set->info_buffer_offset);
377         *offload_req = *offloads;
378         offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
379         offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
380         offload_req->header.size = extlen;
381
382         ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
383         if (ret != 0) {
384                 device_printf(dev, "hv send offload request failed, ret=%d!\n",
385                     ret);
386                 goto cleanup;
387         }
388
389         ret = sema_timedwait(&request->wait_sema, 5 * hz);
390         if (ret != 0) {
391                 device_printf(dev, "hv send offload request timeout\n");
392                 goto cleanup;
393         }
394
395         set_complete = &request->response_msg.msg.set_complete;
396         if (set_complete->status == RNDIS_STATUS_SUCCESS) {
397                 device_printf(dev, "hv send offload request succeeded\n");
398                 ret = 0;
399         } else {
400                 if (set_complete->status == STATUS_NOT_SUPPORTED) {
401                         device_printf(dev, "HV Not support offload\n");
402                         ret = 0;
403                 } else {
404                         ret = set_complete->status;
405                 }
406         }
407
408 cleanup:
409         hv_put_rndis_request(rndis_dev, request);
410
411         return (ret);
412 }
413
414 /*
415  * RNDIS filter receive indicate status
416  */
417 static void 
418 hv_rf_receive_indicate_status(rndis_device *device, const rndis_msg *response)
419 {
420         const rndis_indicate_status *indicate = &response->msg.indicate_status;
421                 
422         switch(indicate->status) {
423         case RNDIS_STATUS_MEDIA_CONNECT:
424                 netvsc_linkstatus_callback(device->sc, 1);
425                 break;
426         case RNDIS_STATUS_MEDIA_DISCONNECT:
427                 netvsc_linkstatus_callback(device->sc, 0);
428                 break;
429         default:
430                 /* TODO: */
431                 device_printf(device->sc->hn_dev,
432                     "unknown status %d received\n", indicate->status);
433                 break;
434         }
435 }
436
437 static int
438 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hn_recvinfo *info)
439 {
440         const rndis_per_packet_info *ppi;
441         uint32_t mask, len;
442
443         info->vlan_info = NULL;
444         info->csum_info = NULL;
445         info->hash_info = NULL;
446         info->hash_value = NULL;
447
448         if (rpkt->per_pkt_info_offset == 0)
449                 return 0;
450
451         ppi = (const rndis_per_packet_info *)
452             ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
453         len = rpkt->per_pkt_info_length;
454         mask = 0;
455
456         while (len != 0) {
457                 const void *ppi_dptr;
458                 uint32_t ppi_dlen;
459
460                 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
461                         return EINVAL;
462                 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
463                 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
464
465                 switch (ppi->type) {
466                 case ieee_8021q_info:
467                         if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
468                                 return EINVAL;
469                         info->vlan_info = ppi_dptr;
470                         mask |= HV_RF_RECVINFO_VLAN;
471                         break;
472
473                 case tcpip_chksum_info:
474                         if (__predict_false(ppi_dlen <
475                             sizeof(rndis_tcp_ip_csum_info)))
476                                 return EINVAL;
477                         info->csum_info = ppi_dptr;
478                         mask |= HV_RF_RECVINFO_CSUM;
479                         break;
480
481                 case nbl_hash_value:
482                         if (__predict_false(ppi_dlen <
483                             sizeof(struct rndis_hash_value)))
484                                 return EINVAL;
485                         info->hash_value = ppi_dptr;
486                         mask |= HV_RF_RECVINFO_HASHVAL;
487                         break;
488
489                 case nbl_hash_info:
490                         if (__predict_false(ppi_dlen <
491                             sizeof(struct rndis_hash_info)))
492                                 return EINVAL;
493                         info->hash_info = ppi_dptr;
494                         mask |= HV_RF_RECVINFO_HASHINF;
495                         break;
496
497                 default:
498                         goto skip;
499                 }
500
501                 if (mask == HV_RF_RECVINFO_ALL) {
502                         /* All found; done */
503                         break;
504                 }
505 skip:
506                 if (__predict_false(len < ppi->size))
507                         return EINVAL;
508                 len -= ppi->size;
509                 ppi = (const rndis_per_packet_info *)
510                     ((const uint8_t *)ppi + ppi->size);
511         }
512         return 0;
513 }
514
515 /*
516  * RNDIS filter receive data
517  */
518 static void
519 hv_rf_receive_data(struct hn_rx_ring *rxr, const void *data, int dlen)
520 {
521         const rndis_msg *message = data;
522         const rndis_packet *rndis_pkt;
523         uint32_t data_offset;
524         struct hn_recvinfo info;
525
526         rndis_pkt = &message->msg.packet;
527
528         /*
529          * Fixme:  Handle multiple rndis pkt msgs that may be enclosed in this
530          * netvsc packet (ie tot_data_buf_len != message_length)
531          */
532
533         /* Remove rndis header, then pass data packet up the stack */
534         data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset;
535
536         dlen -= data_offset;
537         if (dlen < rndis_pkt->data_length) {
538                 if_printf(rxr->hn_ifp,
539                     "total length %u is less than data length %u\n",
540                     dlen, rndis_pkt->data_length);
541                 return;
542         }
543
544         dlen = rndis_pkt->data_length;
545         data = (const uint8_t *)data + data_offset;
546
547         if (hv_rf_find_recvinfo(rndis_pkt, &info)) {
548                 if_printf(rxr->hn_ifp, "recvinfo parsing failed\n");
549                 return;
550         }
551         netvsc_recv(rxr, data, dlen, &info);
552 }
553
554 /*
555  * RNDIS filter on receive
556  */
557 int
558 hv_rf_on_receive(struct hn_softc *sc, struct hn_rx_ring *rxr,
559     const void *data, int dlen)
560 {
561         rndis_device *rndis_dev;
562         const rndis_msg *rndis_hdr;
563
564         rndis_dev = sc->rndis_dev;
565         if (rndis_dev->state == RNDIS_DEV_UNINITIALIZED)
566                 return (EINVAL);
567
568         rndis_hdr = data;
569         switch (rndis_hdr->ndis_msg_type) {
570
571         /* data message */
572         case REMOTE_NDIS_PACKET_MSG:
573                 hv_rf_receive_data(rxr, data, dlen);
574                 break;
575         /* completion messages */
576         case REMOTE_NDIS_INITIALIZE_CMPLT:
577         case REMOTE_NDIS_QUERY_CMPLT:
578         case REMOTE_NDIS_SET_CMPLT:
579         case REMOTE_NDIS_RESET_CMPLT:
580         case REMOTE_NDIS_KEEPALIVE_CMPLT:
581                 hv_rf_receive_response(rndis_dev, rndis_hdr);
582                 break;
583         /* notification message */
584         case REMOTE_NDIS_INDICATE_STATUS_MSG:
585                 hv_rf_receive_indicate_status(rndis_dev, rndis_hdr);
586                 break;
587         default:
588                 printf("hv_rf_on_receive():  Unknown msg_type 0x%x\n",
589                         rndis_hdr->ndis_msg_type);
590                 break;
591         }
592
593         return (0);
594 }
595
596 /*
597  * RNDIS filter query device
598  */
599 static int
600 hv_rf_query_device(rndis_device *device, uint32_t oid, void *result,
601                    uint32_t *result_size)
602 {
603         rndis_request *request;
604         uint32_t in_result_size = *result_size;
605         rndis_query_request *query;
606         rndis_query_complete *query_complete;
607         int ret = 0;
608
609         *result_size = 0;
610         request = hv_rndis_request(device, REMOTE_NDIS_QUERY_MSG,
611             RNDIS_MESSAGE_SIZE(rndis_query_request));
612         if (request == NULL) {
613                 ret = -1;
614                 goto cleanup;
615         }
616
617         /* Set up the rndis query */
618         query = &request->request_msg.msg.query_request;
619         query->oid = oid;
620         query->info_buffer_offset = sizeof(rndis_query_request); 
621         query->info_buffer_length = 0;
622         query->device_vc_handle = 0;
623
624         if (oid == RNDIS_OID_GEN_RSS_CAPABILITIES) {
625                 struct rndis_recv_scale_cap *cap;
626
627                 request->request_msg.msg_len += 
628                         sizeof(struct rndis_recv_scale_cap);
629                 query->info_buffer_length = sizeof(struct rndis_recv_scale_cap);
630                 cap = (struct rndis_recv_scale_cap *)((unsigned long)query + 
631                                                 query->info_buffer_offset);
632                 cap->hdr.type = RNDIS_OBJECT_TYPE_RSS_CAPABILITIES;
633                 cap->hdr.rev = RNDIS_RECEIVE_SCALE_CAPABILITIES_REVISION_2;
634                 cap->hdr.size = sizeof(struct rndis_recv_scale_cap);
635         }
636
637         ret = hv_rf_send_request(device, request, REMOTE_NDIS_QUERY_MSG);
638         if (ret != 0) {
639                 /* Fixme:  printf added */
640                 printf("RNDISFILTER request failed to Send!\n");
641                 goto cleanup;
642         }
643
644         sema_wait(&request->wait_sema);
645
646         /* Copy the response back */
647         query_complete = &request->response_msg.msg.query_complete;
648         
649         if (query_complete->info_buffer_length > in_result_size) {
650                 ret = EINVAL;
651                 goto cleanup;
652         }
653
654         memcpy(result, (void *)((unsigned long)query_complete +
655             query_complete->info_buffer_offset),
656             query_complete->info_buffer_length);
657
658         *result_size = query_complete->info_buffer_length;
659
660 cleanup:
661         if (request != NULL)
662                 hv_put_rndis_request(device, request);
663
664         return (ret);
665 }
666
667 /*
668  * RNDIS filter query device MAC address
669  */
670 static inline int
671 hv_rf_query_device_mac(rndis_device *device)
672 {
673         uint32_t size = ETHER_ADDR_LEN;
674
675         return (hv_rf_query_device(device,
676             RNDIS_OID_802_3_PERMANENT_ADDRESS, device->hw_mac_addr, &size));
677 }
678
679 /*
680  * RNDIS filter query device link status
681  */
682 static inline int
683 hv_rf_query_device_link_status(rndis_device *device)
684 {
685         uint32_t size = sizeof(uint32_t);
686
687         return (hv_rf_query_device(device,
688             RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, &device->link_status, &size));
689 }
690
691 static uint8_t netvsc_hash_key[HASH_KEYLEN] = {
692         0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2,
693         0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0,
694         0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4,
695         0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c,
696         0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa
697 };
698
699 /*
700  * RNDIS set vRSS parameters
701  */
702 static int
703 hv_rf_set_rss_param(rndis_device *device, int num_queue)
704 {
705         rndis_request *request;
706         rndis_set_request *set;
707         rndis_set_complete *set_complete;
708         rndis_recv_scale_param *rssp;
709         uint32_t extlen = sizeof(rndis_recv_scale_param) +
710             (4 * ITAB_NUM) + HASH_KEYLEN;
711         uint32_t *itab, status;
712         uint8_t *keyp;
713         int i, ret;
714
715
716         request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
717             RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
718         if (request == NULL) {
719                 if (bootverbose)
720                         printf("Netvsc: No memory to set vRSS parameters.\n");
721                 ret = -1;
722                 goto cleanup;
723         }
724
725         set = &request->request_msg.msg.set_request;
726         set->oid = RNDIS_OID_GEN_RSS_PARAMETERS;
727         set->info_buffer_length = extlen;
728         set->info_buffer_offset = sizeof(rndis_set_request);
729         set->device_vc_handle = 0;
730
731         /* Fill out the rssp parameter structure */
732         rssp = (rndis_recv_scale_param *)(set + 1);
733         rssp->hdr.type = RNDIS_OBJECT_TYPE_RSS_PARAMETERS;
734         rssp->hdr.rev = RNDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
735         rssp->hdr.size = sizeof(rndis_recv_scale_param);
736         rssp->flag = 0;
737         rssp->hashinfo = RNDIS_HASH_FUNC_TOEPLITZ | RNDIS_HASH_IPV4 |
738             RNDIS_HASH_TCP_IPV4 | RNDIS_HASH_IPV6 | RNDIS_HASH_TCP_IPV6;
739         rssp->indirect_tabsize = 4 * ITAB_NUM;
740         rssp->indirect_taboffset = sizeof(rndis_recv_scale_param);
741         rssp->hashkey_size = HASH_KEYLEN;
742         rssp->hashkey_offset = rssp->indirect_taboffset +
743             rssp->indirect_tabsize;
744
745         /* Set indirection table entries */
746         itab = (uint32_t *)(rssp + 1);
747         for (i = 0; i < ITAB_NUM; i++)
748                 itab[i] = i % num_queue;
749
750         /* Set hash key values */
751         keyp = (uint8_t *)((unsigned long)rssp + rssp->hashkey_offset);
752         for (i = 0; i < HASH_KEYLEN; i++)
753                 keyp[i] = netvsc_hash_key[i];
754
755         ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
756         if (ret != 0) {
757                 goto cleanup;
758         }
759
760         /*
761          * Wait for the response from the host.  Another thread will signal
762          * us when the response has arrived.  In the failure case,
763          * sema_timedwait() returns a non-zero status after waiting 5 seconds.
764          */
765         ret = sema_timedwait(&request->wait_sema, 5 * hz);
766         if (ret == 0) {
767                 /* Response received, check status */
768                 set_complete = &request->response_msg.msg.set_complete;
769                 status = set_complete->status;
770                 if (status != RNDIS_STATUS_SUCCESS) {
771                         /* Bad response status, return error */
772                         if (bootverbose)
773                                 printf("Netvsc: Failed to set vRSS "
774                                     "parameters.\n");
775                         ret = -2;
776                 } else {
777                         if (bootverbose)
778                                 printf("Netvsc: Successfully set vRSS "
779                                     "parameters.\n");
780                 }
781         } else {
782                 /*
783                  * We cannot deallocate the request since we may still
784                  * receive a send completion for it.
785                  */
786                 printf("Netvsc: vRSS set timeout, id = %u, ret = %d\n",
787                     request->request_msg.msg.init_request.request_id, ret);
788                 goto exit;
789         }
790
791 cleanup:
792         if (request != NULL) {
793                 hv_put_rndis_request(device, request);
794         }
795 exit:
796         return (ret);
797 }
798
799 /*
800  * RNDIS filter set packet filter
801  * Sends an rndis request with the new filter, then waits for a response
802  * from the host.
803  * Returns zero on success, non-zero on failure.
804  */
805 static int
806 hv_rf_set_packet_filter(rndis_device *device, uint32_t new_filter)
807 {
808         rndis_request *request;
809         rndis_set_request *set;
810         rndis_set_complete *set_complete;
811         uint32_t status;
812         int ret;
813
814         request = hv_rndis_request(device, REMOTE_NDIS_SET_MSG,
815             RNDIS_MESSAGE_SIZE(rndis_set_request) + sizeof(uint32_t));
816         if (request == NULL) {
817                 ret = -1;
818                 goto cleanup;
819         }
820
821         /* Set up the rndis set */
822         set = &request->request_msg.msg.set_request;
823         set->oid = RNDIS_OID_GEN_CURRENT_PACKET_FILTER;
824         set->info_buffer_length = sizeof(uint32_t);
825         set->info_buffer_offset = sizeof(rndis_set_request); 
826
827         memcpy((void *)((unsigned long)set + sizeof(rndis_set_request)),
828             &new_filter, sizeof(uint32_t));
829
830         ret = hv_rf_send_request(device, request, REMOTE_NDIS_SET_MSG);
831         if (ret != 0) {
832                 goto cleanup;
833         }
834
835         /*
836          * Wait for the response from the host.  Another thread will signal
837          * us when the response has arrived.  In the failure case,
838          * sema_timedwait() returns a non-zero status after waiting 5 seconds.
839          */
840         ret = sema_timedwait(&request->wait_sema, 5 * hz);
841         if (ret == 0) {
842                 /* Response received, check status */
843                 set_complete = &request->response_msg.msg.set_complete;
844                 status = set_complete->status;
845                 if (status != RNDIS_STATUS_SUCCESS) {
846                         /* Bad response status, return error */
847                         ret = -2;
848                 }
849         } else {
850                 /*
851                  * We cannot deallocate the request since we may still
852                  * receive a send completion for it.
853                  */
854                 goto exit;
855         }
856
857 cleanup:
858         if (request != NULL) {
859                 hv_put_rndis_request(device, request);
860         }
861 exit:
862         return (ret);
863 }
864
865 /*
866  * RNDIS filter init device
867  */
868 static int
869 hv_rf_init_device(rndis_device *device)
870 {
871         rndis_request *request;
872         rndis_initialize_request *init;
873         rndis_initialize_complete *init_complete;
874         uint32_t status;
875         int ret;
876
877         request = hv_rndis_request(device, REMOTE_NDIS_INITIALIZE_MSG,
878             RNDIS_MESSAGE_SIZE(rndis_initialize_request));
879         if (!request) {
880                 ret = -1;
881                 goto cleanup;
882         }
883
884         /* Set up the rndis set */
885         init = &request->request_msg.msg.init_request;
886         init->major_version = RNDIS_MAJOR_VERSION;
887         init->minor_version = RNDIS_MINOR_VERSION;
888         /*
889          * Per the RNDIS document, this should be set to the max MTU
890          * plus the header size.  However, 2048 works fine, so leaving
891          * it as is.
892          */
893         init->max_xfer_size = 2048;
894         
895         device->state = RNDIS_DEV_INITIALIZING;
896
897         ret = hv_rf_send_request(device, request, REMOTE_NDIS_INITIALIZE_MSG);
898         if (ret != 0) {
899                 device->state = RNDIS_DEV_UNINITIALIZED;
900                 goto cleanup;
901         }
902
903         sema_wait(&request->wait_sema);
904
905         init_complete = &request->response_msg.msg.init_complete;
906         status = init_complete->status;
907         if (status == RNDIS_STATUS_SUCCESS) {
908                 device->state = RNDIS_DEV_INITIALIZED;
909                 ret = 0;
910         } else {
911                 device->state = RNDIS_DEV_UNINITIALIZED; 
912                 ret = -1;
913         }
914
915 cleanup:
916         if (request) {
917                 hv_put_rndis_request(device, request);
918         }
919
920         return (ret);
921 }
922
923 #define HALT_COMPLETION_WAIT_COUNT      25
924
925 /*
926  * RNDIS filter halt device
927  */
928 static int
929 hv_rf_halt_device(rndis_device *device)
930 {
931         rndis_request *request;
932         rndis_halt_request *halt;
933         int i, ret;
934
935         /* Attempt to do a rndis device halt */
936         request = hv_rndis_request(device, REMOTE_NDIS_HALT_MSG,
937             RNDIS_MESSAGE_SIZE(rndis_halt_request));
938         if (request == NULL) {
939                 return (-1);
940         }
941
942         /* initialize "poor man's semaphore" */
943         request->halt_complete_flag = 0;
944
945         /* Set up the rndis set */
946         halt = &request->request_msg.msg.halt_request;
947         halt->request_id = atomic_fetchadd_int(&device->new_request_id, 1);
948         /* Increment to get the new value (call above returns old value) */
949         halt->request_id += 1;
950         
951         ret = hv_rf_send_request(device, request, REMOTE_NDIS_HALT_MSG);
952         if (ret != 0) {
953                 return (-1);
954         }
955
956         /*
957          * Wait for halt response from halt callback.  We must wait for
958          * the transaction response before freeing the request and other
959          * resources.
960          */
961         for (i=HALT_COMPLETION_WAIT_COUNT; i > 0; i--) {
962                 if (request->halt_complete_flag != 0) {
963                         break;
964                 }
965                 DELAY(400);
966         }
967         if (i == 0) {
968                 return (-1);
969         }
970
971         device->state = RNDIS_DEV_UNINITIALIZED;
972
973         hv_put_rndis_request(device, request);
974
975         return (0);
976 }
977
978 /*
979  * RNDIS filter open device
980  */
981 static int
982 hv_rf_open_device(rndis_device *device)
983 {
984         int ret;
985
986         if (device->state != RNDIS_DEV_INITIALIZED) {
987                 return (0);
988         }
989
990         if (hv_promisc_mode != 1) {
991                 ret = hv_rf_set_packet_filter(device, 
992                     NDIS_PACKET_TYPE_BROADCAST     |
993                     NDIS_PACKET_TYPE_ALL_MULTICAST |
994                     NDIS_PACKET_TYPE_DIRECTED);
995         } else {
996                 ret = hv_rf_set_packet_filter(device, 
997                     NDIS_PACKET_TYPE_PROMISCUOUS);
998         }
999
1000         if (ret == 0) {
1001                 device->state = RNDIS_DEV_DATAINITIALIZED;
1002         }
1003
1004         return (ret);
1005 }
1006
1007 /*
1008  * RNDIS filter close device
1009  */
1010 static int
1011 hv_rf_close_device(rndis_device *device)
1012 {
1013         int ret;
1014
1015         if (device->state != RNDIS_DEV_DATAINITIALIZED) {
1016                 return (0);
1017         }
1018
1019         ret = hv_rf_set_packet_filter(device, 0);
1020         if (ret == 0) {
1021                 device->state = RNDIS_DEV_INITIALIZED;
1022         }
1023
1024         return (ret);
1025 }
1026
1027 /*
1028  * RNDIS filter on device add
1029  */
1030 int
1031 hv_rf_on_device_add(struct hn_softc *sc, void *additl_info,
1032     int *nchan0, struct hn_rx_ring *rxr)
1033 {
1034         int ret;
1035         rndis_device *rndis_dev;
1036         rndis_offload_params offloads;
1037         struct rndis_recv_scale_cap rsscaps;
1038         uint32_t rsscaps_size = sizeof(struct rndis_recv_scale_cap);
1039         netvsc_device_info *dev_info = (netvsc_device_info *)additl_info;
1040         device_t dev = sc->hn_dev;
1041         struct hn_nvs_subch_req *req;
1042         const struct hn_nvs_subch_resp *resp;
1043         size_t resp_len;
1044         struct vmbus_xact *xact = NULL;
1045         uint32_t status, nsubch;
1046         int nchan = *nchan0;
1047
1048         rndis_dev = hv_get_rndis_device();
1049         if (rndis_dev == NULL) {
1050                 return (ENOMEM);
1051         }
1052         sc->rndis_dev = rndis_dev;
1053         rndis_dev->sc = sc;
1054
1055         /*
1056          * Let the inner driver handle this first to create the netvsc channel
1057          * NOTE! Once the channel is created, we may get a receive callback 
1058          * (hv_rf_on_receive()) before this call is completed.
1059          * Note:  Earlier code used a function pointer here.
1060          */
1061         ret = hv_nv_on_device_add(sc, rxr);
1062         if (ret != 0) {
1063                 hv_put_rndis_device(rndis_dev);
1064                 return (ret);
1065         }
1066
1067         /*
1068          * Initialize the rndis device
1069          */
1070
1071         /* Send the rndis initialization message */
1072         ret = hv_rf_init_device(rndis_dev);
1073         if (ret != 0) {
1074                 /*
1075                  * TODO: If rndis init failed, we will need to shut down
1076                  * the channel
1077                  */
1078         }
1079
1080         /* Get the mac address */
1081         ret = hv_rf_query_device_mac(rndis_dev);
1082         if (ret != 0) {
1083                 /* TODO: shut down rndis device and the channel */
1084         }
1085
1086         /* config csum offload and send request to host */
1087         memset(&offloads, 0, sizeof(offloads));
1088         offloads.ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1089         offloads.tcp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1090         offloads.udp_ipv4_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1091         offloads.tcp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1092         offloads.udp_ipv6_csum = RNDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED;
1093         offloads.lso_v2_ipv4 = RNDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED;
1094
1095         ret = hv_rf_send_offload_request(sc, &offloads);
1096         if (ret != 0) {
1097                 /* TODO: shut down rndis device and the channel */
1098                 device_printf(dev,
1099                     "hv_rf_send_offload_request failed, ret=%d\n", ret);
1100         }
1101         
1102         memcpy(dev_info->mac_addr, rndis_dev->hw_mac_addr, ETHER_ADDR_LEN);
1103
1104         hv_rf_query_device_link_status(rndis_dev);
1105         
1106         dev_info->link_state = rndis_dev->link_status;
1107
1108         if (sc->hn_nvs_ver < NVSP_PROTOCOL_VERSION_5 || nchan == 1)
1109                 return (0);
1110
1111         memset(&rsscaps, 0, rsscaps_size);
1112         ret = hv_rf_query_device(rndis_dev,
1113                         RNDIS_OID_GEN_RSS_CAPABILITIES,
1114                         &rsscaps, &rsscaps_size);
1115         if ((ret != 0) || (rsscaps.num_recv_que < 2)) {
1116                 device_printf(dev, "hv_rf_query_device failed or "
1117                         "rsscaps.num_recv_que < 2 \n");
1118                 goto out;
1119         }
1120         device_printf(dev, "channel, offered %u, requested %d\n",
1121             rsscaps.num_recv_que, nchan);
1122         if (nchan > rsscaps.num_recv_que)
1123                 nchan = rsscaps.num_recv_que;
1124
1125         if (nchan == 1) {
1126                 device_printf(dev, "only 1 channel is supported, no vRSS\n");
1127                 goto out;
1128         }
1129         
1130         /*
1131          * Ask NVS to allocate sub-channels.
1132          */
1133         xact = vmbus_xact_get(sc->hn_xact, sizeof(*req));
1134         if (xact == NULL) {
1135                 if_printf(sc->hn_ifp, "no xact for nvs subch req\n");
1136                 ret = ENXIO;
1137                 goto out;
1138         }
1139         req = vmbus_xact_req_data(xact);
1140         req->nvs_type = HN_NVS_TYPE_SUBCH_REQ;
1141         req->nvs_op = HN_NVS_SUBCH_OP_ALLOC;
1142         req->nvs_nsubch = nchan - 1;
1143
1144         resp = hn_nvs_xact_execute(sc, xact, req, sizeof(*req), &resp_len);
1145         if (resp == NULL) {
1146                 if_printf(sc->hn_ifp, "exec subch failed\n");
1147                 ret = EIO;
1148                 goto out;
1149         }
1150         if (resp_len < sizeof(*resp)) {
1151                 if_printf(sc->hn_ifp, "invalid subch resp length %zu\n",
1152                     resp_len);
1153                 ret = EINVAL;
1154                 goto out;
1155         }
1156         if (resp->nvs_type != HN_NVS_TYPE_SUBCH_RESP) {
1157                 if_printf(sc->hn_ifp, "not subch resp, type %u\n",
1158                     resp->nvs_type);
1159                 ret = EINVAL;
1160                 goto out;
1161         }
1162
1163         status = resp->nvs_status;
1164         nsubch = resp->nvs_nsubch;
1165         vmbus_xact_put(xact);
1166         xact = NULL;
1167
1168         if (status != HN_NVS_STATUS_OK) {
1169                 if_printf(sc->hn_ifp, "subch req failed: %x\n", status);
1170                 ret = EIO;
1171                 goto out;
1172         }
1173         if (nsubch > nchan - 1) {
1174                 if_printf(sc->hn_ifp, "%u subchans are allocated, requested %u\n",
1175                     nsubch, nchan - 1);
1176                 nsubch = nchan - 1;
1177         }
1178         nchan = nsubch + 1;
1179
1180         ret = hv_rf_set_rss_param(rndis_dev, nchan);
1181         *nchan0 = nchan;
1182 out:
1183         if (xact != NULL)
1184                 vmbus_xact_put(xact);
1185         return (ret);
1186 }
1187
1188 /*
1189  * RNDIS filter on device remove
1190  */
1191 int
1192 hv_rf_on_device_remove(struct hn_softc *sc, boolean_t destroy_channel)
1193 {
1194         rndis_device *rndis_dev = sc->rndis_dev;
1195         int ret;
1196
1197         /* Halt and release the rndis device */
1198         ret = hv_rf_halt_device(rndis_dev);
1199
1200         sc->rndis_dev = NULL;
1201         hv_put_rndis_device(rndis_dev);
1202
1203         /* Pass control to inner driver to remove the device */
1204         ret |= hv_nv_on_device_remove(sc, destroy_channel);
1205
1206         return (ret);
1207 }
1208
1209 /*
1210  * RNDIS filter on open
1211  */
1212 int
1213 hv_rf_on_open(struct hn_softc *sc)
1214 {
1215
1216         return (hv_rf_open_device(sc->rndis_dev));
1217 }
1218
1219 /*
1220  * RNDIS filter on close
1221  */
1222 int 
1223 hv_rf_on_close(struct hn_softc *sc)
1224 {
1225
1226         return (hv_rf_close_device(sc->rndis_dev));
1227 }
1228
1229 static void
1230 hn_rndis_sent_cb(struct hn_send_ctx *sndc, struct hn_softc *sc,
1231     struct vmbus_channel *chan __unused, const void *data __unused,
1232     int dlen __unused)
1233 {
1234         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1235                 hn_chim_free(sc, sndc->hn_chim_idx);
1236 }
1237
1238 static void
1239 hn_rndis_sent_halt(struct hn_send_ctx *sndc, struct hn_softc *sc,
1240     struct vmbus_channel *chan __unused, const void *data __unused,
1241     int dlen __unused)
1242 {
1243         rndis_request *request = sndc->hn_cbarg;
1244
1245         if (sndc->hn_chim_idx != HN_NVS_CHIM_IDX_INVALID)
1246                 hn_chim_free(sc, sndc->hn_chim_idx);
1247
1248         /*
1249          * Notify hv_rf_halt_device() about halt completion.
1250          * The halt code must wait for completion before freeing
1251          * the transaction resources.
1252          */
1253         request->halt_complete_flag = 1;
1254 }
1255
1256 void
1257 hv_rf_channel_rollup(struct hn_rx_ring *rxr, struct hn_tx_ring *txr)
1258 {
1259
1260         netvsc_channel_rollup(rxr, txr);
1261 }