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