xref: /haiku/src/add-ons/kernel/network/stack/device_interfaces.cpp (revision 6aff37d1c79e20748c683ae224bd629f88a5b0be)
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 (true) {
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 	MutexLocker locker(sLock);
384 	sInterfaces.Remove(interface);
385 	locker.Unlock();
386 
387 	uninit_fifo(&interface->receive_queue);
388 	status_t status;
389 	wait_for_thread(interface->consumer_thread, &status);
390 
391 	net_device* device = interface->device;
392 	const char* moduleName = device->module->info.name;
393 
394 	device->module->uninit_device(device);
395 	put_module(moduleName);
396 
397 	recursive_lock_destroy(&interface->monitor_lock);
398 	recursive_lock_destroy(&interface->receive_lock);
399 	delete interface;
400 }
401 
402 
403 /*!	Finds an interface by the specified index and acquires a reference to it.
404 */
405 struct net_device_interface*
406 get_device_interface(uint32 index)
407 {
408 	MutexLocker locker(sLock);
409 
410 	// TODO: maintain an array of all device interfaces instead
411 	DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
412 	while (net_device_interface* interface = iterator.Next()) {
413 		if (interface->device->index == index) {
414 			if (interface->busy)
415 				break;
416 
417 			if (atomic_add(&interface->ref_count, 1) != 0)
418 				return interface;
419 		}
420 	}
421 
422 	return NULL;
423 }
424 
425 
426 /*!	Finds an interface by the specified name and grabs a reference to it.
427 	If the interface does not yet exist, a new one is created.
428 */
429 struct net_device_interface*
430 get_device_interface(const char* name, bool create)
431 {
432 	MutexLocker locker(sLock);
433 
434 	net_device_interface* interface = find_device_interface(name);
435 	if (interface != NULL) {
436 		if (interface->busy)
437 			return NULL;
438 
439 		if (atomic_add(&interface->ref_count, 1) != 0)
440 			return interface;
441 
442 		// try to recreate interface - it just got removed
443 	}
444 
445 	if (!create)
446 		return NULL;
447 
448 	void* cookie = open_module_list("network/devices");
449 	if (cookie == NULL)
450 		return NULL;
451 
452 	while (true) {
453 		char moduleName[B_FILE_NAME_LENGTH];
454 		size_t length = sizeof(moduleName);
455 		if (read_next_module_name(cookie, moduleName, &length) != B_OK)
456 			break;
457 
458 		TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
459 
460 		net_device_module_info* module;
461 		if (get_module(moduleName, (module_info**)&module) == B_OK) {
462 			net_device* device;
463 			status_t status = module->init_device(name, &device);
464 			if (status == B_OK) {
465 				interface = allocate_device_interface(device, module);
466 				if (interface != NULL)
467 					return interface;
468 
469 				module->uninit_device(device);
470 			}
471 			put_module(moduleName);
472 		}
473 	}
474 
475 	close_module_list(cookie);
476 
477 	return NULL;
478 }
479 
480 
481 /*!	Feeds the device monitors of the \a interface with the specified \a buffer.
482 	You might want to check interface::monitor_count before calling this
483 	function for optimization.
484 */
485 void
486 device_interface_monitor_receive(net_device_interface* interface,
487 	net_buffer* buffer)
488 {
489 	RecursiveLocker locker(interface->monitor_lock);
490 
491 	DeviceMonitorList::Iterator iterator
492 		= interface->monitor_funcs.GetIterator();
493 	while (iterator.HasNext()) {
494 		net_device_monitor* monitor = iterator.Next();
495 		monitor->receive(monitor, buffer);
496 	}
497 }
498 
499 
500 status_t
501 up_device_interface(net_device_interface* interface)
502 {
503 	net_device* device = interface->device;
504 
505 	RecursiveLocker locker(interface->receive_lock);
506 
507 	if (interface->up_count != 0) {
508 		interface->up_count++;
509 		return B_OK;
510 	}
511 
512 	status_t status = device->module->up(device);
513 	if (status != B_OK)
514 		return status;
515 
516 	if (device->module->receive_data != NULL) {
517 		// give the thread a nice name
518 		char name[B_OS_NAME_LENGTH];
519 		snprintf(name, sizeof(name), "%s reader", device->name);
520 
521 		interface->reader_thread = spawn_kernel_thread(device_reader_thread,
522 			name, B_REAL_TIME_DISPLAY_PRIORITY - 10, interface);
523 		if (interface->reader_thread < B_OK)
524 			return interface->reader_thread;
525 	}
526 
527 	device->flags |= IFF_UP;
528 
529 	if (device->module->receive_data != NULL)
530 		resume_thread(interface->reader_thread);
531 
532 	interface->up_count = 1;
533 	return B_OK;
534 }
535 
536 
537 void
538 down_device_interface(net_device_interface* interface)
539 {
540 	// Receive lock must be held when calling down_device_interface.
541 	// Known callers are `interface_protocol_down' which gets
542 	// here via one of the following paths:
543 	//
544 	// - domain_interface_control() [rx lock held, domain lock held]
545 	//    interface_set_down()
546 	//     interface_protocol_down()
547 	//
548 	// - domain_interface_control() [rx lock held, domain lock held]
549 	//    remove_interface_from_domain()
550 	//     delete_interface()
551 	//      interface_set_down()
552 
553 	net_device* device = interface->device;
554 
555 	device->flags &= ~IFF_UP;
556 	device->module->down(device);
557 
558 	notify_device_monitors(interface, B_DEVICE_GOING_DOWN);
559 
560 	if (device->module->receive_data != NULL) {
561 		thread_id readerThread = interface->reader_thread;
562 
563 		// make sure the reader thread is gone before shutting down the interface
564 		status_t status;
565 		wait_for_thread(readerThread, &status);
566 	}
567 }
568 
569 
570 //	#pragma mark - devices stack API
571 
572 
573 /*!	Unregisters a previously registered deframer function. */
574 status_t
575 unregister_device_deframer(net_device* device)
576 {
577 	MutexLocker locker(sLock);
578 
579 	// find device interface for this device
580 	net_device_interface* interface = find_device_interface(device->name);
581 	if (interface == NULL)
582 		return B_DEVICE_NOT_FOUND;
583 
584 	RecursiveLocker _(interface->receive_lock);
585 
586 	if (--interface->deframe_ref_count == 0)
587 		interface->deframe_func = NULL;
588 
589 	return B_OK;
590 }
591 
592 
593 /*!	Registers the deframer function for the specified \a device.
594 	Note, however, that right now, you can only register one single
595 	deframer function per device.
596 
597 	If the need arises, we might want to lift that limitation at a
598 	later time (which would require a slight API change, though).
599 */
600 status_t
601 register_device_deframer(net_device* device, net_deframe_func deframeFunc)
602 {
603 	MutexLocker locker(sLock);
604 
605 	// find device interface for this device
606 	net_device_interface* interface = find_device_interface(device->name);
607 	if (interface == NULL)
608 		return B_DEVICE_NOT_FOUND;
609 
610 	RecursiveLocker _(interface->receive_lock);
611 
612 	if (interface->deframe_func != NULL
613 		&& interface->deframe_func != deframeFunc)
614 		return B_ERROR;
615 
616 	interface->deframe_func = deframeFunc;
617 	interface->deframe_ref_count++;
618 	return B_OK;
619 }
620 
621 
622 /*!	Registers a domain to receive net_buffers from the specified \a device. */
623 status_t
624 register_domain_device_handler(struct net_device* device, int32 type,
625 	struct net_domain* _domain)
626 {
627 	net_domain_private* domain = (net_domain_private*)_domain;
628 	if (domain->module == NULL || domain->module->receive_data == NULL)
629 		return B_BAD_VALUE;
630 
631 	return register_device_handler(device, type, &domain_receive_adapter,
632 		domain);
633 }
634 
635 
636 /*!	Registers a receiving function callback for the specified \a device. */
637 status_t
638 register_device_handler(struct net_device* device, int32 type,
639 	net_receive_func receiveFunc, void* cookie)
640 {
641 	MutexLocker locker(sLock);
642 
643 	// find device interface for this device
644 	net_device_interface* interface = find_device_interface(device->name);
645 	if (interface == NULL)
646 		return B_DEVICE_NOT_FOUND;
647 
648 	RecursiveLocker _(interface->receive_lock);
649 
650 	// see if such a handler already for this device
651 
652 	DeviceHandlerList::Iterator iterator
653 		= interface->receive_funcs.GetIterator();
654 	while (net_device_handler* handler = iterator.Next()) {
655 		if (handler->type == type)
656 			return B_ERROR;
657 	}
658 
659 	// Add new handler
660 
661 	net_device_handler* handler = new(std::nothrow) net_device_handler;
662 	if (handler == NULL)
663 		return B_NO_MEMORY;
664 
665 	handler->func = receiveFunc;
666 	handler->type = type;
667 	handler->cookie = cookie;
668 	interface->receive_funcs.Add(handler);
669 	return B_OK;
670 }
671 
672 
673 /*!	Unregisters a previously registered device handler. */
674 status_t
675 unregister_device_handler(struct net_device* device, int32 type)
676 {
677 	MutexLocker locker(sLock);
678 
679 	// find device interface for this device
680 	net_device_interface* interface = find_device_interface(device->name);
681 	if (interface == NULL)
682 		return B_DEVICE_NOT_FOUND;
683 
684 	RecursiveLocker _(interface->receive_lock);
685 
686 	// search for the handler
687 
688 	DeviceHandlerList::Iterator iterator
689 		= interface->receive_funcs.GetIterator();
690 	while (net_device_handler* handler = iterator.Next()) {
691 		if (handler->type == type) {
692 			// found it
693 			iterator.Remove();
694 			delete handler;
695 			return B_OK;
696 		}
697 	}
698 
699 	return B_BAD_VALUE;
700 }
701 
702 
703 /*!	Registers a device monitor for the specified device. */
704 status_t
705 register_device_monitor(net_device* device, net_device_monitor* monitor)
706 {
707 	if (monitor->receive == NULL || monitor->event == NULL)
708 		return B_BAD_VALUE;
709 
710 	MutexLocker locker(sLock);
711 
712 	// find device interface for this device
713 	net_device_interface* interface = find_device_interface(device->name);
714 	if (interface == NULL)
715 		return B_DEVICE_NOT_FOUND;
716 
717 	RecursiveLocker monitorLocker(interface->monitor_lock);
718 	interface->monitor_funcs.Add(monitor);
719 	atomic_add(&interface->monitor_count, 1);
720 
721 	return B_OK;
722 }
723 
724 
725 /*!	Unregisters a previously registered device monitor. */
726 status_t
727 unregister_device_monitor(net_device* device, net_device_monitor* monitor)
728 {
729 	MutexLocker locker(sLock);
730 
731 	// find device interface for this device
732 	net_device_interface* interface = find_device_interface(device->name);
733 	if (interface == NULL)
734 		return B_DEVICE_NOT_FOUND;
735 
736 	RecursiveLocker monitorLocker(interface->monitor_lock);
737 
738 	// search for the monitor
739 
740 	DeviceMonitorList::Iterator iterator
741 		= interface->monitor_funcs.GetIterator();
742 	while (iterator.HasNext()) {
743 		if (iterator.Next() == monitor) {
744 			iterator.Remove();
745 			atomic_add(&interface->monitor_count, -1);
746 			return B_OK;
747 		}
748 	}
749 
750 	return B_BAD_VALUE;
751 }
752 
753 
754 /*!	This function is called by device modules in case their link
755 	state changed, ie. if an ethernet cable was plugged in or
756 	removed.
757 */
758 status_t
759 device_link_changed(net_device* device)
760 {
761 	notify_link_changed(device);
762 	return B_OK;
763 }
764 
765 
766 /*!	This function is called by device modules once their device got
767 	physically removed, ie. a USB networking card is unplugged.
768 */
769 status_t
770 device_removed(net_device* device)
771 {
772 	MutexLocker locker(sLock);
773 
774 	net_device_interface* interface = find_device_interface(device->name);
775 	if (interface == NULL)
776 		return B_DEVICE_NOT_FOUND;
777 	if (interface->busy)
778 		return B_BUSY;
779 
780 	// Acquire a reference to the device interface being removed
781 	// so our put_() will (eventually) do the final cleanup
782 	atomic_add(&interface->ref_count, 1);
783 	interface->busy = true;
784 	locker.Unlock();
785 
786 	// Propagate the loss of the device throughout the stack.
787 
788 	interface_removed_device_interface(interface);
789 	notify_device_monitors(interface, B_DEVICE_BEING_REMOVED);
790 
791 	// By now all of the monitors must have removed themselves. If they
792 	// didn't, they'll probably wait forever to be callback'ed again.
793 	RecursiveLocker monitorLocker(interface->monitor_lock);
794 	interface->monitor_funcs.RemoveAll();
795 	monitorLocker.Unlock();
796 
797 	// All of the readers should be gone as well since we are out of
798 	// interfaces and put_domain_datalink_protocols() is called for
799 	// each delete_interface().
800 
801 	put_device_interface(interface);
802 
803 	return B_OK;
804 }
805 
806 
807 status_t
808 device_enqueue_buffer(net_device* device, net_buffer* buffer)
809 {
810 	net_device_interface* interface = get_device_interface(device->index);
811 	if (interface == NULL)
812 		return B_DEVICE_NOT_FOUND;
813 
814 	status_t status = fifo_enqueue_buffer(&interface->receive_queue, buffer);
815 
816 	put_device_interface(interface);
817 	return status;
818 }
819 
820 
821 //	#pragma mark -
822 
823 
824 status_t
825 init_device_interfaces()
826 {
827 	mutex_init(&sLock, "net device interfaces");
828 
829 	new (&sInterfaces) DeviceInterfaceList;
830 		// static C++ objects are not initialized in the module startup
831 
832 #if ENABLE_DEBUGGER_COMMANDS
833 	add_debugger_command("net_device_interface", &dump_device_interface,
834 		"Dump the given network device interface");
835 	add_debugger_command("net_device_interfaces", &dump_device_interfaces,
836 		"Dump network device interfaces");
837 #endif
838 	return B_OK;
839 }
840 
841 
842 status_t
843 uninit_device_interfaces()
844 {
845 #if ENABLE_DEBUGGER_COMMANDS
846 	remove_debugger_command("net_device_interface", &dump_device_interface);
847 	remove_debugger_command("net_device_interfaces", &dump_device_interfaces);
848 #endif
849 
850 	mutex_destroy(&sLock);
851 	return B_OK;
852 }
853 
854