* 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:
Axel Dörfler
2009-02-16 11:13:28 +00:00
parent 86a0cf15e4
commit 3c13a5f5b3
4 changed files with 364 additions and 405 deletions
+98 -107
View File
@@ -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:
@@ -31,28 +31,28 @@
struct datalink_protocol : net_protocol { struct datalink_protocol : net_protocol {
struct net_domain_private *domain; struct net_domain_private* domain;
}; };
struct interface_protocol : net_datalink_protocol { struct interface_protocol : net_datalink_protocol {
struct net_device_module_info *device_module; struct net_device_module_info* device_module;
struct net_device *device; struct net_device* device;
}; };
static status_t static status_t
device_reader_thread(void *_interface) device_reader_thread(void* _interface)
{ {
net_device_interface *interface = (net_device_interface *)_interface; net_device_interface* interface = (net_device_interface*)_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;
status = device->module->receive_data(device, &buffer); status = device->module->receive_data(device, &buffer);
locker.Lock(); locker.Lock();
@@ -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,26 +75,17 @@ 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;
} }
static struct sockaddr ** static struct sockaddr**
interface_address(net_interface *interface, int32 option) interface_address(net_interface* interface, int32 option)
{ {
switch (option) { switch (option) {
case SIOCSIFADDR: case SIOCSIFADDR:
@@ -118,8 +108,8 @@ 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;
route.destination = interface->address; route.destination = interface->address;
@@ -141,8 +131,8 @@ 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;
route.destination = interface->address; route.destination = interface->address;
@@ -164,16 +154,16 @@ 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;
size = max_c(size, sizeof(struct sockaddr)); size = max_c(size, sizeof(struct sockaddr));
if (address != NULL && address->sa_len >= size) if (address != NULL && address->sa_len >= size)
return address; return address;
address = (sockaddr *)malloc(size); address = (sockaddr*)malloc(size);
if (address == NULL) if (address == NULL)
return NULL; return NULL;
@@ -185,8 +175,8 @@ reallocate_address(sockaddr **_address, uint32 size)
static status_t static status_t
datalink_control_interface(net_domain_private *domain, int32 option, datalink_control_interface(net_domain_private* domain, int32 option,
void *value, size_t *_length, size_t expected, bool getByName) void* value, size_t* _length, size_t expected, bool getByName)
{ {
if (*_length < expected) if (*_length < expected)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -198,14 +188,14 @@ datalink_control_interface(net_domain_private *domain, int32 option,
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
MutexLocker _(domain->lock); MutexLocker _(domain->lock);
net_interface *interface = NULL; net_interface* interface = NULL;
if (getByName) if (getByName)
interface = find_interface(domain, request.ifr_name); interface = find_interface(domain, request.ifr_name);
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:
@@ -234,10 +224,10 @@ datalink_control_interface(net_domain_private *domain, int32 option,
status_t status_t
datalink_control(net_domain *_domain, int32 option, void *value, datalink_control(net_domain* _domain, int32 option, void* value,
size_t *_length) size_t* _length)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
if (domain == NULL || domain->family == AF_LINK) { if (domain == NULL || domain->family == AF_LINK) {
// the AF_LINK family is already handled completely in the link protocol // the AF_LINK family is already handled completely in the link protocol
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -288,7 +278,7 @@ datalink_control(net_domain *_domain, int32 option, void *value,
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
status_t result = list_domain_interfaces(config.ifc_buf, status_t result = list_domain_interfaces(config.ifc_buf,
(size_t *)&config.ifc_len); (size_t*)&config.ifc_len);
if (result != B_OK) if (result != B_OK)
return result; return result;
@@ -324,7 +314,7 @@ datalink_control(net_domain *_domain, int32 option, void *value,
MutexLocker _(domain->lock); MutexLocker _(domain->lock);
net_interface *interface = find_interface(domain, net_interface* interface = find_interface(domain,
request.ifr_name); request.ifr_name);
if (interface == NULL) if (interface == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -339,10 +329,10 @@ datalink_control(net_domain *_domain, int32 option, void *value,
status_t status_t
datalink_send_data(struct net_route *route, net_buffer *buffer) datalink_send_data(struct net_route* route, net_buffer* buffer)
{ {
net_interface_private *interface = net_interface_private* interface =
(net_interface_private *)route->interface; (net_interface_private*)route->interface;
//dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n", //dprintf("send buffer (%ld bytes) to interface %s (route flags %lx)\n",
// buffer->size, interface->name, route->flags); // buffer->size, interface->name, route->flags);
@@ -373,19 +363,19 @@ datalink_send_data(struct net_route *route, net_buffer *buffer)
status_t status_t
datalink_send_datagram(net_protocol *protocol, net_domain *domain, datalink_send_datagram(net_protocol* protocol, net_domain* domain,
net_buffer *buffer) net_buffer* buffer)
{ {
if (protocol == NULL && domain == NULL) if (protocol == NULL && domain == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
net_protocol_module_info *module = protocol ? protocol->module net_protocol_module_info* module = protocol ? protocol->module
: domain->module; : domain->module;
if (domain == NULL) if (domain == NULL)
domain = protocol->module->get_domain(protocol); domain = protocol->module->get_domain(protocol);
net_route *route = NULL; net_route* route = NULL;
status_t status; status_t status;
if (protocol != NULL && protocol->socket->bound_to_device > 0) { if (protocol != NULL && protocol->socket->bound_to_device > 0) {
status = get_device_route(domain, protocol->socket->bound_to_device, status = get_device_route(domain, protocol->socket->bound_to_device,
@@ -408,21 +398,21 @@ datalink_send_datagram(net_protocol *protocol, net_domain *domain,
\param _matchedType will be set to either zero or MSG_BCAST if non-NULL. \param _matchedType will be set to either zero or MSG_BCAST if non-NULL.
*/ */
bool bool
datalink_is_local_address(net_domain *_domain, const struct sockaddr *address, datalink_is_local_address(net_domain* _domain, const struct sockaddr* address,
net_interface **_interface, uint32 *_matchedType) net_interface** _interface, uint32* _matchedType)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
if (domain == NULL || address == NULL) if (domain == NULL || address == NULL)
return false; return false;
MutexLocker locker(domain->lock); MutexLocker locker(domain->lock);
net_interface *interface = NULL; net_interface* interface = NULL;
net_interface *fallback = NULL; net_interface* fallback = NULL;
uint32 matchedType = 0; uint32 matchedType = 0;
while (true) { while (true) {
interface = (net_interface *)list_get_next_item( interface = (net_interface*)list_get_next_item(
&domain->interfaces, interface); &domain->interfaces, interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -460,20 +450,20 @@ datalink_is_local_address(net_domain *_domain, const struct sockaddr *address,
} }
net_interface * net_interface*
datalink_get_interface_with_address(net_domain *_domain, datalink_get_interface_with_address(net_domain* _domain,
const sockaddr *address) const sockaddr* address)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
if (domain == NULL) if (domain == NULL)
return NULL; return NULL;
MutexLocker _(domain->lock); MutexLocker _(domain->lock);
net_interface *interface = NULL; net_interface* interface = NULL;
while (true) { while (true) {
interface = (net_interface *)list_get_next_item( interface = (net_interface*)list_get_next_item(
&domain->interfaces, interface); &domain->interfaces, interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -490,8 +480,8 @@ datalink_get_interface_with_address(net_domain *_domain,
} }
net_interface * net_interface*
datalink_get_interface(net_domain *domain, uint32 index) datalink_get_interface(net_domain* domain, uint32 index)
{ {
if (index == 0) if (index == 0)
return datalink_get_interface_with_address(domain, NULL); return datalink_get_interface_with_address(domain, NULL);
@@ -518,12 +508,12 @@ datalink_std_ops(int32 op, ...)
status_t status_t
interface_protocol_init(struct net_interface *_interface, interface_protocol_init(struct net_interface* _interface,
net_datalink_protocol **_protocol) net_datalink_protocol** _protocol)
{ {
net_interface_private *interface = (net_interface_private *)_interface; net_interface_private* interface = (net_interface_private*)_interface;
interface_protocol *protocol = new (std::nothrow) interface_protocol; interface_protocol* protocol = new (std::nothrow) interface_protocol;
if (protocol == NULL) if (protocol == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -536,7 +526,7 @@ interface_protocol_init(struct net_interface *_interface,
status_t status_t
interface_protocol_uninit(net_datalink_protocol *protocol) interface_protocol_uninit(net_datalink_protocol* protocol)
{ {
delete protocol; delete protocol;
return B_OK; return B_OK;
@@ -544,12 +534,12 @@ interface_protocol_uninit(net_datalink_protocol *protocol)
status_t status_t
interface_protocol_send_data(net_datalink_protocol *_protocol, interface_protocol_send_data(net_datalink_protocol* _protocol,
net_buffer *buffer) net_buffer* buffer)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol* protocol = (interface_protocol*)_protocol;
net_interface_private *interface net_interface_private* interface
= (net_interface_private *)protocol->interface; = (net_interface_private*)protocol->interface;
// TODO: Need to think about this locking. We can't obtain the // TODO: Need to think about this locking. We can't obtain the
// RX Lock here (nor would it make sense) as the ARP // RX Lock here (nor would it make sense) as the ARP
@@ -560,7 +550,7 @@ interface_protocol_send_data(net_datalink_protocol *_protocol,
DeviceMonitorList::Iterator iterator = DeviceMonitorList::Iterator iterator =
interface->device_interface->monitor_funcs.GetIterator(); interface->device_interface->monitor_funcs.GetIterator();
while (iterator.HasNext()) { while (iterator.HasNext()) {
net_device_monitor *monitor = iterator.Next(); net_device_monitor* monitor = iterator.Next();
monitor->receive(monitor, buffer); monitor->receive(monitor, buffer);
} }
@@ -569,12 +559,12 @@ interface_protocol_send_data(net_datalink_protocol *_protocol,
status_t status_t
interface_protocol_up(net_datalink_protocol *_protocol) interface_protocol_up(net_datalink_protocol* _protocol)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol* protocol = (interface_protocol*)_protocol;
net_device_interface *deviceInterface = net_device_interface* deviceInterface =
((net_interface_private *)protocol->interface)->device_interface; ((net_interface_private*)protocol->interface)->device_interface;
net_device *device = protocol->device; net_device* device = protocol->device;
// This function is called with the RX lock held. // This function is called with the RX lock held.
@@ -610,11 +600,11 @@ interface_protocol_up(net_datalink_protocol *_protocol)
void void
interface_protocol_down(net_datalink_protocol *_protocol) interface_protocol_down(net_datalink_protocol* _protocol)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol* protocol = (interface_protocol*)_protocol;
net_device_interface *deviceInterface = net_device_interface* deviceInterface =
((net_interface_private *)protocol->interface)->device_interface; ((net_interface_private*)protocol->interface)->device_interface;
// This function is called with the RX lock held. // This function is called with the RX lock held.
if (deviceInterface->up_count == 0) if (deviceInterface->up_count == 0)
@@ -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:
@@ -649,12 +640,12 @@ interface_protocol_control(net_datalink_protocol *_protocol,
if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK) if (user_memcpy(&request, argument, sizeof(struct ifreq)) < B_OK)
return B_BAD_ADDRESS; return B_BAD_ADDRESS;
sockaddr **_address = interface_address(interface, option); sockaddr** _address = interface_address(interface, option);
if (_address == NULL) if (_address == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
// allocate new address if needed // allocate new address if needed
sockaddr *address = reallocate_address(_address, sockaddr* address = reallocate_address(_address,
request.ifr_addr.sa_len); request.ifr_addr.sa_len);
// copy new address over // copy new address over
@@ -664,15 +655,15 @@ interface_protocol_control(net_datalink_protocol *_protocol,
if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) { if (option == SIOCSIFADDR || option == SIOCSIFNETMASK) {
// reset netmask and broadcast addresses to defaults // reset netmask and broadcast addresses to defaults
sockaddr *netmask = NULL; sockaddr* netmask = NULL;
sockaddr *oldNetmask = NULL; sockaddr* oldNetmask = NULL;
if (option == SIOCSIFADDR) { if (option == SIOCSIFADDR) {
netmask = reallocate_address(&interface->mask, netmask = reallocate_address(&interface->mask,
request.ifr_addr.sa_len); request.ifr_addr.sa_len);
} else } else
oldNetmask = address; oldNetmask = address;
sockaddr *broadcast = reallocate_address( sockaddr* broadcast = reallocate_address(
&interface->destination, request.ifr_addr.sa_len); &interface->destination, request.ifr_addr.sa_len);
interface->domain->address_module->set_to_defaults( interface->domain->address_module->set_to_defaults(
@@ -691,13 +682,13 @@ interface_protocol_control(net_datalink_protocol *_protocol,
case SIOCGIFDSTADDR: case SIOCGIFDSTADDR:
{ {
// get logical interface address // get logical interface address
sockaddr **_address = interface_address(interface, option); sockaddr** _address = interface_address(interface, option);
if (_address == NULL) if (_address == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
struct ifreq request; struct ifreq request;
sockaddr *address = *_address; sockaddr* address = *_address;
if (address != NULL) if (address != NULL)
memcpy(&request.ifr_addr, address, address->sa_len); memcpy(&request.ifr_addr, address, address->sa_len);
else { else {
@@ -706,7 +697,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
} }
// copy address over // copy address over
return user_memcpy(&((struct ifreq *)argument)->ifr_addr, return user_memcpy(&((struct ifreq*)argument)->ifr_addr,
&request.ifr_addr, request.ifr_addr.sa_len); &request.ifr_addr, request.ifr_addr.sa_len);
} }
@@ -716,7 +707,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
struct ifreq request; struct ifreq request;
request.ifr_flags = interface->flags | interface->device->flags; request.ifr_flags = interface->flags | interface->device->flags;
return user_memcpy(&((struct ifreq *)argument)->ifr_flags, return user_memcpy(&((struct ifreq*)argument)->ifr_flags,
&request.ifr_flags, sizeof(request.ifr_flags)); &request.ifr_flags, sizeof(request.ifr_flags));
} }
@@ -730,14 +721,14 @@ interface_protocol_control(net_datalink_protocol *_protocol,
request.ifr_parameter.sub_type = 0; request.ifr_parameter.sub_type = 0;
// TODO: for now, we ignore the sub type... // TODO: for now, we ignore the sub type...
return user_memcpy(&((struct ifreq *)argument)->ifr_parameter, return user_memcpy(&((struct ifreq*)argument)->ifr_parameter,
&request.ifr_parameter, sizeof(request.ifr_parameter)); &request.ifr_parameter, sizeof(request.ifr_parameter));
} }
case SIOCGIFSTATS: case SIOCGIFSTATS:
{ {
// get stats // get stats
return user_memcpy(&((struct ifreq *)argument)->ifr_stats, return user_memcpy(&((struct ifreq*)argument)->ifr_stats,
&interface->device_interface->device->stats, &interface->device_interface->device->stats,
sizeof(struct ifreq_stats)); sizeof(struct ifreq_stats));
} }
@@ -748,7 +739,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
struct ifreq request; struct ifreq request;
request.ifr_type = interface->type; request.ifr_type = interface->type;
return user_memcpy(&((struct ifreq *)argument)->ifr_type, return user_memcpy(&((struct ifreq*)argument)->ifr_type,
&request.ifr_type, sizeof(request.ifr_type)); &request.ifr_type, sizeof(request.ifr_type));
} }
@@ -758,7 +749,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
struct ifreq request; struct ifreq request;
request.ifr_mtu = interface->mtu; request.ifr_mtu = interface->mtu;
return user_memcpy(&((struct ifreq *)argument)->ifr_mtu, return user_memcpy(&((struct ifreq*)argument)->ifr_mtu,
&request.ifr_mtu, sizeof(request.ifr_mtu)); &request.ifr_mtu, sizeof(request.ifr_mtu));
} }
case SIOCSIFMTU: case SIOCSIFMTU:
@@ -793,7 +784,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
struct ifreq request; struct ifreq request;
request.ifr_media = interface->device->media; request.ifr_media = interface->device->media;
return user_memcpy(&((struct ifreq *)argument)->ifr_media, return user_memcpy(&((struct ifreq*)argument)->ifr_media,
&request.ifr_media, sizeof(request.ifr_media)); &request.ifr_media, sizeof(request.ifr_media));
} }
@@ -803,7 +794,7 @@ interface_protocol_control(net_datalink_protocol *_protocol,
struct ifreq request; struct ifreq request;
request.ifr_metric = interface->metric; request.ifr_metric = interface->metric;
return user_memcpy(&((struct ifreq *)argument)->ifr_metric, return user_memcpy(&((struct ifreq*)argument)->ifr_metric,
&request.ifr_metric, sizeof(request.ifr_metric)); &request.ifr_metric, sizeof(request.ifr_metric));
} }
case SIOCSIFMETRIC: case SIOCSIFMETRIC:
@@ -829,20 +820,20 @@ interface_protocol_control(net_datalink_protocol *_protocol,
static status_t static status_t
interface_protocol_join_multicast(net_datalink_protocol *_protocol, interface_protocol_join_multicast(net_datalink_protocol* _protocol,
const sockaddr *address) const sockaddr* address)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol* protocol = (interface_protocol*)_protocol;
return protocol->device_module->add_multicast(protocol->device, address); return protocol->device_module->add_multicast(protocol->device, address);
} }
static status_t static status_t
interface_protocol_leave_multicast(net_datalink_protocol *_protocol, interface_protocol_leave_multicast(net_datalink_protocol* _protocol,
const sockaddr *address) const sockaddr* address)
{ {
interface_protocol *protocol = (interface_protocol *)_protocol; interface_protocol* protocol = (interface_protocol*)_protocol;
return protocol->device_module->remove_multicast(protocol->device, return protocol->device_module->remove_multicast(protocol->device,
address); address);
+86 -95
View File
@@ -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:
@@ -40,12 +40,12 @@ static list sDomains;
Scans the domain list for the specified family. Scans the domain list for the specified family.
You need to hold the sDomainLock when calling this function. You need to hold the sDomainLock when calling this function.
*/ */
static net_domain_private * static net_domain_private*
lookup_domain(int family) lookup_domain(int family)
{ {
net_domain_private *domain = NULL; net_domain_private* domain = NULL;
while (true) { while (true) {
domain = (net_domain_private *)list_get_next_item(&sDomains, domain); domain = (net_domain_private*)list_get_next_item(&sDomains, domain);
if (domain == NULL) if (domain == NULL)
break; break;
@@ -63,7 +63,7 @@ lookup_domain(int family)
/*! /*!
Gets the domain of the specified family. Gets the domain of the specified family.
*/ */
net_domain * net_domain*
get_domain(int family) get_domain(int family)
{ {
MutexLocker locker(sDomainLock); MutexLocker locker(sDomainLock);
@@ -76,17 +76,17 @@ count_domain_interfaces()
{ {
MutexLocker locker(sDomainLock); MutexLocker locker(sDomainLock);
net_domain_private *domain = NULL; net_domain_private* domain = NULL;
uint32 count = 0; uint32 count = 0;
while (true) { while (true) {
domain = (net_domain_private *)list_get_next_item(&sDomains, domain); domain = (net_domain_private*)list_get_next_item(&sDomains, domain);
if (domain == NULL) if (domain == NULL)
break; break;
net_interface *interface = NULL; net_interface* interface = NULL;
while (true) { while (true) {
interface = (net_interface *)list_get_next_item(&domain->interfaces, interface = (net_interface*)list_get_next_item(&domain->interfaces,
interface); interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -105,23 +105,23 @@ count_domain_interfaces()
returned. returned.
*/ */
status_t status_t
list_domain_interfaces(void *_buffer, size_t *bufferSize) list_domain_interfaces(void* _buffer, size_t* bufferSize)
{ {
MutexLocker locker(sDomainLock); MutexLocker locker(sDomainLock);
UserBuffer buffer(_buffer, *bufferSize); UserBuffer buffer(_buffer, *bufferSize);
net_domain_private *domain = NULL; net_domain_private* domain = NULL;
while (true) { while (true) {
domain = (net_domain_private *)list_get_next_item(&sDomains, domain); domain = (net_domain_private*)list_get_next_item(&sDomains, domain);
if (domain == NULL) if (domain == NULL)
break; break;
MutexLocker locker(domain->lock); MutexLocker locker(domain->lock);
net_interface *interface = NULL; net_interface* interface = NULL;
while (true) { while (true) {
interface = (net_interface *)list_get_next_item(&domain->interfaces, interface = (net_interface*)list_get_next_item(&domain->interfaces,
interface); interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -149,23 +149,23 @@ list_domain_interfaces(void *_buffer, size_t *bufferSize)
status_t status_t
add_interface_to_domain(net_domain *_domain, add_interface_to_domain(net_domain* _domain,
struct ifreq& request) struct ifreq& request)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
const char *deviceName = request.ifr_parameter.device[0] const char* deviceName = request.ifr_parameter.device[0]
? request.ifr_parameter.device : request.ifr_name; ? request.ifr_parameter.device : request.ifr_name;
const char *baseName = request.ifr_parameter.base_name[0] const char* baseName = request.ifr_parameter.base_name[0]
? request.ifr_parameter.base_name : request.ifr_name; ? request.ifr_parameter.base_name : request.ifr_name;
net_device_interface *deviceInterface = get_device_interface(deviceName); net_device_interface* deviceInterface = get_device_interface(deviceName);
if (deviceInterface == NULL) if (deviceInterface == NULL)
return ENODEV; return ENODEV;
MutexLocker locker(domain->lock); MutexLocker locker(domain->lock);
net_interface_private *interface = NULL; net_interface_private* interface = NULL;
status_t status; status_t status;
if (find_interface(domain, request.ifr_name) == NULL) { if (find_interface(domain, request.ifr_name) == NULL) {
@@ -200,140 +200,129 @@ add_interface_to_domain(net_domain *_domain,
You need to hold the domain's lock when calling this function. You need to hold the domain's lock when calling this function.
*/ */
status_t status_t
remove_interface_from_domain(net_interface *interface) remove_interface_from_domain(net_interface* interface)
{ {
net_domain_private *domain = (net_domain_private *)interface->domain; net_domain_private* domain = (net_domain_private*)interface->domain;
list_remove_item(&domain->interfaces, interface); list_remove_item(&domain->interfaces, interface);
notify_interface_removed(interface); notify_interface_removed(interface);
delete_interface((net_interface_private *)interface); delete_interface((net_interface_private*)interface);
return B_OK; return B_OK;
} }
status_t status_t
domain_interface_control(net_domain_private *domain, int32 option, domain_interface_control(net_domain_private* domain, int32 option,
ifreq *request) ifreq* request)
{ {
const char *name = request->ifr_name; const char* name = request->ifr_name;
status_t status = B_OK; status_t status = B_OK;
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
// and domain locks are required, we MUST obtain the RX
// lock before the domain lock. This order MUST NOT ever
// be reversed under the penalty of deadlock.
RecursiveLocker _1(device->rx_lock);
MutexLocker _2(domain->lock);
net_interface *interface = find_interface(domain, name); // The locking protocol dictates that if both the receive lock
if (interface != NULL) { // and domain locks are required, we MUST obtain the receive
switch (option) { // lock before the domain lock.
case SIOCDIFADDR: RecursiveLocker _1(device->receive_lock);
remove_interface_from_domain(interface); MutexLocker _2(domain->lock);
break;
case SIOCSIFFLAGS: net_interface* interface = find_interface(domain, name);
{ if (interface != NULL) {
uint32 requestFlags = request->ifr_flags; switch (option) {
request->ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST); case SIOCDIFADDR:
remove_interface_from_domain(interface);
break;
if ((requestFlags & IFF_UP) != (interface->flags & IFF_UP)) { case SIOCSIFFLAGS:
if (requestFlags & IFF_UP) { {
status = interface->first_info->interface_up( uint32 requestFlags = request->ifr_flags;
interface->first_protocol); request->ifr_flags &= ~(IFF_UP | IFF_LINK | IFF_BROADCAST);
if (status == B_OK)
interface->flags |= IFF_UP; if ((requestFlags & IFF_UP) != (interface->flags & IFF_UP)) {
} else { if (requestFlags & IFF_UP) {
interface_set_down(interface); status = interface->first_info->interface_up(
} interface->first_protocol);
if (status == B_OK)
interface->flags |= IFF_UP;
} else {
interface_set_down(interface);
} }
if (status == B_OK) {
// TODO: why shouldn't we able to delete IFF_BROADCAST?
interface->flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
interface->flags |= request->ifr_flags;
}
break;
} }
if (status == B_OK) {
// TODO: why shouldn't we able to delete IFF_BROADCAST?
interface->flags &= IFF_UP | IFF_LINK | IFF_BROADCAST;
interface->flags |= request->ifr_flags;
}
break;
} }
} }
} }
// 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);
net_domain_private *domain = NULL; net_domain_private* domain = NULL;
while (true) { while (true) {
domain = (net_domain_private *)list_get_next_item(&sDomains, domain); domain = (net_domain_private*)list_get_next_item(&sDomains, domain);
if (domain == NULL) if (domain == NULL)
break; break;
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);
} }
} }
status_t status_t
register_domain(int family, const char *name, register_domain(int family, const char* name,
struct net_protocol_module_info *module, struct net_protocol_module_info* module,
struct net_address_module_info *addressModule, struct net_address_module_info* addressModule,
net_domain **_domain) net_domain** _domain)
{ {
TRACE(("register_domain(%d, %s)\n", family, name)); TRACE(("register_domain(%d, %s)\n", family, name));
MutexLocker locker(sDomainLock); MutexLocker locker(sDomainLock);
struct net_domain_private *domain = lookup_domain(family); struct net_domain_private* domain = lookup_domain(family);
if (domain != NULL) if (domain != NULL)
return B_NAME_IN_USE; return B_NAME_IN_USE;
domain = new (std::nothrow) net_domain_private; domain = new(std::nothrow) net_domain_private;
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;
@@ -350,18 +339,20 @@ 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);
list_remove_item(&sDomains, domain); list_remove_item(&sDomains, 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;
+143 -166
View File
@@ -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:
@@ -41,11 +41,11 @@ static uint32 sDeviceIndex;
static status_t static status_t
device_consumer_thread(void *_interface) device_consumer_thread(void* _interface)
{ {
net_device_interface *interface = (net_device_interface *)_interface; net_device_interface* interface = (net_device_interface*)_interface;
net_device *device = interface->device; net_device* device = interface->device;
net_buffer *buffer; net_buffer* buffer;
while (true) { while (true) {
ssize_t status = fifo_dequeue_buffer(&interface->receive_queue, 0, ssize_t status = fifo_dequeue_buffer(&interface->receive_queue, 0,
@@ -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);
} }
@@ -85,14 +82,12 @@ device_consumer_thread(void *_interface)
} }
static net_device_interface * static net_device_interface*
find_device_interface(const char *name) 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,30 +96,33 @@ 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)
{ {
net_domain_private *domain = (net_domain_private *)cookie; net_domain_private* domain = (net_domain_private*)cookie;
buffer->interface = find_interface(domain, device->index); buffer->interface = find_interface(domain, device->index);
return domain->module->receive_data(buffer); return domain->module->receive_data(buffer);
} }
static net_device_interface * static net_device_interface*
allocate_device_interface(net_device *device, net_device_module_info *module) 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;
@@ -171,14 +167,12 @@ 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,17 +181,16 @@ 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*
find_interface(struct net_domain *domain, const char *name) find_interface(struct net_domain* domain, const char* name)
{ {
net_interface_private *interface = NULL; net_interface_private* interface = NULL;
while (true) { while (true) {
interface = (net_interface_private *)list_get_next_item( interface = (net_interface_private*)list_get_next_item(
&domain->interfaces, interface); &domain->interfaces, interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -210,17 +203,16 @@ 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*
find_interface(struct net_domain *domain, uint32 index) find_interface(struct net_domain* domain, uint32 index)
{ {
net_interface_private *interface = NULL; net_interface_private* interface = NULL;
while (true) { while (true) {
interface = (net_interface_private *)list_get_next_item( interface = (net_interface_private*)list_get_next_item(
&domain->interfaces, interface); &domain->interfaces, interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -234,11 +226,10 @@ find_interface(struct net_domain *domain, uint32 index)
status_t 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;
@@ -276,7 +267,7 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
// Grab a reference to the networking stack, to make sure it won't be // Grab a reference to the networking stack, to make sure it won't be
// unloaded as long as an interface exists // unloaded as long as an interface exists
module_info *module; module_info* module;
get_module(gNetStackInterfaceModule.info.name, &module); get_module(gNetStackInterfaceModule.info.name, &module);
*_interface = interface; *_interface = interface;
@@ -285,7 +276,7 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
void void
interface_set_down(net_interface *interface) interface_set_down(net_interface* interface)
{ {
if ((interface->flags & IFF_UP) == 0) if ((interface->flags & IFF_UP) == 0)
return; return;
@@ -296,7 +287,7 @@ interface_set_down(net_interface *interface)
void void
delete_interface(net_interface_private *interface) delete_interface(net_interface_private* interface)
{ {
// deleting an interface is fairly complex as we need // deleting an interface is fairly complex as we need
// to clear all references to it throughout the stack // to clear all references to it throughout the stack
@@ -332,23 +323,23 @@ delete_interface(net_interface_private *interface)
void void
put_interface(struct net_interface_private *interface) put_interface(struct net_interface_private* interface)
{ {
// TODO: reference counting // TODO: reference counting
// TODO: better locking scheme // TODO: better locking scheme
mutex_unlock(&((net_domain_private *)interface->domain)->lock); mutex_unlock(&((net_domain_private*)interface->domain)->lock);
} }
struct net_interface_private * struct net_interface_private*
get_interface(net_domain *_domain, const char *name) get_interface(net_domain* _domain, const char* name)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
mutex_lock(&domain->lock); mutex_lock(&domain->lock);
net_interface_private *interface = NULL; net_interface_private* interface = NULL;
while (true) { while (true) {
interface = (net_interface_private *)list_get_next_item( interface = (net_interface_private*)list_get_next_item(
&domain->interfaces, interface); &domain->interfaces, interface);
if (interface == NULL) if (interface == NULL)
break; break;
@@ -366,9 +357,9 @@ get_interface(net_domain *_domain, const char *name)
void void
get_device_interface_address(net_device_interface *interface, sockaddr *_address) get_device_interface_address(net_device_interface* interface, sockaddr* _address)
{ {
sockaddr_dl &address = *(sockaddr_dl *)_address; sockaddr_dl &address = *(sockaddr_dl*)_address;
address.sdl_family = AF_LINK; address.sdl_family = AF_LINK;
address.sdl_index = interface->device->index; address.sdl_index = interface->device->index;
@@ -402,28 +393,24 @@ 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.
*/ */
status_t status_t
list_device_interfaces(void *_buffer, size_t *bufferSize) list_device_interfaces(void* _buffer, size_t* bufferSize)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
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,12 +419,11 @@ 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
put_device_interface(struct net_device_interface *interface) put_device_interface(struct net_device_interface* interface)
{ {
if (atomic_add(&interface->ref_count, -1) != 1) if (atomic_add(&interface->ref_count, -1) != 1)
return; return;
@@ -451,28 +437,27 @@ put_device_interface(struct net_device_interface *interface)
status_t status; status_t status;
wait_for_thread(interface->consumer_thread, &status); wait_for_thread(interface->consumer_thread, &status);
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,16 +468,15 @@ 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*
get_device_interface(const char *name, bool create) get_device_interface(const char* name, bool create)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
net_device_interface *interface = find_device_interface(name); net_device_interface* interface = find_device_interface(name);
if (interface != NULL) { if (interface != NULL) {
if (atomic_add(&interface->ref_count, 1) != 0) if (atomic_add(&interface->ref_count, 1) != 0)
return interface; return interface;
@@ -503,7 +487,7 @@ get_device_interface(const char *name, bool create)
if (!create) if (!create)
return NULL; return NULL;
void *cookie = open_module_list("network/devices"); void* cookie = open_module_list("network/devices");
if (cookie == NULL) if (cookie == NULL)
return NULL; return NULL;
@@ -515,14 +499,15 @@ get_device_interface(const char *name, bool create)
TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name)); TRACE(("get_device_interface: ask \"%s\" for %s\n", moduleName, name));
net_device_module_info *module; net_device_module_info* module;
if (get_module(moduleName, (module_info **)&module) == B_OK) { if (get_module(moduleName, (module_info**)&module) == B_OK) {
net_device *device; net_device* device;
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);
@@ -534,9 +519,9 @@ 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:
// //
@@ -549,7 +534,7 @@ down_device_interface(net_device_interface *interface)
// delete_interface() // delete_interface()
// interface_set_down() // interface_set_down()
net_device *device = interface->device; net_device* device = interface->device;
device->flags &= ~IFF_UP; device->flags &= ~IFF_UP;
device->module->down(device); device->module->down(device);
@@ -557,42 +542,36 @@ 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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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,29 +580,27 @@ 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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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,44 +609,46 @@ 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)
{ {
net_domain_private *domain = (net_domain_private *)_domain; net_domain_private* domain = (net_domain_private*)_domain;
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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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;
} }
// Add new handler // Add new handler
net_device_handler *handler = new (std::nothrow) net_device_handler; net_device_handler* handler = new(std::nothrow) net_device_handler;
if (handler == NULL) if (handler == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
@@ -681,24 +660,24 @@ 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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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,8 +690,9 @@ 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)
{ {
if (monitor->receive == NULL || monitor->event == NULL) if (monitor->receive == NULL || monitor->event == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -720,27 +700,28 @@ register_device_monitor(net_device *device, net_device_monitor *monitor)
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// find device interface for this device // find device interface for this device
net_device_interface *interface = find_device_interface(device->name); net_device_interface* interface = find_device_interface(device->name);
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,32 +737,29 @@ 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.
*/ */
status_t status_t
device_link_changed(net_device *device) device_link_changed(net_device* device)
{ {
notify_link_changed(device); notify_link_changed(device);
return B_OK; return B_OK;
} }
/*! /*! 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)
{ {
MutexLocker locker(sInterfaceLock); MutexLocker locker(sInterfaceLock);
// hold a reference to the device interface being removed // hold a reference to the device interface being removed
// so our put_() will (eventually) do the final cleanup // so our put_() will (eventually) do the final cleanup
net_device_interface *interface = get_device_interface(device->name, false); net_device_interface* interface = get_device_interface(device->name, false);
if (interface == NULL) if (interface == NULL)
return ENODEV; return ENODEV;
@@ -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);
@@ -814,10 +792,9 @@ device_removed(net_device *device)
status_t 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;
+37 -37
View File
@@ -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:
@@ -18,7 +18,7 @@
struct net_device_handler : public DoublyLinkedListLinkImpl<net_device_handler> { struct net_device_handler : public DoublyLinkedListLinkImpl<net_device_handler> {
net_receive_func func; net_receive_func func;
int32 type; int32 type;
void *cookie; void* cookie;
}; };
typedef DoublyLinkedList<net_device_handler> DeviceHandlerList; typedef DoublyLinkedList<net_device_handler> DeviceHandlerList;
@@ -27,7 +27,7 @@ typedef DoublyLinkedList<net_device_monitor,
DoublyLinkedListCLink<net_device_monitor> > DeviceMonitorList; DoublyLinkedListCLink<net_device_monitor> > DeviceMonitorList;
struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> { struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
struct net_device *device; struct net_device* device;
thread_id reader_thread; thread_id reader_thread;
uint32 up_count; uint32 up_count;
// a device can be brought up by more than one interface // a device can be brought up by more than one interface
@@ -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;
@@ -49,7 +49,7 @@ typedef DoublyLinkedList<net_device_interface> DeviceInterfaceList;
struct net_interface_private : net_interface { struct net_interface_private : net_interface {
char base_name[IF_NAMESIZE]; char base_name[IF_NAMESIZE];
net_device_interface *device_interface; net_device_interface* device_interface;
net_route_private direct_route; net_route_private direct_route;
}; };
@@ -58,44 +58,44 @@ status_t init_interfaces();
status_t uninit_interfaces(); status_t uninit_interfaces();
// interfaces // interfaces
struct net_interface_private *find_interface(struct net_domain *domain, struct net_interface_private* find_interface(struct net_domain* domain,
const char *name); const char* name);
struct net_interface_private *find_interface(struct net_domain *domain, struct net_interface_private* find_interface(struct net_domain* domain,
uint32 index); uint32 index);
void put_interface(struct net_interface_private *interface); void put_interface(struct net_interface_private* interface);
struct net_interface_private *get_interface(net_domain *domain, struct net_interface_private* get_interface(net_domain* domain,
const char *name); const char* name);
status_t create_interface(net_domain *domain, const char *name, 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,
sockaddr *address); sockaddr* address);
uint32 count_device_interfaces(); uint32 count_device_interfaces();
status_t list_device_interfaces(void *buffer, size_t *_bufferSize); status_t list_device_interfaces(void* buffer, size_t* _bufferSize);
void put_device_interface(struct net_device_interface *interface); void put_device_interface(struct net_device_interface* interface);
struct net_device_interface *get_device_interface(uint32 index); struct net_device_interface* get_device_interface(uint32 index);
struct net_device_interface *get_device_interface(const char *name, struct net_device_interface* get_device_interface(const char* name,
bool create = true); bool create = true);
void down_device_interface(net_device_interface *interface); void down_device_interface(net_device_interface* interface);
// devices // devices
status_t unregister_device_deframer(net_device *device); status_t unregister_device_deframer(net_device* device);
status_t register_device_deframer(net_device *device, net_deframe_func deframeFunc); status_t register_device_deframer(net_device* device, net_deframe_func deframeFunc);
status_t register_domain_device_handler(struct net_device *device, int32 type, status_t register_domain_device_handler(struct net_device* device, int32 type,
struct net_domain *domain); struct net_domain* domain);
status_t register_device_handler(struct net_device *device, int32 type, status_t register_device_handler(struct net_device* device, int32 type,
net_receive_func receiveFunc, void *cookie); net_receive_func receiveFunc, void* cookie);
status_t unregister_device_handler(struct net_device *device, int32 type); status_t unregister_device_handler(struct net_device* device, int32 type);
status_t register_device_monitor(struct net_device *device, status_t register_device_monitor(struct net_device* device,
struct net_device_monitor *monitor); struct net_device_monitor* monitor);
status_t unregister_device_monitor(struct net_device *device, status_t unregister_device_monitor(struct net_device* device,
struct net_device_monitor *monitor); struct net_device_monitor* monitor);
status_t device_link_changed(net_device *device); status_t device_link_changed(net_device* device);
status_t device_removed(net_device *device); status_t device_removed(net_device* device);
status_t device_enqueue_buffer(net_device *device, net_buffer *buffer); status_t device_enqueue_buffer(net_device* device, net_buffer* buffer);
#endif // INTERFACES_H #endif // INTERFACES_H