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