* Renamed net_device_interface::rx_lock to receive_lock.
* Cleanup, improved comments, removed useless ones. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29232 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -47,9 +47,9 @@ device_reader_thread(void *_interface)
|
|||||||
net_device* device = interface->device;
|
net_device* device = interface->device;
|
||||||
status_t status = B_OK;
|
status_t status = B_OK;
|
||||||
|
|
||||||
RecursiveLocker locker(interface->rx_lock);
|
RecursiveLocker locker(interface->receive_lock);
|
||||||
|
|
||||||
while (device->flags & IFF_UP) {
|
while ((device->flags & IFF_UP) != 0) {
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
net_buffer* buffer;
|
net_buffer* buffer;
|
||||||
@@ -61,8 +61,7 @@ device_reader_thread(void *_interface)
|
|||||||
// feed device monitors
|
// feed device monitors
|
||||||
DeviceMonitorList::Iterator iterator =
|
DeviceMonitorList::Iterator iterator =
|
||||||
interface->monitor_funcs.GetIterator();
|
interface->monitor_funcs.GetIterator();
|
||||||
while (iterator.HasNext()) {
|
while (net_device_monitor* monitor = iterator.Next()) {
|
||||||
net_device_monitor *monitor = iterator.Next();
|
|
||||||
monitor->receive(monitor, buffer);
|
monitor->receive(monitor, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,18 +75,9 @@ device_reader_thread(void *_interface)
|
|||||||
fifo_enqueue_buffer(&interface->receive_queue, buffer);
|
fifo_enqueue_buffer(&interface->receive_queue, buffer);
|
||||||
} else {
|
} else {
|
||||||
// In case of error, give the other threads some
|
// In case of error, give the other threads some
|
||||||
// time to run since this is a near real time thread.
|
// time to run since this is a high priority time thread.
|
||||||
//
|
|
||||||
// TODO: can this value be lower? 1000 works fine in
|
|
||||||
// my system. 10ms seems a bit too much and adds
|
|
||||||
// as latency.
|
|
||||||
snooze(10000);
|
snooze(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the interface went down IFF_UP was removed
|
|
||||||
// and the receive_data() above should have been
|
|
||||||
// interrupted. One check should be enough, specially
|
|
||||||
// considering the snooze above.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@@ -118,7 +108,7 @@ interface_address(net_interface *interface, int32 option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
remove_default_routes(net_interface_private* interface, int32 option)
|
remove_default_routes(net_interface_private* interface, int32 option)
|
||||||
{
|
{
|
||||||
net_route route;
|
net_route route;
|
||||||
@@ -141,7 +131,7 @@ remove_default_routes(net_interface_private *interface, int32 option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
static void
|
||||||
add_default_routes(net_interface_private* interface, int32 option)
|
add_default_routes(net_interface_private* interface, int32 option)
|
||||||
{
|
{
|
||||||
net_route route;
|
net_route route;
|
||||||
@@ -164,7 +154,7 @@ add_default_routes(net_interface_private *interface, int32 option)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sockaddr *
|
static sockaddr*
|
||||||
reallocate_address(sockaddr** _address, uint32 size)
|
reallocate_address(sockaddr** _address, uint32 size)
|
||||||
{
|
{
|
||||||
sockaddr* address = *_address;
|
sockaddr* address = *_address;
|
||||||
@@ -205,7 +195,7 @@ datalink_control_interface(net_domain_private *domain, int32 option,
|
|||||||
else
|
else
|
||||||
interface = find_interface(domain, request.ifr_index);
|
interface = find_interface(domain, request.ifr_index);
|
||||||
|
|
||||||
status_t status = (interface == NULL) ? ENODEV : B_OK;
|
status_t status = interface == NULL ? ENODEV : B_OK;
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case SIOCGIFINDEX:
|
case SIOCGIFINDEX:
|
||||||
@@ -632,11 +622,12 @@ interface_protocol_down(net_datalink_protocol *_protocol)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
interface_protocol_control(net_datalink_protocol *_protocol,
|
interface_protocol_control(net_datalink_protocol* _protocol, int32 option,
|
||||||
int32 option, void *argument, size_t length)
|
void* argument, size_t length)
|
||||||
{
|
{
|
||||||
interface_protocol* protocol = (interface_protocol*)_protocol;
|
interface_protocol* protocol = (interface_protocol*)_protocol;
|
||||||
net_interface_private *interface = (net_interface_private *)protocol->interface;
|
net_interface_private* interface
|
||||||
|
= (net_interface_private*)protocol->interface;
|
||||||
|
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case SIOCSIFADDR:
|
case SIOCSIFADDR:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2008, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -221,12 +221,11 @@ domain_interface_control(net_domain_private *domain, int32 option,
|
|||||||
net_device_interface* device = get_device_interface(name, false);
|
net_device_interface* device = get_device_interface(name, false);
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
else {
|
|
||||||
// The locking protocol dictates that if both the RX lock
|
// The locking protocol dictates that if both the receive lock
|
||||||
// and domain locks are required, we MUST obtain the RX
|
// and domain locks are required, we MUST obtain the receive
|
||||||
// lock before the domain lock. This order MUST NOT ever
|
// lock before the domain lock.
|
||||||
// be reversed under the penalty of deadlock.
|
RecursiveLocker _1(device->receive_lock);
|
||||||
RecursiveLocker _1(device->rx_lock);
|
|
||||||
MutexLocker _2(domain->lock);
|
MutexLocker _2(domain->lock);
|
||||||
|
|
||||||
net_interface* interface = find_interface(domain, name);
|
net_interface* interface = find_interface(domain, name);
|
||||||
@@ -261,40 +260,30 @@ domain_interface_control(net_domain_private *domain, int32 option,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If the SIOCDIFADDR call above removed the last interface
|
// If the SIOCDIFADDR call above removed the last interface associated with
|
||||||
// associated with the device interface, this put_() will
|
// the device interface, this will effectively remove the interface
|
||||||
// effectively remove the interface
|
|
||||||
put_device_interface(device);
|
put_device_interface(device);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! You need to hold the domain lock when calling this function. */
|
||||||
void
|
void
|
||||||
domain_interface_went_down(net_interface* interface)
|
domain_interface_went_down(net_interface* interface)
|
||||||
{
|
{
|
||||||
// the domain should be locked here. always check
|
ASSERT_LOCKED_MUTEX(&((net_domain_private*)interface->domain)->lock);
|
||||||
// all callers to be sure. We get here via
|
|
||||||
// interface_set_down().
|
|
||||||
|
|
||||||
dprintf("domain_interface_went_down(%i, %s)\n",
|
TRACE(("domain_interface_went_down(%i, %s)\n",
|
||||||
interface->domain->family, interface->name);
|
interface->domain->family, interface->name));
|
||||||
|
|
||||||
// domain might have been locked by:
|
|
||||||
// - domain_removed_device_interface() <--- here
|
|
||||||
// remove_interface_from_domain()
|
|
||||||
// delete_interface()
|
|
||||||
// interface_set_down()
|
|
||||||
// - datalink_control() <--- here
|
|
||||||
// interface_set_down()
|
|
||||||
invalidate_routes(interface->domain, interface);
|
invalidate_routes(interface->domain, interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
domain_removed_device_interface(net_device_interface *interface)
|
domain_removed_device_interface(net_device_interface* deviceInterface)
|
||||||
{
|
{
|
||||||
MutexLocker locker(sDomainLock);
|
MutexLocker locker(sDomainLock);
|
||||||
|
|
||||||
@@ -306,12 +295,12 @@ domain_removed_device_interface(net_device_interface *interface)
|
|||||||
|
|
||||||
MutexLocker locker(domain->lock);
|
MutexLocker locker(domain->lock);
|
||||||
|
|
||||||
net_interface_private *priv = find_interface(domain,
|
net_interface_private* interface = find_interface(domain,
|
||||||
interface->device->name);
|
deviceInterface->device->name);
|
||||||
if (priv == NULL)
|
if (interface == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
remove_interface_from_domain(priv);
|
remove_interface_from_domain(interface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,7 +322,7 @@ register_domain(int family, const char *name,
|
|||||||
if (domain == NULL)
|
if (domain == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
mutex_init_etc(&domain->lock, name, MUTEX_FLAG_CLONE_NAME);
|
mutex_init(&domain->lock, name);
|
||||||
|
|
||||||
domain->family = family;
|
domain->family = family;
|
||||||
domain->name = name;
|
domain->name = name;
|
||||||
@@ -352,7 +341,8 @@ register_domain(int family, const char *name,
|
|||||||
status_t
|
status_t
|
||||||
unregister_domain(net_domain* _domain)
|
unregister_domain(net_domain* _domain)
|
||||||
{
|
{
|
||||||
TRACE(("unregister_domain(%p, %d, %s)\n", _domain, _domain->family, _domain->name));
|
TRACE(("unregister_domain(%p, %d, %s)\n", _domain, _domain->family,
|
||||||
|
_domain->name));
|
||||||
|
|
||||||
net_domain_private* domain = (net_domain_private*)_domain;
|
net_domain_private* domain = (net_domain_private*)_domain;
|
||||||
MutexLocker locker(sDomainLock);
|
MutexLocker locker(sDomainLock);
|
||||||
@@ -361,7 +351,8 @@ unregister_domain(net_domain *_domain)
|
|||||||
|
|
||||||
net_interface_private* interface = NULL;
|
net_interface_private* interface = NULL;
|
||||||
while (true) {
|
while (true) {
|
||||||
interface = (net_interface_private *)list_remove_head_item(&domain->interfaces);
|
interface = (net_interface_private*)list_remove_head_item(
|
||||||
|
&domain->interfaces);
|
||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -56,19 +56,16 @@ device_consumer_thread(void *_interface)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (buffer->interface != NULL) {
|
if (buffer->interface != NULL) {
|
||||||
// if the interface is already specified this buffer was
|
// if the interface is already specified, this buffer was
|
||||||
// delivered locally.
|
// delivered locally.
|
||||||
|
if (buffer->interface->domain->module->receive_data(buffer) == B_OK)
|
||||||
net_domain *domain = buffer->interface->domain;
|
|
||||||
|
|
||||||
if (domain->module->receive_data(buffer) == B_OK)
|
|
||||||
buffer = NULL;
|
buffer = NULL;
|
||||||
} else {
|
} else {
|
||||||
// find handler for this packet
|
// find handler for this packet
|
||||||
DeviceHandlerList::Iterator it2 =
|
DeviceHandlerList::Iterator iterator =
|
||||||
interface->receive_funcs.GetIterator();
|
interface->receive_funcs.GetIterator();
|
||||||
while (buffer && it2.HasNext()) {
|
while (buffer && iterator.HasNext()) {
|
||||||
net_device_handler *handler = it2.Next();
|
net_device_handler* handler = iterator.Next();
|
||||||
|
|
||||||
// if the handler returns B_OK, it consumed the buffer
|
// if the handler returns B_OK, it consumed the buffer
|
||||||
if (handler->type == buffer->type
|
if (handler->type == buffer->type
|
||||||
@@ -77,7 +74,7 @@ device_consumer_thread(void *_interface)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buffer)
|
if (buffer != NULL)
|
||||||
gNetBufferModule.free(buffer);
|
gNetBufferModule.free(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +87,7 @@ find_device_interface(const char *name)
|
|||||||
{
|
{
|
||||||
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
while (net_device_interface* interface = iterator.Next()) {
|
||||||
net_device_interface *interface = iterator.Next();
|
|
||||||
|
|
||||||
if (!strcmp(interface->device->name, name))
|
if (!strcmp(interface->device->name, name))
|
||||||
return interface;
|
return interface;
|
||||||
}
|
}
|
||||||
@@ -101,6 +96,9 @@ find_device_interface(const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! The domain's device receive handler - this will inject the net_buffers into
|
||||||
|
the protocol layer (the domain's registered receive handler).
|
||||||
|
*/
|
||||||
static status_t
|
static status_t
|
||||||
domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer)
|
domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer)
|
||||||
{
|
{
|
||||||
@@ -116,15 +114,15 @@ allocate_device_interface(net_device *device, net_device_module_info *module)
|
|||||||
{
|
{
|
||||||
net_device_interface* interface = new(std::nothrow) net_device_interface;
|
net_device_interface* interface = new(std::nothrow) net_device_interface;
|
||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
goto error_0;
|
return NULL;
|
||||||
|
|
||||||
recursive_lock_init(&interface->rx_lock, "rx lock");
|
recursive_lock_init(&interface->receive_lock, "interface receive lock");
|
||||||
|
|
||||||
char name[128];
|
char name[128];
|
||||||
snprintf(name, sizeof(name), "%s receive queue", device->name);
|
snprintf(name, sizeof(name), "%s receive queue", device->name);
|
||||||
|
|
||||||
if (init_fifo(&interface->receive_queue, name, 16 * 1024 * 1024) < B_OK)
|
if (init_fifo(&interface->receive_queue, name, 16 * 1024 * 1024) < B_OK)
|
||||||
goto error_2;
|
goto error1;
|
||||||
|
|
||||||
interface->device = device;
|
interface->device = device;
|
||||||
interface->up_count = 0;
|
interface->up_count = 0;
|
||||||
@@ -138,7 +136,7 @@ allocate_device_interface(net_device *device, net_device_module_info *module)
|
|||||||
interface->consumer_thread = spawn_kernel_thread(device_consumer_thread,
|
interface->consumer_thread = spawn_kernel_thread(device_consumer_thread,
|
||||||
name, B_DISPLAY_PRIORITY, interface);
|
name, B_DISPLAY_PRIORITY, interface);
|
||||||
if (interface->consumer_thread < B_OK)
|
if (interface->consumer_thread < B_OK)
|
||||||
goto error_3;
|
goto error2;
|
||||||
resume_thread(interface->consumer_thread);
|
resume_thread(interface->consumer_thread);
|
||||||
|
|
||||||
// TODO: proper interface index allocation
|
// TODO: proper interface index allocation
|
||||||
@@ -148,20 +146,18 @@ allocate_device_interface(net_device *device, net_device_module_info *module)
|
|||||||
sInterfaces.Add(interface);
|
sInterfaces.Add(interface);
|
||||||
return interface;
|
return interface;
|
||||||
|
|
||||||
error_3:
|
error2:
|
||||||
uninit_fifo(&interface->receive_queue);
|
uninit_fifo(&interface->receive_queue);
|
||||||
|
error1:
|
||||||
error_2:
|
recursive_lock_destroy(&interface->receive_lock);
|
||||||
recursive_lock_destroy(&interface->rx_lock);
|
|
||||||
delete interface;
|
delete interface;
|
||||||
|
|
||||||
error_0:
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
net_device_interface *
|
static net_device_interface*
|
||||||
grab_device_interface(net_device_interface *interface)
|
acquire_device_interface(net_device_interface* interface)
|
||||||
{
|
{
|
||||||
if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0)
|
if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -173,12 +169,10 @@ grab_device_interface(net_device_interface *interface)
|
|||||||
static void
|
static void
|
||||||
notify_device_monitors(net_device_interface* interface, int32 event)
|
notify_device_monitors(net_device_interface* interface, int32 event)
|
||||||
{
|
{
|
||||||
DeviceMonitorList::Iterator iterator = interface->monitor_funcs.GetIterator();
|
DeviceMonitorList::Iterator iterator
|
||||||
while (iterator.HasNext()) {
|
= interface->monitor_funcs.GetIterator();
|
||||||
// when we call Next() the next item in the list is obtained
|
while (net_device_monitor* monitor = iterator.Next()) {
|
||||||
// so it's safe for the "current" item to remove itself.
|
// it's safe for the "current" item to remove itself.
|
||||||
net_device_monitor *monitor = iterator.Next();
|
|
||||||
|
|
||||||
monitor->event(monitor, event);
|
monitor->event(monitor, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,8 +181,7 @@ notify_device_monitors(net_device_interface *interface, int32 event)
|
|||||||
// #pragma mark - interfaces
|
// #pragma mark - interfaces
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Searches for a specific interface in a domain by name.
|
||||||
Searches for a specific interface in a domain by name.
|
|
||||||
You need to have the domain's lock hold when calling this function.
|
You need to have the domain's lock hold when calling this function.
|
||||||
*/
|
*/
|
||||||
struct net_interface_private*
|
struct net_interface_private*
|
||||||
@@ -210,8 +203,7 @@ find_interface(struct net_domain *domain, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Searches for a specific interface in a domain by index.
|
||||||
Searches for a specific interface in a domain by index.
|
|
||||||
You need to have the domain's lock hold when calling this function.
|
You need to have the domain's lock hold when calling this function.
|
||||||
*/
|
*/
|
||||||
struct net_interface_private*
|
struct net_interface_private*
|
||||||
@@ -237,8 +229,7 @@ status_t
|
|||||||
create_interface(net_domain* domain, const char* name, const char* baseName,
|
create_interface(net_domain* domain, const char* name, const char* baseName,
|
||||||
net_device_interface* deviceInterface, net_interface_private** _interface)
|
net_device_interface* deviceInterface, net_interface_private** _interface)
|
||||||
{
|
{
|
||||||
net_interface_private *interface =
|
net_interface_private* interface = new(std::nothrow) net_interface_private;
|
||||||
new (std::nothrow) net_interface_private;
|
|
||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
@@ -256,7 +247,7 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
|
|||||||
interface->type = 0;
|
interface->type = 0;
|
||||||
interface->mtu = deviceInterface->device->mtu;
|
interface->mtu = deviceInterface->device->mtu;
|
||||||
interface->metric = 0;
|
interface->metric = 0;
|
||||||
interface->device_interface = grab_device_interface(deviceInterface);
|
interface->device_interface = acquire_device_interface(deviceInterface);
|
||||||
|
|
||||||
// setup direct route for bound devices
|
// setup direct route for bound devices
|
||||||
interface->direct_route.destination = NULL;
|
interface->direct_route.destination = NULL;
|
||||||
@@ -402,8 +393,7 @@ count_device_interfaces()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Dumps a list of all interfaces into the supplied userland buffer.
|
||||||
Dumps a list of all interfaces into the supplied userland buffer.
|
|
||||||
If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
|
If the interfaces don't fit into the buffer, an error (\c ENOBUFS) is
|
||||||
returned.
|
returned.
|
||||||
*/
|
*/
|
||||||
@@ -415,15 +405,12 @@ list_device_interfaces(void *_buffer, size_t *bufferSize)
|
|||||||
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
UserBuffer buffer(_buffer, *bufferSize);
|
UserBuffer buffer(_buffer, *bufferSize);
|
||||||
|
|
||||||
while (iterator.HasNext()) {
|
while (net_device_interface* interface = iterator.Next()) {
|
||||||
net_device_interface *interface = iterator.Next();
|
|
||||||
|
|
||||||
ifreq request;
|
ifreq request;
|
||||||
strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE);
|
strlcpy(request.ifr_name, interface->device->name, IF_NAMESIZE);
|
||||||
get_device_interface_address(interface, &request.ifr_addr);
|
get_device_interface_address(interface, &request.ifr_addr);
|
||||||
|
|
||||||
if (buffer.Copy(&request, IF_NAMESIZE
|
if (buffer.Copy(&request, IF_NAMESIZE + request.ifr_addr.sa_len) == NULL)
|
||||||
+ request.ifr_addr.sa_len) == NULL)
|
|
||||||
return buffer.Status();
|
return buffer.Status();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -432,8 +419,7 @@ list_device_interfaces(void *_buffer, size_t *bufferSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Releases the reference for the interface. When all references are
|
||||||
Releases the reference for the interface. When all references are
|
|
||||||
released, the interface is removed.
|
released, the interface is removed.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
@@ -453,26 +439,25 @@ put_device_interface(struct net_device_interface *interface)
|
|||||||
|
|
||||||
net_device* device = interface->device;
|
net_device* device = interface->device;
|
||||||
const char* moduleName = device->module->info.name;
|
const char* moduleName = device->module->info.name;
|
||||||
|
|
||||||
device->module->uninit_device(device);
|
device->module->uninit_device(device);
|
||||||
put_module(moduleName);
|
put_module(moduleName);
|
||||||
|
|
||||||
recursive_lock_destroy(&interface->rx_lock);
|
recursive_lock_destroy(&interface->receive_lock);
|
||||||
delete interface;
|
delete interface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Finds an interface by the specified index and acquires a reference to it.
|
||||||
Finds an interface by the specified index and grabs a reference to it.
|
|
||||||
*/
|
*/
|
||||||
struct net_device_interface*
|
struct net_device_interface*
|
||||||
get_device_interface(uint32 index)
|
get_device_interface(uint32 index)
|
||||||
{
|
{
|
||||||
MutexLocker locker(sInterfaceLock);
|
MutexLocker locker(sInterfaceLock);
|
||||||
|
|
||||||
|
// TODO: maintain an array of all device interfaces instead
|
||||||
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
|
while (net_device_interface* interface = iterator.Next()) {
|
||||||
while (iterator.HasNext()) {
|
|
||||||
net_device_interface *interface = iterator.Next();
|
|
||||||
|
|
||||||
if (interface->device->index == index) {
|
if (interface->device->index == index) {
|
||||||
if (atomic_add(&interface->ref_count, 1) != 0)
|
if (atomic_add(&interface->ref_count, 1) != 0)
|
||||||
return interface;
|
return interface;
|
||||||
@@ -483,8 +468,7 @@ get_device_interface(uint32 index)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Finds an interface by the specified name and grabs a reference to it.
|
||||||
Finds an interface by the specified name and grabs a reference to it.
|
|
||||||
If the interface does not yet exist, a new one is created.
|
If the interface does not yet exist, a new one is created.
|
||||||
*/
|
*/
|
||||||
struct net_device_interface*
|
struct net_device_interface*
|
||||||
@@ -521,8 +505,9 @@ get_device_interface(const char *name, bool create)
|
|||||||
status_t status = module->init_device(name, &device);
|
status_t status = module->init_device(name, &device);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
interface = allocate_device_interface(device, module);
|
interface = allocate_device_interface(device, module);
|
||||||
if (interface)
|
if (interface != NULL)
|
||||||
return interface;
|
return interface;
|
||||||
|
|
||||||
module->uninit_device(device);
|
module->uninit_device(device);
|
||||||
}
|
}
|
||||||
put_module(moduleName);
|
put_module(moduleName);
|
||||||
@@ -536,7 +521,7 @@ get_device_interface(const char *name, bool create)
|
|||||||
void
|
void
|
||||||
down_device_interface(net_device_interface* interface)
|
down_device_interface(net_device_interface* interface)
|
||||||
{
|
{
|
||||||
// RX lock must be held when calling down_device_interface.
|
// Receive lock must be held when calling down_device_interface.
|
||||||
// Known callers are `interface_protocol_down' which gets
|
// Known callers are `interface_protocol_down' which gets
|
||||||
// here via one of the following paths:
|
// here via one of the following paths:
|
||||||
//
|
//
|
||||||
@@ -557,31 +542,25 @@ down_device_interface(net_device_interface *interface)
|
|||||||
notify_device_monitors(interface, B_DEVICE_GOING_DOWN);
|
notify_device_monitors(interface, B_DEVICE_GOING_DOWN);
|
||||||
|
|
||||||
if (device->module->receive_data != NULL) {
|
if (device->module->receive_data != NULL) {
|
||||||
thread_id reader_thread = interface->reader_thread;
|
thread_id readerThread = interface->reader_thread;
|
||||||
|
|
||||||
// TODO when setting the interface down,
|
|
||||||
// should we clear the receive queue?
|
|
||||||
|
|
||||||
// one of the callers must hold a reference to the net_device_interface
|
// one of the callers must hold a reference to the net_device_interface
|
||||||
// usually it is one of the net_interfaces.
|
// usually it is one of the net_interfaces.
|
||||||
recursive_lock_unlock(&interface->rx_lock);
|
recursive_lock_unlock(&interface->receive_lock);
|
||||||
|
|
||||||
// make sure the reader thread is gone before shutting down the interface
|
// make sure the reader thread is gone before shutting down the interface
|
||||||
status_t status;
|
status_t status;
|
||||||
wait_for_thread(reader_thread, &status);
|
wait_for_thread(readerThread, &status);
|
||||||
|
|
||||||
recursive_lock_lock(&interface->rx_lock);
|
recursive_lock_lock(&interface->receive_lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - devices
|
// #pragma mark - devices stack API
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Unregisters a previously registered deframer function. */
|
||||||
Unregisters a previously registered deframer function.
|
|
||||||
This function is part of the net_manager_module_info API.
|
|
||||||
*/
|
|
||||||
status_t
|
status_t
|
||||||
unregister_device_deframer(net_device* device)
|
unregister_device_deframer(net_device* device)
|
||||||
{
|
{
|
||||||
@@ -592,7 +571,7 @@ unregister_device_deframer(net_device *device)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
if (--interface->deframe_ref_count == 0)
|
if (--interface->deframe_ref_count == 0)
|
||||||
interface->deframe_func = NULL;
|
interface->deframe_func = NULL;
|
||||||
@@ -601,15 +580,12 @@ unregister_device_deframer(net_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! Registers the deframer function for the specified \a device.
|
||||||
Registers the deframer function for the specified \a device.
|
|
||||||
Note, however, that right now, you can only register one single
|
Note, however, that right now, you can only register one single
|
||||||
deframer function per device.
|
deframer function per device.
|
||||||
|
|
||||||
If the need arises, we might want to lift that limitation at a
|
If the need arises, we might want to lift that limitation at a
|
||||||
later time (which would require a slight API change, though).
|
later time (which would require a slight API change, though).
|
||||||
|
|
||||||
This function is part of the net_manager_module_info API.
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
register_device_deframer(net_device* device, net_deframe_func deframeFunc)
|
register_device_deframer(net_device* device, net_deframe_func deframeFunc)
|
||||||
@@ -621,9 +597,10 @@ register_device_deframer(net_device *device, net_deframe_func deframeFunc)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc)
|
if (interface->deframe_func != NULL
|
||||||
|
&& interface->deframe_func != deframeFunc)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
interface->deframe_func = deframeFunc;
|
interface->deframe_func = deframeFunc;
|
||||||
@@ -632,6 +609,7 @@ register_device_deframer(net_device *device, net_deframe_func deframeFunc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Registers a domain to receive net_buffers from the specified \a device. */
|
||||||
status_t
|
status_t
|
||||||
register_domain_device_handler(struct net_device* device, int32 type,
|
register_domain_device_handler(struct net_device* device, int32 type,
|
||||||
struct net_domain* _domain)
|
struct net_domain* _domain)
|
||||||
@@ -640,10 +618,12 @@ register_domain_device_handler(struct net_device *device, int32 type,
|
|||||||
if (domain->module == NULL || domain->module->receive_data == NULL)
|
if (domain->module == NULL || domain->module->receive_data == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
return register_device_handler(device, type, &domain_receive_adapter, domain);
|
return register_device_handler(device, type, &domain_receive_adapter,
|
||||||
|
domain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Registers a receiving function callback for the specified \a device. */
|
||||||
status_t
|
status_t
|
||||||
register_device_handler(struct net_device* device, int32 type,
|
register_device_handler(struct net_device* device, int32 type,
|
||||||
net_receive_func receiveFunc, void* cookie)
|
net_receive_func receiveFunc, void* cookie)
|
||||||
@@ -655,14 +635,13 @@ register_device_handler(struct net_device *device, int32 type,
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
// see if such a handler already for this device
|
// see if such a handler already for this device
|
||||||
|
|
||||||
DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
|
DeviceHandlerList::Iterator iterator
|
||||||
while (iterator.HasNext()) {
|
= interface->receive_funcs.GetIterator();
|
||||||
net_device_handler *handler = iterator.Next();
|
while (net_device_handler* handler = iterator.Next()) {
|
||||||
|
|
||||||
if (handler->type == type)
|
if (handler->type == type)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
@@ -681,6 +660,7 @@ register_device_handler(struct net_device *device, int32 type,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Unregisters a previously registered device handler. */
|
||||||
status_t
|
status_t
|
||||||
unregister_device_handler(struct net_device* device, int32 type)
|
unregister_device_handler(struct net_device* device, int32 type)
|
||||||
{
|
{
|
||||||
@@ -691,14 +671,13 @@ unregister_device_handler(struct net_device *device, int32 type)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
// search for the handler
|
// search for the handler
|
||||||
|
|
||||||
DeviceHandlerList::Iterator iterator = interface->receive_funcs.GetIterator();
|
DeviceHandlerList::Iterator iterator
|
||||||
while (iterator.HasNext()) {
|
= interface->receive_funcs.GetIterator();
|
||||||
net_device_handler *handler = iterator.Next();
|
while (net_device_handler* handler = iterator.Next()) {
|
||||||
|
|
||||||
if (handler->type == type) {
|
if (handler->type == type) {
|
||||||
// found it
|
// found it
|
||||||
iterator.Remove();
|
iterator.Remove();
|
||||||
@@ -711,6 +690,7 @@ unregister_device_handler(struct net_device *device, int32 type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Registers a device monitor for the specified device. */
|
||||||
status_t
|
status_t
|
||||||
register_device_monitor(net_device* device, net_device_monitor* monitor)
|
register_device_monitor(net_device* device, net_device_monitor* monitor)
|
||||||
{
|
{
|
||||||
@@ -724,12 +704,13 @@ register_device_monitor(net_device *device, net_device_monitor *monitor)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
interface->monitor_funcs.Add(monitor);
|
interface->monitor_funcs.Add(monitor);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Unregisters a previously registered device monitor. */
|
||||||
status_t
|
status_t
|
||||||
unregister_device_monitor(net_device* device, net_device_monitor* monitor)
|
unregister_device_monitor(net_device* device, net_device_monitor* monitor)
|
||||||
{
|
{
|
||||||
@@ -740,7 +721,7 @@ unregister_device_monitor(net_device *device, net_device_monitor *monitor)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
// search for the monitor
|
// search for the monitor
|
||||||
|
|
||||||
@@ -756,8 +737,7 @@ unregister_device_monitor(net_device *device, net_device_monitor *monitor)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! This function is called by device modules in case their link
|
||||||
This function is called by device modules in case their link
|
|
||||||
state changed, ie. if an ethernet cable was plugged in or
|
state changed, ie. if an ethernet cable was plugged in or
|
||||||
removed.
|
removed.
|
||||||
*/
|
*/
|
||||||
@@ -769,10 +749,8 @@ device_link_changed(net_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*! This function is called by device modules once their device got
|
||||||
This function is called by device modules once their device got
|
|
||||||
physically removed, ie. a USB networking card is unplugged.
|
physically removed, ie. a USB networking card is unplugged.
|
||||||
It is part of the net_manager_module_info API.
|
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
device_removed(net_device* device)
|
device_removed(net_device* device)
|
||||||
@@ -789,7 +767,7 @@ device_removed(net_device *device)
|
|||||||
// This is very complex, refer to delete_interface() for
|
// This is very complex, refer to delete_interface() for
|
||||||
// further details.
|
// further details.
|
||||||
|
|
||||||
RecursiveLocker _(interface->rx_lock);
|
RecursiveLocker _(interface->receive_lock);
|
||||||
|
|
||||||
// this will possibly call:
|
// this will possibly call:
|
||||||
// remove_interface_from_domain() [domain gets locked]
|
// remove_interface_from_domain() [domain gets locked]
|
||||||
@@ -804,7 +782,7 @@ device_removed(net_device *device)
|
|||||||
interface->monitor_funcs.RemoveAll();
|
interface->monitor_funcs.RemoveAll();
|
||||||
|
|
||||||
// All of the readers should be gone as well since we are out of
|
// All of the readers should be gone as well since we are out of
|
||||||
// interfaces and `put_domain_datalink_protocols' is called for
|
// interfaces and put_domain_datalink_protocols() is called for
|
||||||
// each delete_interface().
|
// each delete_interface().
|
||||||
|
|
||||||
put_device_interface(interface);
|
put_device_interface(interface);
|
||||||
@@ -817,7 +795,6 @@ status_t
|
|||||||
device_enqueue_buffer(net_device* device, net_buffer* buffer)
|
device_enqueue_buffer(net_device* device, net_buffer* buffer)
|
||||||
{
|
{
|
||||||
net_device_interface* interface = get_device_interface(device->index);
|
net_device_interface* interface = get_device_interface(device->index);
|
||||||
|
|
||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return ENODEV;
|
return ENODEV;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2007, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -39,7 +39,7 @@ struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
|
|||||||
DeviceMonitorList monitor_funcs;
|
DeviceMonitorList monitor_funcs;
|
||||||
DeviceHandlerList receive_funcs;
|
DeviceHandlerList receive_funcs;
|
||||||
|
|
||||||
recursive_lock rx_lock;
|
recursive_lock receive_lock;
|
||||||
|
|
||||||
thread_id consumer_thread;
|
thread_id consumer_thread;
|
||||||
net_fifo receive_queue;
|
net_fifo receive_queue;
|
||||||
@@ -69,7 +69,7 @@ status_t create_interface(net_domain *domain, const char *name,
|
|||||||
const char* baseName, net_device_interface* deviceInterface,
|
const char* baseName, net_device_interface* deviceInterface,
|
||||||
struct net_interface_private** _interface);
|
struct net_interface_private** _interface);
|
||||||
void delete_interface(net_interface_private* interface);
|
void delete_interface(net_interface_private* interface);
|
||||||
void interface_set_down(net_interface *);
|
void interface_set_down(net_interface* interface);
|
||||||
|
|
||||||
// device interfaces
|
// device interfaces
|
||||||
void get_device_interface_address(net_device_interface* interface,
|
void get_device_interface_address(net_device_interface* interface,
|
||||||
|
|||||||
Reference in New Issue
Block a user