started some work to properly handle device_removed() and setting interfaces down in general.

- remove all routes that use interfaces going down.
 - when a device is going down, remove associated domain interfaces.
 - interfaces weren't getting a properly referenced device interface, fixed.
 - down call down_device_interface when deleting a interface, instead set it down and let the upcounts do its job.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20600 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-04-06 06:23:35 +00:00
parent 0b10ed0573
commit c64fecca78
7 changed files with 135 additions and 11 deletions
@@ -63,6 +63,16 @@ domain_receive_adapter(void *cookie, net_buffer *buffer)
}
net_device_interface *
grab_device_interface(net_device_interface *interface)
{
if (interface == NULL || atomic_add(&interface->ref_count, 1) == 0)
return NULL;
return interface;
}
// #pragma mark - interfaces
@@ -135,7 +145,7 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
interface->type = 0;
interface->mtu = deviceInterface->device->mtu;
interface->metric = 0;
interface->device_interface = deviceInterface;
interface->device_interface = grab_device_interface(deviceInterface);
status_t status = get_domain_datalink_protocols(interface);
if (status < B_OK) {
@@ -153,14 +163,33 @@ create_interface(net_domain *domain, const char *name, const char *baseName,
}
void
interface_set_down(net_interface *interface)
{
if ((interface->flags & IFF_UP) == 0)
return;
// TODO: IFF_LINK should belong in device only
interface->flags &= ~(IFF_UP | IFF_LINK);
interface->first_info->interface_down(interface->first_protocol);
}
void
delete_interface(net_interface_private *interface)
{
if ((interface->flags & IFF_UP) != 0) {
// the interface is still up - we need to change that before deleting it
interface->flags &= ~IFF_UP;
down_device_interface(interface->device_interface);
}
// deleting an interface is fairly complex as we need
// to clear all references to it throughout the stack
// this will possibly call (if IFF_UP):
// interface_protocol_down()
// domain_interface_went_down()
// invalidate_routes()
// remove_route()
// update_route_infos()
// get_route_internal()
// down_device_interface() -- if upcount reaches 0
interface_set_down(interface);
put_device_interface(interface->device_interface);
@@ -388,9 +417,15 @@ down_device_interface(net_device_interface *interface)
{
net_device *device = interface->device;
dprintf("down_device_interface(%s)\n", interface->name);
device->flags &= ~IFF_UP;
interface->module->down(device);
// TODO: there is a race condition between the previous
// ->down and device->module->receive_data which
// locks us here waiting for the reader_thread
// make sure the reader thread is gone before shutting down the interface
status_t status;
wait_for_thread(interface->reader_thread, &status);
@@ -600,7 +635,25 @@ status_t
device_removed(net_device *device)
{
BenaphoreLocker locker(sInterfaceLock);
// TODO: all what this function should do is to clear the IFF_UP flag of the interfaces.
net_device_interface *interface = find_device_interface(device->name);
if (interface == NULL)
return ENODEV;
// Propagate the loss of the device throughout the stack.
// This is very complex, refer to delete_interface() for
// further details.
// this will possibly call:
// remove_interface_from_domain() [domain gets locked]
// delete_interface()
// ... [see delete_interface()]
domain_removed_device_interface(interface);
// TODO: make sure all readers are gone
// make sure all watchers are gone
// remove device interface
return B_OK;
}