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