176404edcSAsim Jamshed #include <stdio.h> 276404edcSAsim Jamshed #include <stdlib.h> 376404edcSAsim Jamshed #include <pthread.h> 476404edcSAsim Jamshed #include "addr_pool.h" 5*152f7c19SAsim 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 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 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; 11476404edcSAsim 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; 16676404edcSAsim Jamshed rss_core = GetRSSCPUCore(daddr_h, saddr_h, dport_h, sport_h, num_queues); 16776404edcSAsim Jamshed if (rss_core != core) 16876404edcSAsim Jamshed continue; 16976404edcSAsim Jamshed 17076404edcSAsim Jamshed ap->pool[cnt].addr.sin_addr.s_addr = saddr; 17176404edcSAsim Jamshed ap->pool[cnt].addr.sin_port = htons(sport_h); 17276404edcSAsim Jamshed ap->mapper[i].addrmap[j] = &ap->pool[cnt]; 17376404edcSAsim Jamshed TAILQ_INSERT_TAIL(&ap->free_list, &ap->pool[cnt], addr_link); 17476404edcSAsim Jamshed cnt++; 17576404edcSAsim Jamshed } 17676404edcSAsim Jamshed } 17776404edcSAsim Jamshed 17876404edcSAsim Jamshed ap->num_entry = cnt; 17976404edcSAsim Jamshed ap->num_free = cnt; 18076404edcSAsim Jamshed ap->num_used = 0; 18176404edcSAsim Jamshed //fprintf(stderr, "CPU %d: Created %d address entries.\n", core, cnt); 18276404edcSAsim Jamshed if (ap->num_entry < g_config.mos->max_concurrency) { 18376404edcSAsim Jamshed fprintf(stderr, "[WARINING] Available # addresses (%d) is smaller than" 18476404edcSAsim Jamshed " the max concurrency (%d).\n", 18576404edcSAsim Jamshed ap->num_entry, g_config.mos->max_concurrency); 18676404edcSAsim Jamshed } 18776404edcSAsim Jamshed 18876404edcSAsim Jamshed pthread_mutex_unlock(&ap->lock); 18976404edcSAsim Jamshed 19076404edcSAsim Jamshed return ap; 19176404edcSAsim Jamshed } 19276404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 19376404edcSAsim Jamshed void 19476404edcSAsim Jamshed DestroyAddressPool(addr_pool_t ap) 19576404edcSAsim Jamshed { 19676404edcSAsim Jamshed if (!ap) 19776404edcSAsim Jamshed return; 19876404edcSAsim Jamshed 19976404edcSAsim Jamshed if (ap->pool) { 20076404edcSAsim Jamshed free(ap->pool); 20176404edcSAsim Jamshed ap->pool = NULL; 20276404edcSAsim Jamshed } 20376404edcSAsim Jamshed 20476404edcSAsim Jamshed if (ap->mapper) { 20576404edcSAsim Jamshed free(ap->mapper); 20676404edcSAsim Jamshed ap->mapper = NULL; 20776404edcSAsim Jamshed } 20876404edcSAsim Jamshed 20976404edcSAsim Jamshed pthread_mutex_destroy(&ap->lock); 21076404edcSAsim Jamshed 21176404edcSAsim Jamshed free(ap); 21276404edcSAsim Jamshed } 21376404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 21476404edcSAsim Jamshed int 21576404edcSAsim Jamshed FetchAddress(addr_pool_t ap, int core, int num_queues, 21676404edcSAsim Jamshed const struct sockaddr_in *daddr, struct sockaddr_in *saddr) 21776404edcSAsim Jamshed { 21876404edcSAsim Jamshed struct addr_entry *walk, *next; 21976404edcSAsim Jamshed int rss_core; 22076404edcSAsim Jamshed int ret = -1; 22176404edcSAsim Jamshed 22276404edcSAsim Jamshed if (!ap || !daddr || !saddr) 22376404edcSAsim Jamshed return -1; 22476404edcSAsim Jamshed 22576404edcSAsim Jamshed pthread_mutex_lock(&ap->lock); 22676404edcSAsim Jamshed 22776404edcSAsim Jamshed walk = TAILQ_FIRST(&ap->free_list); 22876404edcSAsim Jamshed while (walk) { 22976404edcSAsim Jamshed next = TAILQ_NEXT(walk, addr_link); 23076404edcSAsim Jamshed 23176404edcSAsim Jamshed if (saddr->sin_addr.s_addr != INADDR_ANY && 23276404edcSAsim Jamshed walk->addr.sin_addr.s_addr != saddr->sin_addr.s_addr) { 23376404edcSAsim Jamshed walk = next; 23476404edcSAsim Jamshed continue; 23576404edcSAsim Jamshed } 23676404edcSAsim Jamshed 23776404edcSAsim Jamshed if (saddr->sin_port != INPORT_ANY && 23876404edcSAsim Jamshed walk->addr.sin_port != saddr->sin_port) { 23976404edcSAsim Jamshed walk = next; 24076404edcSAsim Jamshed continue; 24176404edcSAsim Jamshed } 24276404edcSAsim Jamshed 24376404edcSAsim Jamshed rss_core = GetRSSCPUCore(ntohl(walk->addr.sin_addr.s_addr), 24476404edcSAsim Jamshed ntohl(daddr->sin_addr.s_addr), ntohs(walk->addr.sin_port), 24576404edcSAsim Jamshed ntohs(daddr->sin_port), num_queues); 24676404edcSAsim Jamshed 24776404edcSAsim Jamshed if (core == rss_core) 24876404edcSAsim Jamshed break; 24976404edcSAsim Jamshed 25076404edcSAsim Jamshed walk = next; 25176404edcSAsim Jamshed } 25276404edcSAsim Jamshed 25376404edcSAsim Jamshed if (walk) { 25476404edcSAsim Jamshed *saddr = walk->addr; 25576404edcSAsim Jamshed TAILQ_REMOVE(&ap->free_list, walk, addr_link); 25676404edcSAsim Jamshed TAILQ_INSERT_TAIL(&ap->used_list, walk, addr_link); 25776404edcSAsim Jamshed ap->num_free--; 25876404edcSAsim Jamshed ap->num_used++; 25976404edcSAsim Jamshed ret = 0; 26076404edcSAsim Jamshed } 26176404edcSAsim Jamshed 26276404edcSAsim Jamshed pthread_mutex_unlock(&ap->lock); 26376404edcSAsim Jamshed 26476404edcSAsim Jamshed return ret; 26576404edcSAsim Jamshed } 26676404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 26776404edcSAsim Jamshed int 26876404edcSAsim Jamshed FreeAddress(addr_pool_t ap, const struct sockaddr_in *addr) 26976404edcSAsim Jamshed { 27076404edcSAsim Jamshed struct addr_entry *walk, *next; 27176404edcSAsim Jamshed int ret = -1; 27276404edcSAsim Jamshed 27376404edcSAsim Jamshed if (!ap || !addr) 27476404edcSAsim Jamshed return -1; 27576404edcSAsim Jamshed 27676404edcSAsim Jamshed pthread_mutex_lock(&ap->lock); 27776404edcSAsim Jamshed 27876404edcSAsim Jamshed if (ap->mapper) { 27976404edcSAsim Jamshed uint32_t addr_h = ntohl(addr->sin_addr.s_addr); 28076404edcSAsim Jamshed uint16_t port_h = ntohs(addr->sin_port); 28176404edcSAsim Jamshed int index = addr_h - ap->addr_base; 28276404edcSAsim Jamshed 28376404edcSAsim Jamshed if (index >= 0 || index < ap->num_addr) { 28476404edcSAsim Jamshed walk = ap->mapper[addr_h - ap->addr_base].addrmap[port_h]; 28576404edcSAsim Jamshed } else { 28676404edcSAsim Jamshed walk = NULL; 28776404edcSAsim Jamshed } 28876404edcSAsim Jamshed 28976404edcSAsim Jamshed } else { 29076404edcSAsim Jamshed walk = TAILQ_FIRST(&ap->used_list); 29176404edcSAsim Jamshed while (walk) { 29276404edcSAsim Jamshed next = TAILQ_NEXT(walk, addr_link); 29376404edcSAsim Jamshed if (addr->sin_port == walk->addr.sin_port && 29476404edcSAsim Jamshed addr->sin_addr.s_addr == walk->addr.sin_addr.s_addr) { 29576404edcSAsim Jamshed break; 29676404edcSAsim Jamshed } 29776404edcSAsim Jamshed 29876404edcSAsim Jamshed walk = next; 29976404edcSAsim Jamshed } 30076404edcSAsim Jamshed 30176404edcSAsim Jamshed } 30276404edcSAsim Jamshed 30376404edcSAsim Jamshed if (walk) { 30476404edcSAsim Jamshed TAILQ_REMOVE(&ap->used_list, walk, addr_link); 30576404edcSAsim Jamshed TAILQ_INSERT_TAIL(&ap->free_list, walk, addr_link); 30676404edcSAsim Jamshed ap->num_free++; 30776404edcSAsim Jamshed ap->num_used--; 30876404edcSAsim Jamshed ret = 0; 30976404edcSAsim Jamshed } 31076404edcSAsim Jamshed 31176404edcSAsim Jamshed pthread_mutex_unlock(&ap->lock); 31276404edcSAsim Jamshed 31376404edcSAsim Jamshed return ret; 31476404edcSAsim Jamshed } 31576404edcSAsim Jamshed /*----------------------------------------------------------------------------*/ 316