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* 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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