Gilles Chanteperdrix wrote:
> Hi,
> 
> here is a repost of the rtnet-hash-port.diff patch. Only, without the
> "receiving" bit, and with the INADDR_ANY bit fixed.

OK, almost ready for merge.

BTW, did you also happen to measure the performance gain (and for how
many sockets)?

> 
> 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;

Unfortunately, hlist is not available with kernel 2.4. Please provide
wrappers as well.

>  };
>  
>  /***
> @@ -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]);
>  }
>  
>  
> 

Jan

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------------
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