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