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.


-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
RTnet-developers mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rtnet-developers

Reply via email to