1 /* 2 * Copyright 2006-2017, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 */ 8 9 10 #include "device_interfaces.h" 11 #include "domains.h" 12 #include "interfaces.h" 13 #include "stack_private.h" 14 #include "utility.h" 15 16 #include <net_device.h> 17 18 #include <lock.h> 19 #include <util/AutoLock.h> 20 21 #include <KernelExport.h> 22 23 #include <net/if_dl.h> 24 #include <netinet/in.h> 25 #include <new> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 31 //#define TRACE_DEVICE_INTERFACES 32 #ifdef TRACE_DEVICE_INTERFACES 33 # define TRACE(x) dprintf x 34 #else 35 # define TRACE(x) ; 36 #endif 37 38 39 static mutex sLock; 40 static DeviceInterfaceList sInterfaces; 41 static uint32 sDeviceIndex; 42 43 44 /*! A service thread for each device interface. It just reads as many packets 45 as available, deframes them, and puts them into the receive queue of the 46 device interface. 47 */ 48 static status_t 49 device_reader_thread(void* _interface) 50 { 51 net_device_interface* interface = (net_device_interface*)_interface; 52 net_device* device = interface->device; 53 status_t status = B_OK; 54 55 while ((device->flags & IFF_UP) != 0) { 56 net_buffer* buffer; 57 status = device->module->receive_data(device, &buffer); 58 if (status == B_OK) { 59 // feed device monitors 60 if (atomic_get(&interface->monitor_count) > 0) 61 device_interface_monitor_receive(interface, buffer); 62 63 ASSERT(buffer->interface_address == NULL); 64 65 if (interface->deframe_func(interface->device, buffer) != B_OK) { 66 gNetBufferModule.free(buffer); 67 atomic_add((int32*)&device->stats.receive.dropped, 1); 68 continue; 69 } 70 71 const size_t packetSize = buffer->size; 72 status = fifo_enqueue_buffer(&interface->receive_queue, buffer); 73 if (status == B_OK) { 74 atomic_add((int32*)&device->stats.receive.packets, 1); 75 atomic_add64((int64*)&device->stats.receive.bytes, packetSize); 76 } else { 77 gNetBufferModule.free(buffer); 78 atomic_add((int32*)&device->stats.receive.dropped, 1); 79 } 80 } else if (status == B_DEVICE_NOT_FOUND) { 81 device_removed(device); 82 return status; 83 } else { 84 atomic_add((int32*)&device->stats.receive.errors, 1); 85 86 // In case of error, give the other threads some 87 // time to run since this is a high priority time thread. 88 snooze(10000); 89 } 90 } 91 92 return status; 93 } 94 95 96 static status_t 97 device_consumer_thread(void* _interface) 98 { 99 net_device_interface* interface = (net_device_interface*)_interface; 100 net_device* device = interface->device; 101 net_buffer* buffer; 102 103 while (atomic_get(&interface->ref_count) > 0) { 104 ssize_t status = fifo_dequeue_buffer(&interface->receive_queue, 0, 105 B_INFINITE_TIMEOUT, &buffer); 106 if (status != B_OK) { 107 if (status == B_INTERRUPTED) 108 continue; 109 break; 110 } 111 112 if (buffer->interface_address != NULL) { 113 // If the interface is already specified, this buffer was 114 // delivered locally. 115 if (buffer->interface_address->domain->module->receive_data(buffer) 116 == B_OK) 117 buffer = NULL; 118 } else { 119 sockaddr_dl& linkAddress = *(sockaddr_dl*)buffer->source; 120 int32 genericType = buffer->type; 121 int32 specificType = B_NET_FRAME_TYPE(linkAddress.sdl_type, 122 ntohs(linkAddress.sdl_e_type)); 123 124 buffer->index = interface->device->index; 125 126 // Find handler for this packet 127 128 RecursiveLocker locker(interface->receive_lock); 129 130 DeviceHandlerList::Iterator iterator 131 = interface->receive_funcs.GetIterator(); 132 while (buffer != NULL && iterator.HasNext()) { 133 net_device_handler* handler = iterator.Next(); 134 135 // If the handler returns B_OK, it consumed the buffer - first 136 // handler wins. 137 if ((handler->type == genericType 138 || handler->type == specificType) 139 && handler->func(handler->cookie, device, buffer) == B_OK) 140 buffer = NULL; 141 } 142 } 143 144 if (buffer != NULL) 145 gNetBufferModule.free(buffer); 146 } 147 148 return B_OK; 149 } 150 151 152 /*! The domain's device receive handler - this will inject the net_buffers into 153 the protocol layer (the domain's registered receive handler). 154 */ 155 static status_t 156 domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer) 157 { 158 net_domain_private* domain = (net_domain_private*)cookie; 159 160 return domain->module->receive_data(buffer); 161 } 162 163 164 static net_device_interface* 165 find_device_interface(const char* name) 166 { 167 ASSERT_LOCKED_MUTEX(&sLock); 168 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 169 170 while (net_device_interface* interface = iterator.Next()) { 171 if (!strcmp(interface->device->name, name)) 172 return interface; 173 } 174 175 return NULL; 176 } 177 178 179 static net_device_interface* 180 allocate_device_interface(net_device* device, net_device_module_info* module) 181 { 182 net_device_interface* interface = new(std::nothrow) net_device_interface; 183 if (interface == NULL) 184 return NULL; 185 186 recursive_lock_init(&interface->receive_lock, "device interface receive"); 187 recursive_lock_init(&interface->monitor_lock, "device interface monitors"); 188 189 char name[128]; 190 snprintf(name, sizeof(name), "%s receive queue", device->name); 191 192 if (init_fifo(&interface->receive_queue, name, 16 * 1024 * 1024) < B_OK) 193 goto error1; 194 195 interface->device = device; 196 interface->up_count = 0; 197 interface->ref_count = 1; 198 interface->busy = false; 199 interface->monitor_count = 0; 200 interface->deframe_func = NULL; 201 interface->deframe_ref_count = 0; 202 203 snprintf(name, sizeof(name), "%s consumer", device->name); 204 205 interface->reader_thread = -1; 206 interface->consumer_thread = spawn_kernel_thread(device_consumer_thread, 207 name, B_DISPLAY_PRIORITY, interface); 208 if (interface->consumer_thread < B_OK) 209 goto error2; 210 resume_thread(interface->consumer_thread); 211 212 // TODO: proper interface index allocation 213 device->index = ++sDeviceIndex; 214 device->module = module; 215 216 sInterfaces.Add(interface); 217 return interface; 218 219 error2: 220 uninit_fifo(&interface->receive_queue); 221 error1: 222 recursive_lock_destroy(&interface->receive_lock); 223 recursive_lock_destroy(&interface->monitor_lock); 224 delete interface; 225 226 return NULL; 227 } 228 229 230 static void 231 notify_device_monitors(net_device_interface* interface, int32 event) 232 { 233 RecursiveLocker locker(interface->monitor_lock); 234 235 DeviceMonitorList::Iterator iterator 236 = interface->monitor_funcs.GetIterator(); 237 while (net_device_monitor* monitor = iterator.Next()) { 238 // it's safe for the "current" item to remove itself. 239 monitor->event(monitor, event); 240 } 241 } 242 243 244 #if ENABLE_DEBUGGER_COMMANDS 245 246 247 static int 248 dump_device_interface(int argc, char** argv) 249 { 250 if (argc != 2) { 251 kprintf("usage: %s [address]\n", argv[0]); 252 return 0; 253 } 254 255 net_device_interface* interface 256 = (net_device_interface*)parse_expression(argv[1]); 257 258 kprintf("device: %p\n", interface->device); 259 kprintf("reader_thread: %" B_PRId32 "\n", interface->reader_thread); 260 kprintf("up_count: %" B_PRIu32 "\n", interface->up_count); 261 kprintf("ref_count: %" B_PRId32 "\n", interface->ref_count); 262 kprintf("deframe_func: %p\n", interface->deframe_func); 263 kprintf("deframe_ref_count: %" B_PRId32 "\n", interface->ref_count); 264 kprintf("consumer_thread: %" B_PRId32 "\n", interface->consumer_thread); 265 266 kprintf("monitor_count: %" B_PRId32 "\n", interface->monitor_count); 267 kprintf("monitor_lock: %p\n", &interface->monitor_lock); 268 kprintf("monitor_funcs:\n"); 269 DeviceMonitorList::Iterator monitorIterator 270 = interface->monitor_funcs.GetIterator(); 271 while (monitorIterator.HasNext()) 272 kprintf(" %p\n", monitorIterator.Next()); 273 274 kprintf("receive_lock: %p\n", &interface->receive_lock); 275 kprintf("receive_queue: %p\n", &interface->receive_queue); 276 kprintf("receive_funcs:\n"); 277 DeviceHandlerList::Iterator handlerIterator 278 = interface->receive_funcs.GetIterator(); 279 while (handlerIterator.HasNext()) 280 kprintf(" %p\n", handlerIterator.Next()); 281 282 return 0; 283 } 284 285 286 static int 287 dump_device_interfaces(int argc, char** argv) 288 { 289 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 290 while (net_device_interface* interface = iterator.Next()) { 291 kprintf(" %p %s\n", interface, interface->device->name); 292 } 293 294 return 0; 295 } 296 297 298 #endif // ENABLE_DEBUGGER_COMMANDS 299 300 301 // #pragma mark - device interfaces 302 303 304 net_device_interface* 305 acquire_device_interface(net_device_interface* interface) 306 { 307 if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0) 308 return NULL; 309 310 return interface; 311 } 312 313 314 void 315 get_device_interface_address(net_device_interface* interface, 316 sockaddr* _address) 317 { 318 sockaddr_dl &address = *(sockaddr_dl*)_address; 319 320 address.sdl_family = AF_LINK; 321 address.sdl_index = interface->device->index; 322 address.sdl_type = interface->device->type; 323 address.sdl_nlen = strlen(interface->device->name); 324 address.sdl_slen = 0; 325 memcpy(address.sdl_data, interface->device->name, address.sdl_nlen); 326 327 address.sdl_alen = interface->device->address.length; 328 memcpy(LLADDR(&address), interface->device->address.data, address.sdl_alen); 329 330 address.sdl_len = sizeof(sockaddr_dl) - sizeof(address.sdl_data) 331 + address.sdl_nlen + address.sdl_alen; 332 } 333 334 335 uint32 336 count_device_interfaces() 337 { 338 MutexLocker locker(sLock); 339 340 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 341 uint32 count = 0; 342 343 while (iterator.HasNext()) { 344 iterator.Next(); 345 count++; 346 } 347 348 return count; 349 } 350 351 352 /*! Dumps a list of all interfaces into the supplied userland buffer. 353 If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is 354 returned. 355 */ 356 status_t 357 list_device_interfaces(void* _buffer, size_t* bufferSize) 358 { 359 MutexLocker locker(sLock); 360 361 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 362 UserBuffer buffer(_buffer, *bufferSize); 363 364 while (net_device_interface* interface = iterator.Next()) { 365 buffer.Push(interface->device->name, IF_NAMESIZE); 366 367 sockaddr_storage address; 368 get_device_interface_address(interface, (sockaddr*)&address); 369 370 buffer.Push(&address, address.ss_len); 371 if (IF_NAMESIZE + address.ss_len < (int)sizeof(ifreq)) 372 buffer.Pad(sizeof(ifreq) - IF_NAMESIZE - address.ss_len); 373 374 if (buffer.Status() != B_OK) 375 return buffer.Status(); 376 } 377 378 *bufferSize = buffer.BytesConsumed(); 379 return B_OK; 380 } 381 382 383 /*! Releases the reference for the interface. When all references are 384 released, the interface is removed. 385 */ 386 void 387 put_device_interface(struct net_device_interface* interface) 388 { 389 if (interface == NULL) 390 return; 391 392 if (atomic_add(&interface->ref_count, -1) != 1) 393 return; 394 395 // Indicate we are in the process of destroying this interface 396 // by setting its ref_count to 0. 397 interface->ref_count = 0; 398 399 MutexLocker locker(sLock); 400 sInterfaces.Remove(interface); 401 locker.Unlock(); 402 403 uninit_fifo(&interface->receive_queue); 404 wait_for_thread(interface->consumer_thread, NULL); 405 406 net_device* device = interface->device; 407 const char* moduleName = device->module->info.name; 408 409 device->module->uninit_device(device); 410 put_module(moduleName); 411 412 recursive_lock_destroy(&interface->monitor_lock); 413 recursive_lock_destroy(&interface->receive_lock); 414 delete interface; 415 } 416 417 418 /*! Finds an interface by the specified index and acquires a reference to it. 419 */ 420 struct net_device_interface* 421 get_device_interface(uint32 index) 422 { 423 MutexLocker locker(sLock); 424 425 // TODO: maintain an array of all device interfaces instead 426 DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator(); 427 while (net_device_interface* interface = iterator.Next()) { 428 if (interface->device->index == index) { 429 if (interface->busy) 430 break; 431 432 if (atomic_add(&interface->ref_count, 1) != 0) 433 return interface; 434 } 435 } 436 437 return NULL; 438 } 439 440 441 /*! Finds an interface by the specified name and grabs a reference to it. 442 If the interface does not yet exist, a new one is created. 443 */ 444 struct net_device_interface* 445 get_device_interface(const char* name, bool create) 446 { 447 MutexLocker locker(sLock); 448 449 net_device_interface* interface = find_device_interface(name); 450 if (interface != NULL) { 451 if (interface->busy) 452 return NULL; 453 454 if (atomic_add(&interface->ref_count, 1) != 0) 455 return interface; 456 457 // try to recreate interface - it just got removed 458 } 459 460 if (!create) 461 return NULL; 462 463 void* cookie = open_module_list("network/devices"); 464 if (cookie == NULL) 465 return NULL; 466 467 while (true) { 468 char moduleName[B_FILE_NAME_LENGTH]; 469 size_t length = sizeof(moduleName); 470 if (read_next_module_name(cookie, moduleName, &length) != B_OK) 471 break; 472 473 TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name)); 474 475 net_device_module_info* module; 476 if (get_module(moduleName, (module_info**)&module) == B_OK) { 477 net_device* device; 478 status_t status = module->init_device(name, &device); 479 if (status == B_OK) { 480 interface = allocate_device_interface(device, module); 481 if (interface != NULL) { 482 close_module_list(cookie); 483 return interface; 484 } 485 486 module->uninit_device(device); 487 } 488 put_module(moduleName); 489 } 490 } 491 492 close_module_list(cookie); 493 494 return NULL; 495 } 496 497 498 /*! Feeds the device monitors of the \a interface with the specified \a buffer. 499 You might want to check interface::monitor_count before calling this 500 function for optimization. 501 */ 502 void 503 device_interface_monitor_receive(net_device_interface* interface, 504 net_buffer* buffer) 505 { 506 RecursiveLocker locker(interface->monitor_lock); 507 508 DeviceMonitorList::Iterator iterator 509 = interface->monitor_funcs.GetIterator(); 510 while (iterator.HasNext()) { 511 net_device_monitor* monitor = iterator.Next(); 512 monitor->receive(monitor, buffer); 513 } 514 } 515 516 517 status_t 518 up_device_interface(net_device_interface* interface) 519 { 520 net_device* device = interface->device; 521 522 RecursiveLocker locker(interface->receive_lock); 523 524 if (interface->up_count != 0) { 525 interface->up_count++; 526 return B_OK; 527 } 528 529 status_t status = device->module->up(device); 530 if (status != B_OK) 531 return status; 532 533 if (device->module->receive_data != NULL) { 534 // give the thread a nice name 535 char name[B_OS_NAME_LENGTH]; 536 snprintf(name, sizeof(name), "%s reader", device->name); 537 538 interface->reader_thread = spawn_kernel_thread(device_reader_thread, 539 name, B_REAL_TIME_DISPLAY_PRIORITY - 10, interface); 540 if (interface->reader_thread < B_OK) 541 return interface->reader_thread; 542 } 543 544 device->flags |= IFF_UP; 545 546 if (device->module->receive_data != NULL) 547 resume_thread(interface->reader_thread); 548 549 interface->up_count = 1; 550 return B_OK; 551 } 552 553 554 void 555 down_device_interface(net_device_interface* interface) 556 { 557 // Receive lock must be held when calling down_device_interface. 558 // Known callers are `interface_protocol_down' which gets 559 // here via one of the following paths: 560 // 561 // - Interface::Control() 562 // Interface::SetDown() 563 // interface_protocol_down() 564 // 565 // - datalink_control() 566 // remove_interface() 567 // Interface::SetDown() etc. 568 // 569 // - device_removed() 570 // interface_removed_device_interface() 571 // remove_interface() etc. 572 573 net_device* device = interface->device; 574 575 device->flags &= ~IFF_UP; 576 device->module->down(device); 577 578 notify_device_monitors(interface, B_DEVICE_GOING_DOWN); 579 580 if (device->module->receive_data != NULL) { 581 thread_id readerThread = interface->reader_thread; 582 583 // make sure the reader thread is gone before shutting down the interface 584 // (note that we may be the reader thread) 585 status_t status; 586 wait_for_thread(readerThread, &status); 587 } 588 } 589 590 591 // #pragma mark - devices stack API 592 593 594 /*! Unregisters a previously registered deframer function. */ 595 status_t 596 unregister_device_deframer(net_device* device) 597 { 598 MutexLocker locker(sLock); 599 600 // find device interface for this device 601 net_device_interface* interface = find_device_interface(device->name); 602 if (interface == NULL) 603 return B_DEVICE_NOT_FOUND; 604 605 RecursiveLocker _(interface->receive_lock); 606 607 if (--interface->deframe_ref_count == 0) 608 interface->deframe_func = NULL; 609 610 return B_OK; 611 } 612 613 614 /*! Registers the deframer function for the specified \a device. 615 Note, however, that right now, you can only register one single 616 deframer function per device. 617 618 If the need arises, we might want to lift that limitation at a 619 later time (which would require a slight API change, though). 620 */ 621 status_t 622 register_device_deframer(net_device* device, net_deframe_func deframeFunc) 623 { 624 MutexLocker locker(sLock); 625 626 // find device interface for this device 627 net_device_interface* interface = find_device_interface(device->name); 628 if (interface == NULL) 629 return B_DEVICE_NOT_FOUND; 630 631 RecursiveLocker _(interface->receive_lock); 632 633 if (interface->deframe_func != NULL 634 && interface->deframe_func != deframeFunc) 635 return B_ERROR; 636 637 interface->deframe_func = deframeFunc; 638 interface->deframe_ref_count++; 639 return B_OK; 640 } 641 642 643 /*! Registers a domain to receive net_buffers from the specified \a device. */ 644 status_t 645 register_domain_device_handler(struct net_device* device, int32 type, 646 struct net_domain* _domain) 647 { 648 net_domain_private* domain = (net_domain_private*)_domain; 649 if (domain->module == NULL || domain->module->receive_data == NULL) 650 return B_BAD_VALUE; 651 652 return register_device_handler(device, type, &domain_receive_adapter, 653 domain); 654 } 655 656 657 /*! Registers a receiving function callback for the specified \a device. */ 658 status_t 659 register_device_handler(struct net_device* device, int32 type, 660 net_receive_func receiveFunc, void* cookie) 661 { 662 MutexLocker locker(sLock); 663 664 // find device interface for this device 665 net_device_interface* interface = find_device_interface(device->name); 666 if (interface == NULL) 667 return B_DEVICE_NOT_FOUND; 668 669 RecursiveLocker _(interface->receive_lock); 670 671 // see if such a handler already for this device 672 673 DeviceHandlerList::Iterator iterator 674 = interface->receive_funcs.GetIterator(); 675 while (net_device_handler* handler = iterator.Next()) { 676 if (handler->type == type) 677 return B_ERROR; 678 } 679 680 // Add new handler 681 682 net_device_handler* handler = new(std::nothrow) net_device_handler; 683 if (handler == NULL) 684 return B_NO_MEMORY; 685 686 handler->func = receiveFunc; 687 handler->type = type; 688 handler->cookie = cookie; 689 interface->receive_funcs.Add(handler); 690 return B_OK; 691 } 692 693 694 /*! Unregisters a previously registered device handler. */ 695 status_t 696 unregister_device_handler(struct net_device* device, int32 type) 697 { 698 MutexLocker locker(sLock); 699 700 // find device interface for this device 701 net_device_interface* interface = find_device_interface(device->name); 702 if (interface == NULL) 703 return B_DEVICE_NOT_FOUND; 704 705 RecursiveLocker _(interface->receive_lock); 706 707 // search for the handler 708 709 DeviceHandlerList::Iterator iterator 710 = interface->receive_funcs.GetIterator(); 711 while (net_device_handler* handler = iterator.Next()) { 712 if (handler->type == type) { 713 // found it 714 iterator.Remove(); 715 delete handler; 716 return B_OK; 717 } 718 } 719 720 return B_BAD_VALUE; 721 } 722 723 724 /*! Registers a device monitor for the specified device. */ 725 status_t 726 register_device_monitor(net_device* device, net_device_monitor* monitor) 727 { 728 if (monitor->receive == NULL || monitor->event == NULL) 729 return B_BAD_VALUE; 730 731 MutexLocker locker(sLock); 732 733 // find device interface for this device 734 net_device_interface* interface = find_device_interface(device->name); 735 if (interface == NULL) 736 return B_DEVICE_NOT_FOUND; 737 738 RecursiveLocker monitorLocker(interface->monitor_lock); 739 interface->monitor_funcs.Add(monitor); 740 atomic_add(&interface->monitor_count, 1); 741 742 return B_OK; 743 } 744 745 746 /*! Unregisters a previously registered device monitor. */ 747 status_t 748 unregister_device_monitor(net_device* device, net_device_monitor* monitor) 749 { 750 MutexLocker locker(sLock); 751 752 // find device interface for this device 753 net_device_interface* interface = find_device_interface(device->name); 754 if (interface == NULL) 755 return B_DEVICE_NOT_FOUND; 756 757 RecursiveLocker monitorLocker(interface->monitor_lock); 758 759 // search for the monitor 760 761 DeviceMonitorList::Iterator iterator 762 = interface->monitor_funcs.GetIterator(); 763 while (iterator.HasNext()) { 764 if (iterator.Next() == monitor) { 765 iterator.Remove(); 766 atomic_add(&interface->monitor_count, -1); 767 return B_OK; 768 } 769 } 770 771 return B_BAD_VALUE; 772 } 773 774 775 /*! This function is called by device modules in case their link 776 state changed, ie. if an ethernet cable was plugged in or 777 removed. 778 */ 779 status_t 780 device_link_changed(net_device* device) 781 { 782 notify_link_changed(device); 783 return B_OK; 784 } 785 786 787 /*! This function is called by device modules once their device got 788 physically removed, ie. a USB networking card is unplugged. 789 */ 790 status_t 791 device_removed(net_device* device) 792 { 793 MutexLocker locker(sLock); 794 795 net_device_interface* interface = find_device_interface(device->name); 796 if (interface == NULL) 797 return B_DEVICE_NOT_FOUND; 798 if (interface->busy) 799 return B_BUSY; 800 801 // Acquire a reference to the device interface being removed 802 // so our put_() will (eventually) do the final cleanup 803 atomic_add(&interface->ref_count, 1); 804 interface->busy = true; 805 locker.Unlock(); 806 807 // Propagate the loss of the device throughout the stack. 808 809 interface_removed_device_interface(interface); 810 notify_device_monitors(interface, B_DEVICE_BEING_REMOVED); 811 812 // By now all of the monitors must have removed themselves. If they 813 // didn't, they'll probably wait forever to be callback'ed again. 814 RecursiveLocker monitorLocker(interface->monitor_lock); 815 interface->monitor_funcs.RemoveAll(); 816 monitorLocker.Unlock(); 817 818 // All of the readers should be gone as well since we are out of 819 // interfaces and put_domain_datalink_protocols() is called for 820 // each delete_interface(). 821 822 put_device_interface(interface); 823 824 return B_OK; 825 } 826 827 828 status_t 829 device_enqueue_buffer(net_device* device, net_buffer* buffer) 830 { 831 net_device_interface* interface = get_device_interface(device->index); 832 if (interface == NULL) 833 return B_DEVICE_NOT_FOUND; 834 835 status_t status = interface->deframe_func(interface->device, buffer); 836 if (status != B_OK) { 837 gNetBufferModule.free(buffer); 838 return status; 839 } 840 841 status = fifo_enqueue_buffer(&interface->receive_queue, buffer); 842 843 put_device_interface(interface); 844 return status; 845 } 846 847 848 // #pragma mark - 849 850 851 status_t 852 init_device_interfaces() 853 { 854 mutex_init(&sLock, "net device interfaces"); 855 856 new (&sInterfaces) DeviceInterfaceList; 857 // static C++ objects are not initialized in the module startup 858 859 #if ENABLE_DEBUGGER_COMMANDS 860 add_debugger_command("net_device_interface", &dump_device_interface, 861 "Dump the given network device interface"); 862 add_debugger_command("net_device_interfaces", &dump_device_interfaces, 863 "Dump network device interfaces"); 864 #endif 865 return B_OK; 866 } 867 868 869 status_t 870 uninit_device_interfaces() 871 { 872 #if ENABLE_DEBUGGER_COMMANDS 873 remove_debugger_command("net_device_interface", &dump_device_interface); 874 remove_debugger_command("net_device_interfaces", &dump_device_interfaces); 875 #endif 876 877 mutex_destroy(&sLock); 878 return B_OK; 879 } 880 881