This repository has been archived by the owner on Sep 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
sd.c
154 lines (126 loc) · 3.36 KB
/
sd.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
/*
* Copyright (c) 2023 Cisco and/or its affiliates. All rights reserved.
*
* SPDX-License-Identifier: MIT OR GPL-2.0-only
*
* Licensed under the MIT license <LICENSE.MIT or https://opensource.org/licenses/MIT> or the GPLv2 license
* <LICENSE.GPL or https://opensource.org/license/gpl-2-0>, at your option. This file may not be copied,
* modified, or distributed except according to those terms.
*/
#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME
#include <linux/slab.h>
#include <linux/hashtable.h>
#include <linux/crc32c.h>
#include "sd.h"
static service_discovery_table *sd_table;
DEFINE_MUTEX(sd_table_mutex);
static void sd_table_lock(void)
{
mutex_lock(&sd_table_mutex);
}
static void sd_table_unlock(void)
{
mutex_unlock(&sd_table_mutex);
}
service_discovery_table *service_discovery_table_create()
{
service_discovery_table *table = kzalloc(sizeof(service_discovery_table), GFP_KERNEL);
hash_init(table->htable);
return table;
}
void sd_table_init()
{
sd_table = service_discovery_table_create();
}
static u64 sd_entry_hash(const char *name, int len)
{
return crc32c((u32)~1, name, len);
}
void service_discovery_table_entry_add(service_discovery_table *table, service_discovery_entry *entry)
{
if (!table || !entry)
{
return;
}
u64 key = sd_entry_hash(entry->address, strlen(entry->address));
hash_add(table->htable, &entry->node, key);
}
static service_discovery_entry *sd_table_entry_get_locked(const char *address)
{
struct service_discovery_entry *entry;
u64 key = sd_entry_hash(address, strlen(address));
hash_for_each_possible(sd_table->htable, entry, node, key)
{
if (strncmp(entry->address, address, strlen(address)) == 0)
return entry;
}
return NULL;
}
service_discovery_entry *sd_table_entry_get(const char *address)
{
sd_table_lock();
service_discovery_entry *entry = sd_table_entry_get_locked(address);
sd_table_unlock();
return entry;
}
static void sd_table_entry_del_locked(service_discovery_entry *entry)
{
if (!entry)
{
return;
}
pr_debug("remove entry # address[%s]", entry->address);
hash_del(&entry->node);
}
void sd_table_entry_del(service_discovery_entry *entry)
{
sd_table_lock();
sd_table_entry_del_locked(entry);
sd_table_unlock();
}
static void service_discovery_entry_free(service_discovery_entry *entry)
{
if (!entry)
{
return;
}
kfree(entry->address);
size_t i;
for (i = 0; i < entry->labels_len; i++)
{
kfree(entry->labels[i]);
}
kfree(entry->labels);
kfree(entry);
}
static void service_discovery_table_free_locked(service_discovery_table *table)
{
if (!table)
{
return;
}
service_discovery_entry *entry;
int i;
hash_for_each(table->htable, i, entry, node)
{
pr_debug("delete entry # address[%s]", entry->address);
sd_table_entry_del_locked(entry);
service_discovery_entry_free(entry);
}
kfree(table);
}
void sd_table_replace(service_discovery_table *table)
{
sd_table_lock();
pr_debug("cleanup current sd table entries");
service_discovery_table_free_locked(sd_table);
pr_debug("replace sd table");
sd_table = table;
sd_table_unlock();
}
void sd_table_free()
{
sd_table_lock();
service_discovery_table_free_locked(sd_table);
sd_table_unlock();
}