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