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