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
device_reader_thread(void * _interface)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
device_consumer_thread(void * _interface)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
domain_receive_adapter(void * cookie,net_device * device,net_buffer * buffer)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*
find_device_interface(const char * name)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*
allocate_device_interface(net_device * device,net_device_module_info * module)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
notify_device_monitors(net_device_interface * interface,int32 event)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
dump_device_interface(int argc,char ** argv)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
dump_device_interfaces(int argc,char ** argv)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*
acquire_device_interface(net_device_interface * 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
get_device_interface_address(net_device_interface * interface,sockaddr * _address)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
count_device_interfaces()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
list_device_interfaces(void * _buffer,size_t * bufferSize)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
put_device_interface(struct net_device_interface * interface)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*
get_device_interface(uint32 index)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*
get_device_interface(const char * name,bool create)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
device_interface_monitor_receive(net_device_interface * interface,net_buffer * buffer)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
up_device_interface(net_device_interface * interface)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
down_device_interface(net_device_interface * interface)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
unregister_device_deframer(net_device * device)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
register_device_deframer(net_device * device,net_deframe_func deframeFunc)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
register_domain_device_handler(struct net_device * device,int32 type,struct net_domain * _domain)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
register_device_handler(struct net_device * device,int32 type,net_receive_func receiveFunc,void * cookie)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
unregister_device_handler(struct net_device * device,int32 type)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
register_device_monitor(net_device * device,net_device_monitor * monitor)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
unregister_device_monitor(net_device * device,net_device_monitor * monitor)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
device_link_changed(net_device * device)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
device_removed(net_device * device)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
device_enqueue_buffer(net_device * device,net_buffer * buffer)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
init_device_interfaces()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
uninit_device_interfaces()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