network: Update device statistics (mostly) in the stack.
We bypass device logic in datalink_send_routed_data() in the case of RTF_LOCAL, so if we don't update the stats there, they'll never get updated. Furthermore, there's places packets can be dropped inside the device reader thread. So, we might as well consolidate the stats-updating logic and get it out of drivers. (The only remaining case where drivers need to update stats is when they drop a packet in receive(), as the stack can't tell when an error from receive() is due to a dropped packet or not.) Fixes a potential leak on packet drops in the device reader thread, and fixes loopback statistics for TCP/UDP/etc.
This commit is contained in:
@@ -448,14 +448,10 @@ dialup_send_data(net_device* _device, net_buffer* buffer)
|
||||
}
|
||||
device->last_closing_flag_sequence_time = system_time();
|
||||
|
||||
device->stats.send.packets++;
|
||||
device->stats.send.bytes += bytesWritten;
|
||||
status = B_OK;
|
||||
goto done;
|
||||
|
||||
err:
|
||||
device->stats.send.errors++;
|
||||
|
||||
done:
|
||||
free(ioVectors);
|
||||
free(packet);
|
||||
@@ -502,20 +498,16 @@ dialup_receive_data(net_device* _device, net_buffer** _buffer)
|
||||
|
||||
status = gBufferModule->trim(buffer, bytesRead);
|
||||
if (status < B_OK) {
|
||||
device->stats.receive.dropped++;
|
||||
atomic_add((int32*)&device->stats.receive.dropped, 1);
|
||||
goto err;
|
||||
}
|
||||
|
||||
device->stats.receive.bytes += bytesRead;
|
||||
device->stats.receive.packets++;
|
||||
|
||||
*_buffer = buffer;
|
||||
status = B_OK;
|
||||
goto done;
|
||||
|
||||
err:
|
||||
gBufferModule->free(buffer);
|
||||
device->stats.receive.errors++;
|
||||
|
||||
done:
|
||||
free(packet);
|
||||
|
||||
@@ -313,8 +313,7 @@ ethernet_send_data(net_device *_device, net_buffer *buffer)
|
||||
if (gBufferModule->count_iovecs(allocated) > 1) {
|
||||
dprintf("ethernet_send_data: no write buffer, cannot perform scatter I/O\n");
|
||||
gBufferModule->free(allocated);
|
||||
device->stats.send.errors++;
|
||||
return B_NOT_SUPPORTED;
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
gBufferModule->get_iovecs(buffer, &iovec, 1);
|
||||
@@ -328,15 +327,11 @@ ethernet_send_data(net_device *_device, net_buffer *buffer)
|
||||
//dprintf("sent: %ld\n", bytesWritten);
|
||||
|
||||
if (bytesWritten < 0) {
|
||||
atomic_add((int32*)&device->stats.send.errors, 1);
|
||||
if (allocated)
|
||||
gBufferModule->free(allocated);
|
||||
return errno;
|
||||
}
|
||||
|
||||
atomic_add((int32*)&device->stats.send.packets, 1);
|
||||
atomic_add64((int64*)&device->stats.send.bytes, bytesWritten);
|
||||
|
||||
gBufferModule->free(original);
|
||||
if (allocated)
|
||||
gBufferModule->free(allocated);
|
||||
@@ -382,7 +377,6 @@ ethernet_receive_data(net_device *_device, net_buffer **_buffer)
|
||||
|
||||
bytesRead = read(device->fd, iovec.iov_base, iovec.iov_len);
|
||||
if (bytesRead < 0) {
|
||||
atomic_add((int32*)&device->stats.receive.errors, 1);
|
||||
status = errno;
|
||||
goto err;
|
||||
}
|
||||
@@ -397,9 +391,6 @@ ethernet_receive_data(net_device *_device, net_buffer **_buffer)
|
||||
goto err;
|
||||
}
|
||||
|
||||
atomic_add((int32*)&device->stats.receive.packets, 1);
|
||||
atomic_add64((int64*)&device->stats.receive.bytes, bytesRead);
|
||||
|
||||
*_buffer = buffer;
|
||||
return B_OK;
|
||||
|
||||
|
||||
@@ -110,14 +110,7 @@ loopback_control(net_device *device, int32 op, void *argument,
|
||||
status_t
|
||||
loopback_send_data(net_device *device, net_buffer *buffer)
|
||||
{
|
||||
status_t status = sStackModule->device_enqueue_buffer(device, buffer);
|
||||
if (status == B_OK) {
|
||||
atomic_add64((int64*)&device->stats.send.bytes, buffer->size);
|
||||
atomic_add((int32*)&device->stats.send.packets, 1);
|
||||
} else {
|
||||
atomic_add((int32*)&device->stats.send.errors, 1);
|
||||
}
|
||||
return status;
|
||||
return sStackModule->device_enqueue_buffer(device, buffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -247,13 +247,6 @@ tunnel_write(void* _cookie, off_t position, const void* data, size_t* _length)
|
||||
if (status != B_OK)
|
||||
gBufferModule->free(buffer);
|
||||
|
||||
if (status == B_OK) {
|
||||
atomic_add((int32*)&cookie->device->stats.receive.packets, 1);
|
||||
atomic_add64((int64*)&cookie->device->stats.receive.bytes, buffer->size);
|
||||
} else {
|
||||
atomic_add((int32*)&cookie->device->stats.receive.errors, 1);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -468,14 +461,10 @@ tunnel_send_data(net_device* _device, net_buffer* buffer)
|
||||
status = gStackModule->fifo_enqueue_buffer(
|
||||
&device->send_queue, buffer);
|
||||
if (status == B_OK) {
|
||||
atomic_add((int32*)&device->stats.send.packets, 1);
|
||||
atomic_add64((int64*)&device->stats.send.bytes, buffer->size);
|
||||
} else {
|
||||
atomic_add((int32*)&device->stats.send.errors, 1);
|
||||
MutexLocker selectLocker(device->select_lock);
|
||||
notify_select_event_pool(device->select_pool, B_SELECT_READ);
|
||||
}
|
||||
|
||||
MutexLocker selectLocker(device->select_lock);
|
||||
notify_select_event_pool(device->select_pool, B_SELECT_READ);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -193,13 +193,11 @@ ppp_send_data(net_device *_device, net_buffer *buffer)
|
||||
ppp_device *device = (ppp_device *)_device;
|
||||
|
||||
if (buffer->size > device->frame_size || buffer->size < device->header_length) {
|
||||
device->stats.send.errors++;
|
||||
dprintf("sorry! fail send ppp packet, size wrong!\n");
|
||||
return B_BAD_VALUE;
|
||||
return EMSGSIZE;
|
||||
}
|
||||
|
||||
if (device->KPPP_Interface == NULL) {
|
||||
device->stats.send.errors++;
|
||||
dprintf("Fail send ppp packet, no eth for ppp!\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
@@ -209,14 +207,10 @@ ppp_send_data(net_device *_device, net_buffer *buffer)
|
||||
status_t status = device->KPPP_Interface->Send(buffer, 0x0021); // IP_PROTOCOL 0x0021
|
||||
|
||||
if (status != B_OK) {
|
||||
device->stats.send.errors++;
|
||||
dprintf("KPPP_Interface->Send(buffer, 0x0021 IP) fail\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
device->stats.send.packets++;
|
||||
device->stats.send.bytes += net_buffer_size;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -239,8 +233,6 @@ ppp_receive_data(net_device *_device, net_buffer **_buffer)
|
||||
}
|
||||
|
||||
// (*_buffer)->interface_address = NULL; // strange need to put here
|
||||
device->stats.receive.bytes += (*_buffer)->size;
|
||||
device->stats.receive.packets++;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,21 @@ fill_address(const sockaddr* from, sockaddr* to, size_t maxLength)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_device_send_stats(struct net_device* device, status_t status, size_t packetSize)
|
||||
{
|
||||
if (status == B_OK) {
|
||||
atomic_add((int32*)&device->stats.send.packets, 1);
|
||||
atomic_add64((int64*)&device->stats.send.bytes, packetSize);
|
||||
} else {
|
||||
if (status == ENOBUFS || status == EMSGSIZE)
|
||||
atomic_add((int32*)&device->stats.send.dropped, 1);
|
||||
else
|
||||
atomic_add((int32*)&device->stats.send.errors, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - datalink module
|
||||
|
||||
|
||||
@@ -411,8 +426,12 @@ datalink_send_routed_data(struct net_route* route, net_buffer* buffer)
|
||||
}
|
||||
|
||||
// this one goes back to the domain directly
|
||||
return fifo_enqueue_buffer(
|
||||
const size_t packetSize = buffer->size;
|
||||
status_t status = fifo_enqueue_buffer(
|
||||
&interface->DeviceInterface()->receive_queue, buffer);
|
||||
update_device_send_stats(interface->DeviceInterface()->device,
|
||||
status, packetSize);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((route->flags & RTF_GATEWAY) != 0) {
|
||||
@@ -721,7 +740,10 @@ interface_protocol_send_data(net_datalink_protocol* _protocol,
|
||||
if (atomic_get(&interface->DeviceInterface()->monitor_count) > 0)
|
||||
device_interface_monitor_receive(interface->DeviceInterface(), buffer);
|
||||
|
||||
return protocol->device_module->send_data(protocol->device, buffer);
|
||||
const size_t packetSize = buffer->size;
|
||||
status_t status = protocol->device_module->send_data(protocol->device, buffer);
|
||||
update_device_send_stats(protocol->device, status, packetSize);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,14 +64,25 @@ device_reader_thread(void* _interface)
|
||||
|
||||
if (interface->deframe_func(interface->device, buffer) != B_OK) {
|
||||
gNetBufferModule.free(buffer);
|
||||
atomic_add((int32*)&device->stats.receive.dropped, 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
fifo_enqueue_buffer(&interface->receive_queue, buffer);
|
||||
const size_t packetSize = buffer->size;
|
||||
status = fifo_enqueue_buffer(&interface->receive_queue, buffer);
|
||||
if (status == B_OK) {
|
||||
atomic_add((int32*)&device->stats.receive.packets, 1);
|
||||
atomic_add64((int64*)&device->stats.receive.bytes, packetSize);
|
||||
} else {
|
||||
gNetBufferModule.free(buffer);
|
||||
atomic_add((int32*)&device->stats.receive.dropped, 1);
|
||||
}
|
||||
} else if (status == B_DEVICE_NOT_FOUND) {
|
||||
device_removed(device);
|
||||
return status;
|
||||
} else {
|
||||
atomic_add((int32*)&device->stats.receive.errors, 1);
|
||||
|
||||
// In case of error, give the other threads some
|
||||
// time to run since this is a high priority time thread.
|
||||
snooze(10000);
|
||||
|
||||
Reference in New Issue
Block a user