* Converted the hash used to the BOpenHashTable instead of khash - basically
just applied r38391 to the IPv6 code (no time to resolve the TODO, and put that into a shared class). * Fixed failure on init handling. * Not tested, but should work at least better than before, as the hashtable has never been initialized before... * This closes bug #7795. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42399 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2011, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -77,8 +77,8 @@ typedef DoublyLinkedList<struct net_buffer,
|
|||||||
struct ipv6_packet_key {
|
struct ipv6_packet_key {
|
||||||
in6_addr source;
|
in6_addr source;
|
||||||
in6_addr destination;
|
in6_addr destination;
|
||||||
|
// We use uint32 here due to the hash function
|
||||||
uint32 id;
|
uint32 id;
|
||||||
// using u32 for the field allows to feed the whole structure in hash func.
|
|
||||||
uint32 protocol;
|
uint32 protocol;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,23 +95,56 @@ public:
|
|||||||
{ return fReceivedLastFragment
|
{ return fReceivedLastFragment
|
||||||
&& fBytesLeft == 0; }
|
&& fBytesLeft == 0; }
|
||||||
|
|
||||||
static uint32 Hash(void* _packet, const void* _key,
|
const ipv6_packet_key& Key() const { return fKey; }
|
||||||
uint32 range);
|
FragmentPacket*& HashTableLink() { return fNext; }
|
||||||
static int Compare(void* _packet, const void* _key);
|
|
||||||
static int32 NextOffset()
|
|
||||||
{ return offsetof(FragmentPacket, fNext); }
|
|
||||||
static void StaleTimer(struct net_timer* timer, void* data);
|
static void StaleTimer(struct net_timer* timer, void* data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FragmentPacket* fNext;
|
FragmentPacket* fNext;
|
||||||
struct ipv6_packet_key fKey;
|
struct ipv6_packet_key fKey;
|
||||||
bool fReceivedLastFragment;
|
uint32 fIndex;
|
||||||
int32 fBytesLeft;
|
int32 fBytesLeft;
|
||||||
FragmentList fFragments;
|
FragmentList fFragments;
|
||||||
net_timer fTimer;
|
net_timer fTimer;
|
||||||
|
bool fReceivedLastFragment;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct FragmentHashDefinition {
|
||||||
|
typedef ipv6_packet_key KeyType;
|
||||||
|
typedef FragmentPacket ValueType;
|
||||||
|
|
||||||
|
size_t HashKey(const KeyType& key) const
|
||||||
|
{
|
||||||
|
return jenkins_hashword((const uint32*)&key,
|
||||||
|
sizeof(ipv6_packet_key) / sizeof(uint32), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Hash(ValueType* value) const
|
||||||
|
{
|
||||||
|
return HashKey(value->Key());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Compare(const KeyType& key, ValueType* value) const
|
||||||
|
{
|
||||||
|
const ipv6_packet_key& packetKey = value->Key();
|
||||||
|
|
||||||
|
return packetKey.id == key.id
|
||||||
|
&& packetKey.source == key.source
|
||||||
|
&& packetKey.destination == key.destination
|
||||||
|
&& packetKey.protocol == key.protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
ValueType*& GetLink(ValueType* value) const
|
||||||
|
{
|
||||||
|
return value->HashTableLink();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BOpenHashTable<FragmentHashDefinition, false, true> FragmentTable;
|
||||||
|
|
||||||
|
|
||||||
class RawSocket
|
class RawSocket
|
||||||
: public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
: public DoublyLinkedListLinkImpl<RawSocket>, public DatagramSocket<> {
|
||||||
public:
|
public:
|
||||||
@@ -177,7 +210,7 @@ static net_socket_module_info* sSocketModule;
|
|||||||
static RawSocketList sRawSockets;
|
static RawSocketList sRawSockets;
|
||||||
static mutex sRawSocketsLock;
|
static mutex sRawSocketsLock;
|
||||||
static mutex sFragmentLock;
|
static mutex sFragmentLock;
|
||||||
static hash_table* sFragmentHash;
|
static FragmentTable sFragmentHash;
|
||||||
static int32 sFragmentID;
|
static int32 sFragmentID;
|
||||||
static mutex sMulticastGroupsLock;
|
static mutex sMulticastGroupsLock;
|
||||||
|
|
||||||
@@ -241,8 +274,8 @@ RawSocket::RawSocket(net_socket* socket)
|
|||||||
FragmentPacket::FragmentPacket(const ipv6_packet_key &key)
|
FragmentPacket::FragmentPacket(const ipv6_packet_key &key)
|
||||||
:
|
:
|
||||||
fKey(key),
|
fKey(key),
|
||||||
fReceivedLastFragment(false),
|
fBytesLeft(IPV6_MAXPACKET),
|
||||||
fBytesLeft(IPV6_MAXPACKET)
|
fReceivedLastFragment(false)
|
||||||
{
|
{
|
||||||
gStackModule->init_timer(&fTimer, FragmentPacket::StaleTimer, this);
|
gStackModule->init_timer(&fTimer, FragmentPacket::StaleTimer, this);
|
||||||
}
|
}
|
||||||
@@ -296,6 +329,9 @@ FragmentPacket::AddFragment(uint16 start, uint16 end, net_buffer* buffer,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fIndex = buffer->index;
|
||||||
|
// adopt the buffer's device index
|
||||||
|
|
||||||
TRACE(" previous: %p, next: %p", previous, next);
|
TRACE(" previous: %p, next: %p", previous, next);
|
||||||
|
|
||||||
// If we have parts of the data already, truncate as needed
|
// If we have parts of the data already, truncate as needed
|
||||||
@@ -423,33 +459,13 @@ FragmentPacket::Reassemble(net_buffer* to)
|
|||||||
if (buffer != to)
|
if (buffer != to)
|
||||||
panic("ipv6 packet reassembly did not work correctly.");
|
panic("ipv6 packet reassembly did not work correctly.");
|
||||||
|
|
||||||
|
to->index = fIndex;
|
||||||
|
// reset the buffer's device index
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
FragmentPacket::Compare(void* _packet, const void* _key)
|
|
||||||
{
|
|
||||||
const ipv6_packet_key* key = (ipv6_packet_key*)_key;
|
|
||||||
ipv6_packet_key* packetKey = &((FragmentPacket*)_packet)->fKey;
|
|
||||||
|
|
||||||
return memcmp(packetKey, key, sizeof(ipv6_packet_key));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
uint32
|
|
||||||
FragmentPacket::Hash(void* _packet, const void* _key, uint32 range)
|
|
||||||
{
|
|
||||||
const struct ipv6_packet_key* key = (struct ipv6_packet_key*)_key;
|
|
||||||
FragmentPacket* packet = (FragmentPacket*)_packet;
|
|
||||||
if (packet != NULL)
|
|
||||||
key = &packet->fKey;
|
|
||||||
|
|
||||||
return jenkins_hashword((const uint32*)key,
|
|
||||||
sizeof(ipv6_packet_key) / sizeof(uint32), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
FragmentPacket::StaleTimer(struct net_timer* timer, void* data)
|
FragmentPacket::StaleTimer(struct net_timer* timer, void* data)
|
||||||
{
|
{
|
||||||
@@ -457,7 +473,7 @@ FragmentPacket::StaleTimer(struct net_timer* timer, void* data)
|
|||||||
TRACE("Assembling FragmentPacket %p timed out!", packet);
|
TRACE("Assembling FragmentPacket %p timed out!", packet);
|
||||||
|
|
||||||
MutexLocker locker(&sFragmentLock);
|
MutexLocker locker(&sFragmentLock);
|
||||||
hash_remove(sFragmentHash, packet);
|
sFragmentHash.Remove(packet);
|
||||||
locker.Unlock();
|
locker.Unlock();
|
||||||
|
|
||||||
if (!packet->fFragments.IsEmpty()) {
|
if (!packet->fFragments.IsEmpty()) {
|
||||||
@@ -529,7 +545,7 @@ reassemble_fragments(const IPv6Header &header, net_buffer** _buffer, uint16 offs
|
|||||||
// TODO: Make locking finer grained.
|
// TODO: Make locking finer grained.
|
||||||
MutexLocker locker(&sFragmentLock);
|
MutexLocker locker(&sFragmentLock);
|
||||||
|
|
||||||
FragmentPacket* packet = (FragmentPacket*)hash_lookup(sFragmentHash, &key);
|
FragmentPacket* packet = sFragmentHash.Lookup(key);
|
||||||
if (packet == NULL) {
|
if (packet == NULL) {
|
||||||
// New fragment packet
|
// New fragment packet
|
||||||
packet = new (std::nothrow) FragmentPacket(key);
|
packet = new (std::nothrow) FragmentPacket(key);
|
||||||
@@ -537,7 +553,7 @@ reassemble_fragments(const IPv6Header &header, net_buffer** _buffer, uint16 offs
|
|||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// add packet to hash
|
// add packet to hash
|
||||||
status = hash_insert(sFragmentHash, packet);
|
status = sFragmentHash.Insert(packet);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
delete packet;
|
delete packet;
|
||||||
return status;
|
return status;
|
||||||
@@ -560,7 +576,7 @@ reassemble_fragments(const IPv6Header &header, net_buffer** _buffer, uint16 offs
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
if (packet->IsComplete()) {
|
if (packet->IsComplete()) {
|
||||||
hash_remove(sFragmentHash, packet);
|
sFragmentHash.Remove(packet);
|
||||||
// no matter if reassembling succeeds, we won't need this packet
|
// no matter if reassembling succeeds, we won't need this packet
|
||||||
// anymore
|
// anymore
|
||||||
|
|
||||||
@@ -1619,12 +1635,17 @@ init_ipv6()
|
|||||||
sMulticastState = new MulticastState();
|
sMulticastState = new MulticastState();
|
||||||
if (sMulticastState == NULL) {
|
if (sMulticastState == NULL) {
|
||||||
status = B_NO_MEMORY;
|
status = B_NO_MEMORY;
|
||||||
goto err;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = sMulticastState->Init();
|
status = sMulticastState->Init();
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err;
|
goto err2;
|
||||||
|
|
||||||
|
new (&sFragmentHash) FragmentTable();
|
||||||
|
status = sFragmentHash.Init(256);
|
||||||
|
if (status != B_OK)
|
||||||
|
goto err3;
|
||||||
|
|
||||||
new (&sRawSockets) RawSocketList;
|
new (&sRawSockets) RawSocketList;
|
||||||
// static initializers do not work in the kernel,
|
// static initializers do not work in the kernel,
|
||||||
@@ -1634,18 +1655,21 @@ init_ipv6()
|
|||||||
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_RAW, 0,
|
status = gStackModule->register_domain_protocols(AF_INET6, SOCK_RAW, 0,
|
||||||
NET_IPV6_MODULE_NAME, NULL);
|
NET_IPV6_MODULE_NAME, NULL);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err;
|
goto err3;
|
||||||
|
|
||||||
status = gStackModule->register_domain(AF_INET6, "internet6", &gIPv6Module,
|
status = gStackModule->register_domain(AF_INET6, "internet6", &gIPv6Module,
|
||||||
&gIPv6AddressModule, &sDomain);
|
&gIPv6AddressModule, &sDomain);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
goto err;
|
goto err3;
|
||||||
|
|
||||||
TRACE("init_ipv6: OK");
|
TRACE("init_ipv6: OK");
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err:
|
err3:
|
||||||
|
sFragmentHash.~FragmentTable();
|
||||||
|
err2:
|
||||||
delete sMulticastState;
|
delete sMulticastState;
|
||||||
|
err1:
|
||||||
mutex_destroy(&sReceivingProtocolLock);
|
mutex_destroy(&sReceivingProtocolLock);
|
||||||
mutex_destroy(&sMulticastGroupsLock);
|
mutex_destroy(&sMulticastGroupsLock);
|
||||||
mutex_destroy(&sRawSocketsLock);
|
mutex_destroy(&sRawSocketsLock);
|
||||||
@@ -1665,6 +1689,7 @@ uninit_ipv6()
|
|||||||
gStackModule->put_domain_receiving_protocol(sDomain, i);
|
gStackModule->put_domain_receiving_protocol(sDomain, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sFragmentHash.~FragmentTable();
|
||||||
delete sMulticastState;
|
delete sMulticastState;
|
||||||
|
|
||||||
gStackModule->unregister_domain(sDomain);
|
gStackModule->unregister_domain(sDomain);
|
||||||
|
|||||||
Reference in New Issue
Block a user