source: mainline/uspace/lib/nic/src/nic_addr_db.c@ 13eecc4

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 13eecc4 was c477c80, checked in by Jiri Svoboda <jiri@…>, 7 years ago

Fix some common misspellings

  • Property mode set to 100644
File size: 6.3 KB
Line 
1/*
2 * Copyright (c) 2011 Radim Vansa
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/**
30 * @addtogroup libnic
31 * @{
32 */
33/**
34 * @file
35 * @brief Generic hash-set based database of addresses
36 */
37#include "nic_addr_db.h"
38#include <assert.h>
39#include <stdlib.h>
40#include <stdbool.h>
41#include <errno.h>
42#include <mem.h>
43#include <adt/hash_table.h>
44#include <macros.h>
45#include <stdint.h>
46
47/**
48 * Helper structure for keeping the address in the hash set.
49 */
50typedef struct nic_addr_entry {
51 ht_link_t link;
52 uint8_t len;
53 uint8_t addr[1];
54} nic_addr_entry_t;
55
56/*
57 * Hash table helper functions
58 */
59typedef struct {
60 size_t len;
61 const uint8_t *addr;
62} addr_key_t;
63
64static bool nic_addr_key_equal(void *key_arg, const ht_link_t *item)
65{
66 addr_key_t *key = (addr_key_t *)key_arg;
67 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
68
69 return memcmp(entry->addr, key->addr, entry->len) == 0;
70}
71
72static size_t addr_hash(size_t len, const uint8_t *addr)
73{
74 size_t hash = 0;
75
76 for (size_t i = 0; i < len; ++i) {
77 hash = (hash << 5) ^ addr[i];
78 }
79
80 return hash;
81}
82
83static size_t nic_addr_key_hash(void *k)
84{
85 addr_key_t *key = (addr_key_t *)k;
86 return addr_hash(key->len, key->addr);
87}
88
89static size_t nic_addr_hash(const ht_link_t *item)
90{
91 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
92 return addr_hash(entry->len, entry->addr);
93}
94
95static void nic_addr_removed(ht_link_t *item)
96{
97 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
98
99 free(entry);
100}
101
102static hash_table_ops_t set_ops = {
103 .hash = nic_addr_hash,
104 .key_hash = nic_addr_key_hash,
105 .key_equal = nic_addr_key_equal,
106 .equal = NULL,
107 .remove_callback = nic_addr_removed
108};
109
110/**
111 * Initialize the database
112 *
113 * @param[in,out] db Uninitialized storage
114 * @param[in] addr_len Size of addresses in the db
115 *
116 * @return EOK If successfully initialized
117 * @return EINVAL If the address length is too big
118 * @return ENOMEM If there was not enough memory to initialize the storage
119 */
120errno_t nic_addr_db_init(nic_addr_db_t *db, size_t addr_len)
121{
122 assert(db);
123
124 if (addr_len > UCHAR_MAX)
125 return EINVAL;
126
127 if (!hash_table_create(&db->set, 0, 0, &set_ops))
128 return ENOMEM;
129
130 db->addr_len = addr_len;
131 return EOK;
132}
133
134/**
135 * Remove all records from the DB
136 *
137 * @param db
138 */
139void nic_addr_db_clear(nic_addr_db_t *db)
140{
141 assert(db);
142 hash_table_clear(&db->set);
143}
144
145/**
146 * Free the memory used by db, including all records...
147 *
148 * @param db
149 */
150void nic_addr_db_destroy(nic_addr_db_t *db)
151{
152 assert(db);
153 hash_table_destroy(&db->set);
154}
155
156/**
157 * Insert an address to the db
158 *
159 * @param db
160 * @param addr Inserted address. Length is implicitly concluded from the
161 * db's address length.
162 *
163 * @return EOK If the address was inserted
164 * @return ENOMEM If there was not enough memory
165 * @return EEXIST If this address already is in the db
166 */
167errno_t nic_addr_db_insert(nic_addr_db_t *db, const uint8_t *addr)
168{
169 assert(db && addr);
170
171 addr_key_t key = {
172 .len = db->addr_len,
173 .addr = addr
174 };
175
176 if (hash_table_find(&db->set, &key))
177 return EEXIST;
178
179 nic_addr_entry_t *entry = malloc(sizeof(nic_addr_entry_t) + db->addr_len - 1);
180 if (entry == NULL)
181 return ENOMEM;
182
183 entry->len = (uint8_t) db->addr_len;
184 memcpy(entry->addr, addr, db->addr_len);
185
186 hash_table_insert(&db->set, &entry->link);
187 return EOK;
188}
189
190/**
191 * Remove the address from the db
192 *
193 * @param db
194 * @param addr Removed address.
195 *
196 * @return EOK If the address was removed
197 * @return ENOENT If there is no address
198 */
199errno_t nic_addr_db_remove(nic_addr_db_t *db, const uint8_t *addr)
200{
201 assert(db && addr);
202
203 addr_key_t key = {
204 .len = db->addr_len,
205 .addr = addr
206 };
207
208 if (hash_table_remove(&db->set, &key))
209 return EOK;
210 else
211 return ENOENT;
212}
213
214/**
215 * Test if the address is contained in the db
216 *
217 * @param db
218 * @param addr Tested addresss
219 *
220 * @return true if the address is in the db, false otherwise
221 */
222bool nic_addr_db_contains(const nic_addr_db_t *db, const uint8_t *addr)
223{
224 assert(db && addr);
225
226 addr_key_t key = {
227 .len = db->addr_len,
228 .addr = addr
229 };
230
231 return 0 != hash_table_find(&db->set, &key);
232}
233
234/**
235 * Helper structure for nic_addr_db_foreach
236 */
237typedef struct {
238 void (*func)(const uint8_t *, void *);
239 void *arg;
240} nic_addr_db_fe_arg_t;
241
242/**
243 * Helper function for nic_addr_db_foreach
244 */
245static bool nic_addr_db_fe_helper(ht_link_t *item, void *arg)
246{
247 nic_addr_db_fe_arg_t *hs = (nic_addr_db_fe_arg_t *) arg;
248 nic_addr_entry_t *entry = member_to_inst(item, nic_addr_entry_t, link);
249 hs->func(entry->addr, hs->arg);
250 return true;
251}
252
253/**
254 * Executes a user-defined function on all addresses in the DB. The function
255 * must not change the addresses.
256 *
257 * @param db
258 * @param func User-defined function
259 * @param arg Custom argument passed to the function
260 */
261void nic_addr_db_foreach(const nic_addr_db_t *db,
262 void (*func)(const uint8_t *, void *), void *arg)
263{
264 nic_addr_db_fe_arg_t hs = { .func = func, .arg = arg };
265 hash_table_apply((hash_table_t *)&db->set, nic_addr_db_fe_helper, &hs);
266}
267
268/** @}
269 */
Note: See TracBrowser for help on using the repository browser.