xref: /mOS-networking-stack/core/src/addr_pool.c (revision 8c9e1184)
176404edcSAsim Jamshed #include <stdio.h>
276404edcSAsim Jamshed #include <stdlib.h>
376404edcSAsim Jamshed #include <pthread.h>
476404edcSAsim Jamshed #include "addr_pool.h"
5152f7c19SAsim Jamshed #include "util.h"
676404edcSAsim Jamshed #include "debug.h"
776404edcSAsim Jamshed #include "config.h"
876404edcSAsim Jamshed 
976404edcSAsim Jamshed #define MIN_PORT (1025)
1076404edcSAsim Jamshed #define MAX_PORT (65535 + 1)
1176404edcSAsim Jamshed 
1276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1376404edcSAsim Jamshed struct addr_entry
1476404edcSAsim Jamshed {
1576404edcSAsim Jamshed 	struct sockaddr_in addr;
1676404edcSAsim Jamshed 	TAILQ_ENTRY(addr_entry) addr_link;
1776404edcSAsim Jamshed };
1876404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
1976404edcSAsim Jamshed struct addr_map
2076404edcSAsim Jamshed {
2176404edcSAsim Jamshed 	struct addr_entry *addrmap[MAX_PORT];
2276404edcSAsim Jamshed };
2376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
2476404edcSAsim Jamshed struct addr_pool
2576404edcSAsim Jamshed {
2676404edcSAsim Jamshed 	struct addr_entry *pool;		/* address pool */
2776404edcSAsim Jamshed 	struct addr_map *mapper;		/* address map  */
2876404edcSAsim Jamshed 
2976404edcSAsim Jamshed 	uint32_t addr_base;				/* in host order */
3076404edcSAsim Jamshed 	int num_addr;					/* number of addresses in use */
3176404edcSAsim Jamshed 
3276404edcSAsim Jamshed 	int num_entry;
3376404edcSAsim Jamshed 	int num_free;
3476404edcSAsim Jamshed 	int num_used;
3576404edcSAsim Jamshed 
3676404edcSAsim Jamshed 	pthread_mutex_t lock;
3776404edcSAsim Jamshed 	TAILQ_HEAD(, addr_entry) free_list;
3876404edcSAsim Jamshed 	TAILQ_HEAD(, addr_entry) used_list;
3976404edcSAsim Jamshed };
4076404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
4176404edcSAsim Jamshed addr_pool_t
CreateAddressPool(in_addr_t addr_base,int num_addr)4276404edcSAsim Jamshed CreateAddressPool(in_addr_t addr_base, int num_addr)
4376404edcSAsim Jamshed {
4476404edcSAsim Jamshed 	struct addr_pool *ap;
4576404edcSAsim Jamshed 	int num_entry;
4676404edcSAsim Jamshed 	int i, j, cnt;
4776404edcSAsim Jamshed 	in_addr_t addr;
4876404edcSAsim Jamshed 	uint32_t addr_h;
4976404edcSAsim Jamshed 
5076404edcSAsim Jamshed 	ap = (addr_pool_t)calloc(1, sizeof(struct addr_pool));
5176404edcSAsim Jamshed 	if (!ap)
5276404edcSAsim Jamshed 		return NULL;
5376404edcSAsim Jamshed 
5476404edcSAsim Jamshed 	/* initialize address pool */
5576404edcSAsim Jamshed 	num_entry = num_addr * (MAX_PORT - MIN_PORT);
5676404edcSAsim Jamshed 	ap->pool = (struct addr_entry *)calloc(num_entry, sizeof(struct addr_entry));
5776404edcSAsim Jamshed 	if (!ap->pool) {
5876404edcSAsim Jamshed 		free(ap);
5976404edcSAsim Jamshed 		return NULL;
6076404edcSAsim Jamshed 	}
6176404edcSAsim Jamshed 
6276404edcSAsim Jamshed 	/* initialize address map */
6376404edcSAsim Jamshed 	ap->mapper = (struct addr_map *)calloc(num_addr, sizeof(struct addr_map));
6476404edcSAsim Jamshed 	if (!ap->mapper) {
6576404edcSAsim Jamshed 		free(ap->pool);
6676404edcSAsim Jamshed 		free(ap);
6776404edcSAsim Jamshed 		return NULL;
6876404edcSAsim Jamshed 	}
6976404edcSAsim Jamshed 
7076404edcSAsim Jamshed 	TAILQ_INIT(&ap->free_list);
7176404edcSAsim Jamshed 	TAILQ_INIT(&ap->used_list);
7276404edcSAsim Jamshed 
7376404edcSAsim Jamshed 	if (pthread_mutex_init(&ap->lock, NULL)) {
7476404edcSAsim Jamshed 		free(ap->pool);
7576404edcSAsim Jamshed 		free(ap);
7676404edcSAsim Jamshed 		return NULL;
7776404edcSAsim Jamshed 	}
7876404edcSAsim Jamshed 
7976404edcSAsim Jamshed 	pthread_mutex_lock(&ap->lock);
8076404edcSAsim Jamshed 
8176404edcSAsim Jamshed 	ap->addr_base = ntohl(addr_base);
8276404edcSAsim Jamshed 	ap->num_addr = num_addr;
8376404edcSAsim Jamshed 
8476404edcSAsim Jamshed 	cnt = 0;
8576404edcSAsim Jamshed 	for (i = 0; i < num_addr; i++) {
8676404edcSAsim Jamshed 		addr_h = ap->addr_base + i;
8776404edcSAsim Jamshed 		addr = htonl(addr_h);
8876404edcSAsim Jamshed 		for (j = MIN_PORT; j < MAX_PORT; j++) {
8976404edcSAsim Jamshed 			ap->pool[cnt].addr.sin_addr.s_addr = addr;
9076404edcSAsim Jamshed 			ap->pool[cnt].addr.sin_port = htons(j);
9176404edcSAsim Jamshed 			ap->mapper[i].addrmap[j] = &ap->pool[cnt];
9276404edcSAsim Jamshed 
9376404edcSAsim Jamshed 			TAILQ_INSERT_TAIL(&ap->free_list, &ap->pool[cnt], addr_link);
9476404edcSAsim Jamshed 
9576404edcSAsim Jamshed 			if ((++cnt) >= num_entry)
9676404edcSAsim Jamshed 				break;
9776404edcSAsim Jamshed 		}
9876404edcSAsim Jamshed 	}
9976404edcSAsim Jamshed 	ap->num_entry = cnt;
10076404edcSAsim Jamshed 	ap->num_free = cnt;
10176404edcSAsim Jamshed 	ap->num_used = 0;
10276404edcSAsim Jamshed 
10376404edcSAsim Jamshed 	pthread_mutex_unlock(&ap->lock);
10476404edcSAsim Jamshed 
10576404edcSAsim Jamshed 	return ap;
10676404edcSAsim Jamshed }
10776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
10876404edcSAsim Jamshed addr_pool_t
CreateAddressPoolPerCore(int core,int num_queues,in_addr_t saddr_base,int num_addr,in_addr_t daddr,in_port_t dport)10976404edcSAsim Jamshed CreateAddressPoolPerCore(int core, int num_queues,
11076404edcSAsim Jamshed 		in_addr_t saddr_base, int num_addr, in_addr_t daddr, in_port_t dport)
11176404edcSAsim Jamshed {
11276404edcSAsim Jamshed 	struct addr_pool *ap;
11376404edcSAsim Jamshed 	int num_entry;
114*8c9e1184SAsim Jamshed 	int i, j, cnt;
11576404edcSAsim Jamshed 	in_addr_t saddr;
11676404edcSAsim Jamshed 	uint32_t saddr_h, daddr_h;
11776404edcSAsim Jamshed 	uint16_t sport_h, dport_h;
11876404edcSAsim Jamshed 	int rss_core;
11976404edcSAsim Jamshed 
12076404edcSAsim Jamshed 	ap = (addr_pool_t)calloc(1, sizeof(struct addr_pool));
12176404edcSAsim Jamshed 	if (!ap)
12276404edcSAsim Jamshed 		return NULL;
12376404edcSAsim Jamshed 
12476404edcSAsim Jamshed 	/* initialize address pool */
12576404edcSAsim Jamshed 	num_entry = (num_addr * (MAX_PORT - MIN_PORT)) / num_queues;
12676404edcSAsim Jamshed 	ap->pool = (struct addr_entry *)calloc(num_entry, sizeof(struct addr_entry));
12776404edcSAsim Jamshed 	if (!ap->pool) {
12876404edcSAsim Jamshed 		free(ap);
12976404edcSAsim Jamshed 		return NULL;
13076404edcSAsim Jamshed 	}
13176404edcSAsim Jamshed 
13276404edcSAsim Jamshed 	/* initialize address map */
13376404edcSAsim Jamshed 	ap->mapper = (struct addr_map *)calloc(num_addr, sizeof(struct addr_map));
13476404edcSAsim Jamshed 	if (!ap->mapper) {
13576404edcSAsim Jamshed 		free(ap->pool);
13676404edcSAsim Jamshed 		free(ap);
13776404edcSAsim Jamshed 		return NULL;
13876404edcSAsim Jamshed 	}
13976404edcSAsim Jamshed 
14076404edcSAsim Jamshed 	TAILQ_INIT(&ap->free_list);
14176404edcSAsim Jamshed 	TAILQ_INIT(&ap->used_list);
14276404edcSAsim Jamshed 
14376404edcSAsim Jamshed 	if (pthread_mutex_init(&ap->lock, NULL)) {
14476404edcSAsim Jamshed 		free(ap->pool);
14576404edcSAsim Jamshed 		free(ap);
14676404edcSAsim Jamshed 		return NULL;
14776404edcSAsim Jamshed 	}
14876404edcSAsim Jamshed 
14976404edcSAsim Jamshed 	pthread_mutex_lock(&ap->lock);
15076404edcSAsim Jamshed 
15176404edcSAsim Jamshed 	ap->addr_base = ntohl(saddr_base);
15276404edcSAsim Jamshed 	ap->num_addr = num_addr;
15376404edcSAsim Jamshed 	daddr_h = ntohl(daddr);
15476404edcSAsim Jamshed 	dport_h = ntohs(dport);
15576404edcSAsim Jamshed 
15676404edcSAsim Jamshed 	/* search address space to get RSS-friendly addresses */
15776404edcSAsim Jamshed 	cnt = 0;
15876404edcSAsim Jamshed 	for (i = 0; i < num_addr; i++) {
15976404edcSAsim Jamshed 		saddr_h = ap->addr_base + i;
16076404edcSAsim Jamshed 		saddr = htonl(saddr_h);
16176404edcSAsim Jamshed 		for (j = MIN_PORT; j < MAX_PORT; j++) {
16276404edcSAsim Jamshed 			if (cnt >= num_entry)
16376404edcSAsim Jamshed 				break;
16476404edcSAsim Jamshed 
16576404edcSAsim Jamshed 			sport_h = j;
166b88bd7d2SAsim Jamshed 			rss_core = GetRSSCPUCore(daddr_h, saddr_h, dport_h, sport_h,
167*8c9e1184SAsim Jamshed 						 num_queues);
16876404edcSAsim Jamshed 			if (rss_core != core)
16976404edcSAsim Jamshed 				continue;
17076404edcSAsim Jamshed 
17176404edcSAsim Jamshed 			ap->pool[cnt].addr.sin_addr.s_addr = saddr;
17276404edcSAsim Jamshed 			ap->pool[cnt].addr.sin_port = htons(sport_h);
17376404edcSAsim Jamshed 			ap->mapper[i].addrmap[j] = &ap->pool[cnt];
17476404edcSAsim Jamshed 			TAILQ_INSERT_TAIL(&ap->free_list, &ap->pool[cnt], addr_link);
17576404edcSAsim Jamshed 			cnt++;
17676404edcSAsim Jamshed 		}
17776404edcSAsim Jamshed 	}
17876404edcSAsim Jamshed 
17976404edcSAsim Jamshed 	ap->num_entry = cnt;
18076404edcSAsim Jamshed 	ap->num_free = cnt;
18176404edcSAsim Jamshed 	ap->num_used = 0;
18276404edcSAsim Jamshed 	//fprintf(stderr, "CPU %d: Created %d address entries.\n", core, cnt);
18376404edcSAsim Jamshed 	if (ap->num_entry < g_config.mos->max_concurrency) {
18476404edcSAsim Jamshed 		fprintf(stderr, "[WARINING] Available # addresses (%d) is smaller than"
18576404edcSAsim Jamshed 				" the max concurrency (%d).\n",
18676404edcSAsim Jamshed 				ap->num_entry, g_config.mos->max_concurrency);
18776404edcSAsim Jamshed 	}
18876404edcSAsim Jamshed 
18976404edcSAsim Jamshed 	pthread_mutex_unlock(&ap->lock);
19076404edcSAsim Jamshed 
19176404edcSAsim Jamshed 	return ap;
19276404edcSAsim Jamshed }
19376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
19476404edcSAsim Jamshed void
DestroyAddressPool(addr_pool_t ap)19576404edcSAsim Jamshed DestroyAddressPool(addr_pool_t ap)
19676404edcSAsim Jamshed {
19776404edcSAsim Jamshed 	if (!ap)
19876404edcSAsim Jamshed 		return;
19976404edcSAsim Jamshed 
20076404edcSAsim Jamshed 	if (ap->pool) {
20176404edcSAsim Jamshed 		free(ap->pool);
20276404edcSAsim Jamshed 		ap->pool = NULL;
20376404edcSAsim Jamshed 	}
20476404edcSAsim Jamshed 
20576404edcSAsim Jamshed 	if (ap->mapper) {
20676404edcSAsim Jamshed 		free(ap->mapper);
20776404edcSAsim Jamshed 		ap->mapper = NULL;
20876404edcSAsim Jamshed 	}
20976404edcSAsim Jamshed 
21076404edcSAsim Jamshed 	pthread_mutex_destroy(&ap->lock);
21176404edcSAsim Jamshed 
21276404edcSAsim Jamshed 	free(ap);
21376404edcSAsim Jamshed }
21476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
21576404edcSAsim Jamshed int
FetchAddress(addr_pool_t ap,int core,int num_queues,const struct sockaddr_in * daddr,struct sockaddr_in * saddr)21676404edcSAsim Jamshed FetchAddress(addr_pool_t ap, int core, int num_queues,
21776404edcSAsim Jamshed 		const struct sockaddr_in *daddr, struct sockaddr_in *saddr)
21876404edcSAsim Jamshed {
21976404edcSAsim Jamshed 	struct addr_entry *walk, *next;
220*8c9e1184SAsim Jamshed 	int rss_core;
22176404edcSAsim Jamshed 	int ret = -1;
22276404edcSAsim Jamshed 
22376404edcSAsim Jamshed 	if (!ap || !daddr || !saddr)
22476404edcSAsim Jamshed 		return -1;
22576404edcSAsim Jamshed 
22676404edcSAsim Jamshed 	pthread_mutex_lock(&ap->lock);
22776404edcSAsim Jamshed 
22876404edcSAsim Jamshed 	walk = TAILQ_FIRST(&ap->free_list);
22976404edcSAsim Jamshed 	while (walk) {
23076404edcSAsim Jamshed 		next = TAILQ_NEXT(walk, addr_link);
23176404edcSAsim Jamshed 
23276404edcSAsim Jamshed 		if (saddr->sin_addr.s_addr != INADDR_ANY &&
23376404edcSAsim Jamshed 		    walk->addr.sin_addr.s_addr != saddr->sin_addr.s_addr) {
23476404edcSAsim Jamshed 			walk = next;
23576404edcSAsim Jamshed 			continue;
23676404edcSAsim Jamshed 		}
23776404edcSAsim Jamshed 
23876404edcSAsim Jamshed 		if (saddr->sin_port != INPORT_ANY &&
23976404edcSAsim Jamshed 		    walk->addr.sin_port != saddr->sin_port) {
24076404edcSAsim Jamshed 			walk = next;
24176404edcSAsim Jamshed 			continue;
24276404edcSAsim Jamshed 		}
24376404edcSAsim Jamshed 
24476404edcSAsim Jamshed 		rss_core = GetRSSCPUCore(ntohl(walk->addr.sin_addr.s_addr),
24576404edcSAsim Jamshed 				ntohl(daddr->sin_addr.s_addr), ntohs(walk->addr.sin_port),
246*8c9e1184SAsim Jamshed 					 ntohs(daddr->sin_port), num_queues);
24776404edcSAsim Jamshed 
24876404edcSAsim Jamshed 		if (core == rss_core)
24976404edcSAsim Jamshed 			break;
25076404edcSAsim Jamshed 
25176404edcSAsim Jamshed 		walk = next;
25276404edcSAsim Jamshed 	}
25376404edcSAsim Jamshed 
25476404edcSAsim Jamshed 	if (walk) {
25576404edcSAsim Jamshed 		*saddr = walk->addr;
25676404edcSAsim Jamshed 		TAILQ_REMOVE(&ap->free_list, walk, addr_link);
25776404edcSAsim Jamshed 		TAILQ_INSERT_TAIL(&ap->used_list, walk, addr_link);
25876404edcSAsim Jamshed 		ap->num_free--;
25976404edcSAsim Jamshed 		ap->num_used++;
26076404edcSAsim Jamshed 		ret = 0;
26176404edcSAsim Jamshed 	}
26276404edcSAsim Jamshed 
26376404edcSAsim Jamshed 	pthread_mutex_unlock(&ap->lock);
26476404edcSAsim Jamshed 
26576404edcSAsim Jamshed 	return ret;
26676404edcSAsim Jamshed }
26776404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
26876404edcSAsim Jamshed int
FetchAddressPerCore(addr_pool_t ap,int core,int num_queues,const struct sockaddr_in * daddr,struct sockaddr_in * saddr)2692efd908dSAsim Jamshed FetchAddressPerCore(addr_pool_t ap, int core, int num_queues,
2702efd908dSAsim Jamshed 		    const struct sockaddr_in *daddr, struct sockaddr_in *saddr)
2712efd908dSAsim Jamshed {
2722efd908dSAsim Jamshed 	struct addr_entry *walk;
2732efd908dSAsim Jamshed 	int ret = -1;
2742efd908dSAsim Jamshed 
2752efd908dSAsim Jamshed 	if (!ap || !daddr || !saddr)
2762efd908dSAsim Jamshed 		return -1;
2772efd908dSAsim Jamshed 
2782efd908dSAsim Jamshed 	pthread_mutex_lock(&ap->lock);
2792efd908dSAsim Jamshed 
2802efd908dSAsim Jamshed 	/* we don't need to calculate RSSCPUCore if mtcp_init_rss is called */
2812efd908dSAsim Jamshed 	walk = TAILQ_FIRST(&ap->free_list);
2822efd908dSAsim Jamshed 	if (walk) {
2832efd908dSAsim Jamshed 		*saddr = walk->addr;
2842efd908dSAsim Jamshed 		TAILQ_REMOVE(&ap->free_list, walk, addr_link);
2852efd908dSAsim Jamshed 		TAILQ_INSERT_TAIL(&ap->used_list, walk, addr_link);
2862efd908dSAsim Jamshed 		ap->num_free--;
2872efd908dSAsim Jamshed 		ap->num_used++;
2882efd908dSAsim Jamshed 		ret = 0;
2892efd908dSAsim Jamshed 	}
2902efd908dSAsim Jamshed 
2912efd908dSAsim Jamshed 	pthread_mutex_unlock(&ap->lock);
2922efd908dSAsim Jamshed 
2932efd908dSAsim Jamshed 	return ret;
2942efd908dSAsim Jamshed }
2952efd908dSAsim Jamshed /*----------------------------------------------------------------------------*/
2962efd908dSAsim Jamshed int
FreeAddress(addr_pool_t ap,const struct sockaddr_in * addr)29776404edcSAsim Jamshed FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr)
29876404edcSAsim Jamshed {
29976404edcSAsim Jamshed 	struct addr_entry *walk, *next;
30076404edcSAsim Jamshed 	int ret = -1;
30176404edcSAsim Jamshed 
30276404edcSAsim Jamshed 	if (!ap || !addr)
30376404edcSAsim Jamshed 		return -1;
30476404edcSAsim Jamshed 
30576404edcSAsim Jamshed 	pthread_mutex_lock(&ap->lock);
30676404edcSAsim Jamshed 
30776404edcSAsim Jamshed 	if (ap->mapper) {
30876404edcSAsim Jamshed 		uint32_t addr_h = ntohl(addr->sin_addr.s_addr);
30976404edcSAsim Jamshed 		uint16_t port_h = ntohs(addr->sin_port);
31076404edcSAsim Jamshed 		int index = addr_h - ap->addr_base;
31176404edcSAsim Jamshed 
31277f2f4e7SAsim Jamshed 		if (index >= 0 && index < ap->num_addr) {
31376404edcSAsim Jamshed 			walk = ap->mapper[addr_h - ap->addr_base].addrmap[port_h];
31476404edcSAsim Jamshed 		} else {
31576404edcSAsim Jamshed 			walk = NULL;
31676404edcSAsim Jamshed 		}
31776404edcSAsim Jamshed 
31876404edcSAsim Jamshed 	} else {
31976404edcSAsim Jamshed 		walk = TAILQ_FIRST(&ap->used_list);
32076404edcSAsim Jamshed 		while (walk) {
32176404edcSAsim Jamshed 			next = TAILQ_NEXT(walk, addr_link);
32276404edcSAsim Jamshed 			if (addr->sin_port == walk->addr.sin_port &&
32376404edcSAsim Jamshed 					addr->sin_addr.s_addr == walk->addr.sin_addr.s_addr) {
32476404edcSAsim Jamshed 				break;
32576404edcSAsim Jamshed 			}
32676404edcSAsim Jamshed 
32776404edcSAsim Jamshed 			walk = next;
32876404edcSAsim Jamshed 		}
32976404edcSAsim Jamshed 
33076404edcSAsim Jamshed 	}
33176404edcSAsim Jamshed 
33276404edcSAsim Jamshed 	if (walk) {
33376404edcSAsim Jamshed 		TAILQ_REMOVE(&ap->used_list, walk, addr_link);
33476404edcSAsim Jamshed 		TAILQ_INSERT_TAIL(&ap->free_list, walk, addr_link);
33576404edcSAsim Jamshed 		ap->num_free++;
33676404edcSAsim Jamshed 		ap->num_used--;
33776404edcSAsim Jamshed 		ret = 0;
33876404edcSAsim Jamshed 	}
33976404edcSAsim Jamshed 
34076404edcSAsim Jamshed 	pthread_mutex_unlock(&ap->lock);
34176404edcSAsim Jamshed 
34276404edcSAsim Jamshed 	return ret;
34376404edcSAsim Jamshed }
34476404edcSAsim Jamshed /*----------------------------------------------------------------------------*/
345