* 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:
@@ -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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user