ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ipcache.c
(Generate patch)

Comparing ircd-hybrid/trunk/src/ipcache.c (file contents):
Revision 5347 by michael, Sun Jan 11 12:42:20 2015 UTC vs.
Revision 8611 by michael, Thu Nov 1 15:56:52 2018 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2015 ircd-hybrid development team
4 > *  Copyright (c) 1997-2018 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 28 | Line 28
28   #include "list.h"
29   #include "ipcache.h"
30   #include "event.h"
31 < #include "mempool.h"
31 > #include "memory.h"
32   #include "conf.h"
33   #include "ircd.h"
34 + #include "patricia.h"
35  
36  
37 < static dlink_list ip_hash_table[IP_HASH_SIZE];
38 < static mp_pool_t *ip_entry_pool;
37 > static dlink_list ipcache_list;
38 > static patricia_tree_t *ipcache_trie_v6;
39 > static patricia_tree_t *ipcache_trie_v4;
40  
41  
42 <
43 < /* ipcache_hash_address()
42 < *
43 < * input        - pointer to an irc_inaddr
44 < * output       - integer value used as index into hash table
45 < * side effects - hopefully, none
46 < */
47 < static uint32_t
48 < ipcache_hash_address(const struct irc_ssaddr *addr)
42 > static void *
43 > ipcache_get_trie(void *addr)
44   {
45 <  if (addr->ss.ss_family == AF_INET)
46 <  {
52 <    const struct sockaddr_in *const v4 = (const struct sockaddr_in *)addr;
53 <    uint32_t hash = 0, ip = ntohl(v4->sin_addr.s_addr);
54 <
55 <    hash = ((ip >> 12) + ip) & (IP_HASH_SIZE - 1);
56 <    return hash;
57 <  }
45 >  if (((struct sockaddr *)addr)->sa_family == AF_INET6)
46 >    return ipcache_trie_v6;
47    else
48 <  {
60 <    const struct sockaddr_in6 *const v6 = (const struct sockaddr_in6 *)addr;
61 <    uint32_t hash = 0, *const ip = (uint32_t *)&v6->sin6_addr.s6_addr;
62 <
63 <    hash  = ip[0] ^ ip[3];
64 <    hash ^= hash >> 16;
65 <    hash ^= hash >> 8;
66 <    hash  = hash & (IP_HASH_SIZE - 1);
67 <    return hash;
68 <  }
48 >    return ipcache_trie_v4;
49   }
50  
51   /* ipcache_find_or_add_address()
# Line 78 | Line 58 | ipcache_hash_address(const struct irc_ss
58   * count set to 0.
59   */
60   struct ip_entry *
61 < ipcache_find_or_add_address(struct irc_ssaddr *addr)
61 > ipcache_record_find_or_add(void *addr)
62   {
63 <  dlink_node *node = NULL;
64 <  struct ip_entry *iptr = NULL;
85 <  const uint32_t hash_index = ipcache_hash_address(addr);
86 <  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
87 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
63 >  patricia_tree_t *ptrie = ipcache_get_trie(addr);
64 >  patricia_node_t *pnode = patricia_make_and_lookup_addr(ptrie, addr, 0);
65  
66 <  DLINK_FOREACH(node, ip_hash_table[hash_index].head)
67 <  {
91 <    iptr = node->data;
66 >  if (pnode->data)  /* Deliberate crash if 'pnode' is NULL */
67 >    return pnode->data;  /* Already added to the trie */
68  
69 <    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
70 <      continue;
69 >  struct ip_entry *iptr = xcalloc(sizeof(*iptr));
70 >  iptr->trie_pointer = ptrie;
71 >  dlinkAdd(pnode, &iptr->node, &ipcache_list);
72  
73 <    if (addr->ss.ss_family == AF_INET6)
74 <    {
75 <      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
76 <      if (!memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
100 <        return iptr;  /* Found entry already in hash, return it. */
101 <    }
102 <    else
103 <    {
104 <      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
105 <      if (!memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
106 <        return iptr;  /* Found entry already in hash, return it. */
107 <    }
108 <  }
73 >  PATRICIA_DATA_SET(pnode, iptr);
74 >
75 >  return iptr;
76 > }
77  
78 <  iptr = mp_pool_get(ip_entry_pool);
79 <  memcpy(&iptr->ip, addr, sizeof(struct irc_ssaddr));
78 > static void
79 > ipcache_record_delete(patricia_node_t *pnode)
80 > {
81 >  struct ip_entry *iptr = PATRICIA_DATA_GET(pnode, struct ip_entry);
82  
83 <  dlinkAdd(iptr, &iptr->node, &ip_hash_table[hash_index]);
83 >  if (iptr->count_local == 0 && iptr->count_remote == 0 &&
84 >      (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
85 >  {
86 >    patricia_remove(iptr->trie_pointer, pnode);
87  
88 <  return iptr;
88 >    dlinkDelete(&iptr->node, &ipcache_list);
89 >    xfree(iptr);
90 >  }
91   }
92  
93   /* ipcache_remove_addres()
# Line 125 | Line 100 | ipcache_find_or_add_address(struct irc_s
100   *                 the struct ip_entry is returned to the ip_entry_heap
101   */
102   void
103 < ipcache_remove_address(struct irc_ssaddr *addr)
103 > ipcache_record_remove(void *addr, int local)
104   {
105 <  dlink_node *node = NULL;
131 <  const uint32_t hash_index = ipcache_hash_address(addr);
132 <  struct sockaddr_in *v4 = (struct sockaddr_in *)addr, *ptr_v4;
133 <  struct sockaddr_in6 *v6 = (struct sockaddr_in6 *)addr, *ptr_v6;
105 >  patricia_node_t *pnode = patricia_try_search_exact_addr(ipcache_get_trie(addr), addr, 0);
106  
107 <  DLINK_FOREACH(node, ip_hash_table[hash_index].head)
108 <  {
137 <    struct ip_entry *iptr = node->data;
107 >  if (pnode == NULL)
108 >    return;
109  
110 <    if (iptr->ip.ss.ss_family != addr->ss.ss_family)
111 <      continue;
110 >  struct ip_entry *iptr = PATRICIA_DATA_GET(pnode, struct ip_entry);
111 >  assert(iptr->count_local > 0 || iptr->count_remote > 0);
112  
113 <    if (addr->ss.ss_family == AF_INET6)
114 <    {
115 <      ptr_v6 = (struct sockaddr_in6 *)&iptr->ip;
116 <      if (memcmp(&v6->sin6_addr, &ptr_v6->sin6_addr, sizeof(struct in6_addr)))
117 <        continue;
118 <    }
148 <    else
149 <    {
150 <      ptr_v4 = (struct sockaddr_in *)&iptr->ip;
151 <      if (memcmp(&v4->sin_addr, &ptr_v4->sin_addr, sizeof(struct in_addr)))
152 <        continue;
153 <    }
154 <
155 <    assert(iptr->count > 0);
156 <
157 <    if (--iptr->count == 0 &&
158 <        (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
159 <    {
160 <      dlinkDelete(&iptr->node, &ip_hash_table[hash_index]);
161 <      mp_pool_release(iptr);
162 <      return;
163 <    }
164 <  }
113 >  if (local)
114 >    --iptr->count_local;
115 >  else
116 >    --iptr->count_remote;
117 >
118 >  ipcache_record_delete(pnode);
119   }
120  
121   /* ipcache_remove_expired_entries()
# Line 171 | Line 125 | ipcache_remove_address(struct irc_ssaddr
125   * side effects - free up all ip entries with no connections
126   */
127   static void
128 < ipcache_remove_expired_entries(void *unused)
128 > ipcache_remove_expired_records(void *unused)
129   {
130 <  dlink_node *node = NULL, *node_next = NULL;
130 >  dlink_node *node, *node_next;
131  
132 <  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
133 <  {
180 <    DLINK_FOREACH_SAFE(node, node_next, ip_hash_table[i].head)
181 <    {
182 <      struct ip_entry *iptr = node->data;
183 <
184 <      if (iptr->count == 0 &&
185 <          (CurrentTime - iptr->last_attempt) >= ConfigGeneral.throttle_time)
186 <      {
187 <        dlinkDelete(&iptr->node, &ip_hash_table[i]);
188 <        mp_pool_release(iptr);
189 <      }
190 <    }
191 <  }
132 >  DLINK_FOREACH_SAFE(node, node_next, ipcache_list.head)
133 >    ipcache_record_delete(node->data);
134   }
135  
136   /* ipcache_get_stats()
# Line 202 | Line 144 | ipcache_remove_expired_entries(void *unu
144   * used in the hash.
145   */
146   void
147 < ipcache_get_stats(unsigned int *const number_ips_stored, uint64_t *const mem_ips_stored)
147 > ipcache_get_stats(unsigned int *const number_ips_stored, size_t *const mem_ips_stored)
148   {
149 <  for (unsigned int i = 0; i < IP_HASH_SIZE; ++i)
150 <    *number_ips_stored += dlink_list_length(&ip_hash_table[i]);
151 <  *mem_ips_stored = *number_ips_stored * sizeof(struct ip_entry);
149 >  /* TBD: inaccurate for now as it does only count the amount of memory for struct ip_entry items */
150 >  (*number_ips_stored) = dlink_list_length(&ipcache_list);
151 >  (*mem_ips_stored) = dlink_list_length(&ipcache_list) * sizeof(struct ip_entry);
152   }
153  
154   void
# Line 214 | Line 156 | ipcache_init(void)
156   {
157    static struct event event_expire_ipcache =
158    {
159 <    .name = "ipcache_remove_expired_entries",
160 <    .handler = ipcache_remove_expired_entries,
159 >    .name = "ipcache_remove_expired_records",
160 >    .handler = ipcache_remove_expired_records,
161      .when = 123
162    };
163  
164 +  ipcache_trie_v6 = patricia_new(128);
165 +  ipcache_trie_v4 = patricia_new( 32);
166 +
167    event_add(&event_expire_ipcache, NULL);
223  ip_entry_pool = mp_pool_new(sizeof(struct ip_entry), MP_CHUNK_SIZE_IP_ENTRY);
168   }

Comparing ircd-hybrid/trunk/src/ipcache.c (property svn:eol-style):
Revision 5347 by michael, Sun Jan 11 12:42:20 2015 UTC vs.
Revision 8611 by michael, Thu Nov 1 15:56:52 2018 UTC

# Line 0 | Line 1
1 + native

Comparing ircd-hybrid/trunk/src/ipcache.c (property svn:keywords):
Revision 5347 by michael, Sun Jan 11 12:42:20 2015 UTC vs.
Revision 8611 by michael, Thu Nov 1 15:56:52 2018 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)