* 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 destination;
struct net_interface *interface;
union {
struct {
uint16 start;
uint16 end;
} fragment;
uint32 sequence;
uint32 offset;
};
uint32 flags;
uint32 size;
uint8 protocol;
@@ -71,13 +71,7 @@ struct ipv4_header {
#define FRAGMENT_TIMEOUT 60000000LL
// discard fragment after 60 seconds
struct ipv4_fragment : DoublyLinkedListLinkImpl<ipv4_fragment> {
uint16 start;
uint16 end;
net_buffer *buffer;
};
typedef DoublyLinkedList<struct ipv4_fragment> FragmentList;
typedef DoublyLinkedList<struct net_buffer, DoublyLinkedListCLink<struct net_buffer> > FragmentList;
struct ipv4_packet_key {
in_addr_t source;
@@ -243,11 +237,9 @@ FragmentPacket::~FragmentPacket()
sStackModule->set_timer(&fTimer, -1);
// delete all fragments
ipv4_fragment *fragment;
while ((fragment = fFragments.RemoveHead()) != NULL) {
if (fragment->buffer != NULL)
gBufferModule->free(fragment->buffer);
delete fragment;
net_buffer *buffer;
while ((buffer = fFragments.RemoveHead()) != NULL) {
gBufferModule->free(buffer);
}
}
@@ -267,11 +259,10 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// Search for a position in the list to insert the fragment
FragmentList::ReverseIterator iterator = fFragments.GetReverseIterator();
ipv4_fragment *previous = NULL;
ipv4_fragment *next = NULL;
net_buffer *previous = NULL;
net_buffer *next = NULL;
while ((previous = iterator.Next()) != NULL) {
if (previous->start <= start) {
if (previous->fragment.start <= start) {
// The new fragment can be inserted after this one
break;
}
@@ -281,7 +272,8 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
// 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
gBufferModule->free(buffer);
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 (previous != NULL && previous->end > start) {
TRACE((" remove header %d bytes\n", previous->end - start));
gBufferModule->remove_header(buffer, previous->end - start);
start = previous->end;
if (previous != NULL && previous->fragment.end > start) {
TRACE((" remove header %d bytes\n", previous->fragment.end - start));
gBufferModule->remove_header(buffer, previous->fragment.end - start);
start = previous->fragment.end;
}
if (next != NULL && next->start < end) {
TRACE((" remove trailer %d bytes\n", next->start - end));
gBufferModule->remove_trailer(buffer, next->start - end);
end = next->start;
if (next != NULL && next->fragment.start < end) {
TRACE((" remove trailer %d bytes\n", next->fragment.start - end));
gBufferModule->remove_trailer(buffer, next->fragment.start - end);
end = next->fragment.start;
}
// 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
// report an error (in which case we're not responsible for freeing it)
if (previous != NULL && previous->end == start) {
status_t status = gBufferModule->merge(buffer, previous->buffer, false);
TRACE((" merge previous: %s\n", strerror(status)));
if (status < B_OK)
return status;
if (previous != NULL && previous->fragment.end == start) {
fFragments.Remove(previous);
previous->buffer = buffer;
previous->end = end;
buffer->fragment.start = previous->fragment.start;
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
fBytesLeft -= end - start;
@@ -327,14 +325,20 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
TRACE((" hole length: %d\n", (int)fBytesLeft));
return B_OK;
} else if (next != NULL && next->start == end) {
status_t status = gBufferModule->merge(buffer, next->buffer, true);
TRACE((" merge next: %s\n", strerror(status)));
if (status < B_OK)
return status;
} else if (next != NULL && next->fragment.start == end) {
fFragments.Remove(next);
next->buffer = buffer;
next->start = start;
buffer->fragment.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
fBytesLeft -= end - start;
@@ -349,17 +353,13 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer *buffer,
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", fragment, start, end));
if (fragment == NULL)
return B_NO_MEMORY;
TRACE((" new fragment: %p, bytes %d-%d\n", buffer, start, end));
fragment->start = start;
fragment->end = end;
fragment->buffer = buffer;
fFragments.Insert(next, fragment);
buffer->fragment.start = start;
buffer->fragment.end = end;
fFragments.Insert(next, buffer);
// update length of the hole, if any
fBytesLeft -= end - start;
@@ -387,21 +387,19 @@ FragmentPacket::Reassemble(net_buffer *to)
net_buffer *buffer = NULL;
ipv4_fragment *fragment;
net_buffer *fragment;
while ((fragment = fFragments.RemoveHead()) != NULL) {
if (buffer != NULL) {
status_t status;
if (to == fragment->buffer) {
status = gBufferModule->merge(fragment->buffer, buffer, false);
buffer = fragment->buffer;
if (to == fragment) {
status = gBufferModule->merge(fragment, buffer, false);
buffer = fragment;
} else
status = gBufferModule->merge(buffer, fragment->buffer, true);
status = gBufferModule->merge(buffer, fragment, true);
if (status < B_OK)
return status;
} else
buffer = fragment->buffer;
delete fragment;
buffer = fragment;
}
if (buffer != to)
@@ -568,8 +566,8 @@ static status_t
send_fragments(ipv4_protocol *protocol, struct net_route *route,
net_buffer *buffer, uint32 mtu)
{
dprintf("ipv4 needs to fragment (size %lu, MTU %lu), but that's not yet tested...\n",
buffer->size, mtu);
TRACE(("ipv4 needs to fragment (size %lu, MTU %lu)...\n",
buffer->size, mtu));
NetBufferHeader<ipv4_header> bufferHeader(buffer);
if (bufferHeader.Status() < B_OK)
@@ -223,6 +223,7 @@ create_buffer(size_t headerSpace)
buffer->source.ss_len = 0;
buffer->destination.ss_len = 0;
buffer->interface = NULL;
buffer->offset = 0;
buffer->flags = 0;
buffer->size = 0;