xref: /mOS-networking-stack/core/src/addr_pool.c (revision b88bd7d2)
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <pthread.h>
4 #include "addr_pool.h"
5 #include "util.h"
6 #include "debug.h"
7 #include "config.h"
8 
9 #define MIN_PORT (1025)
10 #define MAX_PORT (65535 + 1)
11 
12 /*----------------------------------------------------------------------------*/
13 struct addr_entry
14 {
15 	struct sockaddr_in addr;
16 	TAILQ_ENTRY(addr_entry) addr_link;
17 };
18 /*----------------------------------------------------------------------------*/
19 struct addr_map
20 {
21 	struct addr_entry *addrmap[MAX_PORT];
22 };
23 /*----------------------------------------------------------------------------*/
24 struct addr_pool
25 {
26 	struct addr_entry *pool;		/* address pool */
27 	struct addr_map *mapper;		/* address map  */
28 
29 	uint32_t addr_base;				/* in host order */
30 	int num_addr;					/* number of addresses in use */
31 
32 	int num_entry;
33 	int num_free;
34 	int num_used;
35 
36 	pthread_mutex_t lock;
37 	TAILQ_HEAD(, addr_entry) free_list;
38 	TAILQ_HEAD(, addr_entry) used_list;
39 };
40 /*----------------------------------------------------------------------------*/
41 addr_pool_t
42 CreateAddressPool(in_addr_t addr_base, int num_addr)
43 {
44 	struct addr_pool *ap;
45 	int num_entry;
46 	int i, j, cnt;
47 	in_addr_t addr;
48 	uint32_t addr_h;
49 
50 	ap = (addr_pool_t)calloc(1, sizeof(struct addr_pool));
51 	if (!ap)
52 		return NULL;
53 
54 	/* initialize address pool */
55 	num_entry = num_addr * (MAX_PORT - MIN_PORT);
56 	ap->pool = (struct addr_entry *)calloc(num_entry, sizeof(struct addr_entry));
57 	if (!ap->pool) {
58 		free(ap);
59 		return NULL;
60 	}
61 
62 	/* initialize address map */
63 	ap->mapper = (struct addr_map *)calloc(num_addr, sizeof(struct addr_map));
64 	if (!ap->mapper) {
65 		free(ap->pool);
66 		free(ap);
67 		return NULL;
68 	}
69 
70 	TAILQ_INIT(&ap->free_list);
71 	TAILQ_INIT(&ap->used_list);
72 
73 	if (pthread_mutex_init(&ap->lock, NULL)) {
74 		free(ap->pool);
75 		free(ap);
76 		return NULL;
77 	}
78 
79 	pthread_mutex_lock(&ap->lock);
80 
81 	ap->addr_base = ntohl(addr_base);
82 	ap->num_addr = num_addr;
83 
84 	cnt = 0;
85 	for (i = 0; i < num_addr; i++) {
86 		addr_h = ap->addr_base + i;
87 		addr = htonl(addr_h);
88 		for (j = MIN_PORT; j < MAX_PORT; j++) {
89 			ap->pool[cnt].addr.sin_addr.s_addr = addr;
90 			ap->pool[cnt].addr.sin_port = htons(j);
91 			ap->mapper[i].addrmap[j] = &ap->pool[cnt];
92 
93 			TAILQ_INSERT_TAIL(&ap->free_list, &ap->pool[cnt], addr_link);
94 
95 			if ((++cnt) >= num_entry)
96 				break;
97 		}
98 	}
99 	ap->num_entry = cnt;
100 	ap->num_free = cnt;
101 	ap->num_used = 0;
102 
103 	pthread_mutex_unlock(&ap->lock);
104 
105 	return ap;
106 }
107 /*----------------------------------------------------------------------------*/
108 addr_pool_t
109 CreateAddressPoolPerCore(int core, int num_queues,
110 		in_addr_t saddr_base, int num_addr, in_addr_t daddr, in_port_t dport)
111 {
112 	struct addr_pool *ap;
113 	int num_entry;
114 	int i, j, cnt, endian_check;
115 	in_addr_t saddr;
116 	uint32_t saddr_h, daddr_h;
117 	uint16_t sport_h, dport_h;
118 	int rss_core;
119 
120 	ap = (addr_pool_t)calloc(1, sizeof(struct addr_pool));
121 	if (!ap)
122 		return NULL;
123 
124 	/* initialize address pool */
125 	num_entry = (num_addr * (MAX_PORT - MIN_PORT)) / num_queues;
126 	ap->pool = (struct addr_entry *)calloc(num_entry, sizeof(struct addr_entry));
127 	if (!ap->pool) {
128 		free(ap);
129 		return NULL;
130 	}
131 
132 	/* initialize address map */
133 	ap->mapper = (struct addr_map *)calloc(num_addr, sizeof(struct addr_map));
134 	if (!ap->mapper) {
135 		free(ap->pool);
136 		free(ap);
137 		return NULL;
138 	}
139 
140 	TAILQ_INIT(&ap->free_list);
141 	TAILQ_INIT(&ap->used_list);
142 
143 	if (pthread_mutex_init(&ap->lock, NULL)) {
144 		free(ap->pool);
145 		free(ap);
146 		return NULL;
147 	}
148 
149 	endian_check = FetchEndianType();
150 	pthread_mutex_lock(&ap->lock);
151 
152 	ap->addr_base = ntohl(saddr_base);
153 	ap->num_addr = num_addr;
154 	daddr_h = ntohl(daddr);
155 	dport_h = ntohs(dport);
156 
157 	/* search address space to get RSS-friendly addresses */
158 	cnt = 0;
159 	for (i = 0; i < num_addr; i++) {
160 		saddr_h = ap->addr_base + i;
161 		saddr = htonl(saddr_h);
162 		for (j = MIN_PORT; j < MAX_PORT; j++) {
163 			if (cnt >= num_entry)
164 				break;
165 
166 			sport_h = j;
167 			rss_core = GetRSSCPUCore(daddr_h, saddr_h, dport_h, sport_h,
168 						 num_queues, endian_check);
169 			if (rss_core != core)
170 				continue;
171 
172 			ap->pool[cnt].addr.sin_addr.s_addr = saddr;
173 			ap->pool[cnt].addr.sin_port = htons(sport_h);
174 			ap->mapper[i].addrmap[j] = &ap->pool[cnt];
175 			TAILQ_INSERT_TAIL(&ap->free_list, &ap->pool[cnt], addr_link);
176 			cnt++;
177 		}
178 	}
179 
180 	ap->num_entry = cnt;
181 	ap->num_free = cnt;
182 	ap->num_used = 0;
183 	//fprintf(stderr, "CPU %d: Created %d address entries.\n", core, cnt);
184 	if (ap->num_entry < g_config.mos->max_concurrency) {
185 		fprintf(stderr, "[WARINING] Available # addresses (%d) is smaller than"
186 				" the max concurrency (%d).\n",
187 				ap->num_entry, g_config.mos->max_concurrency);
188 	}
189 
190 	pthread_mutex_unlock(&ap->lock);
191 
192 	return ap;
193 }
194 /*----------------------------------------------------------------------------*/
195 void
196 DestroyAddressPool(addr_pool_t ap)
197 {
198 	if (!ap)
199 		return;
200 
201 	if (ap->pool) {
202 		free(ap->pool);
203 		ap->pool = NULL;
204 	}
205 
206 	if (ap->mapper) {
207 		free(ap->mapper);
208 		ap->mapper = NULL;
209 	}
210 
211 	pthread_mutex_destroy(&ap->lock);
212 
213 	free(ap);
214 }
215 /*----------------------------------------------------------------------------*/
216 int
217 FetchAddress(addr_pool_t ap, int core, int num_queues,
218 		const struct sockaddr_in *daddr, struct sockaddr_in *saddr)
219 {
220 	struct addr_entry *walk, *next;
221 	int rss_core, endian_check;
222 	int ret = -1;
223 
224 	if (!ap || !daddr || !saddr)
225 		return -1;
226 
227 	endian_check = FetchEndianType();
228 	pthread_mutex_lock(&ap->lock);
229 
230 	walk = TAILQ_FIRST(&ap->free_list);
231 	while (walk) {
232 		next = TAILQ_NEXT(walk, addr_link);
233 
234 		if (saddr->sin_addr.s_addr != INADDR_ANY &&
235 		    walk->addr.sin_addr.s_addr != saddr->sin_addr.s_addr) {
236 			walk = next;
237 			continue;
238 		}
239 
240 		if (saddr->sin_port != INPORT_ANY &&
241 		    walk->addr.sin_port != saddr->sin_port) {
242 			walk = next;
243 			continue;
244 		}
245 
246 		rss_core = GetRSSCPUCore(ntohl(walk->addr.sin_addr.s_addr),
247 				ntohl(daddr->sin_addr.s_addr), ntohs(walk->addr.sin_port),
248 					 ntohs(daddr->sin_port), num_queues, endian_check);
249 
250 		if (core == rss_core)
251 			break;
252 
253 		walk = next;
254 	}
255 
256 	if (walk) {
257 		*saddr = walk->addr;
258 		TAILQ_REMOVE(&ap->free_list, walk, addr_link);
259 		TAILQ_INSERT_TAIL(&ap->used_list, walk, addr_link);
260 		ap->num_free--;
261 		ap->num_used++;
262 		ret = 0;
263 	}
264 
265 	pthread_mutex_unlock(&ap->lock);
266 
267 	return ret;
268 }
269 /*----------------------------------------------------------------------------*/
270 int
271 FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr)
272 {
273 	struct addr_entry *walk, *next;
274 	int ret = -1;
275 
276 	if (!ap || !addr)
277 		return -1;
278 
279 	pthread_mutex_lock(&ap->lock);
280 
281 	if (ap->mapper) {
282 		uint32_t addr_h = ntohl(addr->sin_addr.s_addr);
283 		uint16_t port_h = ntohs(addr->sin_port);
284 		int index = addr_h - ap->addr_base;
285 
286 		if (index >= 0 || index < ap->num_addr) {
287 			walk = ap->mapper[addr_h - ap->addr_base].addrmap[port_h];
288 		} else {
289 			walk = NULL;
290 		}
291 
292 	} else {
293 		walk = TAILQ_FIRST(&ap->used_list);
294 		while (walk) {
295 			next = TAILQ_NEXT(walk, addr_link);
296 			if (addr->sin_port == walk->addr.sin_port &&
297 					addr->sin_addr.s_addr == walk->addr.sin_addr.s_addr) {
298 				break;
299 			}
300 
301 			walk = next;
302 		}
303 
304 	}
305 
306 	if (walk) {
307 		TAILQ_REMOVE(&ap->used_list, walk, addr_link);
308 		TAILQ_INSERT_TAIL(&ap->free_list, walk, addr_link);
309 		ap->num_free++;
310 		ap->num_used--;
311 		ret = 0;
312 	}
313 
314 	pthread_mutex_unlock(&ap->lock);
315 
316 	return ret;
317 }
318 /*----------------------------------------------------------------------------*/
319