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