* Added an offset/sequence field to the net_buffer - this can and will be used

by the TCP implementation for its reorder and retransmit queues.
* The ipv4_fragment is no longer needed, as we can use the above field there
  as well - this saves one extra allocation per received fragment.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19369 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-11-25 11:29:36 +00:00
parent 7c0541c12f
commit 604d21a600
3 changed files with 65 additions and 58 deletions
+8
View File
@@ -22,6 +22,14 @@ typedef struct net_buffer {
struct sockaddr_storage source; struct sockaddr_storage source;
struct sockaddr_storage destination; struct sockaddr_storage destination;
struct net_interface *interface; struct net_interface *interface;
union {
struct {
uint16 start;
uint16 end;
} fragment;
uint32 sequence;
uint32 offset;
};
uint32 flags; uint32 flags;
uint32 size; uint32 size;
uint8 protocol; uint8 protocol;
@@ -71,13 +71,7 @@ struct ipv4_header {
#define FRAGMENT_TIMEOUT 60000000LL #define FRAGMENT_TIMEOUT 60000000LL
// discard fragment after 60 seconds // discard fragment after 60 seconds
struct ipv4_fragment : DoublyLinkedListLinkImpl<ipv4_fragment> { typedef DoublyLinkedList<struct net_buffer, DoublyLinkedListCLink<struct net_buffer> > FragmentList;
uint16 start;
uint16 end;
net_buffer *buffer;
};
typedef DoublyLinkedList<struct ipv4_fragment> FragmentList;
struct ipv4_packet_key { struct ipv4_packet_key {
in_addr_t source; in_addr_t source;
@@ -243,11 +237,9 @@ FragmentPacket::~FragmentPacket()
sStackModule->set_timer(&fTimer, -1); sStackModule->set_timer(&fTimer, -1);
// delete all fragments // delete all fragments
ipv4_fragment *fragment; net_buffer *buffer;
while ((fragment = fFragments.RemoveHead()) != NULL) { while ((buffer = fFragments.RemoveHead()) != NULL) {
if (fragment->buffer != NULL) gBufferModule->free(buffer);
gBufferModule->free(fragment->buffer);
delete fragment;
} }
} }
@@ -267,11 +259,10 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// Search for a position in the list to insert the fragment // Search for a position in the list to insert the fragment
FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator(); FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator();
ipv4_fragment *previous = NULL; net_buffer *previous = NULL;
ipv4_fragment *next = NULL; net_buffer *next = NULL;
while ((previous = iterator.Next()) != NULL) { while ((previous = iterator.Next()) != NULL) {
if (previous->fragment.start <= start) {
if (previous->start <= start) {
// The new fragment can be inserted after this one // The new fragment can be inserted after this one
break; break;
} }
@@ -281,7 +272,8 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// See if we already have the fragment's data // See if we already have the fragment's data
if (previous != NULL && previous->start <= start && previous->end >= end) { if (previous != NULL && previous->fragment.start <= start
&& previous->fragment.end >= end) {
// we do, so we can just drop this fragment // we do, so we can just drop this fragment
gBufferModule->free(buffer); gBufferModule->free(buffer);
return B_OK; return B_OK;
@@ -291,15 +283,15 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// If we have parts of the data already, truncate as needed // If we have parts of the data already, truncate as needed
if (previous != NULL && previous->end > start) { if (previous != NULL && previous->fragment.end > start) {
TRACE((" remove header %d bytes\n", previous->end - start)); TRACE((" remove header %d bytes\n", previous->fragment.end - start));
gBufferModule->remove_header(buffer, previous->end - start); gBufferModule->remove_header(buffer, previous->fragment.end - start);
start = previous->end; start = previous->fragment.end;
} }
if (next != NULL && next->start < end) { if (next != NULL && next->fragment.start < end) {
TRACE((" remove trailer %d bytes\n", next->start - end)); TRACE((" remove trailer %d bytes\n", next->fragment.start - end));
gBufferModule->remove_trailer(buffer, next->start - end); gBufferModule->remove_trailer(buffer, next->fragment.start - end);
end = next->start; end = next->fragment.start;
} }
// Now try if we can already merge the fragments together // Now try if we can already merge the fragments together
@@ -307,14 +299,20 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// We will always keep the last buffer received, so that we can still // We will always keep the last buffer received, so that we can still
// report an error (in which case we're not responsible for freeing it) // report an error (in which case we're not responsible for freeing it)
if (previous != NULL && previous->end == start) { if (previous != NULL && previous->fragment.end == start) {
status_t status = gBufferModule->merge(buffer, previous->buffer, false); fFragments.Remove(previous);
TRACE((" merge previous: %s\n", strerror(status)));
if (status < B_OK)
return status;
previous->buffer = buffer; buffer->fragment.start = previous->fragment.start;
previous->end = end; buffer->fragment.end = end;
status_t status = gBufferModule->merge(buffer, previous, false);
TRACE((" merge previous: %s\n", strerror(status)));
if (status < B_OK) {
fFragments.Insert(next, previous);
return status;
}
fFragments.Insert(next, buffer);
// cut down existing hole // cut down existing hole
fBytesLeft -= end - start; fBytesLeft -= end - start;
@@ -327,14 +325,20 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
TRACE((" hole length: %d\n", (int)fBytesLeft)); TRACE((" hole length: %d\n", (int)fBytesLeft));
return B_OK; return B_OK;
} else if (next != NULL && next->start == end) { } else if (next != NULL && next->fragment.start == end) {
status_t status = gBufferModule->merge(buffer, next->buffer, true); fFragments.Remove(next);
TRACE((" merge next: %s\n", strerror(status)));
if (status < B_OK)
return status;
next->buffer = buffer; buffer->fragment.start = start;
next->start = start; buffer->fragment.end = next->fragment.end;
status_t status = gBufferModule->merge(buffer, next, true);
TRACE((" merge next: %s\n", strerror(status)));
if (status < B_OK) {
fFragments.Insert((net_buffer *)previous->link.next, next);
return status;
}
fFragments.Insert((net_buffer *)previous->link.next, buffer);
// cut down existing hole // cut down existing hole
fBytesLeft -= end - start; fBytesLeft -= end - start;
@@ -349,17 +353,13 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
return B_OK; return B_OK;
} }
// We couldn't merge the fragments, so we need to add a new fragment // We couldn't merge the fragments, so we need to add it as is
ipv4_fragment *fragment = new (std::nothrow) ipv4_fragment; TRACE((" new fragment: %p, bytes %d-%d\n", buffer, start, end));
TRACE((" new fragment: %p, bytes %d-%d\n", fragment, start, end));
if (fragment == NULL)
return B_NO_MEMORY;
fragment->start = start; buffer->fragment.start = start;
fragment->end = end; buffer->fragment.end = end;
fragment->buffer = buffer; fFragments.Insert(next, buffer);
fFragments.Insert(next, fragment);
// update length of the hole, if any // update length of the hole, if any
fBytesLeft -= end - start; fBytesLeft -= end - start;
@@ -387,21 +387,19 @@ FragmentPacket::Reassemble(net_buffer *to)
net_buffer *buffer = NULL; net_buffer *buffer = NULL;
ipv4_fragment *fragment; net_buffer *fragment;
while ((fragment = fFragments.RemoveHead()) != NULL) { while ((fragment = fFragments.RemoveHead()) != NULL) {
if (buffer != NULL) { if (buffer != NULL) {
status_t status; status_t status;
if (to == fragment->buffer) { if (to == fragment) {
status = gBufferModule->merge(fragment->buffer, buffer, false); status = gBufferModule->merge(fragment, buffer, false);
buffer = fragment->buffer; buffer = fragment;
} else } else
status = gBufferModule->merge(buffer, fragment->buffer, true); status = gBufferModule->merge(buffer, fragment, true);
if (status < B_OK) if (status < B_OK)
return status; return status;
} else } else
buffer = fragment->buffer; buffer = fragment;
delete fragment;
} }
if (buffer != to) if (buffer != to)
@@ -568,8 +566,8 @@ static status_t
send_fragments(ipv4_protocol *protocol, struct net_route *route, send_fragments(ipv4_protocol *protocol, struct net_route *route,
net_buffer *buffer, uint32 mtu) net_buffer *buffer, uint32 mtu)
{ {
dprintf("ipv4 needs to fragment (size %lu, MTU %lu), but that's not yet tested...\n", TRACE(("ipv4 needs to fragment (size %lu, MTU %lu)...\n",
buffer->size, mtu); buffer->size, mtu));
NetBufferHeader<ipv4_header> bufferHeader(buffer); NetBufferHeader<ipv4_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK) if (bufferHeader.Status() < B_OK)
@@ -223,6 +223,7 @@ create_buffer(size_t headerSpace)
buffer->source.ss_len = 0; buffer->source.ss_len = 0;
buffer->destination.ss_len = 0; buffer->destination.ss_len = 0;
buffer->interface = NULL; buffer->interface = NULL;
buffer->offset = 0;
buffer->flags = 0; buffer->flags = 0;
buffer->size = 0; buffer->size = 0;