1 /*
2 * Copyright 2013, 2018, Jérôme Duval, jerome.duval@gmail.com.
3 * Copyright 2017, Philippe Houdoin, philippe.houdoin@gmail.com.
4 * Distributed under the terms of the MIT License.
5 */
6
7
8 #include <net/if_media.h>
9 #include <netinet/in.h>
10 #include <netinet/ip.h>
11 #include <netinet/ip6.h>
12 #include <new>
13
14 #include <ethernet.h>
15 #include <kernel.h>
16 #include <lock.h>
17 #include <net_buffer.h>
18 #include <util/AutoLock.h>
19 #include <util/DoublyLinkedList.h>
20 #include <virtio.h>
21
22 #include "ether_driver.h"
23 #define ETHER_ADDR_LEN ETHER_ADDRESS_LENGTH
24 #include "virtio_net.h"
25
26
27 #define VIRTIO_NET_DRIVER_MODULE_NAME "drivers/network/virtio_net/driver_v1"
28 #define VIRTIO_NET_DEVICE_MODULE_NAME "drivers/network/virtio_net/device_v1"
29 #define VIRTIO_NET_DEVICE_ID_GENERATOR "virtio_net/device_id"
30
31 #define BUFFER_SIZE 2048
32 #define MAX_FRAME_SIZE 1536
33
34
35 struct virtio_net_rx_hdr {
36 struct virtio_net_hdr hdr;
37 uint8 pad[4];
38 } _PACKED;
39
40
41 struct virtio_net_tx_hdr {
42 union {
43 struct virtio_net_hdr hdr;
44 struct virtio_net_hdr_mrg_rxbuf mhdr;
45 };
46 } _PACKED;
47
48
49 struct BufInfo : DoublyLinkedListLinkImpl<BufInfo> {
50 char* buffer;
51 struct virtio_net_hdr* hdr;
52 physical_entry entry;
53 physical_entry hdrEntry;
54 uint32 rxUsedLength;
55 };
56
57
58 typedef DoublyLinkedList<BufInfo> BufInfoList;
59
60
61 typedef struct {
62 device_node* node;
63 ::virtio_device virtio_device;
64 virtio_device_interface* virtio;
65
66 uint64 features;
67
68 uint32 pairsCount;
69
70 ::virtio_queue* rxQueues;
71 uint16* rxSizes;
72
73 BufInfo** rxBufInfos;
74 sem_id rxDone;
75 area_id rxArea;
76 BufInfoList rxFullList;
77 mutex rxLock;
78
79 ::virtio_queue* txQueues;
80 uint16* txSizes;
81
82 BufInfo** txBufInfos;
83 sem_id txDone;
84 area_id txArea;
85 BufInfoList txFreeList;
86 mutex txLock;
87
88 ::virtio_queue ctrlQueue;
89
90 bool nonblocking;
91 bool promiscuous;
92 uint32 maxframesize;
93 ether_address_t macaddr;
94
95 #define MAX_MULTI 128
96 uint32 multiCount;
97 ether_address_t multi[MAX_MULTI];
98
99 } virtio_net_driver_info;
100
101
102 typedef struct {
103 virtio_net_driver_info* info;
104 } virtio_net_handle;
105
106
107 #include <stdio.h>
108 #include <string.h>
109 #include <stdlib.h>
110
111 #include <fs/devfs.h>
112
113
114 //#define TRACE_VIRTIO_NET
115 #ifdef TRACE_VIRTIO_NET
116 # define TRACE(x...) dprintf("virtio_net: " x)
117 #else
118 # define TRACE(x...) ;
119 #endif
120 #define ERROR(x...) dprintf("\33[33mvirtio_net:\33[0m " x)
121 #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
122
123
124 static device_manager_info* sDeviceManager;
125 static net_buffer_module_info* sBufferModule;
126
127
128 static void virtio_net_rxDone(void* driverCookie, void* cookie);
129 static void virtio_net_txDone(void* driverCookie, void* cookie);
130
131
132 const char*
get_feature_name(uint64 feature)133 get_feature_name(uint64 feature)
134 {
135 switch (feature) {
136 case VIRTIO_NET_F_CSUM:
137 return "host checksum";
138 case VIRTIO_NET_F_GUEST_CSUM:
139 return "guest checksum";
140 case VIRTIO_NET_F_MTU:
141 return "mtu";
142 case VIRTIO_NET_F_MAC:
143 return "macaddress";
144 case VIRTIO_NET_F_GSO:
145 return "host allgso";
146 case VIRTIO_NET_F_GUEST_TSO4:
147 return "guest tso4";
148 case VIRTIO_NET_F_GUEST_TSO6:
149 return "guest tso6";
150 case VIRTIO_NET_F_GUEST_ECN:
151 return "guest tso6+ecn";
152 case VIRTIO_NET_F_GUEST_UFO:
153 return "guest ufo";
154 case VIRTIO_NET_F_HOST_TSO4:
155 return "host tso4";
156 case VIRTIO_NET_F_HOST_TSO6:
157 return "host tso6";
158 case VIRTIO_NET_F_HOST_ECN:
159 return "host tso6+ecn";
160 case VIRTIO_NET_F_HOST_UFO:
161 return "host UFO";
162 case VIRTIO_NET_F_MRG_RXBUF:
163 return "host mergerxbuffers";
164 case VIRTIO_NET_F_STATUS:
165 return "status";
166 case VIRTIO_NET_F_CTRL_VQ:
167 return "control vq";
168 case VIRTIO_NET_F_CTRL_RX:
169 return "rx mode";
170 case VIRTIO_NET_F_CTRL_VLAN:
171 return "vlan filter";
172 case VIRTIO_NET_F_CTRL_RX_EXTRA:
173 return "rx mode extra";
174 case VIRTIO_NET_F_GUEST_ANNOUNCE:
175 return "guest announce";
176 case VIRTIO_NET_F_MQ:
177 return "multiqueue";
178 case VIRTIO_NET_F_CTRL_MAC_ADDR:
179 return "set macaddress";
180 }
181 return NULL;
182 }
183
184
185 static status_t
virtio_net_drain_queues(virtio_net_driver_info * info)186 virtio_net_drain_queues(virtio_net_driver_info* info)
187 {
188 BufInfo* buf = NULL;
189 while (info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf, NULL))
190 info->txFreeList.Add(buf);
191
192 while (info->virtio->queue_dequeue(info->rxQueues[0], NULL, NULL))
193 ;
194
195 while (info->rxFullList.RemoveHead() != NULL)
196 ;
197
198 return B_OK;
199 }
200
201
202 static status_t
virtio_net_rx_enqueue_buf(virtio_net_driver_info * info,BufInfo * buf)203 virtio_net_rx_enqueue_buf(virtio_net_driver_info* info, BufInfo* buf)
204 {
205 CALLED();
206 physical_entry entries[2];
207 entries[0] = buf->hdrEntry;
208 entries[1] = buf->entry;
209
210 memset(buf->hdr, 0, sizeof(struct virtio_net_hdr));
211
212 // queue the rx buffer
213 status_t status = info->virtio->queue_request_v(info->rxQueues[0],
214 entries, 0, 2, buf);
215 if (status != B_OK) {
216 ERROR("rx queueing on queue %d failed (%s)\n", 0, strerror(status));
217 return status;
218 }
219
220 return B_OK;
221 }
222
223
224 static status_t
virtio_net_ctrl_exec_cmd(virtio_net_driver_info * info,int cmd,bool value)225 virtio_net_ctrl_exec_cmd(virtio_net_driver_info* info, int cmd, bool value)
226 {
227 struct {
228 struct virtio_net_ctrl_hdr hdr;
229 uint8 pad1;
230 uint8 onoff;
231 uint8 pad2;
232 uint8 ack;
233 } s __attribute__((aligned(2)));
234
235 s.hdr.net_class = VIRTIO_NET_CTRL_RX;
236 s.hdr.cmd = cmd;
237 s.onoff = value;
238 s.ack = VIRTIO_NET_ERR;
239
240 physical_entry entries[3];
241 status_t status = get_memory_map(&s.hdr, sizeof(s.hdr), &entries[0], 1);
242 if (status != B_OK)
243 return status;
244 status = get_memory_map(&s.onoff, sizeof(s.onoff), &entries[1], 1);
245 if (status != B_OK)
246 return status;
247 status = get_memory_map(&s.ack, sizeof(s.ack), &entries[2], 1);
248 if (status != B_OK)
249 return status;
250
251 if (!info->virtio->queue_is_empty(info->ctrlQueue))
252 return B_ERROR;
253
254 status = info->virtio->queue_request_v(info->ctrlQueue, entries, 2, 1,
255 NULL);
256 if (status != B_OK)
257 return status;
258
259 while (!info->virtio->queue_dequeue(info->ctrlQueue, NULL, NULL))
260 spin(10);
261
262 return s.ack == VIRTIO_NET_OK ? B_OK : B_IO_ERROR;
263 }
264
265
266 static status_t
virtio_net_set_promisc(virtio_net_driver_info * info,bool on)267 virtio_net_set_promisc(virtio_net_driver_info* info, bool on)
268 {
269 return virtio_net_ctrl_exec_cmd(info, VIRTIO_NET_CTRL_RX_PROMISC, on);
270 }
271
272
273 static int
vtnet_set_allmulti(virtio_net_driver_info * info,bool on)274 vtnet_set_allmulti(virtio_net_driver_info* info, bool on)
275 {
276 return virtio_net_ctrl_exec_cmd(info, VIRTIO_NET_CTRL_RX_ALLMULTI, on);
277 }
278
279
280 #define ROUND_TO_PAGE_SIZE(x) (((x) + (B_PAGE_SIZE) - 1) & ~((B_PAGE_SIZE) - 1))
281
282
283 // #pragma mark - device module API
284
285
286 static status_t
virtio_net_init_device(void * _info,void ** _cookie)287 virtio_net_init_device(void* _info, void** _cookie)
288 {
289 CALLED();
290 virtio_net_driver_info* info = (virtio_net_driver_info*)_info;
291
292 device_node* parent = sDeviceManager->get_parent_node(info->node);
293 sDeviceManager->get_driver(parent, (driver_module_info**)&info->virtio,
294 (void**)&info->virtio_device);
295 sDeviceManager->put_node(parent);
296
297 info->virtio->negotiate_features(info->virtio_device,
298 VIRTIO_NET_F_STATUS | VIRTIO_NET_F_MAC | VIRTIO_NET_F_MTU
299 | VIRTIO_NET_F_CTRL_VQ | VIRTIO_NET_F_CTRL_RX | VIRTIO_NET_F_GUEST_CSUM
300 /* | VIRTIO_NET_F_MQ */,
301 &info->features, &get_feature_name);
302
303 if ((info->features & VIRTIO_NET_F_MQ) != 0
304 && (info->features & VIRTIO_NET_F_CTRL_VQ) != 0
305 && info->virtio->read_device_config(info->virtio_device,
306 offsetof(struct virtio_net_config, max_virtqueue_pairs),
307 &info->pairsCount, sizeof(info->pairsCount)) == B_OK) {
308 system_info sysinfo;
309 if (get_system_info(&sysinfo) == B_OK
310 && info->pairsCount > sysinfo.cpu_count) {
311 info->pairsCount = sysinfo.cpu_count;
312 }
313 } else
314 info->pairsCount = 1;
315
316 // TODO read config
317
318 // Setup queues
319 uint32 queueCount = info->pairsCount * 2;
320 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0)
321 queueCount++;
322 ::virtio_queue virtioQueues[queueCount];
323 status_t status = info->virtio->alloc_queues(info->virtio_device, queueCount,
324 virtioQueues, NULL);
325 if (status != B_OK) {
326 ERROR("queue allocation failed (%s)\n", strerror(status));
327 return status;
328 }
329
330 char* rxBuffer;
331 char* txBuffer;
332
333 info->rxQueues = new(std::nothrow) virtio_queue[info->pairsCount];
334 info->txQueues = new(std::nothrow) virtio_queue[info->pairsCount];
335 info->rxSizes = new(std::nothrow) uint16[info->pairsCount];
336 info->txSizes = new(std::nothrow) uint16[info->pairsCount];
337 if (info->rxQueues == NULL || info->txQueues == NULL
338 || info->rxSizes == NULL || info->txSizes == NULL) {
339 status = B_NO_MEMORY;
340 goto err1;
341 }
342 for (uint32 i = 0; i < info->pairsCount; i++) {
343 info->rxQueues[i] = virtioQueues[i * 2];
344 info->txQueues[i] = virtioQueues[i * 2 + 1];
345 info->rxSizes[i] = info->virtio->queue_size(info->rxQueues[i]) / 2;
346 info->txSizes[i] = info->virtio->queue_size(info->txQueues[i]) / 2;
347 }
348 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0)
349 info->ctrlQueue = virtioQueues[info->pairsCount * 2];
350
351 info->rxBufInfos = new(std::nothrow) BufInfo*[info->rxSizes[0]];
352 info->txBufInfos = new(std::nothrow) BufInfo*[info->txSizes[0]];
353 if (info->rxBufInfos == NULL || info->txBufInfos == NULL) {
354 status = B_NO_MEMORY;
355 goto err2;
356 }
357 memset(info->rxBufInfos, 0, sizeof(BufInfo*) * info->rxSizes[0]);
358 memset(info->txBufInfos, 0, sizeof(BufInfo*) * info->txSizes[0]);
359
360 // create receive buffer area
361 info->rxArea = create_area("virtionet rx buffer", (void**)&rxBuffer,
362 B_ANY_KERNEL_BLOCK_ADDRESS, ROUND_TO_PAGE_SIZE(
363 BUFFER_SIZE * info->rxSizes[0]),
364 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
365 if (info->rxArea < B_OK) {
366 status = info->rxArea;
367 goto err3;
368 }
369
370 // initialize receive buffer descriptors
371 for (int i = 0; i < info->rxSizes[0]; i++) {
372 BufInfo* buf = new(std::nothrow) BufInfo;
373 if (buf == NULL) {
374 status = B_NO_MEMORY;
375 goto err4;
376 }
377
378 info->rxBufInfos[i] = buf;
379 buf->hdr = (struct virtio_net_hdr*)((addr_t)rxBuffer
380 + i * BUFFER_SIZE);
381 buf->buffer = (char*)((addr_t)buf->hdr + sizeof(virtio_net_rx_hdr));
382
383 status = get_memory_map(buf->buffer,
384 BUFFER_SIZE - sizeof(virtio_net_rx_hdr), &buf->entry, 1);
385 if (status != B_OK)
386 goto err4;
387
388 status = get_memory_map(buf->hdr, sizeof(struct virtio_net_hdr),
389 &buf->hdrEntry, 1);
390 if (status != B_OK)
391 goto err4;
392 }
393
394 // create transmit buffer area
395 info->txArea = create_area("virtionet tx buffer", (void**)&txBuffer,
396 B_ANY_KERNEL_BLOCK_ADDRESS, ROUND_TO_PAGE_SIZE(
397 BUFFER_SIZE * info->txSizes[0]),
398 B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA);
399 if (info->txArea < B_OK) {
400 status = info->txArea;
401 goto err5;
402 }
403
404 // initialize transmit buffer descriptors
405 for (int i = 0; i < info->txSizes[0]; i++) {
406 BufInfo* buf = new(std::nothrow) BufInfo;
407 if (buf == NULL) {
408 status = B_NO_MEMORY;
409 goto err6;
410 }
411
412 info->txBufInfos[i] = buf;
413 buf->hdr = (struct virtio_net_hdr*)((addr_t)txBuffer
414 + i * BUFFER_SIZE);
415 buf->buffer = (char*)((addr_t)buf->hdr + sizeof(virtio_net_tx_hdr));
416
417 status = get_memory_map(buf->buffer,
418 BUFFER_SIZE - sizeof(virtio_net_tx_hdr), &buf->entry, 1);
419 if (status != B_OK)
420 goto err6;
421
422 status = get_memory_map(buf->hdr, sizeof(struct virtio_net_hdr),
423 &buf->hdrEntry, 1);
424 if (status != B_OK)
425 goto err6;
426
427 info->txFreeList.Add(buf);
428 }
429
430 mutex_init(&info->rxLock, "virtionet rx lock");
431 mutex_init(&info->txLock, "virtionet tx lock");
432
433 // Setup interrupt
434 status = info->virtio->setup_interrupt(info->virtio_device, NULL, info);
435 if (status != B_OK) {
436 ERROR("interrupt setup failed (%s)\n", strerror(status));
437 goto err6;
438 }
439
440 status = info->virtio->queue_setup_interrupt(info->rxQueues[0],
441 virtio_net_rxDone, info);
442 if (status != B_OK) {
443 ERROR("queue interrupt setup failed (%s)\n", strerror(status));
444 goto err6;
445 }
446
447 status = info->virtio->queue_setup_interrupt(info->txQueues[0],
448 virtio_net_txDone, info);
449 if (status != B_OK) {
450 ERROR("queue interrupt setup failed (%s)\n", strerror(status));
451 goto err6;
452 }
453
454 if ((info->features & VIRTIO_NET_F_CTRL_VQ) != 0) {
455 status = info->virtio->queue_setup_interrupt(info->ctrlQueue,
456 NULL, info);
457 if (status != B_OK) {
458 ERROR("queue interrupt setup failed (%s)\n", strerror(status));
459 goto err6;
460 }
461 }
462
463 *_cookie = info;
464 return B_OK;
465
466 err6:
467 for (int i = 0; i < info->txSizes[0]; i++)
468 delete info->txBufInfos[i];
469 err5:
470 delete_area(info->txArea);
471 err4:
472 for (int i = 0; i < info->rxSizes[0]; i++)
473 delete info->rxBufInfos[i];
474 err3:
475 delete_area(info->rxArea);
476 err2:
477 delete[] info->rxBufInfos;
478 delete[] info->txBufInfos;
479 err1:
480 delete[] info->rxQueues;
481 delete[] info->txQueues;
482 delete[] info->rxSizes;
483 delete[] info->txSizes;
484 return status;
485 }
486
487
488 static void
virtio_net_uninit_device(void * _cookie)489 virtio_net_uninit_device(void* _cookie)
490 {
491 CALLED();
492 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie;
493
494 info->virtio->free_interrupts(info->virtio_device);
495
496 mutex_destroy(&info->rxLock);
497 mutex_destroy(&info->txLock);
498
499 while (true) {
500 BufInfo* buf = info->txFreeList.RemoveHead();
501 if (buf == NULL)
502 break;
503 }
504
505 for (int i = 0; i < info->rxSizes[0]; i++) {
506 delete info->rxBufInfos[i];
507 }
508 for (int i = 0; i < info->txSizes[0]; i++) {
509 delete info->txBufInfos[i];
510 }
511 delete_area(info->rxArea);
512 delete_area(info->txArea);
513 delete[] info->rxBufInfos;
514 delete[] info->txBufInfos;
515 delete[] info->rxSizes;
516 delete[] info->txSizes;
517 delete[] info->rxQueues;
518 delete[] info->txQueues;
519
520 info->virtio->free_queues(info->virtio_device);
521 }
522
523
524 static status_t
virtio_net_open(void * _info,const char * path,int openMode,void ** _cookie)525 virtio_net_open(void* _info, const char* path, int openMode, void** _cookie)
526 {
527 CALLED();
528 virtio_net_driver_info* info = (virtio_net_driver_info*)_info;
529
530 virtio_net_handle* handle = (virtio_net_handle*)malloc(
531 sizeof(virtio_net_handle));
532 if (handle == NULL)
533 return B_NO_MEMORY;
534
535 info->nonblocking = (openMode & O_NONBLOCK) != 0;
536 info->maxframesize = MAX_FRAME_SIZE;
537 info->rxDone = create_sem(0, "virtio_net_rx");
538 info->txDone = create_sem(1, "virtio_net_tx");
539 if (info->rxDone < B_OK || info->txDone < B_OK)
540 goto error;
541 handle->info = info;
542
543 if ((info->features & VIRTIO_NET_F_MAC) != 0) {
544 info->virtio->read_device_config(info->virtio_device,
545 offsetof(struct virtio_net_config, mac),
546 &info->macaddr, sizeof(info->macaddr));
547 }
548
549 if ((info->features & VIRTIO_NET_F_MTU) != 0) {
550 dprintf("virtio_net: mtu feature\n");
551 uint16 mtu;
552 info->virtio->read_device_config(info->virtio_device,
553 offsetof(struct virtio_net_config, mtu),
554 &mtu, sizeof(mtu));
555 // check against minimum MTU
556 if (mtu > 68)
557 info->maxframesize = mtu;
558 else
559 info->virtio->clear_feature(info->virtio_device, VIRTIO_NET_F_MTU);
560 } else {
561 dprintf("virtio_net: no mtu feature\n");
562 }
563
564 for (int i = 0; i < info->rxSizes[0]; i++)
565 virtio_net_rx_enqueue_buf(info, info->rxBufInfos[i]);
566
567 *_cookie = handle;
568 return B_OK;
569
570 error:
571 delete_sem(info->rxDone);
572 delete_sem(info->txDone);
573 info->rxDone = info->txDone = -1;
574 free(handle);
575 return B_ERROR;
576 }
577
578
579 static status_t
virtio_net_close(void * cookie)580 virtio_net_close(void* cookie)
581 {
582 virtio_net_handle* handle = (virtio_net_handle*)cookie;
583 CALLED();
584
585 virtio_net_driver_info* info = handle->info;
586 delete_sem(info->rxDone);
587 delete_sem(info->txDone);
588 info->rxDone = info->txDone = -1;
589
590 return B_OK;
591 }
592
593
594 static status_t
virtio_net_free(void * cookie)595 virtio_net_free(void* cookie)
596 {
597 CALLED();
598 virtio_net_handle* handle = (virtio_net_handle*)cookie;
599
600 virtio_net_driver_info* info = handle->info;
601 virtio_net_drain_queues(info);
602 free(handle);
603 return B_OK;
604 }
605
606
607 static void
virtio_net_rxDone(void * driverCookie,void * cookie)608 virtio_net_rxDone(void* driverCookie, void* cookie)
609 {
610 CALLED();
611 virtio_net_driver_info* info = (virtio_net_driver_info*)cookie;
612
613 release_sem_etc(info->rxDone, 1, B_DO_NOT_RESCHEDULE);
614 }
615
616
617 static status_t
virtio_net_receive(void * cookie,net_buffer ** _buffer)618 virtio_net_receive(void* cookie, net_buffer** _buffer)
619 {
620 CALLED();
621 virtio_net_handle* handle = (virtio_net_handle*)cookie;
622 virtio_net_driver_info* info = handle->info;
623
624 MutexLocker rxLocker(info->rxLock);
625 while (info->rxFullList.Head() == NULL) {
626 rxLocker.Unlock();
627
628 if (info->nonblocking)
629 return B_WOULD_BLOCK;
630 TRACE("virtio_net_read: waiting\n");
631 status_t status = acquire_sem(info->rxDone);
632 if (status != B_OK) {
633 ERROR("acquire_sem(rxDone) failed (%s)\n", strerror(status));
634 return status;
635 }
636 int32 semCount = 0;
637 get_sem_count(info->rxDone, &semCount);
638 if (semCount > 0)
639 acquire_sem_etc(info->rxDone, semCount, B_RELATIVE_TIMEOUT, 0);
640
641 rxLocker.Lock();
642 while (info->rxDone != -1) {
643 uint32 usedLength = 0;
644 BufInfo* buf = NULL;
645 if (!info->virtio->queue_dequeue(info->rxQueues[0], (void**)&buf,
646 &usedLength) || buf == NULL) {
647 break;
648 }
649
650 if (usedLength > sizeof(virtio_net_hdr))
651 buf->rxUsedLength = usedLength - sizeof(virtio_net_hdr);
652 else
653 buf->rxUsedLength = 0;
654 info->rxFullList.Add(buf);
655 }
656 TRACE("virtio_net_read: finished waiting\n");
657 }
658
659 net_buffer* buffer = sBufferModule->create(0);
660 if (buffer == NULL)
661 return B_NO_MEMORY;
662
663 BufInfo* buf = info->rxFullList.RemoveHead();
664 rxLocker.Unlock();
665
666 if (sBufferModule->append(buffer, buf->buffer, buf->rxUsedLength) != B_OK) {
667 sBufferModule->free(buffer);
668 buffer = NULL;
669 }
670 const uint8_t flags = buf->hdr->flags;
671 rxLocker.Lock();
672 virtio_net_rx_enqueue_buf(info, buf);
673 rxLocker.Unlock();
674
675 if (buffer == NULL)
676 return B_NO_MEMORY;
677
678 if ((flags & (VIRTIO_NET_HDR_F_DATA_VALID | VIRTIO_NET_HDR_F_NEEDS_CSUM)) != 0) {
679 buffer->buffer_flags |= NET_BUFFER_L3_CHECKSUM_VALID;
680
681 // virtio also checks the L4 checksum for common protocols.
682 uint16 etherType;
683 if (sBufferModule->read(buffer, offsetof(ether_header, type),
684 ðerType, sizeof(etherType)) == B_OK) {
685 uint8 protocol = 0;
686 etherType = ntohs(etherType);
687 if (etherType == ETHER_TYPE_IP) {
688 sBufferModule->read(buffer,
689 ETHER_HEADER_LENGTH + offsetof(struct ip, ip_p),
690 &protocol, sizeof(protocol));
691 } else if (etherType == ETHER_TYPE_IPV6) {
692 sBufferModule->read(buffer,
693 ETHER_HEADER_LENGTH + offsetof(struct ip6_hdr, ip6_nxt),
694 &protocol, sizeof(protocol));
695 }
696 if (protocol == IPPROTO_TCP || protocol == IPPROTO_UDP)
697 buffer->buffer_flags |= NET_BUFFER_L4_CHECKSUM_VALID;
698 }
699
700 if ((flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) != 0) {
701 // The data is known to be valid but the checksum in the packet is incomplete.
702 // Ignore this flag for now; the stack accepts packets with CHECKSUM_VALID set.
703 }
704 }
705
706 *_buffer = buffer;
707 return B_OK;
708 }
709
710
711 static void
virtio_net_txDone(void * driverCookie,void * cookie)712 virtio_net_txDone(void* driverCookie, void* cookie)
713 {
714 CALLED();
715 virtio_net_driver_info* info = (virtio_net_driver_info*)cookie;
716
717 release_sem_etc(info->txDone, 1, B_DO_NOT_RESCHEDULE);
718 }
719
720
721 static status_t
virtio_net_send(void * cookie,net_buffer * buffer)722 virtio_net_send(void* cookie, net_buffer* buffer)
723 {
724 CALLED();
725 virtio_net_handle* handle = (virtio_net_handle*)cookie;
726 virtio_net_driver_info* info = handle->info;
727
728 mutex_lock(&info->txLock);
729 while (info->txFreeList.Head() == NULL) {
730 mutex_unlock(&info->txLock);
731 if (info->nonblocking)
732 return B_WOULD_BLOCK;
733
734 status_t status = acquire_sem(info->txDone);
735 if (status != B_OK) {
736 ERROR("acquire_sem(txDone) failed (%s)\n", strerror(status));
737 return status;
738 }
739
740 int32 semCount = 0;
741 get_sem_count(info->txDone, &semCount);
742 if (semCount > 0)
743 acquire_sem_etc(info->txDone, semCount, B_RELATIVE_TIMEOUT, 0);
744
745 mutex_lock(&info->txLock);
746 while (info->txDone != -1) {
747 BufInfo* buf = NULL;
748 if (!info->virtio->queue_dequeue(info->txQueues[0], (void**)&buf,
749 NULL) || buf == NULL) {
750 break;
751 }
752
753 info->txFreeList.Add(buf);
754 }
755 }
756 BufInfo* buf = info->txFreeList.RemoveHead();
757
758 const size_t size = MIN(MAX_FRAME_SIZE, buffer->size);
759 TRACE("virtio_net_write: copying %lu\n", size);
760 if (sBufferModule->read(buffer, 0, buf->buffer, size) != B_OK) {
761 info->txFreeList.Add(buf);
762 mutex_unlock(&info->txLock);
763 return B_BAD_DATA;
764 }
765 memset(buf->hdr, 0, sizeof(virtio_net_hdr));
766
767 physical_entry entries[2];
768 entries[0] = buf->hdrEntry;
769 entries[0].size = sizeof(virtio_net_hdr);
770 entries[1] = buf->entry;
771 entries[1].size = size;
772
773 // queue the virtio_net_hdr + buffer data
774 status_t status = info->virtio->queue_request_v(info->txQueues[0],
775 entries, 2, 0, buf);
776 mutex_unlock(&info->txLock);
777
778 if (status != B_OK) {
779 ERROR("tx queueing on queue %d failed (%s)\n", 0, strerror(status));
780 return status;
781 }
782
783 sBufferModule->free(buffer);
784 return B_OK;
785 }
786
787
788 static status_t
virtio_net_ioctl(void * cookie,uint32 op,void * buffer,size_t length)789 virtio_net_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
790 {
791 // CALLED();
792 virtio_net_handle* handle = (virtio_net_handle*)cookie;
793 virtio_net_driver_info* info = handle->info;
794
795 // TRACE("ioctl(op = %lx)\n", op);
796
797 switch (op) {
798 case ETHER_GETADDR:
799 TRACE("ioctl: get macaddr\n");
800 return user_memcpy(buffer, &info->macaddr, sizeof(info->macaddr));
801
802 case ETHER_INIT:
803 TRACE("ioctl: init\n");
804 return B_OK;
805
806 case ETHER_GETFRAMESIZE:
807 TRACE("ioctl: get frame size\n");
808 if (length != sizeof(info->maxframesize))
809 return B_BAD_VALUE;
810
811 return user_memcpy(buffer, &info->maxframesize,
812 sizeof(info->maxframesize));
813
814 case ETHER_SETPROMISC:
815 {
816 TRACE("ioctl: set promisc\n");
817 int32 value;
818 if (length != sizeof(value))
819 return B_BAD_VALUE;
820 if (user_memcpy(&value, buffer, sizeof(value)) != B_OK)
821 return B_BAD_ADDRESS;
822 if (info->promiscuous == value)
823 return B_OK;
824 info->promiscuous = value;
825 return virtio_net_set_promisc(info, value != 0);
826 }
827 case ETHER_NONBLOCK:
828 {
829 TRACE("ioctl: non blocking ? %s\n",
830 info->nonblocking ? "yes" : "no");
831 int32 value;
832 if (length != sizeof(value))
833 return B_BAD_VALUE;
834 if (user_memcpy(&value, buffer, sizeof(value)) != B_OK)
835 return B_BAD_ADDRESS;
836 info->nonblocking = value == 0;
837 return B_OK;
838 }
839 case ETHER_ADDMULTI:
840 {
841 uint32 i, multiCount = info->multiCount;
842 TRACE("ioctl: add multicast\n");
843
844 if ((info->features & VIRTIO_NET_F_CTRL_RX) == 0)
845 return B_NOT_SUPPORTED;
846
847 if (multiCount == MAX_MULTI)
848 return B_ERROR;
849
850 for (i = 0; i < multiCount; i++) {
851 if (memcmp(&info->multi[i], buffer,
852 sizeof(info->multi[0])) == 0) {
853 break;
854 }
855 }
856
857 if (i == multiCount) {
858 memcpy(&info->multi[i], buffer, sizeof(info->multi[i]));
859 info->multiCount++;
860 }
861 if (info->multiCount == 1) {
862 TRACE("Enabling multicast\n");
863 vtnet_set_allmulti(info, true);
864 }
865
866 return B_OK;
867 }
868 case ETHER_REMMULTI:
869 {
870 uint32 i, multiCount = info->multiCount;
871 TRACE("ioctl: remove multicast\n");
872
873 if ((info->features & VIRTIO_NET_F_CTRL_RX) == 0)
874 return B_NOT_SUPPORTED;
875
876 for (i = 0; i < multiCount; i++) {
877 if (memcmp(&info->multi[i], buffer,
878 sizeof(info->multi[0])) == 0) {
879 break;
880 }
881 }
882
883 if (i != multiCount) {
884 if (i < multiCount - 1) {
885 memmove(&info->multi[i], &info->multi[i + 1],
886 sizeof(info->multi[i]) * (multiCount - i - 1));
887 }
888 info->multiCount--;
889 if (info->multiCount == 0) {
890 TRACE("Disabling multicast\n");
891 vtnet_set_allmulti(info, false);
892 }
893 return B_OK;
894 }
895 return B_BAD_VALUE;
896 }
897 case ETHER_GET_LINK_STATE:
898 {
899 TRACE("ioctl: get link state\n");
900 ether_link_state_t state;
901 uint16 status = VIRTIO_NET_S_LINK_UP;
902 if ((info->features & VIRTIO_NET_F_STATUS) != 0) {
903 info->virtio->read_device_config(info->virtio_device,
904 offsetof(struct virtio_net_config, status),
905 &status, sizeof(status));
906 }
907 state.media = ((status & VIRTIO_NET_S_LINK_UP) != 0 ? IFM_ACTIVE : 0)
908 | IFM_ETHER | IFM_FULL_DUPLEX | IFM_10G_T;
909 state.speed = 10000000000ULL;
910 state.quality = 1000;
911
912 return user_memcpy(buffer, &state, sizeof(ether_link_state_t));
913 }
914
915 case ETHER_SEND_NET_BUFFER:
916 if (buffer == NULL || length == 0)
917 return B_BAD_DATA;
918 if (!IS_KERNEL_ADDRESS(buffer))
919 return B_BAD_ADDRESS;
920 return virtio_net_send(cookie, (net_buffer*)buffer);
921
922 case ETHER_RECEIVE_NET_BUFFER:
923 if (buffer == NULL || length == 0)
924 return B_BAD_DATA;
925 if (!IS_KERNEL_ADDRESS(buffer))
926 return B_BAD_ADDRESS;
927 return virtio_net_receive(cookie, (net_buffer**)buffer);
928
929 default:
930 ERROR("ioctl: unknown message %" B_PRIx32 "\n", op);
931 break;
932 }
933
934
935 return B_DEV_INVALID_IOCTL;
936 }
937
938
939 // #pragma mark - driver module API
940
941
942 static float
virtio_net_supports_device(device_node * parent)943 virtio_net_supports_device(device_node* parent)
944 {
945 CALLED();
946 const char* bus;
947 uint16 deviceType;
948
949 // make sure parent is really the Virtio bus manager
950 if (sDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
951 return -1;
952
953 if (strcmp(bus, "virtio"))
954 return 0.0;
955
956 // check whether it's really a Direct Access Device
957 if (sDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM,
958 &deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_NETWORK)
959 return 0.0;
960
961 TRACE("Virtio network device found!\n");
962
963 return 0.6;
964 }
965
966
967 static status_t
virtio_net_register_device(device_node * node)968 virtio_net_register_device(device_node* node)
969 {
970 CALLED();
971
972 device_attr attrs[] = {
973 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "Virtio Network"} },
974 { NULL }
975 };
976
977 return sDeviceManager->register_node(node, VIRTIO_NET_DRIVER_MODULE_NAME,
978 attrs, NULL, NULL);
979 }
980
981
982 static status_t
virtio_net_init_driver(device_node * node,void ** cookie)983 virtio_net_init_driver(device_node* node, void** cookie)
984 {
985 CALLED();
986
987 virtio_net_driver_info* info = (virtio_net_driver_info*)malloc(
988 sizeof(virtio_net_driver_info));
989 if (info == NULL)
990 return B_NO_MEMORY;
991
992 memset(info, 0, sizeof(*info));
993
994 info->node = node;
995
996 *cookie = info;
997 return B_OK;
998 }
999
1000
1001 static void
virtio_net_uninit_driver(void * _cookie)1002 virtio_net_uninit_driver(void* _cookie)
1003 {
1004 CALLED();
1005 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie;
1006 free(info);
1007 }
1008
1009
1010 static status_t
virtio_net_register_child_devices(void * _cookie)1011 virtio_net_register_child_devices(void* _cookie)
1012 {
1013 CALLED();
1014 virtio_net_driver_info* info = (virtio_net_driver_info*)_cookie;
1015 status_t status;
1016
1017 int32 id = sDeviceManager->create_id(VIRTIO_NET_DEVICE_ID_GENERATOR);
1018 if (id < 0)
1019 return id;
1020
1021 char name[64];
1022 snprintf(name, sizeof(name), "net/virtio/%" B_PRId32,
1023 id);
1024
1025 status = sDeviceManager->publish_device(info->node, name,
1026 VIRTIO_NET_DEVICE_MODULE_NAME);
1027
1028 return status;
1029 }
1030
1031
1032 // #pragma mark -
1033
1034
1035 module_dependency module_dependencies[] = {
1036 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
1037 {NET_BUFFER_MODULE_NAME, (module_info**)&sBufferModule},
1038 {}
1039 };
1040
1041 struct device_module_info sVirtioNetDevice = {
1042 {
1043 VIRTIO_NET_DEVICE_MODULE_NAME,
1044 0,
1045 NULL
1046 },
1047
1048 virtio_net_init_device,
1049 virtio_net_uninit_device,
1050 NULL, // remove,
1051
1052 virtio_net_open,
1053 virtio_net_close,
1054 virtio_net_free,
1055 NULL, // read
1056 NULL, // write
1057 NULL, // io
1058 virtio_net_ioctl,
1059
1060 NULL, // select
1061 NULL, // deselect
1062 };
1063
1064 struct driver_module_info sVirtioNetDriver = {
1065 {
1066 VIRTIO_NET_DRIVER_MODULE_NAME,
1067 0,
1068 NULL
1069 },
1070
1071 virtio_net_supports_device,
1072 virtio_net_register_device,
1073 virtio_net_init_driver,
1074 virtio_net_uninit_driver,
1075 virtio_net_register_child_devices,
1076 NULL, // rescan
1077 NULL, // removed
1078 };
1079
1080 module_info* modules[] = {
1081 (module_info*)&sVirtioNetDriver,
1082 (module_info*)&sVirtioNetDevice,
1083 NULL
1084 };
1085