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