]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hyperv/netvsc/hv_rndis_filter.c
hyperv/vmbus: Move channel packet types definition to vmbus.h
[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 hn_softc *sc,
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->gpa_cnt = 1;
252
253         packet->gpa[0].gpa_page =
254             hv_get_phys_addr(&request->request_msg) >> PAGE_SHIFT;
255         packet->gpa[0].gpa_len = request->request_msg.msg_len;
256         packet->gpa[0].gpa_ofs =
257             (unsigned long)&request->request_msg & (PAGE_SIZE - 1);
258
259         if (packet->gpa[0].gpa_ofs + packet->gpa[0].gpa_len > PAGE_SIZE) {
260                 packet->gpa_cnt = 2;
261                 packet->gpa[0].gpa_len = PAGE_SIZE - packet->gpa[0].gpa_ofs;
262                 packet->gpa[1].gpa_page =
263                         hv_get_phys_addr((char*)&request->request_msg +
264                                 packet->gpa[0].gpa_len) >> PAGE_SHIFT;
265                 packet->gpa[1].gpa_ofs = 0;
266                 packet->gpa[1].gpa_len = request->request_msg.msg_len -
267                     packet->gpa[0].gpa_len;
268         }
269
270         packet->compl.send.send_completion_context = request; /* packet */
271         if (message_type != REMOTE_NDIS_HALT_MSG) {
272                 packet->compl.send.on_send_completion =
273                     hv_rf_on_send_request_completion;
274         } else {
275                 packet->compl.send.on_send_completion =
276                     hv_rf_on_send_request_halt_completion;
277         }
278         packet->compl.send.send_completion_tid = (unsigned long)device;
279         if (packet->tot_data_buf_len < net_dev->send_section_size) {
280                 send_buf_section_idx = hv_nv_get_next_send_section(net_dev);
281                 if (send_buf_section_idx !=
282                         NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) {
283                         char *dest = ((char *)net_dev->send_buf +
284                                 send_buf_section_idx * net_dev->send_section_size);
285
286                         memcpy(dest, &request->request_msg, request->request_msg.msg_len);
287                         packet->send_buf_section_idx = send_buf_section_idx;
288                         packet->send_buf_section_size = packet->tot_data_buf_len;
289                         packet->gpa_cnt = 0;
290                         goto sendit;
291                 }
292                 /* Failed to allocate chimney send buffer; move on */
293         }
294         packet->send_buf_section_idx = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX;
295         packet->send_buf_section_size = 0;
296
297 sendit:
298         ret = hv_nv_on_send(device->net_dev->sc->hn_prichan, packet);
299
300         return (ret);
301 }
302
303 /*
304  * RNDIS filter receive response
305  */
306 static void 
307 hv_rf_receive_response(rndis_device *device, rndis_msg *response)
308 {
309         rndis_request *request = NULL;
310         rndis_request *next_request;
311         boolean_t found = FALSE;
312
313         mtx_lock(&device->req_lock);
314         request = STAILQ_FIRST(&device->myrequest_list);
315         while (request != NULL) {
316                 /*
317                  * All request/response message contains request_id as the
318                  * first field
319                  */
320                 if (request->request_msg.msg.init_request.request_id ==
321                                       response->msg.init_complete.request_id) {
322                         found = TRUE;
323                         break;
324                 }
325                 next_request = STAILQ_NEXT(request, mylist_entry);
326                 request = next_request;
327         }
328         mtx_unlock(&device->req_lock);
329
330         if (found) {
331                 if (response->msg_len <= sizeof(rndis_msg)) {
332                         memcpy(&request->response_msg, response,
333                             response->msg_len);
334                 } else {
335                         if (response->ndis_msg_type == REMOTE_NDIS_RESET_CMPLT) {
336                                 /* Does not have a request id field */
337                                 request->response_msg.msg.reset_complete.status =
338                                     STATUS_BUFFER_OVERFLOW;
339                         } else {
340                                 request->response_msg.msg.init_complete.status =
341                                     STATUS_BUFFER_OVERFLOW;
342                         }
343                 }
344
345                 sema_post(&request->wait_sema);
346         }
347 }
348
349 int
350 hv_rf_send_offload_request(struct hn_softc *sc,
351     rndis_offload_params *offloads)
352 {
353         rndis_request *request;
354         rndis_set_request *set;
355         rndis_offload_params *offload_req;
356         rndis_set_complete *set_complete;       
357         rndis_device *rndis_dev;
358         device_t dev = sc->hn_dev;
359         netvsc_dev *net_dev = sc->net_dev;
360         uint32_t vsp_version = net_dev->nvsp_version;
361         uint32_t extlen = sizeof(rndis_offload_params);
362         int ret;
363
364         if (vsp_version <= NVSP_PROTOCOL_VERSION_4) {
365                 extlen = VERSION_4_OFFLOAD_SIZE;
366                 /* On NVSP_PROTOCOL_VERSION_4 and below, we do not support
367                  * UDP checksum offload.
368                  */
369                 offloads->udp_ipv4_csum = 0;
370                 offloads->udp_ipv6_csum = 0;
371         }
372
373         rndis_dev = net_dev->extension;
374
375         request = hv_rndis_request(rndis_dev, REMOTE_NDIS_SET_MSG,
376             RNDIS_MESSAGE_SIZE(rndis_set_request) + extlen);
377         if (!request)
378                 return (ENOMEM);
379
380         set = &request->request_msg.msg.set_request;
381         set->oid = RNDIS_OID_TCP_OFFLOAD_PARAMETERS;
382         set->info_buffer_length = extlen;
383         set->info_buffer_offset = sizeof(rndis_set_request);
384         set->device_vc_handle = 0;
385
386         offload_req = (rndis_offload_params *)((unsigned long)set +
387             set->info_buffer_offset);
388         *offload_req = *offloads;
389         offload_req->header.type = RNDIS_OBJECT_TYPE_DEFAULT;
390         offload_req->header.revision = RNDIS_OFFLOAD_PARAMETERS_REVISION_3;
391         offload_req->header.size = extlen;
392
393         ret = hv_rf_send_request(rndis_dev, request, REMOTE_NDIS_SET_MSG);
394         if (ret != 0) {
395                 device_printf(dev, "hv send offload request failed, ret=%d!\n",
396                     ret);
397                 goto cleanup;
398         }
399
400         ret = sema_timedwait(&request->wait_sema, 5 * hz);
401         if (ret != 0) {
402                 device_printf(dev, "hv send offload request timeout\n");
403                 goto cleanup;
404         }
405
406         set_complete = &request->response_msg.msg.set_complete;
407         if (set_complete->status == RNDIS_STATUS_SUCCESS) {
408                 device_printf(dev, "hv send offload request succeeded\n");
409                 ret = 0;
410         } else {
411                 if (set_complete->status == STATUS_NOT_SUPPORTED) {
412                         device_printf(dev, "HV Not support offload\n");
413                         ret = 0;
414                 } else {
415                         ret = set_complete->status;
416                 }
417         }
418
419 cleanup:
420         hv_put_rndis_request(rndis_dev, request);
421
422         return (ret);
423 }
424
425 /*
426  * RNDIS filter receive indicate status
427  */
428 static void 
429 hv_rf_receive_indicate_status(rndis_device *device, rndis_msg *response)
430 {
431         rndis_indicate_status *indicate = &response->msg.indicate_status;
432                 
433         switch(indicate->status) {
434         case RNDIS_STATUS_MEDIA_CONNECT:
435                 netvsc_linkstatus_callback(device->net_dev->sc, 1);
436                 break;
437         case RNDIS_STATUS_MEDIA_DISCONNECT:
438                 netvsc_linkstatus_callback(device->net_dev->sc, 0);
439                 break;
440         default:
441                 /* TODO: */
442                 device_printf(device->net_dev->sc->hn_dev,
443                     "unknown status %d received\n", indicate->status);
444                 break;
445         }
446 }
447
448 static int
449 hv_rf_find_recvinfo(const rndis_packet *rpkt, struct hv_rf_recvinfo *info)
450 {
451         const rndis_per_packet_info *ppi;
452         uint32_t mask, len;
453
454         info->vlan_info = NULL;
455         info->csum_info = NULL;
456         info->hash_info = NULL;
457         info->hash_value = NULL;
458
459         if (rpkt->per_pkt_info_offset == 0)
460                 return 0;
461
462         ppi = (const rndis_per_packet_info *)
463             ((const uint8_t *)rpkt + rpkt->per_pkt_info_offset);
464         len = rpkt->per_pkt_info_length;
465         mask = 0;
466
467         while (len != 0) {
468                 const void *ppi_dptr;
469                 uint32_t ppi_dlen;
470
471                 if (__predict_false(ppi->size < ppi->per_packet_info_offset))
472                         return EINVAL;
473                 ppi_dlen = ppi->size - ppi->per_packet_info_offset;
474                 ppi_dptr = (const uint8_t *)ppi + ppi->per_packet_info_offset;
475
476                 switch (ppi->type) {
477                 case ieee_8021q_info:
478                         if (__predict_false(ppi_dlen < sizeof(ndis_8021q_info)))
479                                 return EINVAL;
480                         info->vlan_info = ppi_dptr;
481                         mask |= HV_RF_RECVINFO_VLAN;
482                         break;
483
484                 case tcpip_chksum_info:
485                         if (__predict_false(ppi_dlen <
486                             sizeof(rndis_tcp_ip_csum_info)))
487                                 return EINVAL;
488                         info->csum_info = ppi_dptr;
489                         mask |= HV_RF_RECVINFO_CSUM;
490                         break;
491
492                 case nbl_hash_value:
493                         if (__predict_false(ppi_dlen <
494                             sizeof(struct rndis_hash_value)))
495                                 return EINVAL;
496                         info->hash_value = ppi_dptr;
497                         mask |= HV_RF_RECVINFO_HASHVAL;
498                         break;
499
500                 case nbl_hash_info:
501                         if (__predict_false(ppi_dlen <
502                             sizeof(struct rndis_hash_info)))
503                                 return EINVAL;
504                         info->hash_info = ppi_dptr;
505                         mask |= HV_RF_RECVINFO_HASHINF;
506                         break;
507
508                 default:
509                         goto skip;
510                 }
511
512                 if (mask == HV_RF_RECVINFO_ALL) {
513                         /* All found; done */
514                         break;
515                 }
516 skip:
517                 if (__predict_false(len < ppi->size))
518                         return EINVAL;
519                 len -= ppi->size;
520                 ppi = (const rndis_per_packet_info *)
521                     ((const uint8_t *)ppi + ppi->size);
522         }
523         return 0;
524 }
525
526 /*
527  * RNDIS filter receive data
528  */
529 static void
530 hv_rf_receive_data(rndis_device *device, rndis_msg *message,
531     struct hv_vmbus_channel *chan, netvsc_packet *pkt)
532 {
533         rndis_packet *rndis_pkt;
534         uint32_t data_offset;
535         device_t dev = device->net_dev->sc->hn_dev;
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                 device_printf(dev,
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                 device_printf(dev, "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(chan, 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 hv_vmbus_channel *chan, 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(rndis_dev, rndis_hdr, chan, 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 = HW_MACADDR_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)
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);
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, HW_MACADDR_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 = hv_vmbus_channel_send_packet(sc->hn_prichan, init_pkt,
1170             sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt,
1171             VMBUS_CHANPKT_TYPE_INBAND, VMBUS_CHANPKT_FLAG_RC);
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 hv_vmbus_channel *chan)
1270 {
1271
1272         netvsc_channel_rollup(chan);
1273 }