Re: [RTnet-developers] Maintaining UDP sockets in a hash instead of a list.
Brought to you by:
bet-frogger,
kiszka
|
From: Gilles C. <gil...@xe...> - 2008-08-25 14:53:27
|
Hi,
here is a repost of the rtnet-hash-port.diff patch. Only, without the
"receiving" bit, and with the INADDR_ANY bit fixed.
Index: stack/ipv4/udp.c
===================================================================
--- stack/ipv4/udp.c (révision 1186)
+++ stack/ipv4/udp.c (copie de travail)
@@ -29,6 +29,7 @@
#include <linux/udp.h>
#include <linux/tcp.h>
#include <net/checksum.h>
+#include <linux/list.h>
#include <rtskb.h>
#include <rtnet_internal.h>
@@ -51,6 +52,7 @@ struct udp_socket {
u16 sport; /* local port */
u32 saddr; /* local ip-addr */
struct rtsocket *sock;
+ struct hlist_node link;
};
/***
@@ -80,12 +82,49 @@ static u32 port_bitmap[
static struct udp_socket port_registry[RT_UDP_SOCKETS];
static rtdm_lock_t udp_socket_base_lock = RTDM_LOCK_UNLOCKED;
+static struct hlist_head port_hash[RT_UDP_SOCKETS * 2];
+#define port_hash_mask (RT_UDP_SOCKETS * 2 - 1)
+
module_param(auto_port_start, uint, 0444);
module_param(auto_port_mask, uint, 0444);
MODULE_PARM_DESC(auto_port_start, "Start of automatically assigned port range");
MODULE_PARM_DESC(auto_port_mask,
"Mask that defines port range for automatic assignment");
+static inline struct udp_socket *port_hash_search(u32 saddr, u16 sport)
+{
+ unsigned bucket = sport & port_hash_mask;
+ struct udp_socket *sock;
+ struct hlist_node *n;
+
+ hlist_for_each_entry(sock, n, &port_hash[bucket], link)
+ if (sock->sport == sport &&
+ (saddr == INADDR_ANY
+ || sock->saddr == saddr
+ || sock->saddr == INADDR_ANY))
+ return sock;
+
+ return NULL;
+}
+
+static inline int port_hash_insert(struct udp_socket *sock, u32 saddr, u16 sport)
+{
+ unsigned bucket;
+
+ if (port_hash_search(saddr, sport))
+ return -EADDRINUSE;
+
+ bucket = sport & port_hash_mask;
+ sock->saddr = saddr;
+ sock->sport = sport;
+ hlist_add_head(&sock->link, &port_hash[bucket]);
+ return 0;
+}
+
+static inline void port_hash_del(struct udp_socket *sock)
+{
+ hlist_del(&sock->link);
+}
/***
* rt_udp_v4_lookup
@@ -93,48 +132,20 @@ MODULE_PARM_DESC(auto_port_mask,
static inline struct rtsocket *rt_udp_v4_lookup(u32 daddr, u16 dport)
{
rtdm_lockctx_t context;
- int index;
- int bit;
- int bitmap_index;
-#if BITS_PER_LONG == 32
- unsigned long bitmap;
-#elif BITS_PER_LONG == 64
- u32 bitmap;
-#else
-#error please include asm/types.h
-#endif
- struct rtsocket *sock;
-
+ struct udp_socket *sock;
- for (bitmap_index = 0; bitmap_index < ((RT_UDP_SOCKETS + 31) / 32);
- bitmap_index++) {
- bit = 0;
- index = bitmap_index * 32;
-
- rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
+ rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
+ sock = port_hash_search(daddr, dport);
+ if (sock) {
+ rt_socket_reference(sock->sock);
- bitmap = port_bitmap[bitmap_index];
- while (bitmap != 0) {
- if (test_bit(bit, &bitmap)) {
- if ((port_registry[index].sport == dport) &&
- ((port_registry[index].saddr == INADDR_ANY) ||
- (port_registry[index].saddr == daddr))) {
- sock = port_registry[index].sock;
- rt_socket_reference(sock);
-
- rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
-
- return sock;
- }
- clear_bit(bit, &bitmap);
- }
- index++;
- bit++;
- }
+ rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
- rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+ return sock->sock;
}
+ rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+
return NULL;
}
@@ -168,15 +179,22 @@ int rt_udp_bind(struct rtsocket *sock, c
return -EINVAL;
}
+ port_hash_del(&port_registry[index]);
+ if (port_hash_insert(&port_registry[index],
+ usin->sin_addr.s_addr,
+ usin->sin_port ?: index + auto_port_start)) {
+ port_hash_insert(&port_registry[index],
+ port_registry[index].saddr,
+ port_registry[index].sport);
+ rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+ return -EADDRINUSE;
+ }
+
/* set the source-addr */
- sock->prot.inet.saddr = usin->sin_addr.s_addr;
+ sock->prot.inet.saddr = port_registry[index].saddr;
/* set source port, if not set by user */
- if ((sock->prot.inet.sport = usin->sin_port) == 0)
- sock->prot.inet.sport = index + auto_port_start;
-
- port_registry[index].sport = sock->prot.inet.sport;
- port_registry[index].saddr = sock->prot.inet.saddr;
+ sock->prot.inet.sport = port_registry[index].sport;
rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
@@ -280,8 +298,7 @@ int rt_udp_socket(struct rtdm_dev_contex
sock->prot.inet.sport = index + auto_port_start;
/* register UDP socket */
- port_registry[index].sport = sock->prot.inet.sport;
- port_registry[index].saddr = INADDR_ANY;
+ port_hash_insert(&port_registry[index], INADDR_ANY, sock->prot.inet.sport);
port_registry[index].sock = sock;
rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
@@ -310,6 +327,7 @@ int rt_udp_close(struct rtdm_dev_context
if (sock->prot.inet.reg_index >= 0) {
port = sock->prot.inet.reg_index;
clear_bit(port % 32, &port_bitmap[port / 32]);
+ port_hash_del(&port_registry[port]);
free_ports++;
@@ -575,7 +593,7 @@ ssize_t rt_udp_sendmsg(struct rtdm_dev_c
return err;
/* we found a route, remember the routing dest-addr could be the netmask */
- ufh.saddr = saddr ?: rt.rtdev->local_ip;
+ ufh.saddr = saddr != INADDR_ANY ? saddr : rt.rtdev->local_ip;
ufh.daddr = daddr;
ufh.uh.dest = dport;
ufh.uh.len = htons(ulen);
@@ -692,19 +710,21 @@ static struct rtinet_protocol udp_protoc
.init_socket = &rt_udp_socket
};
-
-
/***
* rt_udp_init
*/
void __init rt_udp_init(void)
{
+ int i;
if ((auto_port_start < 0) || (auto_port_start >= 0x10000 - RT_UDP_SOCKETS))
auto_port_start = 1024;
auto_port_start = htons(auto_port_start & (auto_port_mask & 0xFFFF));
auto_port_mask = htons(auto_port_mask | 0xFFFF0000);
rt_inet_add_protocol(&udp_protocol);
+
+ for (i = 0; i < ARRAY_SIZE(port_hash); i++)
+ INIT_HLIST_HEAD(&port_hash[i]);
}
--
Gilles.
|