Hi,

here is another patch to RTnet, which replaces the list of UDP sockets
with a hash, so makes the searching for an RTnet registered socket a bit
faster.

Regards.

-- 
                                                 Gilles.
--- rtnet-0.9.8/stack/ipv4/udp.c        2006-12-11 17:29:52.000000000 +0100
+++ rtnet/stack/ipv4/udp.c      2008-04-02 11:39:14.000000000 +0200
@@ -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>
@@ -49,8 +50,10 @@
  */
 struct udp_socket {
     u16             sport;      /* local port */
+    u16             receiving;
     u32             saddr;      /* local ip-addr */
     struct rtsocket *sock;
+    struct hlist_node link;
 };
 
 /***
@@ -80,12 +83,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 +133,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;
-
-
-    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);
-
-        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);
+    struct udp_socket *sock;
 
-                    rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+    rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
+    sock = port_hash_search(daddr, dport);
+    if (sock && sock->receiving) {
+           rt_socket_reference(sock->sock);
 
-                    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 +180,24 @@ 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;
+    sock->prot.inet.sport = port_registry[index].sport;
 
-    port_registry[index].sport = sock->prot.inet.sport;
-    port_registry[index].saddr = sock->prot.inet.saddr;
+    port_registry[index].receiving = 1;
 
     rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
 
@@ -283,8 +304,8 @@ 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].receiving = 0;
     port_registry[index].sock  = sock;
 
     rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
@@ -313,6 +334,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++;
 
@@ -375,13 +397,23 @@ ssize_t rt_udp_recvmsg(struct rtdm_dev_c
     struct udphdr       *uh;
     struct sockaddr_in  *sin;
     nanosecs_rel_t      timeout = sock->timeout;
-    int                 ret;
+    int                 ret, index;
+    rtdm_lockctx_t  context;
 
 
     /* non-blocking receive? */
     if (testbits(msg_flags, MSG_DONTWAIT))
         timeout = -1;
 
+    rtdm_lock_get_irqsave(&udp_socket_base_lock, context);
+    if ((index = sock->prot.inet.reg_index) < 0) {
+           rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+        /* socket is being closed */
+           return -EBADF;
+    }
+    port_registry[index].receiving = 1;
+    rtdm_lock_put_irqrestore(&udp_socket_base_lock, context);
+           
     ret = rtdm_sem_timeddown(&sock->pending_sem, timeout, NULL);
     if (unlikely(ret < 0))
         switch (ret) {
@@ -576,14 +608,8 @@ ssize_t rt_udp_sendmsg(struct rtdm_dev_c
     if (err)
         return err;
 
-    /* check if specified source address fits */
-    if ((saddr != INADDR_ANY) && (saddr != rt.rtdev->local_ip)) {
-        rtdev_dereference(rt.rtdev);
-        return -EHOSTUNREACH;
-    }
-
     /* we found a route, remember the routing dest-addr could be the netmask */
-    ufh.saddr     = rt.rtdev->local_ip;
+    ufh.saddr     = saddr ?: rt.rtdev->local_ip;
     ufh.daddr     = daddr;
     ufh.uh.dest   = dport;
     ufh.uh.len    = htons(ulen);
@@ -771,19 +798,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]);
 }
 
 
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
RTnet-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rtnet-developers

Reply via email to